Compare commits
318
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
967908029f | ||
|
|
8560248ea4 | ||
|
|
fa85cf2471 | ||
|
|
8b34881d46 | ||
|
|
de0cad550d | ||
|
|
1f7f84d7a2 | ||
|
|
12c7976b2e | ||
|
|
3e5e301263 | ||
|
|
b1e84b8127 | ||
|
|
44af467936 | ||
|
|
d404934819 | ||
|
|
e908685036 | ||
|
|
d79f5c6c92 | ||
|
|
5b93ea7484 | ||
|
|
c7c552f56a | ||
|
|
d09bc9b76c | ||
|
|
a637478552 | ||
|
|
827a48e31b | ||
|
|
7feb27958b | ||
|
|
89423a10e7 | ||
|
|
47fa9c6a07 | ||
|
|
4390216bca | ||
|
|
6206c775cc | ||
|
|
a078107c51 | ||
|
|
7121a753ba | ||
|
|
0b065bc850 | ||
|
|
1b97908085 | ||
|
|
f8ca84ecc8 | ||
|
|
772ed7d894 | ||
|
|
4adcc35a20 | ||
|
|
8b03d1ba85 | ||
|
|
c7a2971f0d | ||
|
|
7e48976f2f | ||
|
|
1361e3907d | ||
|
|
a03943e158 | ||
|
|
283f5fe681 | ||
|
|
6f5ceb97e8 | ||
|
|
6086132442 | ||
|
|
6a3e6c5d41 | ||
|
|
c6e7e72fa6 | ||
|
|
9148258da9 | ||
|
|
8aa988ad5d | ||
|
|
3a2ec16125 | ||
|
|
5e6df07adb | ||
|
|
f65f931764 | ||
|
|
76b41b3ec0 | ||
|
|
58dda43f19 | ||
|
|
fbf82e4ff6 | ||
|
|
105f89079e | ||
|
|
945636ed0e | ||
|
|
967a18eb8c | ||
|
|
682584d49c | ||
|
|
fe9454abb6 | ||
|
|
b75f13682a | ||
|
|
8173b468c7 | ||
|
|
f7fa5055c7 | ||
|
|
6699f71e2e | ||
|
|
7de0131815 | ||
|
|
4cd960bd3a | ||
|
|
88082dc136 | ||
|
|
8da76d18d2 | ||
|
|
0a6e5734fe | ||
|
|
18336a2936 | ||
|
|
9af03fc80b | ||
|
|
baf09ea081 | ||
|
|
a23a47b216 | ||
|
|
2129d9a4f1 | ||
|
|
528154d68d | ||
|
|
a8deea5def | ||
|
|
fa7d17e0da | ||
|
|
9f7d5736d3 | ||
|
|
229b94e3fb | ||
|
|
94aa25e138 | ||
|
|
998f7bd093 | ||
|
|
df093c9c41 | ||
|
|
d13f3903e6 | ||
|
|
bc0c2a1460 | ||
|
|
e15c28140d | ||
|
|
23a8f83785 | ||
|
|
c91e698800 | ||
|
|
ee776a8d0e | ||
|
|
60082f90b6 | ||
|
|
ef1ddbceea | ||
|
|
f69a26e3df | ||
|
|
9c97b6cca0 | ||
|
|
ada0a17521 | ||
|
|
94a8232cdc | ||
|
|
e2127ad549 | ||
|
|
ff384ebb03 | ||
|
|
89301ba3ca | ||
|
|
24195b4502 | ||
|
|
979b4ae736 | ||
|
|
f37a91e99c | ||
|
|
1600263109 | ||
|
|
2ffcea6578 | ||
|
|
1a982e0671 | ||
|
|
fa3642d1b8 | ||
|
|
4a40a3e863 | ||
|
|
d9cd325a92 | ||
|
|
20f2d74e20 | ||
|
|
50097f912c | ||
|
|
25d58bbe16 | ||
|
|
4d789d01ed | ||
|
|
75dae20268 | ||
|
|
b9c3501d37 | ||
|
|
8099e80b5c | ||
|
|
bcf08e1e84 | ||
|
|
ee9347075e | ||
|
|
c9154db2b3 | ||
|
|
a1d7a34927 | ||
|
|
3287622a0b | ||
|
|
234d66d56b | ||
|
|
10a0103662 | ||
|
|
e6bd619d6b | ||
|
|
c8a53bc4bd | ||
|
|
a88d4e9904 | ||
|
|
e5d0c8fd70 | ||
|
|
8828890cc8 | ||
|
|
a71babd667 | ||
|
|
73ca8408af | ||
|
|
bbc4aea7e9 | ||
|
|
f104863a21 | ||
|
|
8b17dea125 | ||
|
|
7cad5815c1 | ||
|
|
5da7d11d8b | ||
|
|
a597ba69d7 | ||
|
|
7762b23d0a | ||
|
|
c2f2f0a769 | ||
|
|
6c687ff50c | ||
|
|
4c0e29057c | ||
|
|
6a6a59f612 | ||
|
|
0c4277cf73 | ||
|
|
0563913e28 | ||
|
|
3ca23bb830 | ||
|
|
9172fc12db | ||
|
|
8e0c0de7ba | ||
|
|
3546747222 | ||
|
|
15a52d57d8 | ||
|
|
cb8566ed91 | ||
|
|
1b16d8fbca | ||
|
|
b942c04bbe | ||
|
|
ab718835c0 | ||
|
|
4fc94b5310 | ||
|
|
95c5e19748 | ||
|
|
491b582a48 | ||
|
|
3d02a0e788 | ||
|
|
d2d8908df3 | ||
|
|
8f2e581db3 | ||
|
|
88bbd78f1c | ||
|
|
731b7c0d41 | ||
|
|
fb32d4fb3d | ||
|
|
e9637d1780 | ||
|
|
02402b2860 | ||
|
|
ad79a151ff | ||
|
|
15f839e349 | ||
|
|
8e2c36a109 | ||
|
|
fc0303dc3f | ||
|
|
092605c07e | ||
|
|
1caab5cd44 | ||
|
|
c1c04e5b14 | ||
|
|
2056e9be48 | ||
|
|
641fdaa958 | ||
|
|
d09e3b2647 | ||
|
|
5a3dcb824b | ||
|
|
6a2e44da9c | ||
|
|
1983f3deb7 | ||
|
|
fc564d228c | ||
|
|
c04b7e9425 | ||
|
|
2a2b7922d6 | ||
|
|
bc9e58e420 | ||
|
|
7bc3b5e886 | ||
|
|
9626adb81a | ||
|
|
2730cab765 | ||
|
|
673ab658f9 | ||
|
|
d04c3b366e | ||
|
|
d0facf7fd9 | ||
|
|
2dfda4db70 | ||
|
|
1a9c191e1f | ||
|
|
8a3bb90e67 | ||
|
|
5f9d9ca11c | ||
|
|
ffd2101e02 | ||
|
|
923f5b6051 | ||
|
|
f194891195 | ||
|
|
8b1edd63bb | ||
|
|
b3f3f40df3 | ||
|
|
9cebfc6611 | ||
|
|
91c805ff02 | ||
|
|
bc40d5954b | ||
|
|
b15032407a | ||
|
|
65c10cd5e4 | ||
|
|
94527c2abf | ||
|
|
ad857cea1b | ||
|
|
781a550b3c | ||
|
|
c27716f35a | ||
|
|
00828a3b8f | ||
|
|
845e0a880b | ||
|
|
7e89d0b709 | ||
|
|
d936e5b936 | ||
|
|
acea5fb524 | ||
|
|
a7c648d9ac | ||
|
|
6f27e7b292 | ||
|
|
586f1fb5ab | ||
|
|
767b9d400a | ||
|
|
0a91022bba | ||
|
|
3f8f7a186a | ||
|
|
2927da6955 | ||
|
|
b748dfa9f5 | ||
|
|
f09837f7f7 | ||
|
|
1180bc4798 | ||
|
|
41574d6537 | ||
|
|
f164e703ea | ||
|
|
58adbfe9de | ||
|
|
c029b16d34 | ||
|
|
19961d1493 | ||
|
|
9decf3a4aa | ||
|
|
8514657bf5 | ||
|
|
f6828172d5 | ||
|
|
a2ea1dd6b5 | ||
|
|
d37f35258e | ||
|
|
7ec5ea089e | ||
|
|
c4791180f9 | ||
|
|
074ba95836 | ||
|
|
0a8127c6a7 | ||
|
|
4cf36c89ba | ||
|
|
c927ccb89b | ||
|
|
a6687d00a2 | ||
|
|
a61f3864f0 | ||
|
|
e8f7bc8e45 | ||
|
|
97e5bae5e8 | ||
|
|
06d0539dca | ||
|
|
e471c02f49 | ||
|
|
035aa608f8 | ||
|
|
25452671fb | ||
|
|
ffa13d0e65 | ||
|
|
0d1399cca2 | ||
|
|
9fb0d69cde | ||
|
|
2251d41f2c | ||
|
|
1e743b7c52 | ||
|
|
34c395cc2d | ||
|
|
c10d72c877 | ||
|
|
f2f12cfdc6 | ||
|
|
886cfc1122 | ||
|
|
4c59e8105d | ||
|
|
603cb4cb28 | ||
|
|
c09baf7d95 | ||
|
|
f370b414d5 | ||
|
|
b806829091 | ||
|
|
a8fde54f20 | ||
|
|
bc22e8a464 | ||
|
|
b55bad2778 | ||
|
|
f4f4df493c | ||
|
|
19725ed3f4 | ||
|
|
08139ab379 | ||
|
|
36eebb4992 | ||
|
|
ef97a8f73d | ||
|
|
32f254b50f | ||
|
|
86c9b0bd37 | ||
|
|
7325eec877 | ||
|
|
d5dfb6c52e | ||
|
|
1cfcb66003 | ||
|
|
f37cda5337 | ||
|
|
69f42498a3 | ||
|
|
0cab2cbcf0 | ||
|
|
5af52493f5 | ||
|
|
f40fb18204 | ||
|
|
2e4d1c58d4 | ||
|
|
e4fb6187a4 | ||
|
|
873bfe9ac4 | ||
|
|
dccd58ebe7 | ||
|
|
746f022a43 | ||
|
|
5e4df7625a | ||
|
|
d407199412 | ||
|
|
06ee1a8c4b | ||
|
|
fb802bab76 | ||
|
|
dbe41d23f9 | ||
|
|
795d2339bd | ||
|
|
1c79ab091b | ||
|
|
0ab9469674 | ||
|
|
27928a3fed | ||
|
|
fac3033bc6 | ||
|
|
93abad38db | ||
|
|
890b865cce | ||
|
|
0cf9feb7f7 | ||
|
|
74e66f6aec | ||
|
|
69c77420e3 | ||
|
|
42a726f5de | ||
|
|
f067ee01c5 | ||
|
|
60ee23b290 | ||
|
|
0a6297b21e | ||
|
|
1f600856ed | ||
|
|
71b01350b7 | ||
|
|
1938b66414 | ||
|
|
f33a43f28a | ||
|
|
95b349f68c | ||
|
|
bbfc1bef1e | ||
|
|
eeff4bef88 | ||
|
|
afaae976be | ||
|
|
5e902dd313 | ||
|
|
c213bab266 | ||
|
|
6de33e89ea | ||
|
|
2b72a7617c | ||
|
|
227d366140 | ||
|
|
fcf59cc559 | ||
|
|
f7e74f190b | ||
|
|
4112e9319a | ||
|
|
94123f82cb | ||
|
|
f8aeeda21c | ||
|
|
fd9f21fad6 | ||
|
|
f002728b9b | ||
|
|
6bd70ae4a5 | ||
|
|
a06bb99cce | ||
|
|
3ee2ab0db4 | ||
|
|
87e1b0d2e5 | ||
|
|
8483beb771 | ||
|
|
1f9a109c30 | ||
|
|
dab06bc0a3 | ||
|
|
6a898e4d32 | ||
|
|
4d51451bfb |
@@ -50,6 +50,7 @@ variables:
|
||||
AUTOTEST_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/autotest.git
|
||||
MFEM_DATA_REPO: https://github.com/mfem/data.git
|
||||
ARTIFACTS_DIR: artifacts
|
||||
SLURM_OVERLAP: 1
|
||||
|
||||
# The pipeline is divided into stages. Usually, jobs in a given stage wait for
|
||||
# the preceding stages to complete before to start. However, we sometimes use
|
||||
|
||||
@@ -12,6 +12,21 @@ Version 4.3.1 (development)
|
||||
===========================
|
||||
- Added support for hr-adaptivity using TMOP-based error estimator.
|
||||
|
||||
- Adding lowest order Nedelec and Raviart-Thomas basis functions on wedge
|
||||
shaped elements.
|
||||
|
||||
- Added initial support for meshes with pyramidal elements, including several
|
||||
pyramidal meshes in the data/ directory and support for the lowest order H1,
|
||||
Nedelec, Raviart-Thomas, and L2 basis functions on pyramids.
|
||||
|
||||
- Updated the hypre interface according to changes in hypre-2.22.1. The ADS
|
||||
solver is now fully working on GPUs.
|
||||
|
||||
- Tetrahedral meshes no longer need to be reordered to support high order
|
||||
Nedelec basis functions. This will allow future support for Nedelec basis
|
||||
functions on wedges and pyramids which are not amenable to reordering. The
|
||||
ReorientTetMesh method of the Mesh and ParMesh classes has been deprecated.
|
||||
|
||||
|
||||
Version 4.3, released on July 29, 2021
|
||||
======================================
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
cff-version: 1.2.0
|
||||
message: "If you use MFEM, please cite it as follows."
|
||||
authors:
|
||||
- family-names: "MFEM Team"
|
||||
title: "MFEM: Modular Finite Element Methods [Software]"
|
||||
doi: 10.11578/dc.20171025.1248
|
||||
url: "https://mfem.org"
|
||||
preferred-citation:
|
||||
type: article
|
||||
authors:
|
||||
- family-names: "Anderson"
|
||||
given-names: "Robert"
|
||||
orcid: "https://orcid.org/0000-0002-3508-9944"
|
||||
- family-names: "Andrej"
|
||||
given-names: "Julian"
|
||||
orcid: "https://orcid.org/0000-0001-7661-4840"
|
||||
- family-names: "Barker"
|
||||
given-names: "Andrew"
|
||||
orcid: "https://orcid.org/0000-0003-3572-911X"
|
||||
- family-names: "Bramwell"
|
||||
given-names: "Jamie"
|
||||
- family-names: "Camier"
|
||||
given-names: "Jean-Sylvain"
|
||||
orcid: "https://orcid.org/0000-0003-2421-1999"
|
||||
- family-names: "Cerveny"
|
||||
given-names: "Jakub"
|
||||
orcid: "https://orcid.org/0000-0003-4231-2531"
|
||||
- family-names: "Dobrev"
|
||||
given-names: "Veselin"
|
||||
orcid: "https://orcid.org/0000-0003-1793-5622"
|
||||
- family-names: "Dudouit"
|
||||
given-names: "Yohann"
|
||||
orcid: "https://orcid.org/0000-0001-5831-561X"
|
||||
- family-names: "Fisher"
|
||||
given-names: "Aaron"
|
||||
- family-names: "Kolev"
|
||||
given-names: "Tzanio"
|
||||
orcid: "https://orcid.org/0000-0002-2810-3090"
|
||||
- family-names: "Pazner"
|
||||
given-names: "Will"
|
||||
orcid: "https://orcid.org/0000-0003-4885-2934"
|
||||
- family-names: "Stowell"
|
||||
given-names: "Mark"
|
||||
orcid: "https://orcid.org/0000-0002-5389-7435"
|
||||
- family-names: "Tomov"
|
||||
given-names: "Vladimir"
|
||||
orcid: "https://orcid.org/0000-0002-1846-6816"
|
||||
- family-names: "Akkerman"
|
||||
given-names: "Ido"
|
||||
orcid: "https://orcid.org/0000-0002-5937-0300"
|
||||
- family-names: "Dahm"
|
||||
given-names: "Johann"
|
||||
orcid: "https://orcid.org/0000-0001-9657-3564"
|
||||
- family-names: "Medina"
|
||||
given-names: "David"
|
||||
- family-names: "Zampini"
|
||||
given-names: "Stefano"
|
||||
orcid: "https://orcid.org/0000-0002-0435-0433"
|
||||
doi: "10.1016/j.camwa.2020.06.009"
|
||||
journal: "Computers \\& Mathematics with Applications"
|
||||
month: 1
|
||||
start: 42 # First page number
|
||||
end: 74 # Last page number
|
||||
title: "MFEM: A Modular Finite Element Methods Library"
|
||||
volume: 81
|
||||
year: 2021
|
||||
@@ -175,6 +175,10 @@ else()
|
||||
set(MFEM_DEBUG OFF)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
add_definitions(-D_USE_MATH_DEFINES)
|
||||
endif()
|
||||
|
||||
# MPI -> hypre; PETSc (optional)
|
||||
if (MFEM_USE_MPI)
|
||||
find_package(MPI REQUIRED)
|
||||
|
||||
@@ -549,7 +549,7 @@ The specific libraries and their options are:
|
||||
Options: HYPRE_OPT, HYPRE_LIB.
|
||||
Versions: HYPRE >= 2.10.0b (HYPRE built without CUDA)
|
||||
HYPRE >= 2.20.0 (HYPRE built with '--enable-mixedint')
|
||||
HYPRE >= 2.22.0 (HYPRE built with CUDA)
|
||||
HYPRE >= 2.22.1 (HYPRE built with CUDA)
|
||||
|
||||
- METIS, used when MFEM_USE_METIS = YES. If using METIS 5, set
|
||||
MFEM_USE_METIS_5 = YES (default is to use METIS 4).
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
MFEM INLINE mesh v1.0
|
||||
|
||||
type = pyramid
|
||||
nx = 4
|
||||
ny = 4
|
||||
nz = 4
|
||||
sx = 1.0
|
||||
sy = 1.0
|
||||
sz = 1.0
|
||||
@@ -0,0 +1,43 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
# PYRAMID = 7
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
2
|
||||
1 7 4 3 2 1 0
|
||||
1 7 1 2 3 4 5
|
||||
|
||||
boundary
|
||||
8
|
||||
1 2 0 2 1
|
||||
2 2 0 3 2
|
||||
3 2 0 4 3
|
||||
4 2 0 1 4
|
||||
5 2 1 2 5
|
||||
6 2 2 3 5
|
||||
7 2 3 4 5
|
||||
8 2 4 1 5
|
||||
|
||||
vertices
|
||||
6
|
||||
3
|
||||
0 0 -1
|
||||
1 0 0
|
||||
0 1 0
|
||||
-1 0 0
|
||||
0 -1 0
|
||||
0 0 1
|
||||
@@ -0,0 +1,38 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
# PYRAMID = 7
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
1
|
||||
1 7 0 1 2 3 4
|
||||
|
||||
boundary
|
||||
5
|
||||
1 3 3 2 1 0
|
||||
2 2 0 1 4
|
||||
3 2 1 2 4
|
||||
4 2 2 3 4
|
||||
5 2 3 0 4
|
||||
|
||||
vertices
|
||||
5
|
||||
3
|
||||
0 0 0
|
||||
1 0 0
|
||||
1 1 0
|
||||
0 1 0
|
||||
0 0 1
|
||||
@@ -206,9 +206,9 @@ int main(int argc, char *argv[])
|
||||
cout << "Size of linear system: " << A->Height() << endl;
|
||||
|
||||
// 11. Solve the linear system A X = B.
|
||||
MFEM_PERF_BEGIN("Solve A X=B");
|
||||
if (!pa)
|
||||
{
|
||||
MFEM_PERF_SCOPE("Solve A X=B (FA)");
|
||||
#ifndef MFEM_USE_SUITESPARSE
|
||||
// Use a simple symmetric Gauss-Seidel preconditioner with PCG.
|
||||
GSSmoother M((SparseMatrix&)(*A));
|
||||
@@ -223,6 +223,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else // Jacobi preconditioning in partial assembly mode
|
||||
{
|
||||
MFEM_PERF_SCOPE("Solve A X=B (PA)");
|
||||
if (UsesTensorBasis(fespace))
|
||||
{
|
||||
OperatorJacobiSmoother M(a, ess_tdof_list);
|
||||
@@ -233,7 +234,6 @@ int main(int argc, char *argv[])
|
||||
CG(*A, B, X, 1, 400, 1e-12, 0.0);
|
||||
}
|
||||
}
|
||||
MFEM_PERF_END("Solve A X=B");
|
||||
// 12. Recover the solution as a finite element grid function.
|
||||
a.RecoverFEMSolution(X, b, x);
|
||||
|
||||
|
||||
+19
-18
@@ -231,28 +231,29 @@ int main(int argc, char *argv[])
|
||||
// 13. Solve the linear system A X = B.
|
||||
// * With full assembly, use the BoomerAMG preconditioner from hypre.
|
||||
// * With partial assembly, use Jacobi smoothing, for now.
|
||||
MFEM_PERF_BEGIN("Solve A X = B");
|
||||
Solver *prec = NULL;
|
||||
if (pa)
|
||||
{
|
||||
if (UsesTensorBasis(fespace))
|
||||
MFEM_PERF_SCOPE("Solve A X=B");
|
||||
Solver *prec = NULL;
|
||||
if (pa)
|
||||
{
|
||||
prec = new OperatorJacobiSmoother(a, ess_tdof_list);
|
||||
if (UsesTensorBasis(fespace))
|
||||
{
|
||||
prec = new OperatorJacobiSmoother(a, ess_tdof_list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prec = new HypreBoomerAMG;
|
||||
}
|
||||
CGSolver cg(MPI_COMM_WORLD);
|
||||
cg.SetRelTol(1e-12);
|
||||
cg.SetMaxIter(2000);
|
||||
cg.SetPrintLevel(1);
|
||||
if (prec) { cg.SetPreconditioner(*prec); }
|
||||
cg.SetOperator(*A);
|
||||
cg.Mult(B, X);
|
||||
delete prec;
|
||||
}
|
||||
else
|
||||
{
|
||||
prec = new HypreBoomerAMG;
|
||||
}
|
||||
CGSolver cg(MPI_COMM_WORLD);
|
||||
cg.SetRelTol(1e-12);
|
||||
cg.SetMaxIter(2000);
|
||||
cg.SetPrintLevel(1);
|
||||
if (prec) { cg.SetPreconditioner(*prec); }
|
||||
cg.SetOperator(*A);
|
||||
cg.Mult(B, X);
|
||||
delete prec;
|
||||
MFEM_PERF_END("Solve A X = B");
|
||||
// 14. Recover the parallel grid function corresponding to X. This is the
|
||||
// local finite element solution on each processor.
|
||||
a.RecoverFEMSolution(X, b, x);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// ex1 -m ../data/fichera.mesh
|
||||
// ex1 -m ../data/fichera-mixed.mesh
|
||||
// ex1 -m ../data/toroid-wedge.mesh
|
||||
// ex1 -m ../data/octahedron.mesh -o 1
|
||||
// ex1 -m ../data/periodic-annulus-sector.msh
|
||||
// ex1 -m ../data/periodic-torus-sector.msh
|
||||
// ex1 -m ../data/square-disc-p2.vtk -o 2
|
||||
|
||||
@@ -118,7 +118,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 7. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use the Nedelec finite elements of the specified order.
|
||||
|
||||
+7
-4
@@ -24,7 +24,10 @@
|
||||
// class ConductionOperator defining C(u)), as well as their
|
||||
// implicit time integration. Note that implementing the method
|
||||
// ConductionOperator::ImplicitSolve is the only requirement for
|
||||
// high-order implicit (SDIRK) time integration.
|
||||
// high-order implicit (SDIRK) time integration. In this example,
|
||||
// the diffusion operator is linearized by evaluating with the
|
||||
// lagged solution from the previous timestep, so there is only
|
||||
// a linear solve.
|
||||
//
|
||||
// We recommend viewing examples 2, 9 and 10 before viewing this
|
||||
// example.
|
||||
@@ -326,8 +329,8 @@ ConductionOperator::ConductionOperator(FiniteElementSpace &f, double al,
|
||||
void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
|
||||
{
|
||||
// Compute:
|
||||
// du_dt = M^{-1}*-K(u)
|
||||
// for du_dt
|
||||
// du_dt = M^{-1}*-Ku
|
||||
// for du_dt, where K is linearized by using u from the previous timestep
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, du_dt);
|
||||
@@ -338,7 +341,7 @@ void ConductionOperator::ImplicitSolve(const double dt,
|
||||
{
|
||||
// Solve the equation:
|
||||
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
|
||||
// for du_dt
|
||||
// for du_dt, where K is linearized by using u from the previous timestep
|
||||
if (!T)
|
||||
{
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
|
||||
+8
-5
@@ -24,8 +24,11 @@
|
||||
// class ConductionOperator defining C(u)), as well as their
|
||||
// implicit time integration. Note that implementing the method
|
||||
// ConductionOperator::ImplicitSolve is the only requirement for
|
||||
// high-order implicit (SDIRK) time integration. Optional saving
|
||||
// with ADIOS2 (adios2.readthedocs.io) is also illustrated.
|
||||
// high-order implicit (SDIRK) time integration. In this example,
|
||||
// the diffusion operator is linearized by evaluating with the
|
||||
// lagged solution from the previous timestep, so there is only
|
||||
// a linear solve. Optional saving with ADIOS2
|
||||
// (adios2.readthedocs.io) is also illustrated.
|
||||
//
|
||||
// We recommend viewing examples 2, 9 and 10 before viewing this
|
||||
// example.
|
||||
@@ -420,8 +423,8 @@ ConductionOperator::ConductionOperator(ParFiniteElementSpace &f, double al,
|
||||
void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
|
||||
{
|
||||
// Compute:
|
||||
// du_dt = M^{-1}*-K(u)
|
||||
// for du_dt
|
||||
// du_dt = M^{-1}*-Ku
|
||||
// for du_dt, where K is linearized by using u from the previous timestep
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, du_dt);
|
||||
@@ -432,7 +435,7 @@ void ConductionOperator::ImplicitSolve(const double dt,
|
||||
{
|
||||
// Solve the equation:
|
||||
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
|
||||
// for du_dt
|
||||
// for du_dt, where K is linearized by using u from the previous timestep
|
||||
if (!T)
|
||||
{
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// mpirun -np 4 ex1p -m ../data/fichera.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/fichera-mixed.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/toroid-wedge.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/octahedron.mesh -o 1
|
||||
// mpirun -np 4 ex1p -m ../data/periodic-annulus-sector.msh
|
||||
// mpirun -np 4 ex1p -m ../data/periodic-torus-sector.msh
|
||||
// mpirun -np 4 ex1p -m ../data/square-disc-p2.vtk -o 2
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
// ex22 -m ../data/inline-hex.mesh -o 2 -p 1
|
||||
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2
|
||||
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2 -pa
|
||||
// ex22 -m ../data/inline-wedge.mesh -o 1
|
||||
// ex22 -m ../data/inline-pyramid.mesh -o 1
|
||||
// ex22 -m ../data/star.mesh -r 1 -o 2 -sigma 10.0
|
||||
//
|
||||
// Device sample runs:
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 1
|
||||
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 2
|
||||
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 1 -p 2 -pa
|
||||
// mpirun -np 4 ex22p -m ../data/inline-wedge.mesh -o 1
|
||||
// mpirun -np 4 ex22p -m ../data/inline-pyramid.mesh -o 1
|
||||
// mpirun -np 4 ex22p -m ../data/star.mesh -o 2 -sigma 10.0
|
||||
//
|
||||
// Device sample runs:
|
||||
|
||||
@@ -113,7 +113,6 @@ int main(int argc, char *argv[])
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
mesh->ReorientTetMesh();
|
||||
|
||||
// 5. Define a finite element space on the mesh. Here we use Nedelec or
|
||||
// Raviart-Thomas finite elements of the specified order.
|
||||
|
||||
@@ -141,7 +141,6 @@ int main(int argc, char *argv[])
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 7. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use Nedelec or Raviart-Thomas finite elements of the specified order.
|
||||
|
||||
+3
-5
@@ -92,7 +92,7 @@ class PMLDiagMatrixCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
CartesianPML * pml = nullptr;
|
||||
void (*Function)(const Vector &, CartesianPML * , Vector &);
|
||||
void (*Function)(const Vector &, CartesianPML *, Vector &);
|
||||
public:
|
||||
PMLDiagMatrixCoefficient(int dim, void(*F)(const Vector &, CartesianPML *,
|
||||
Vector &),
|
||||
@@ -277,10 +277,8 @@ int main(int argc, char *argv[])
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
|
||||
// 6. Reorient mesh in case of a tet mesh
|
||||
mesh->ReorientTetMesh();
|
||||
|
||||
// Set element attributes in order to distinguish elements in the PML region
|
||||
// 6. Set element attributes in order to distinguish elements in the
|
||||
// PML region
|
||||
pml->SetAttributes(mesh);
|
||||
|
||||
// 7. Define a finite element space on the mesh. Here we use the Nedelec
|
||||
|
||||
+1
-4
@@ -92,7 +92,7 @@ class PMLDiagMatrixCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
CartesianPML * pml = nullptr;
|
||||
void (*Function)(const Vector &, CartesianPML * , Vector &);
|
||||
void (*Function)(const Vector &, CartesianPML *, Vector &);
|
||||
public:
|
||||
PMLDiagMatrixCoefficient(int dim, void(*F)(const Vector &, CartesianPML *,
|
||||
Vector &),
|
||||
@@ -316,9 +316,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// 7a. Reorient mesh in case of a tet mesh
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 8. Set element attributes in order to distinguish elements in the PML
|
||||
pml->SetAttributes(pmesh);
|
||||
|
||||
|
||||
+2
-1
@@ -16,6 +16,8 @@
|
||||
// ex3 -m ../data/beam-hex-nurbs.mesh
|
||||
// ex3 -m ../data/amr-hex.mesh
|
||||
// ex3 -m ../data/fichera-amr.mesh
|
||||
// ex3 -m ../data/ref-prism.mesh -o 1
|
||||
// ex3 -m ../data/octahedron.mesh -o 1
|
||||
// ex3 -m ../data/star-surf.mesh -o 1
|
||||
// ex3 -m ../data/mobius-strip.mesh -f 0.1
|
||||
// ex3 -m ../data/klein-bottle.mesh -f 0.1
|
||||
@@ -113,7 +115,6 @@ int main(int argc, char *argv[])
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
mesh->ReorientTetMesh();
|
||||
|
||||
// 5. Define a finite element space on the mesh. Here we use the Nedelec
|
||||
// finite elements of the specified order.
|
||||
|
||||
+3
-4
@@ -16,6 +16,8 @@
|
||||
// mpirun -np 4 ex3p -m ../data/beam-hex-nurbs.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/amr-quad.mesh -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/amr-hex.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/ref-prism.mesh -o 1
|
||||
// mpirun -np 4 ex3p -m ../data/octahedron.mesh -o 1
|
||||
// mpirun -np 4 ex3p -m ../data/star-surf.mesh -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/mobius-strip.mesh -o 2 -f 0.1
|
||||
// mpirun -np 4 ex3p -m ../data/klein-bottle.mesh -o 2 -f 0.1
|
||||
@@ -139,9 +141,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
|
||||
// meshes need to be reoriented before we can define high-order Nedelec
|
||||
// spaces on them.
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
delete mesh;
|
||||
{
|
||||
@@ -151,7 +151,6 @@ int main(int argc, char *argv[])
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 7. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use the Nedelec finite elements of the specified order.
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
// ex4 -m ../data/amr-hex.mesh
|
||||
// ex4 -m ../data/amr-hex.mesh -o 2 -hb
|
||||
// ex4 -m ../data/fichera-amr.mesh -o 2 -sc
|
||||
// ex4 -m ../data/ref-prism.mesh -o 1
|
||||
// ex4 -m ../data/octahedron.mesh -o 1
|
||||
// ex4 -m ../data/star-surf.mesh -o 1
|
||||
//
|
||||
// Device sample runs:
|
||||
|
||||
+3
-4
@@ -19,6 +19,8 @@
|
||||
// mpirun -np 3 ex4p -m ../data/amr-quad.mesh -o 2 -hb
|
||||
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -sc
|
||||
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -hb
|
||||
// mpirun -np 4 ex4p -m ../data/ref-prism.mesh -o 1
|
||||
// mpirun -np 4 ex4p -m ../data/octahedron.mesh -o 1
|
||||
// mpirun -np 4 ex4p -m ../data/star-surf.mesh -o 3 -hb
|
||||
//
|
||||
// Device sample runs:
|
||||
@@ -135,9 +137,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
|
||||
// meshes need to be reoriented before we can define high-order Nedelec
|
||||
// spaces on them (this is needed in the ADS solver below).
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
delete mesh;
|
||||
{
|
||||
@@ -147,7 +147,6 @@ int main(int argc, char *argv[])
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 7. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use the Raviart-Thomas finite elements of the specified order.
|
||||
|
||||
@@ -106,7 +106,6 @@ int main(int argc, char *argv[])
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 6. Define the trial, interfacial (trace) and test DPG spaces:
|
||||
// - The trial space, x0_space, contains the non-interfacial unknowns and
|
||||
|
||||
@@ -121,9 +121,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
|
||||
// meshes need to be reoriented before we can define high-order Nedelec
|
||||
// spaces on them.
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
delete mesh;
|
||||
{
|
||||
@@ -133,7 +131,6 @@ int main(int argc, char *argv[])
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 6. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use the Nedelec finite elements of the specified order.
|
||||
|
||||
@@ -122,9 +122,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
|
||||
// meshes need to be reoriented before we can define high-order Nedelec
|
||||
// spaces on them (this is needed in the ADS solver below).
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
delete mesh;
|
||||
{
|
||||
@@ -134,7 +132,6 @@ int main(int argc, char *argv[])
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 6. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use the Raviart-Thomas finite elements of the specified order.
|
||||
|
||||
@@ -39,6 +39,7 @@ set(SRCS
|
||||
complex_fem.cpp
|
||||
convergence.cpp
|
||||
datacollection.cpp
|
||||
doftrans.cpp
|
||||
eltrans.cpp
|
||||
estimators.cpp
|
||||
fe.cpp
|
||||
@@ -119,6 +120,7 @@ set(HDRS
|
||||
complex_fem.hpp
|
||||
convergence.hpp
|
||||
datacollection.hpp
|
||||
doftrans.hpp
|
||||
eltrans.hpp
|
||||
estimators.hpp
|
||||
fe.hpp
|
||||
|
||||
+58
-24
@@ -391,6 +391,7 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
}
|
||||
|
||||
ElementTransformation *eltrans;
|
||||
DofTransformation * doftrans;
|
||||
Mesh *mesh = fes -> GetMesh();
|
||||
DenseMatrix elmat, *elmat_p;
|
||||
|
||||
@@ -424,7 +425,7 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
for (int i = 0; i < fes -> GetNE(); i++)
|
||||
{
|
||||
int elem_attr = fes->GetMesh()->GetAttribute(i);
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
if (element_matrices)
|
||||
{
|
||||
elmat_p = &(*element_matrices)(i);
|
||||
@@ -458,6 +459,11 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
{
|
||||
elmat_p = &elmat;
|
||||
}
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformDual(elmat);
|
||||
}
|
||||
elmat_p = &elmat;
|
||||
}
|
||||
if (static_cond)
|
||||
{
|
||||
@@ -503,7 +509,7 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
|
||||
|
||||
const FiniteElement &be = *fes->GetBE(i);
|
||||
fes -> GetBdrElementVDofs (i, vdofs);
|
||||
doftrans = fes -> GetBdrElementVDofs (i, vdofs);
|
||||
eltrans = fes -> GetBdrElementTransformation (i);
|
||||
int k = 0;
|
||||
for (; k < boundary_integs.Size(); k++)
|
||||
@@ -523,17 +529,22 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
boundary_integs[k]->AssembleElementMatrix(be, *eltrans, elemmat);
|
||||
elmat += elemmat;
|
||||
}
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformDual(elmat);
|
||||
}
|
||||
elmat_p = &elmat;
|
||||
if (!static_cond)
|
||||
{
|
||||
mat->AddSubMatrix(vdofs, vdofs, elmat, skip_zeros);
|
||||
mat->AddSubMatrix(vdofs, vdofs, *elmat_p, skip_zeros);
|
||||
if (hybridization)
|
||||
{
|
||||
hybridization->AssembleBdrMatrix(i, elmat);
|
||||
hybridization->AssembleBdrMatrix(i, *elmat_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static_cond->AssembleBdrMatrix(i, elmat);
|
||||
static_cond->AssembleBdrMatrix(i, *elmat_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1318,9 +1329,10 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
return;
|
||||
}
|
||||
|
||||
Array<int> tr_vdofs, te_vdofs;
|
||||
ElementTransformation *eltrans;
|
||||
DenseMatrix elemmat;
|
||||
DofTransformation * dom_dof_trans;
|
||||
DofTransformation * ran_dof_trans;
|
||||
DenseMatrix elmat;
|
||||
|
||||
Mesh *mesh = test_fes -> GetMesh();
|
||||
|
||||
@@ -1333,16 +1345,24 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
{
|
||||
for (int i = 0; i < test_fes -> GetNE(); i++)
|
||||
{
|
||||
trial_fes -> GetElementVDofs (i, tr_vdofs);
|
||||
test_fes -> GetElementVDofs (i, te_vdofs);
|
||||
dom_dof_trans = trial_fes -> GetElementVDofs (i, trial_vdofs);
|
||||
ran_dof_trans = test_fes -> GetElementVDofs (i, test_vdofs);
|
||||
eltrans = test_fes -> GetElementTransformation (i);
|
||||
|
||||
elmat.SetSize(test_vdofs.Size(), trial_vdofs.Size());
|
||||
elmat = 0.0;
|
||||
for (int k = 0; k < domain_integs.Size(); k++)
|
||||
{
|
||||
domain_integs[k] -> AssembleElementMatrix2 (*trial_fes -> GetFE(i),
|
||||
*test_fes -> GetFE(i),
|
||||
*eltrans, elemmat);
|
||||
mat -> AddSubMatrix (te_vdofs, tr_vdofs, elemmat, skip_zeros);
|
||||
elmat += elemmat;
|
||||
}
|
||||
if (ran_dof_trans || dom_dof_trans)
|
||||
{
|
||||
TransformDual(ran_dof_trans, dom_dof_trans, elmat);
|
||||
}
|
||||
mat -> AddSubMatrix (test_vdofs, trial_vdofs, elmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1374,9 +1394,12 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
const int bdr_attr = mesh->GetBdrAttribute(i);
|
||||
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
|
||||
|
||||
trial_fes -> GetBdrElementVDofs (i, tr_vdofs);
|
||||
test_fes -> GetBdrElementVDofs (i, te_vdofs);
|
||||
dom_dof_trans = trial_fes -> GetBdrElementVDofs (i, trial_vdofs);
|
||||
ran_dof_trans = test_fes -> GetBdrElementVDofs (i, test_vdofs);
|
||||
eltrans = test_fes -> GetBdrElementTransformation (i);
|
||||
|
||||
elmat.SetSize(test_vdofs.Size(), trial_vdofs.Size());
|
||||
elmat = 0.0;
|
||||
for (int k = 0; k < boundary_integs.Size(); k++)
|
||||
{
|
||||
if (boundary_integs_marker[k] &&
|
||||
@@ -1385,29 +1408,34 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
boundary_integs[k]->AssembleElementMatrix2 (*trial_fes -> GetBE(i),
|
||||
*test_fes -> GetBE(i),
|
||||
*eltrans, elemmat);
|
||||
mat -> AddSubMatrix (te_vdofs, tr_vdofs, elemmat, skip_zeros);
|
||||
elmat += elemmat;
|
||||
}
|
||||
if (ran_dof_trans || dom_dof_trans)
|
||||
{
|
||||
TransformDual(ran_dof_trans, dom_dof_trans, elmat);
|
||||
}
|
||||
mat -> AddSubMatrix (test_vdofs, trial_vdofs, elmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
|
||||
if (trace_face_integs.Size())
|
||||
{
|
||||
FaceElementTransformations *ftr;
|
||||
Array<int> te_vdofs2;
|
||||
Array<int> test_vdofs2;
|
||||
const FiniteElement *trial_face_fe, *test_fe1, *test_fe2;
|
||||
|
||||
int nfaces = mesh->GetNumFaces();
|
||||
for (int i = 0; i < nfaces; i++)
|
||||
{
|
||||
ftr = mesh->GetFaceElementTransformations(i);
|
||||
trial_fes->GetFaceVDofs(i, tr_vdofs);
|
||||
test_fes->GetElementVDofs(ftr->Elem1No, te_vdofs);
|
||||
trial_fes->GetFaceVDofs(i, trial_vdofs);
|
||||
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs);
|
||||
trial_face_fe = trial_fes->GetFaceElement(i);
|
||||
test_fe1 = test_fes->GetFE(ftr->Elem1No);
|
||||
if (ftr->Elem2No >= 0)
|
||||
{
|
||||
test_fes->GetElementVDofs(ftr->Elem2No, te_vdofs2);
|
||||
te_vdofs.Append(te_vdofs2);
|
||||
test_fes->GetElementVDofs(ftr->Elem2No, test_vdofs2);
|
||||
test_vdofs.Append(test_vdofs2);
|
||||
test_fe2 = test_fes->GetFE(ftr->Elem2No);
|
||||
}
|
||||
else
|
||||
@@ -1421,7 +1449,7 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
{
|
||||
trace_face_integs[k]->AssembleFaceMatrix(*trial_face_fe, *test_fe1,
|
||||
*test_fe2, *ftr, elemmat);
|
||||
mat->AddSubMatrix(te_vdofs, tr_vdofs, elemmat, skip_zeros);
|
||||
mat->AddSubMatrix(test_vdofs, trial_vdofs, elemmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1461,8 +1489,8 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
ftr = mesh->GetBdrFaceTransformations(i);
|
||||
if (ftr)
|
||||
{
|
||||
trial_fes->GetFaceVDofs(ftr->ElementNo, tr_vdofs);
|
||||
test_fes->GetElementVDofs(ftr->Elem1No, te_vdofs);
|
||||
trial_fes->GetFaceVDofs(ftr->ElementNo, trial_vdofs);
|
||||
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs);
|
||||
trial_face_fe = trial_fes->GetFaceElement(ftr->ElementNo);
|
||||
test_fe1 = test_fes->GetFE(ftr->Elem1No);
|
||||
// The test_fe2 object is really a dummy and not used on the
|
||||
@@ -1479,7 +1507,7 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
*test_fe1,
|
||||
*test_fe2,
|
||||
*ftr, elemmat);
|
||||
mat->AddSubMatrix(te_vdofs, tr_vdofs, elemmat, skip_zeros);
|
||||
mat->AddSubMatrix(test_vdofs, trial_vdofs, elemmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1841,6 +1869,8 @@ void DiscreteLinearOperator::Assemble(int skip_zeros)
|
||||
|
||||
Array<int> dom_vdofs, ran_vdofs;
|
||||
ElementTransformation *T;
|
||||
DofTransformation * dom_dof_trans;
|
||||
DofTransformation * ran_dof_trans;
|
||||
const FiniteElement *dom_fe, *ran_fe;
|
||||
DenseMatrix totelmat, elmat;
|
||||
|
||||
@@ -1853,8 +1883,8 @@ void DiscreteLinearOperator::Assemble(int skip_zeros)
|
||||
{
|
||||
for (int i = 0; i < test_fes->GetNE(); i++)
|
||||
{
|
||||
trial_fes->GetElementVDofs(i, dom_vdofs);
|
||||
test_fes->GetElementVDofs(i, ran_vdofs);
|
||||
dom_dof_trans = trial_fes->GetElementVDofs(i, dom_vdofs);
|
||||
ran_dof_trans = test_fes->GetElementVDofs(i, ran_vdofs);
|
||||
T = test_fes->GetElementTransformation(i);
|
||||
dom_fe = trial_fes->GetFE(i);
|
||||
ran_fe = test_fes->GetFE(i);
|
||||
@@ -1867,6 +1897,10 @@ void DiscreteLinearOperator::Assemble(int skip_zeros)
|
||||
elmat);
|
||||
totelmat += elmat;
|
||||
}
|
||||
if (ran_dof_trans || dom_dof_trans)
|
||||
{
|
||||
TransformPrimal(ran_dof_trans, dom_dof_trans, totelmat);
|
||||
}
|
||||
mat->SetSubMatrix(ran_vdofs, dom_vdofs, totelmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@ namespace mfem
|
||||
{
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EAConvectionAssemble1D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EAConvectionAssemble1D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -69,14 +69,14 @@ static void EAConvectionAssemble1D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EAConvectionAssemble2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EAConvectionAssemble2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -146,14 +146,14 @@ static void EAConvectionAssemble2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EAConvectionAssemble3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EAConvectionAssemble3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -21,13 +21,13 @@ namespace mfem
|
||||
// PA Convection Integrator
|
||||
|
||||
// PA Convection Assemble 2D kernel
|
||||
static void PAConvectionSetup2D(const int NQ,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
Vector &op)
|
||||
void PAConvectionSetup2D(const int NQ,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
Vector &op)
|
||||
{
|
||||
constexpr int DIM = 2;
|
||||
|
||||
@@ -60,13 +60,13 @@ static void PAConvectionSetup2D(const int NQ,
|
||||
}
|
||||
|
||||
// PA Convection Assemble 3D kernel
|
||||
static void PAConvectionSetup3D(const int NQ,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
Vector &op)
|
||||
void PAConvectionSetup3D(const int NQ,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
Vector &op)
|
||||
{
|
||||
constexpr int DIM = 3;
|
||||
constexpr int SDIM = DIM;
|
||||
@@ -135,7 +135,7 @@ static void PAConvectionSetup(const int dim,
|
||||
}
|
||||
|
||||
// PA Convection Apply 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void PAConvectionApply2D(const int ne,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
@@ -254,7 +254,7 @@ void PAConvectionApply2D(const int ne,
|
||||
}
|
||||
|
||||
// Optimized PA Convection Apply 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
void SmemPAConvectionApply2D(const int ne,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
@@ -382,7 +382,7 @@ void SmemPAConvectionApply2D(const int ne,
|
||||
}
|
||||
|
||||
// PA Convection Apply 3D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void PAConvectionApply3D(const int ne,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
@@ -563,7 +563,7 @@ void PAConvectionApply3D(const int ne,
|
||||
}
|
||||
|
||||
// Optimized PA Convection Apply 3D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void SmemPAConvectionApply3D(const int ne,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
static void EADGTraceAssemble1DInt(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_int,
|
||||
Vector &eadata_ext,
|
||||
const bool add)
|
||||
void EADGTraceAssemble1DInt(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_int,
|
||||
Vector &eadata_ext,
|
||||
const bool add)
|
||||
{
|
||||
auto D = Reshape(padata.Read(), 2, 2, NF);
|
||||
auto A_int = Reshape(eadata_int.ReadWrite(), 2, NF);
|
||||
@@ -50,11 +50,11 @@ static void EADGTraceAssemble1DInt(const int NF,
|
||||
});
|
||||
}
|
||||
|
||||
static void EADGTraceAssemble1DBdr(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_bdr,
|
||||
const bool add)
|
||||
void EADGTraceAssemble1DBdr(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_bdr,
|
||||
const bool add)
|
||||
{
|
||||
auto D = Reshape(padata.Read(), 2, 2, NF);
|
||||
auto A_bdr = Reshape(eadata_bdr.ReadWrite(), NF);
|
||||
@@ -72,14 +72,14 @@ static void EADGTraceAssemble1DBdr(const int NF,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADGTraceAssemble2DInt(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_int,
|
||||
Vector &eadata_ext,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADGTraceAssemble2DInt(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_int,
|
||||
Vector &eadata_ext,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -128,13 +128,13 @@ static void EADGTraceAssemble2DInt(const int NF,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADGTraceAssemble2DBdr(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_bdr,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADGTraceAssemble2DBdr(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_bdr,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -170,14 +170,14 @@ static void EADGTraceAssemble2DBdr(const int NF,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADGTraceAssemble3DInt(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_int,
|
||||
Vector &eadata_ext,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADGTraceAssemble3DInt(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_int,
|
||||
Vector &eadata_ext,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -268,13 +268,13 @@ static void EADGTraceAssemble3DInt(const int NF,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADGTraceAssemble3DBdr(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_bdr,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADGTraceAssemble3DBdr(const int NF,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata_bdr,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -19,16 +19,16 @@ using namespace std;
|
||||
namespace mfem
|
||||
{
|
||||
// PA DG Trace Integrator
|
||||
static void PADGTraceSetup2D(const int Q1D,
|
||||
const int NF,
|
||||
const Array<double> &w,
|
||||
const Vector &det,
|
||||
const Vector &nor,
|
||||
const Vector &rho,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
const double beta,
|
||||
Vector &op)
|
||||
void PADGTraceSetup2D(const int Q1D,
|
||||
const int NF,
|
||||
const Array<double> &w,
|
||||
const Vector &det,
|
||||
const Vector &nor,
|
||||
const Vector &rho,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
const double beta,
|
||||
Vector &op)
|
||||
{
|
||||
const int VDIM = 2;
|
||||
|
||||
@@ -61,16 +61,16 @@ static void PADGTraceSetup2D(const int Q1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PADGTraceSetup3D(const int Q1D,
|
||||
const int NF,
|
||||
const Array<double> &w,
|
||||
const Vector &det,
|
||||
const Vector &nor,
|
||||
const Vector &rho,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
const double beta,
|
||||
Vector &op)
|
||||
void PADGTraceSetup3D(const int Q1D,
|
||||
const int NF,
|
||||
const Array<double> &w,
|
||||
const Vector &det,
|
||||
const Vector &nor,
|
||||
const Vector &rho,
|
||||
const Vector &vel,
|
||||
const double alpha,
|
||||
const double beta,
|
||||
Vector &op)
|
||||
{
|
||||
const int VDIM = 3;
|
||||
|
||||
@@ -301,7 +301,7 @@ void DGTraceIntegrator::AssemblePABoundaryFaces(const FiniteElementSpace& fes)
|
||||
}
|
||||
|
||||
// PA DGTrace Apply 2D kernel for Gauss-Lobatto/Bernstein
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void PADGTraceApply2D(const int NF,
|
||||
const Array<double> &b,
|
||||
const Array<double> &bt,
|
||||
@@ -392,7 +392,7 @@ void PADGTraceApply2D(const int NF,
|
||||
}
|
||||
|
||||
// PA DGTrace Apply 3D kernel for Gauss-Lobatto/Bernstein
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void PADGTraceApply3D(const int NF,
|
||||
const Array<double> &b,
|
||||
const Array<double> &bt,
|
||||
@@ -537,7 +537,7 @@ void PADGTraceApply3D(const int NF,
|
||||
}
|
||||
|
||||
// Optimized PA DGTrace Apply 3D kernel for Gauss-Lobatto/Bernstein
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
void SmemPADGTraceApply3D(const int NF,
|
||||
const Array<double> &b,
|
||||
const Array<double> &bt,
|
||||
@@ -701,7 +701,7 @@ static void PADGTraceApply(const int dim,
|
||||
}
|
||||
|
||||
// PA DGTrace Apply 2D kernel for Gauss-Lobatto/Bernstein
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void PADGTraceApplyTranspose2D(const int NF,
|
||||
const Array<double> &b,
|
||||
const Array<double> &bt,
|
||||
@@ -797,7 +797,7 @@ void PADGTraceApplyTranspose2D(const int NF,
|
||||
}
|
||||
|
||||
// PA DGTrace Apply Transpose 3D kernel for Gauss-Lobatto/Bernstein
|
||||
template<int T_D1D = 0, int T_Q1D = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
void PADGTraceApplyTranspose3D(const int NF,
|
||||
const Array<double> &b,
|
||||
const Array<double> &bt,
|
||||
@@ -953,7 +953,7 @@ void PADGTraceApplyTranspose3D(const int NF,
|
||||
}
|
||||
|
||||
// Optimized PA DGTrace Apply Transpose 3D kernel for Gauss-Lobatto/Bernstein
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
void SmemPADGTraceApplyTranspose3D(const int NF,
|
||||
const Array<double> &b,
|
||||
const Array<double> &bt,
|
||||
|
||||
@@ -17,14 +17,14 @@ namespace mfem
|
||||
{
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADiffusionAssemble1D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADiffusionAssemble1D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -68,14 +68,14 @@ static void EADiffusionAssemble1D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADiffusionAssemble2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADiffusionAssemble2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -145,14 +145,14 @@ static void EADiffusionAssemble2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EADiffusionAssemble3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EADiffusionAssemble3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -496,14 +496,14 @@ void DiffusionIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PADiffusionDiagonal2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PADiffusionDiagonal2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -562,14 +562,14 @@ static void PADiffusionDiagonal2D(const int NE,
|
||||
|
||||
// Shared memory PA Diffusion Diagonal 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
static void SmemPADiffusionDiagonal2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPADiffusionDiagonal2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -656,14 +656,14 @@ static void SmemPADiffusionDiagonal2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PADiffusionDiagonal3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PADiffusionDiagonal3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
@@ -757,14 +757,14 @@ static void PADiffusionDiagonal3D(const int NE,
|
||||
|
||||
// Shared memory PA Diffusion Diagonal 3D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void SmemPADiffusionDiagonal3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPADiffusionDiagonal3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
@@ -1034,17 +1034,17 @@ static void OccaPADiffusionApply3D(const int D1D,
|
||||
|
||||
// PA Diffusion Apply 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PADiffusionApply2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Array<double> >_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PADiffusionApply2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Array<double> >_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -1156,15 +1156,15 @@ static void PADiffusionApply2D(const int NE,
|
||||
|
||||
// Shared memory PA Diffusion Apply 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
static void SmemPADiffusionApply2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPADiffusionApply2D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -1314,16 +1314,16 @@ static void SmemPADiffusionApply2D(const int NE,
|
||||
|
||||
// PA Diffusion Apply 3D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PADiffusionApply3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Array<double> >,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int d1d = 0, int q1d = 0)
|
||||
void PADiffusionApply3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Array<double> >,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int d1d = 0, int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -1533,15 +1533,15 @@ static MFEM_HOST_DEVICE inline double sign(const int q, const int d)
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void SmemPADiffusionApply3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPADiffusionApply3D(const int NE,
|
||||
const bool symmetric,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -21,12 +21,12 @@ namespace mfem
|
||||
// PA Divergence Integrator
|
||||
|
||||
// PA Divergence Assemble 2D kernel
|
||||
static void PADivergenceSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const double COEFF,
|
||||
Vector &op)
|
||||
void PADivergenceSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const double COEFF,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -51,12 +51,12 @@ static void PADivergenceSetup2D(const int Q1D,
|
||||
}
|
||||
|
||||
// PA Divergence Assemble 3D kernel
|
||||
static void PADivergenceSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const double COEFF,
|
||||
Vector &op)
|
||||
void PADivergenceSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const double COEFF,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -160,16 +160,16 @@ void VectorDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
|
||||
|
||||
// PA Divergence Apply 2D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void PADivergenceApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PADivergenceApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
@@ -281,16 +281,16 @@ static void PADivergenceApply2D(const int NE,
|
||||
// Shared memory PA Divergence Apply 2D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0,
|
||||
const int T_NBZ = 0>
|
||||
static void SmemPADivergenceApply2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPADivergenceApply2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
// TODO
|
||||
MFEM_ASSERT(false, "SHARED MEM NOT PROGRAMMED YET");
|
||||
@@ -298,16 +298,16 @@ static void SmemPADivergenceApply2D(const int NE,
|
||||
|
||||
// PA Divergence Apply 2D kernel transpose
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void PADivergenceApplyTranspose2D(const int NE,
|
||||
const Array<double> &bt,
|
||||
const Array<double> >,
|
||||
const Array<double> &b,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PADivergenceApplyTranspose2D(const int NE,
|
||||
const Array<double> &bt,
|
||||
const Array<double> >,
|
||||
const Array<double> &b,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
@@ -414,16 +414,16 @@ static void PADivergenceApplyTranspose2D(const int NE,
|
||||
|
||||
// PA Vector Divergence Apply 3D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void PADivergenceApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int tr_d1d = 0,
|
||||
int te_d1d = 0,
|
||||
int q1d = 0)
|
||||
void PADivergenceApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int tr_d1d = 0,
|
||||
int te_d1d = 0,
|
||||
int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
@@ -597,16 +597,16 @@ static void PADivergenceApply3D(const int NE,
|
||||
|
||||
// PA Vector Divergence Apply 3D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void PADivergenceApplyTranspose3D(const int NE,
|
||||
const Array<double> &bt,
|
||||
const Array<double> >,
|
||||
const Array<double> &b,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int tr_d1d = 0,
|
||||
int te_d1d = 0,
|
||||
int q1d = 0)
|
||||
void PADivergenceApplyTranspose3D(const int NE,
|
||||
const Array<double> &bt,
|
||||
const Array<double> >,
|
||||
const Array<double> &b,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int tr_d1d = 0,
|
||||
int te_d1d = 0,
|
||||
int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
@@ -775,16 +775,16 @@ static void PADivergenceApplyTranspose3D(const int NE,
|
||||
|
||||
// Shared memory PA Vector Divergence Apply 3D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void SmemPADivergenceApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &q_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPADivergenceApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &q_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
|
||||
+42
-42
@@ -70,12 +70,12 @@ namespace mfem
|
||||
the \b MFEM_SHARED keyword for local arrays. */
|
||||
|
||||
// PA Gradient Assemble 2D kernel
|
||||
static void PAGradientSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
void PAGradientSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -105,12 +105,12 @@ static void PAGradientSetup2D(const int Q1D,
|
||||
}
|
||||
|
||||
// PA Gradient Assemble 3D kernel
|
||||
static void PAGradientSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
void PAGradientSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -254,16 +254,16 @@ void GradientIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
|
||||
|
||||
// PA Gradient Apply 2D kernel
|
||||
template<int T_TR_D1D = 0, int T_TE_D1D = 0, int T_Q1D = 0>
|
||||
static void PAGradientApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAGradientApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
@@ -384,16 +384,16 @@ static void PAGradientApplyTranspose2D(const int NE,
|
||||
|
||||
// PA Gradient Apply 3D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void PAGradientApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int tr_d1d = 0,
|
||||
int te_d1d = 0,
|
||||
int q1d = 0)
|
||||
void PAGradientApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
int tr_d1d = 0,
|
||||
int te_d1d = 0,
|
||||
int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
@@ -579,16 +579,16 @@ static void PAGradientApplyTranspose3D(const int NE,
|
||||
|
||||
// Shared memory PA Gradient Apply 3D kernel
|
||||
template<const int T_TR_D1D = 0, const int T_TE_D1D = 0, const int T_Q1D = 0>
|
||||
static void SmemPAGradientApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPAGradientApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int tr_d1d = 0,
|
||||
const int te_d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
|
||||
+194
-194
@@ -791,12 +791,12 @@ void SmemPAHcurlMassApply3D(const int D1D,
|
||||
}
|
||||
|
||||
// PA H(curl) curl-curl assemble 2D kernel
|
||||
static void PACurlCurlSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff,
|
||||
Vector &op)
|
||||
void PACurlCurlSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -818,13 +818,13 @@ static void PACurlCurlSetup2D(const int Q1D,
|
||||
}
|
||||
|
||||
// PA H(curl) curl-curl assemble 3D kernel
|
||||
static void PACurlCurlSetup3D(const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff,
|
||||
Vector &op)
|
||||
void PACurlCurlSetup3D(const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D*Q1D;
|
||||
const bool symmetric = (coeffDim != 9);
|
||||
@@ -1045,16 +1045,16 @@ void CurlCurlIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
}
|
||||
}
|
||||
|
||||
static void PACurlCurlApply2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &gc,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void PACurlCurlApply2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &gc,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
@@ -1166,19 +1166,19 @@ static void PACurlCurlApply2D(const int D1D,
|
||||
}
|
||||
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void PACurlCurlApply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void PACurlCurlApply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -1677,19 +1677,19 @@ static void PACurlCurlApply3D(const int D1D,
|
||||
}
|
||||
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void SmemPACurlCurlApply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void SmemPACurlCurlApply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -2032,13 +2032,13 @@ void CurlCurlIntegrator::AddMultPA(const Vector &x, Vector &y) const
|
||||
}
|
||||
}
|
||||
|
||||
static void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
@@ -2087,16 +2087,16 @@ static void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
}
|
||||
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void PACurlCurlAssembleDiagonal3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &go,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
void PACurlCurlAssembleDiagonal3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &go,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
@@ -2273,16 +2273,16 @@ static void PACurlCurlAssembleDiagonal3D(const int D1D,
|
||||
}
|
||||
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void SmemPACurlCurlAssembleDiagonal3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &go,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
void SmemPACurlCurlAssembleDiagonal3D(const int D1D,
|
||||
const int Q1D,
|
||||
const bool symmetric,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &go,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -2955,18 +2955,18 @@ void MixedVectorCurlIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
|
||||
// Apply to x corresponding to DOF's in H(curl) (trial), whose curl is
|
||||
// integrated against H(curl) test functions corresponding to y.
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void PAHcurlL2Apply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void PAHcurlL2Apply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -3297,16 +3297,16 @@ static void PAHcurlL2Apply3D(const int D1D,
|
||||
// Apply to x corresponding to DOF's in H(curl) (trial), whose curl is
|
||||
// integrated against H(curl) test functions corresponding to y.
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void SmemPAHcurlL2Apply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void SmemPAHcurlL2Apply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -3585,18 +3585,18 @@ static void SmemPAHcurlL2Apply3D(const int D1D,
|
||||
// Apply to x corresponding to DOF's in H(curl) (trial), whose curl is
|
||||
// integrated against H(div) test functions corresponding to y.
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void PAHcurlHdivApply3D(const int D1D,
|
||||
const int D1Dtest,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void PAHcurlHdivApply3D(const int D1D,
|
||||
const int D1Dtest,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -4071,18 +4071,18 @@ void MixedVectorWeakCurlIntegrator::AssemblePA(const FiniteElementSpace
|
||||
// Apply to x corresponding to DOF's in H(curl) (trial), integrated against curl
|
||||
// of H(curl) test functions corresponding to y.
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void PAHcurlL2Apply3DTranspose(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void PAHcurlL2Apply3DTranspose(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &bot,
|
||||
const Array<double> &bct,
|
||||
const Array<double> &gct,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
// See PAHcurlL2Apply3D for comments.
|
||||
|
||||
@@ -4413,16 +4413,16 @@ static void PAHcurlL2Apply3DTranspose(const int D1D,
|
||||
}
|
||||
|
||||
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
|
||||
static void SmemPAHcurlL2Apply3DTranspose(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
void SmemPAHcurlL2Apply3DTranspose(const int D1D,
|
||||
const int Q1D,
|
||||
const int coeffDim,
|
||||
const int NE,
|
||||
const Array<double> &bo,
|
||||
const Array<double> &bc,
|
||||
const Array<double> &gc,
|
||||
const Vector &pa_data,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
@@ -4675,13 +4675,13 @@ void MixedVectorWeakCurlIntegrator::AddMultPA(const Vector &x, Vector &y) const
|
||||
// Apply to x corresponding to DOFs in H^1 (domain) the (topological) gradient
|
||||
// to get a dof in H(curl) (range). You can think of the range as the "test" space
|
||||
// and the domain as the "trial" space, but there's no integration.
|
||||
static void PAHcurlApplyGradient2D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlApplyGradient2D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto B = Reshape(B_.Read(), c_dofs1D, c_dofs1D);
|
||||
auto G = Reshape(G_.Read(), o_dofs1D, c_dofs1D);
|
||||
@@ -4753,12 +4753,12 @@ static void PAHcurlApplyGradient2D(const int c_dofs1D,
|
||||
}
|
||||
|
||||
// Specialization of PAHcurlApplyGradient2D to the case where B is identity
|
||||
static void PAHcurlApplyGradient2DBId(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlApplyGradient2DBId(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto G = Reshape(G_.Read(), o_dofs1D, c_dofs1D);
|
||||
|
||||
@@ -4822,7 +4822,7 @@ static void PAHcurlApplyGradient2DBId(const int c_dofs1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PAHcurlApplyGradientTranspose2D(
|
||||
void PAHcurlApplyGradientTranspose2D(
|
||||
const int c_dofs1D, const int o_dofs1D, const int NE,
|
||||
const Array<double> &B_, const Array<double> &G_,
|
||||
const Vector &x_, Vector &y_)
|
||||
@@ -4898,7 +4898,7 @@ static void PAHcurlApplyGradientTranspose2D(
|
||||
|
||||
// Specialization of PAHcurlApplyGradientTranspose2D to the case where
|
||||
// B is identity
|
||||
static void PAHcurlApplyGradientTranspose2DBId(
|
||||
void PAHcurlApplyGradientTranspose2DBId(
|
||||
const int c_dofs1D, const int o_dofs1D, const int NE,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_, Vector &y_)
|
||||
@@ -4965,13 +4965,13 @@ static void PAHcurlApplyGradientTranspose2DBId(
|
||||
});
|
||||
}
|
||||
|
||||
static void PAHcurlApplyGradient3D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlApplyGradient3D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto B = Reshape(B_.Read(), c_dofs1D, c_dofs1D);
|
||||
auto G = Reshape(G_.Read(), o_dofs1D, c_dofs1D);
|
||||
@@ -5154,12 +5154,12 @@ static void PAHcurlApplyGradient3D(const int c_dofs1D,
|
||||
}
|
||||
|
||||
// Specialization of PAHcurlApplyGradient3D to the case where
|
||||
static void PAHcurlApplyGradient3DBId(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlApplyGradient3DBId(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto G = Reshape(G_.Read(), o_dofs1D, c_dofs1D);
|
||||
|
||||
@@ -5322,7 +5322,7 @@ static void PAHcurlApplyGradient3DBId(const int c_dofs1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PAHcurlApplyGradientTranspose3D(
|
||||
void PAHcurlApplyGradientTranspose3D(
|
||||
const int c_dofs1D, const int o_dofs1D, const int NE,
|
||||
const Array<double> &B_, const Array<double> &G_,
|
||||
const Vector &x_, Vector &y_)
|
||||
@@ -5507,7 +5507,7 @@ static void PAHcurlApplyGradientTranspose3D(
|
||||
}
|
||||
|
||||
// Specialization of PAHcurlApplyGradientTranspose3D to the case where
|
||||
static void PAHcurlApplyGradientTranspose3DBId(
|
||||
void PAHcurlApplyGradientTranspose3DBId(
|
||||
const int c_dofs1D, const int o_dofs1D, const int NE,
|
||||
const Array<double> &G_,
|
||||
const Vector &x_, Vector &y_)
|
||||
@@ -5789,14 +5789,14 @@ void GradientInterpolator::AddMultTransposePA(const Vector &x, Vector &y) const
|
||||
}
|
||||
}
|
||||
|
||||
static void PAHcurlVecH1IdentityApply3D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlVecH1IdentityApply3D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
|
||||
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
|
||||
@@ -6002,14 +6002,14 @@ static void PAHcurlVecH1IdentityApply3D(const int c_dofs1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PAHcurlVecH1IdentityApplyTranspose3D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlVecH1IdentityApplyTranspose3D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
|
||||
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
|
||||
@@ -6228,14 +6228,14 @@ static void PAHcurlVecH1IdentityApplyTranspose3D(const int c_dofs1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PAHcurlVecH1IdentityApply2D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlVecH1IdentityApply2D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
|
||||
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
|
||||
@@ -6327,14 +6327,14 @@ static void PAHcurlVecH1IdentityApply2D(const int c_dofs1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PAHcurlVecH1IdentityApplyTranspose2D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHcurlVecH1IdentityApplyTranspose2D(const int c_dofs1D,
|
||||
const int o_dofs1D,
|
||||
const int NE,
|
||||
const Array<double> &Bclosed,
|
||||
const Array<double> &Bopen,
|
||||
const Vector &pa_data,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
|
||||
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
|
||||
|
||||
+116
-116
@@ -539,12 +539,12 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
// PA H(div) div-div assemble 2D kernel
|
||||
// NOTE: this is identical to PACurlCurlSetup3D
|
||||
static void PADivDivSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
void PADivDivSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -565,12 +565,12 @@ static void PADivDivSetup2D(const int Q1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PADivDivSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
void PADivDivSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -599,16 +599,16 @@ static void PADivDivSetup3D(const int Q1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PADivDivApply2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &Bot_,
|
||||
const Array<double> &Gct_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PADivDivApply2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &Bot_,
|
||||
const Array<double> &Gct_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
@@ -718,16 +718,16 @@ static void PADivDivApply2D(const int D1D,
|
||||
}); // end of element loop
|
||||
}
|
||||
|
||||
static void PADivDivApply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &Bot_,
|
||||
const Array<double> &Gct_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PADivDivApply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &Bot_,
|
||||
const Array<double> &Gct_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
@@ -967,13 +967,13 @@ void DivDivIntegrator::AddMultPA(const Vector &x, Vector &y) const
|
||||
}
|
||||
}
|
||||
|
||||
static void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
@@ -1023,13 +1023,13 @@ static void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PADivDivAssembleDiagonal3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
void PADivDivAssembleDiagonal3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
@@ -1104,11 +1104,11 @@ void DivDivIntegrator::AssembleDiagonalPA(Vector& diag)
|
||||
}
|
||||
|
||||
// PA H(div)-L2 (div u, p) assemble 2D kernel
|
||||
static void PADivL2Setup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
void PADivL2Setup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -1123,11 +1123,11 @@ static void PADivL2Setup2D(const int Q1D,
|
||||
});
|
||||
}
|
||||
|
||||
static void PADivL2Setup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
void PADivL2Setup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
Vector &coeff_,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -1225,16 +1225,16 @@ VectorFEDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
|
||||
|
||||
// Apply to x corresponding to DOF's in H(div) (trial), whose divergence is
|
||||
// integrated against L_2 test functions corresponding to y.
|
||||
static void PAHdivL2Apply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &L2Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHdivL2Apply3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &L2Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
@@ -1388,16 +1388,16 @@ static void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
// Apply to x corresponding to DOF's in H(div) (trial), whose divergence is
|
||||
// integrated against L_2 test functions corresponding to y.
|
||||
static void PAHdivL2Apply2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &L2Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHdivL2Apply2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &Bo_,
|
||||
const Array<double> &Gc_,
|
||||
const Array<double> &L2Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
@@ -1494,16 +1494,16 @@ static void PAHdivL2Apply2D(const int D1D,
|
||||
}); // end of element loop
|
||||
}
|
||||
|
||||
static void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
@@ -1656,16 +1656,16 @@ static void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
}); // end of element loop
|
||||
}
|
||||
|
||||
static void PAHdivL2ApplyTranspose2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
void PAHdivL2ApplyTranspose2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
@@ -1791,16 +1791,16 @@ void VectorFEDivergenceIntegrator::AddMultTransposePA(const Vector &x,
|
||||
}
|
||||
}
|
||||
|
||||
static void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &D_,
|
||||
Vector &diag_)
|
||||
void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &D_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
@@ -1916,16 +1916,16 @@ static void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
}); // end of element loop
|
||||
}
|
||||
|
||||
static void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &D_,
|
||||
Vector &diag_)
|
||||
void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
|
||||
const int Q1D,
|
||||
const int L2D1D,
|
||||
const int NE,
|
||||
const Array<double> &L2Bo_,
|
||||
const Array<double> &Gct_,
|
||||
const Array<double> &Bot_,
|
||||
const Vector &op_,
|
||||
const Vector &D_,
|
||||
Vector &diag_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
|
||||
|
||||
+21
-21
@@ -17,13 +17,13 @@ namespace mfem
|
||||
{
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EAMassAssemble1D(const int NE,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EAMassAssemble1D(const int NE,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -67,13 +67,13 @@ static void EAMassAssemble1D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EAMassAssemble2D(const int NE,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EAMassAssemble2D(const int NE,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -139,13 +139,13 @@ static void EAMassAssemble2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void EAMassAssemble3D(const int NE,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void EAMassAssemble3D(const int NE,
|
||||
const Array<double> &basis,
|
||||
const Vector &padata,
|
||||
Vector &eadata,
|
||||
const bool add,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
+56
-56
@@ -155,12 +155,12 @@ void MassIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAMassAssembleDiagonal2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAMassAssembleDiagonal2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -201,12 +201,12 @@ static void PAMassAssembleDiagonal2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
static void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -267,12 +267,12 @@ static void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAMassAssembleDiagonal3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAMassAssembleDiagonal3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -336,12 +336,12 @@ static void PAMassAssembleDiagonal3D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void SmemPAMassAssembleDiagonal3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPAMassAssembleDiagonal3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Vector &d_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -569,14 +569,14 @@ static void OccaPAMassApply3D(const int D1D,
|
||||
#endif // MFEM_USE_OCCA
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAMassApply2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAMassApply2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -661,14 +661,14 @@ static void PAMassApply2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
|
||||
static void SmemPAMassApply2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPAMassApply2D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_CONTRACT_VAR(bt_);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
@@ -784,14 +784,14 @@ static void SmemPAMassApply2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAMassApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAMassApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -925,14 +925,14 @@ static void PAMassApply3D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void SmemPAMassApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPAMassApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &bt_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_CONTRACT_VAR(bt_);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
|
||||
@@ -22,12 +22,12 @@ namespace mfem
|
||||
// PA Vector Diffusion Integrator
|
||||
|
||||
// PA Diffusion Assemble 2D kernel
|
||||
static void PAVectorDiffusionSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
void PAVectorDiffusionSetup2D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -59,12 +59,12 @@ static void PAVectorDiffusionSetup2D(const int Q1D,
|
||||
}
|
||||
|
||||
// PA Diffusion Assemble 3D kernel
|
||||
static void PAVectorDiffusionSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
void PAVectorDiffusionSetup3D(const int Q1D,
|
||||
const int NE,
|
||||
const Array<double> &w,
|
||||
const Vector &j,
|
||||
const Vector &c,
|
||||
Vector &op)
|
||||
{
|
||||
const int NQ = Q1D*Q1D*Q1D;
|
||||
auto W = w.Read();
|
||||
@@ -251,7 +251,7 @@ void VectorDiffusionIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
}
|
||||
|
||||
// PA Diffusion Apply 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_VDIM = 0> static
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_VDIM = 0>
|
||||
void PAVectorDiffusionApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
@@ -374,7 +374,7 @@ void PAVectorDiffusionApply2D(const int NE,
|
||||
|
||||
// PA Diffusion Apply 3D kernel
|
||||
template<const int T_D1D = 0,
|
||||
const int T_Q1D = 0> static
|
||||
const int T_Q1D = 0>
|
||||
void PAVectorDiffusionApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
@@ -606,13 +606,13 @@ void VectorDiffusionIntegrator::AddMultPA(const Vector &x, Vector &y) const
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -673,13 +673,13 @@ static void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAVectorDiffusionDiagonal3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAVectorDiffusionDiagonal3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Vector &d,
|
||||
Vector &y,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
|
||||
+30
-30
@@ -104,14 +104,14 @@ void VectorMassIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
|
||||
template<const int T_D1D = 0,
|
||||
const int T_Q1D = 0>
|
||||
static void PAVectorMassApply2D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAVectorMassApply2D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -201,14 +201,14 @@ static void PAVectorMassApply2D(const int NE,
|
||||
|
||||
template<const int T_D1D = 0,
|
||||
const int T_Q1D = 0>
|
||||
static void PAVectorMassApply3D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAVectorMassApply3D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -379,13 +379,13 @@ void VectorMassIntegrator::AddMultPA(const Vector &x, Vector &y) const
|
||||
}
|
||||
|
||||
template<const int T_D1D = 0, const int T_Q1D = 0>
|
||||
static void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
Vector &diag_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
Vector &diag_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -431,13 +431,13 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
}
|
||||
|
||||
template<const int T_D1D = 0, const int T_Q1D = 0>
|
||||
static void PAVectorMassAssembleDiagonal3D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
Vector &diag_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAVectorMassAssembleDiagonal3D(const int NE,
|
||||
const Array<double> &B_,
|
||||
const Array<double> &Bt_,
|
||||
const Vector &op_,
|
||||
Vector &diag_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
|
||||
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability visit https://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#include "fem.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
void DofTransformation::TransformPrimal(Vector &v) const
|
||||
{
|
||||
TransformPrimal(v.GetData());
|
||||
}
|
||||
|
||||
void DofTransformation::TransformPrimalCols(DenseMatrix &V) const
|
||||
{
|
||||
for (int c=0; c<V.Width(); c++)
|
||||
{
|
||||
TransformPrimal(V.GetColumn(c));
|
||||
}
|
||||
}
|
||||
|
||||
void DofTransformation::TransformDual(Vector &v) const
|
||||
{
|
||||
TransformDual(v.GetData());
|
||||
}
|
||||
|
||||
void DofTransformation::TransformDual(DenseMatrix &V) const
|
||||
{
|
||||
TransformDualCols(V);
|
||||
TransformDualRows(V);
|
||||
}
|
||||
|
||||
void DofTransformation::TransformDualRows(DenseMatrix &V) const
|
||||
{
|
||||
Vector row;
|
||||
for (int r=0; r<V.Height(); r++)
|
||||
{
|
||||
V.GetRow(r, row);
|
||||
TransformDual(row);
|
||||
V.SetRow(r, row);
|
||||
}
|
||||
}
|
||||
|
||||
void DofTransformation::TransformDualCols(DenseMatrix &V) const
|
||||
{
|
||||
for (int c=0; c<V.Width(); c++)
|
||||
{
|
||||
TransformDual(V.GetColumn(c));
|
||||
}
|
||||
}
|
||||
|
||||
void DofTransformation::InvTransformPrimal(Vector &v) const
|
||||
{
|
||||
InvTransformPrimal(v.GetData());
|
||||
}
|
||||
|
||||
void TransformPrimal(const DofTransformation *ran_dof_trans,
|
||||
const DofTransformation *dom_dof_trans,
|
||||
DenseMatrix &elmat)
|
||||
{
|
||||
if (ran_dof_trans && dom_dof_trans)
|
||||
{
|
||||
ran_dof_trans->TransformPrimalCols(elmat);
|
||||
dom_dof_trans->TransformDualRows(elmat);
|
||||
}
|
||||
else if (ran_dof_trans)
|
||||
{
|
||||
ran_dof_trans->TransformPrimalCols(elmat);
|
||||
}
|
||||
else if (dom_dof_trans)
|
||||
{
|
||||
dom_dof_trans->TransformDualRows(elmat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If both transformations are NULL this function should not be called
|
||||
}
|
||||
}
|
||||
|
||||
void TransformDual(const DofTransformation *ran_dof_trans,
|
||||
const DofTransformation *dom_dof_trans,
|
||||
DenseMatrix &elmat)
|
||||
{
|
||||
if (ran_dof_trans && dom_dof_trans)
|
||||
{
|
||||
ran_dof_trans->TransformDualCols(elmat);
|
||||
dom_dof_trans->TransformDualRows(elmat);
|
||||
}
|
||||
else if (ran_dof_trans)
|
||||
{
|
||||
ran_dof_trans->TransformDualCols(elmat);
|
||||
}
|
||||
else if (dom_dof_trans)
|
||||
{
|
||||
dom_dof_trans->TransformDualRows(elmat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If both transformations are NULL this function should not be called
|
||||
}
|
||||
}
|
||||
|
||||
void VDofTransformation::TransformPrimal(double *v) const
|
||||
{
|
||||
int size = doftrans_->Size();
|
||||
|
||||
if ((Ordering::Type)ordering_ == Ordering::byNODES || vdim_ == 1)
|
||||
{
|
||||
for (int i=0; i<vdim_; i++)
|
||||
{
|
||||
doftrans_->TransformPrimal(&v[i*size]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vec(size);
|
||||
for (int i=0; i<vdim_; i++)
|
||||
{
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
vec(j) = v[j*vdim_+i];
|
||||
}
|
||||
doftrans_->TransformPrimal(vec);
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
v[j*vdim_+i] = vec(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VDofTransformation::InvTransformPrimal(double *v) const
|
||||
{
|
||||
int size = doftrans_->Height();
|
||||
|
||||
if ((Ordering::Type)ordering_ == Ordering::byNODES)
|
||||
{
|
||||
for (int i=0; i<vdim_; i++)
|
||||
{
|
||||
doftrans_->InvTransformPrimal(&v[i*size]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vec(size);
|
||||
for (int i=0; i<vdim_; i++)
|
||||
{
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
vec(j) = v[j*vdim_+i];
|
||||
}
|
||||
doftrans_->InvTransformPrimal(vec);
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
v[j*vdim_+i] = vec(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VDofTransformation::TransformDual(double *v) const
|
||||
{
|
||||
int size = doftrans_->Size();
|
||||
|
||||
if ((Ordering::Type)ordering_ == Ordering::byNODES)
|
||||
{
|
||||
for (int i=0; i<vdim_; i++)
|
||||
{
|
||||
doftrans_->TransformDual(&v[i*size]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vec(size);
|
||||
for (int i=0; i<vdim_; i++)
|
||||
{
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
vec(j) = v[j*vdim_+i];
|
||||
}
|
||||
doftrans_->TransformDual(vec);
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
v[j*vdim_+i] = vec(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const double ND_DofTransformation::T_data[24] =
|
||||
{
|
||||
1.0, 0.0, 0.0, 1.0,
|
||||
-1.0, -1.0, 0.0, 1.0,
|
||||
0.0, 1.0, -1.0, -1.0,
|
||||
1.0, 0.0, -1.0, -1.0,
|
||||
-1.0, -1.0, 1.0, 0.0,
|
||||
0.0, 1.0, 1.0, 0.0
|
||||
};
|
||||
|
||||
const DenseTensor ND_DofTransformation
|
||||
::T(const_cast<double*>(ND_DofTransformation::T_data), 2, 2, 6);
|
||||
|
||||
const double ND_DofTransformation::TInv_data[24] =
|
||||
{
|
||||
1.0, 0.0, 0.0, 1.0,
|
||||
-1.0, -1.0, 0.0, 1.0,
|
||||
-1.0, -1.0, 1.0, 0.0,
|
||||
1.0, 0.0, -1.0, -1.0,
|
||||
0.0, 1.0, -1.0, -1.0,
|
||||
0.0, 1.0, 1.0, 0.0
|
||||
};
|
||||
|
||||
const DenseTensor ND_DofTransformation
|
||||
::TInv(const_cast<double*>(TInv_data), 2, 2, 6);
|
||||
|
||||
ND_DofTransformation::ND_DofTransformation(int size, int p)
|
||||
: DofTransformation(size),
|
||||
order(p)
|
||||
{
|
||||
}
|
||||
|
||||
ND_TriDofTransformation::ND_TriDofTransformation(int p)
|
||||
: ND_DofTransformation(p*(p + 2), p)
|
||||
{
|
||||
}
|
||||
|
||||
void ND_TriDofTransformation::TransformPrimal(double *v) const
|
||||
{
|
||||
int nedofs = order; // number of DoFs per edge
|
||||
int nfdofs = order*(order-1); // number of DoFs per face
|
||||
|
||||
double data[2];
|
||||
Vector v2(data, 2);
|
||||
|
||||
// Transform face DoFs
|
||||
for (int f=0; f<1; f++)
|
||||
{
|
||||
for (int i=0; i<nfdofs/2; i++)
|
||||
{
|
||||
v2 = &v[3*nedofs + f*nfdofs + 2*i];
|
||||
T(Fo[f]).Mult(v2, &v[3*nedofs + f*nfdofs + 2*i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ND_TriDofTransformation::InvTransformPrimal(double *v) const
|
||||
{
|
||||
int nedofs = order; // number of DoFs per edge
|
||||
int nfdofs = order*(order-1); // number of DoFs per face
|
||||
|
||||
double data[2];
|
||||
Vector v2(data, 2);
|
||||
|
||||
// Transform face DoFs
|
||||
for (int f=0; f<1; f++)
|
||||
{
|
||||
for (int i=0; i<nfdofs/2; i++)
|
||||
{
|
||||
v2 = &v[3*nedofs + f*nfdofs + 2*i];
|
||||
TInv(Fo[f]).Mult(v2, &v[3*nedofs + f*nfdofs + 2*i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ND_TriDofTransformation::TransformDual(double *v) const
|
||||
{
|
||||
int nedofs = order; // number of DoFs per edge
|
||||
int nfdofs = order*(order-1); // number of DoFs per face
|
||||
|
||||
double data[2];
|
||||
Vector v2(data, 2);
|
||||
|
||||
// Transform face DoFs
|
||||
for (int f=0; f<1; f++)
|
||||
{
|
||||
for (int i=0; i<nfdofs/2; i++)
|
||||
{
|
||||
v2 = &v[3*nedofs + f*nfdofs + 2*i];
|
||||
TInv(Fo[f]).MultTranspose(v2, &v[3*nedofs + f*nfdofs + 2*i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ND_TetDofTransformation::ND_TetDofTransformation(int p)
|
||||
: ND_DofTransformation(p*(p + 2)*(p + 3)/2, p)
|
||||
{
|
||||
}
|
||||
|
||||
void ND_TetDofTransformation::TransformPrimal(double *v) const
|
||||
{
|
||||
int nedofs = order; // number of DoFs per edge
|
||||
int nfdofs = order*(order-1); // number of DoFs per face
|
||||
|
||||
double data[2];
|
||||
Vector v2(data, 2);
|
||||
|
||||
// Transform face DoFs
|
||||
for (int f=0; f<4; f++)
|
||||
{
|
||||
for (int i=0; i<nfdofs/2; i++)
|
||||
{
|
||||
v2 = &v[6*nedofs + f*nfdofs + 2*i];
|
||||
T(Fo[f]).Mult(v2, &v[6*nedofs + f*nfdofs + 2*i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ND_TetDofTransformation::InvTransformPrimal(double *v) const
|
||||
{
|
||||
int nedofs = order; // number of DoFs per edge
|
||||
int nfdofs = order*(order-1); // number of DoFs per face
|
||||
|
||||
double data[2];
|
||||
Vector v2(data, 2);
|
||||
|
||||
// Transform face DoFs
|
||||
for (int f=0; f<4; f++)
|
||||
{
|
||||
for (int i=0; i<nfdofs/2; i++)
|
||||
{
|
||||
v2 = &v[6*nedofs + f*nfdofs + 2*i];
|
||||
TInv(Fo[f]).Mult(v2, &v[6*nedofs + f*nfdofs + 2*i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ND_TetDofTransformation::TransformDual(double *v) const
|
||||
{
|
||||
int nedofs = order; // number of DoFs per edge
|
||||
int nfdofs = order*(order-1); // number of DoFs per face
|
||||
|
||||
double data[2];
|
||||
Vector v2(data, 2);
|
||||
|
||||
// Transform face DoFs
|
||||
for (int f=0; f<4; f++)
|
||||
{
|
||||
for (int i=0; i<nfdofs/2; i++)
|
||||
{
|
||||
v2 = &v[6*nedofs + f*nfdofs + 2*i];
|
||||
TInv(Fo[f]).MultTranspose(v2, &v[6*nedofs + f*nfdofs + 2*i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mfem
|
||||
@@ -0,0 +1,277 @@
|
||||
// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
|
||||
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability visit https://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#ifndef MFEM_DOFTRANSFORM
|
||||
#define MFEM_DOFTRANSFORM
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "../linalg/linalg.hpp"
|
||||
#include "intrules.hpp"
|
||||
#include "fe.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/** The DofTransformation class is an abstract base class for a family of
|
||||
transformations that map local degrees of freedom (DoFs), contained within
|
||||
individual elements, to global degrees of freedom, stored within
|
||||
GridFunction objects. These transformations are necessary to ensure that
|
||||
basis functions in neighboring elements align correctly. Closely related but
|
||||
complementary transformations are required for the entries stored in
|
||||
LinearForm and BilinearForm objects. The DofTransformation class is designed
|
||||
to apply the action of both of these types of DoF transformations.
|
||||
|
||||
Let the "primal transformation" be given by the operator T. This means that
|
||||
given a local element vector v the data that must be placed into a
|
||||
GridFunction object is v_t = T * v.
|
||||
|
||||
We also need the inverse of the primal transformation T^{-1} so that we can
|
||||
recover the local element vector from data read out of a GridFunction
|
||||
e.g. v = T^{-1} * v_t.
|
||||
|
||||
We need to preserve the action of our linear forms applied to primal
|
||||
vectors. In other words, if f is the local vector computed by a linear
|
||||
form then f * v = f_t * v_t (where "*" represents an inner product of
|
||||
vectors). This requires that f_t = T^{-T} * f i.e. the "dual transform" is
|
||||
given by the transpose of the inverse of the primal transformation.
|
||||
|
||||
For bilinear forms we require that v^T * A * v = v_t^T * A_t * v_t. This
|
||||
implies that A_t = T^{-T} * A * T^{-1}. This can be accomplished by
|
||||
performing dual transformations of the rows and columns of the matrix A.
|
||||
|
||||
For discrete linear operators the range must be modified with the primal
|
||||
transformation rather than the dual transformation because the result is a
|
||||
primal vector rather than a dual vector. This leads to the transformation
|
||||
D_t = T * D * T^{-1}. This can be accomplished by using a primal
|
||||
transformation on the columns of D and a dual transformation on its rows.
|
||||
*/
|
||||
class DofTransformation
|
||||
{
|
||||
protected:
|
||||
int size_;
|
||||
|
||||
Array<int> Fo;
|
||||
|
||||
DofTransformation(int size)
|
||||
: size_(size) {}
|
||||
|
||||
public:
|
||||
|
||||
inline int Size() const { return size_; }
|
||||
inline int Height() const { return size_; }
|
||||
inline int NumRows() const { return size_; }
|
||||
inline int Width() const { return size_; }
|
||||
inline int NumCols() const { return size_; }
|
||||
|
||||
/** @brief Configure the transformation using face orientations for the
|
||||
current element. */
|
||||
/// The face_orientation array can be obtained from Mesh::GetElementFaces.
|
||||
inline void SetFaceOrientations(const Array<int> & face_orientation)
|
||||
{ Fo = face_orientation; }
|
||||
|
||||
inline const Array<int> & GetFaceOrientations() const { return Fo; }
|
||||
|
||||
/** Transform local DoFs to align with the global DoFs. For example, this
|
||||
transformation can be used to map the local vector computed by
|
||||
FiniteElement::Project() to the transformed vector stored within a
|
||||
GridFunction object. */
|
||||
virtual void TransformPrimal(double *v) const = 0;
|
||||
virtual void TransformPrimal(Vector &v) const;
|
||||
|
||||
/// Transform groups of DoFs stored as dense matrices
|
||||
virtual void TransformPrimalCols(DenseMatrix &V) const;
|
||||
|
||||
/** Inverse transform local DoFs. Used to transform DoFs from a global vector
|
||||
back to their element-local form. For example, this must be used to
|
||||
transform the vector obtained using GridFunction::GetSubVector before it
|
||||
can be used to compute a local interpolation.
|
||||
*/
|
||||
virtual void InvTransformPrimal(double *v) const = 0;
|
||||
virtual void InvTransformPrimal(Vector &v) const;
|
||||
|
||||
/** Transform dual DoFs as computed by a LinearFormIntegrator before summing
|
||||
into a LinearForm object. */
|
||||
virtual void TransformDual(double *v) const = 0;
|
||||
virtual void TransformDual(Vector &v) const;
|
||||
|
||||
/** Transform a matrix of dual DoFs entries as computed by a
|
||||
BilinearFormIntegrator before summing into a BilinearForm object. */
|
||||
virtual void TransformDual(DenseMatrix &V) const;
|
||||
|
||||
/// Transform groups of dual DoFs stored as dense matrices
|
||||
virtual void TransformDualRows(DenseMatrix &V) const;
|
||||
virtual void TransformDualCols(DenseMatrix &V) const;
|
||||
|
||||
virtual ~DofTransformation() {}
|
||||
};
|
||||
|
||||
/** Transform a matrix of DoFs entries from different finite element spaces as
|
||||
computed by a DiscreteInterpolator before copying into a
|
||||
DiscreteLinearOperator.
|
||||
*/
|
||||
void TransformPrimal(const DofTransformation *ran_dof_trans,
|
||||
const DofTransformation *dom_dof_trans,
|
||||
DenseMatrix &elmat);
|
||||
|
||||
/** Transform a matrix of dual DoFs entries from different finite element spaces
|
||||
as computed by a BilinearFormIntegrator before summing into a
|
||||
MixedBilinearForm object.
|
||||
*/
|
||||
void TransformDual(const DofTransformation *ran_dof_trans,
|
||||
const DofTransformation *dom_dof_trans,
|
||||
DenseMatrix &elmat);
|
||||
|
||||
/** The VDofTransformation class implements a nested transformation where an
|
||||
arbitrary DofTransformation is replicated with a vdim >= 1.
|
||||
*/
|
||||
class VDofTransformation : public DofTransformation
|
||||
{
|
||||
private:
|
||||
int vdim_;
|
||||
int ordering_;
|
||||
DofTransformation * doftrans_;
|
||||
|
||||
public:
|
||||
/** @brief Default constructor which requires that SetDofTransformation be
|
||||
called before use. */
|
||||
VDofTransformation(int vdim = 1, int ordering = 0)
|
||||
: DofTransformation(0),
|
||||
vdim_(vdim), ordering_(ordering),
|
||||
doftrans_(NULL) {}
|
||||
|
||||
/// Constructor with a known DofTransformation
|
||||
VDofTransformation(DofTransformation & doftrans, int vdim = 1,
|
||||
int ordering = 0)
|
||||
: DofTransformation(vdim * doftrans.Size()),
|
||||
vdim_(vdim), ordering_(ordering),
|
||||
doftrans_(&doftrans) {}
|
||||
|
||||
/// Set or change the vdim parameter
|
||||
inline void SetVDim(int vdim)
|
||||
{
|
||||
vdim_ = vdim;
|
||||
if (doftrans_)
|
||||
{
|
||||
size_ = vdim_ * doftrans_->Size();
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the current vdim value
|
||||
inline int GetVDim() const { return vdim_; }
|
||||
|
||||
/// Set or change the nested DofTransformation object
|
||||
inline void SetDofTransformation(DofTransformation & doftrans)
|
||||
{
|
||||
size_ = vdim_ * doftrans.Size();
|
||||
doftrans_ = &doftrans;
|
||||
}
|
||||
|
||||
/// Return the nested DofTransformation object
|
||||
inline DofTransformation * GetDofTransformation() const { return doftrans_; }
|
||||
|
||||
inline void SetFaceOrientation(const Array<int> & face_orientation)
|
||||
{ Fo = face_orientation; doftrans_->SetFaceOrientations(face_orientation); }
|
||||
|
||||
using DofTransformation::TransformPrimal;
|
||||
using DofTransformation::InvTransformPrimal;
|
||||
using DofTransformation::TransformDual;
|
||||
|
||||
void TransformPrimal(double *v) const;
|
||||
void InvTransformPrimal(double *v) const;
|
||||
void TransformDual(double *v) const;
|
||||
};
|
||||
|
||||
/** Abstract base class for high-order Nedelec spaces on elements with
|
||||
triangular faces.
|
||||
|
||||
The Nedelec DoFs on the interior of triangular faces come in pairs which
|
||||
share an interpolation point but have different vector directions. These
|
||||
directions depend on the orientation of the face and can therefore differ in
|
||||
neighboring elements. The mapping required to transform these DoFs can be
|
||||
implemented as series of 2x2 linear transformations. The raw data for these
|
||||
linear transformations is stored in the T_data and TInv_data arrays and can
|
||||
be accessed as DenseMatrices using the GetFaceTransform() and
|
||||
GetFaceInverseTransform() methods.
|
||||
*/
|
||||
class ND_DofTransformation : public DofTransformation
|
||||
{
|
||||
protected:
|
||||
static const double T_data[24];
|
||||
static const double TInv_data[24];
|
||||
static const DenseTensor T, TInv;
|
||||
int order;
|
||||
|
||||
ND_DofTransformation(int size, int order);
|
||||
|
||||
public:
|
||||
// Return the 2x2 transformation operator for the given face orientation
|
||||
static const DenseMatrix & GetFaceTransform(int ori) { return T(ori); }
|
||||
|
||||
// Return the 2x2 inverse transformation operator
|
||||
static const DenseMatrix & GetFaceInverseTransform(int ori)
|
||||
{ return TInv(ori); }
|
||||
};
|
||||
|
||||
/// DoF transformation implementation for the Nedelec basis on triangles
|
||||
class ND_TriDofTransformation : public ND_DofTransformation
|
||||
{
|
||||
public:
|
||||
ND_TriDofTransformation(int order);
|
||||
|
||||
using DofTransformation::TransformPrimal;
|
||||
using DofTransformation::InvTransformPrimal;
|
||||
using DofTransformation::TransformDual;
|
||||
|
||||
void TransformPrimal(double *v) const;
|
||||
|
||||
void InvTransformPrimal(double *v) const;
|
||||
|
||||
void TransformDual(double *v) const;
|
||||
};
|
||||
|
||||
/// DoF transformation implementation for the Nedelec basis on tetrahedra
|
||||
class ND_TetDofTransformation : public ND_DofTransformation
|
||||
{
|
||||
public:
|
||||
ND_TetDofTransformation(int order);
|
||||
|
||||
using DofTransformation::TransformPrimal;
|
||||
using DofTransformation::InvTransformPrimal;
|
||||
using DofTransformation::TransformDual;
|
||||
|
||||
void TransformPrimal(double *v) const;
|
||||
|
||||
void InvTransformPrimal(double *v) const;
|
||||
|
||||
void TransformDual(double *v) const;
|
||||
};
|
||||
|
||||
/// DoF transformation implementation for the Nedelec basis on wedge elements
|
||||
/** TODO: (Under development) */
|
||||
class ND_WedgeDofTransformation : public ND_DofTransformation
|
||||
{
|
||||
public:
|
||||
ND_WedgeDofTransformation(int order);
|
||||
|
||||
using DofTransformation::TransformPrimal;
|
||||
using DofTransformation::InvTransformPrimal;
|
||||
using DofTransformation::TransformDual;
|
||||
|
||||
void TransformPrimal(double *v) const;
|
||||
|
||||
void InvTransformPrimal(double *v) const;
|
||||
|
||||
void TransformDual(double *v) const;
|
||||
};
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
#endif // MFEM_DOFTRANSFORM
|
||||
@@ -380,6 +380,7 @@ void IsoparametricTransformation::SetIdentityTransformation(
|
||||
case Geometry::TETRAHEDRON : FElem = &TetrahedronFE; break;
|
||||
case Geometry::CUBE : FElem = &HexahedronFE; break;
|
||||
case Geometry::PRISM : FElem = &WedgeFE; break;
|
||||
case Geometry::PYRAMID : FElem = &PyramidFE; break;
|
||||
default:
|
||||
MFEM_ABORT("unknown Geometry::Type!");
|
||||
}
|
||||
|
||||
+3
-2
@@ -329,7 +329,7 @@ void KellyErrorEstimator::ComputeEstimates()
|
||||
error_estimates(e) = sqrt(factor * error_estimates(e));
|
||||
}
|
||||
|
||||
total_error = error_estimates.Sum();
|
||||
total_error = error_estimates.Norml2();
|
||||
delete flux;
|
||||
return;
|
||||
}
|
||||
@@ -452,9 +452,10 @@ void KellyErrorEstimator::ComputeEstimates()
|
||||
auto pfes = dynamic_cast<ParFiniteElementSpace*>(xfes);
|
||||
MFEM_VERIFY(pfes, "xfes is not a ParFiniteElementSpace pointer");
|
||||
|
||||
double process_local_error = error_estimates.Sum();
|
||||
double process_local_error = pow(error_estimates.Norml2(),2.0);
|
||||
MPI_Allreduce(&process_local_error, &total_error, 1, MPI_DOUBLE,
|
||||
MPI_SUM, pfes->GetComm());
|
||||
total_error = sqrt(total_error);
|
||||
#endif // MFEM_USE_MPI
|
||||
}
|
||||
|
||||
|
||||
+1204
-18
File diff suppressed because it is too large
Load Diff
+219
@@ -1313,6 +1313,64 @@ public:
|
||||
DenseMatrix &dshape) const;
|
||||
};
|
||||
|
||||
/// A linear element defined on a triangular prism
|
||||
class LinearWedgeFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
public:
|
||||
/// Construct the LinearWedgeFiniteElement
|
||||
LinearWedgeFiniteElement();
|
||||
|
||||
/** @brief virtual function which evaluates the values of all
|
||||
shape functions at a given point ip and stores
|
||||
them in the vector shape of dimension Dof (4) */
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
|
||||
/** @brief virtual function which evaluates the values of all
|
||||
partial derivatives of all shape functions at a given
|
||||
point ip and stores them in the matrix dshape (Dof x Dim) (4 x 3)
|
||||
so that each row contains the derivatives of one shape function */
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
|
||||
virtual void ProjectDelta(int vertex, Vector &dofs) const
|
||||
{ dofs = 0.0; dofs(vertex) = 1.0; }
|
||||
|
||||
/** @brief Get the dofs associated with the given @a face.
|
||||
@a *dofs is set to an internal array of the local dofc on the
|
||||
face, while *ndofs is set to the number of dofs on that face.
|
||||
*/
|
||||
virtual void GetFaceDofs(int face, int **dofs, int *ndofs) const;
|
||||
};
|
||||
|
||||
/// A linear element defined on a square pyramid
|
||||
class LinearPyramidFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
public:
|
||||
/// Construct the LinearPyramidFiniteElement
|
||||
LinearPyramidFiniteElement();
|
||||
|
||||
/** @brief virtual function which evaluates the values of all
|
||||
shape functions at a given point ip and stores
|
||||
them in the vector shape of dimension Dof (4) */
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
|
||||
/** @brief virtual function which evaluates the values of all
|
||||
partial derivatives of all shape functions at a given
|
||||
point ip and stores them in the matrix dshape (Dof x Dim) (4 x 3)
|
||||
so that each row contains the derivatives of one shape function */
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
|
||||
virtual void ProjectDelta(int vertex, Vector &dofs) const
|
||||
{ dofs = 0.0; dofs(vertex) = 1.0; }
|
||||
|
||||
/** @brief Get the dofs associated with the given @a face.
|
||||
@a *dofs is set to an internal array of the local dofc on the
|
||||
face, while *ndofs is set to the number of dofs on that face.
|
||||
*/
|
||||
virtual void GetFaceDofs(int face, int **dofs, int *ndofs) const;
|
||||
};
|
||||
|
||||
/// A 2D constant element on a triangle
|
||||
class P0TriangleFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
@@ -1690,6 +1748,32 @@ public:
|
||||
{ dofs(0) = 1.0; }
|
||||
};
|
||||
|
||||
/// A 3D constant element on a wedge
|
||||
class P0WdgFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
public:
|
||||
/// Construct the P0WdgFiniteElement
|
||||
P0WdgFiniteElement ();
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
virtual void ProjectDelta(int vertex, Vector &dofs) const
|
||||
{ dofs(0) = 1.0; }
|
||||
};
|
||||
|
||||
/// A 3D constant element on a pyramid
|
||||
class P0PyrFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
public:
|
||||
/// Construct the P0PyrFiniteElement
|
||||
P0PyrFiniteElement ();
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
virtual void ProjectDelta(int vertex, Vector &dofs) const
|
||||
{ dofs(0) = 1.0; }
|
||||
};
|
||||
|
||||
/** @brief Tensor products of 1D Lagrange1DFiniteElement
|
||||
(only degree 2 is functional) */
|
||||
class LagrangeHexFiniteElement : public NodalFiniteElement
|
||||
@@ -1828,6 +1912,10 @@ public:
|
||||
using FiniteElement::Project;
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void ProjectGrad(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &grad) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -1852,6 +1940,66 @@ public:
|
||||
using FiniteElement::Project;
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void ProjectGrad(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &grad) const;
|
||||
};
|
||||
|
||||
|
||||
/// A 3D 1st order Nedelec element on a wedge
|
||||
class Nedelec1WdgFiniteElement : public VectorFiniteElement
|
||||
{
|
||||
private:
|
||||
static const double tk[9][3];
|
||||
|
||||
public:
|
||||
/// Construct the Nedelec1WdgFiniteElement
|
||||
Nedelec1WdgFiniteElement();
|
||||
virtual void CalcVShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &shape) const;
|
||||
virtual void CalcVShape(ElementTransformation &Trans,
|
||||
DenseMatrix &shape) const
|
||||
{ CalcVShape_ND(Trans, shape); }
|
||||
virtual void CalcCurlShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &curl_shape) const;
|
||||
virtual void GetLocalInterpolation (ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
using FiniteElement::Project;
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void ProjectGrad(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &grad) const;
|
||||
};
|
||||
|
||||
|
||||
/// A 3D 1st order Nedelec element on a pyramid
|
||||
class Nedelec1PyrFiniteElement : public VectorFiniteElement
|
||||
{
|
||||
private:
|
||||
static const double tk[8][3];
|
||||
|
||||
public:
|
||||
/// Construct the Nedelec1PyrFiniteElement
|
||||
Nedelec1PyrFiniteElement();
|
||||
virtual void CalcVShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &shape) const;
|
||||
virtual void CalcVShape(ElementTransformation &Trans,
|
||||
DenseMatrix &shape) const
|
||||
{ CalcVShape_ND(Trans, shape); }
|
||||
virtual void CalcCurlShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &curl_shape) const;
|
||||
virtual void GetLocalInterpolation (ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
using FiniteElement::Project;
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void ProjectGrad(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &grad) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -1945,6 +2093,77 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/// A 3D 0th order Raviert-Thomas element on a wedge
|
||||
class RT0WdgFiniteElement : public VectorFiniteElement
|
||||
{
|
||||
private:
|
||||
static const double nk[5][3];
|
||||
|
||||
public:
|
||||
/// Construct the RT0WdgFiniteElement
|
||||
RT0WdgFiniteElement();
|
||||
|
||||
virtual void CalcVShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &shape) const;
|
||||
|
||||
virtual void CalcVShape(ElementTransformation &Trans,
|
||||
DenseMatrix &shape) const
|
||||
{ CalcVShape_RT(Trans, shape); }
|
||||
|
||||
virtual void CalcDivShape(const IntegrationPoint &ip,
|
||||
Vector &divshape) const;
|
||||
|
||||
virtual void GetLocalInterpolation (ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
|
||||
using FiniteElement::Project;
|
||||
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void ProjectCurl(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &curl) const;
|
||||
};
|
||||
|
||||
|
||||
/// A 3D 0th order Raviert-Thomas element on a pyramid
|
||||
class RT0PyrFiniteElement : public VectorFiniteElement
|
||||
{
|
||||
private:
|
||||
static const double nk[5][3];
|
||||
|
||||
// If true match RT0TetFiniteElement rather than RT_TetrahedronElement(0)
|
||||
bool rt0;
|
||||
|
||||
public:
|
||||
/// Construct the RT0PyrFiniteElement
|
||||
RT0PyrFiniteElement(bool rt0tets = true);
|
||||
|
||||
virtual void CalcVShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &shape) const;
|
||||
|
||||
virtual void CalcVShape(ElementTransformation &Trans,
|
||||
DenseMatrix &shape) const
|
||||
{ CalcVShape_RT(Trans, shape); }
|
||||
|
||||
virtual void CalcDivShape(const IntegrationPoint &ip,
|
||||
Vector &divshape) const;
|
||||
|
||||
virtual void GetLocalInterpolation (ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
|
||||
using FiniteElement::Project;
|
||||
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void ProjectCurl(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &curl) const;
|
||||
};
|
||||
|
||||
|
||||
class RotTriLinearHexFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
public:
|
||||
|
||||
+122
-16
@@ -33,6 +33,9 @@ int FiniteElementCollection::HasFaceDofs(Geometry::Type geom, int p) const
|
||||
case Geometry::PRISM:
|
||||
return max(GetNumDof(Geometry::TRIANGLE, p),
|
||||
GetNumDof(Geometry::SQUARE, p));
|
||||
case Geometry::PYRAMID:
|
||||
return max(GetNumDof(Geometry::TRIANGLE, p),
|
||||
GetNumDof(Geometry::SQUARE, p));
|
||||
default:
|
||||
MFEM_ABORT("unknown geometry type");
|
||||
}
|
||||
@@ -574,6 +577,7 @@ LinearFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
case Geometry::PYRAMID: return &PyramidFE;
|
||||
default:
|
||||
mfem_error ("LinearFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -591,6 +595,7 @@ int LinearFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::TETRAHEDRON: return 0;
|
||||
case Geometry::CUBE: return 0;
|
||||
case Geometry::PRISM: return 0;
|
||||
case Geometry::PYRAMID: return 0;
|
||||
default:
|
||||
mfem_error ("LinearFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1240,6 +1245,7 @@ Const3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
case Geometry::PYRAMID: return &PyramidFE;
|
||||
default:
|
||||
mfem_error ("Const3DFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1257,6 +1263,7 @@ int Const3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::TETRAHEDRON: return 1;
|
||||
case Geometry::CUBE: return 1;
|
||||
case Geometry::PRISM: return 1;
|
||||
case Geometry::PYRAMID: return 1;
|
||||
default:
|
||||
mfem_error ("Const3DFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1277,6 +1284,8 @@ LinearDiscont3DFECollection::FiniteElementForGeometry(
|
||||
switch (GeomType)
|
||||
{
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::PYRAMID: return &PyramidFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
default:
|
||||
mfem_error ("LinearDiscont3DFECollection: unknown geometry type.");
|
||||
@@ -1293,6 +1302,8 @@ int LinearDiscont3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::TRIANGLE: return 0;
|
||||
case Geometry::SQUARE: return 0;
|
||||
case Geometry::TETRAHEDRON: return 4;
|
||||
case Geometry::PYRAMID: return 5;
|
||||
case Geometry::PRISM: return 6;
|
||||
case Geometry::CUBE: return 8;
|
||||
default:
|
||||
mfem_error ("LinearDiscont3DFECollection: unknown geometry type.");
|
||||
@@ -1394,6 +1405,8 @@ ND1_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
case Geometry::CUBE: return &HexahedronFE;
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
case Geometry::PYRAMID: return &PyramidFE;
|
||||
default:
|
||||
mfem_error ("ND1_3DFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1410,6 +1423,8 @@ int ND1_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::SQUARE: return 0;
|
||||
case Geometry::TETRAHEDRON: return 0;
|
||||
case Geometry::CUBE: return 0;
|
||||
case Geometry::PRISM: return 0;
|
||||
case Geometry::PYRAMID: return 0;
|
||||
default:
|
||||
mfem_error ("ND1_3DFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1439,6 +1454,8 @@ RT0_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::SQUARE: return &QuadrilateralFE;
|
||||
case Geometry::CUBE: return &HexahedronFE;
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
case Geometry::PYRAMID: return &PyramidFE;
|
||||
default:
|
||||
mfem_error ("RT0_3DFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1455,6 +1472,8 @@ int RT0_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
case Geometry::SQUARE: return 1;
|
||||
case Geometry::TETRAHEDRON: return 0;
|
||||
case Geometry::CUBE: return 0;
|
||||
case Geometry::PRISM: return 0;
|
||||
case Geometry::PYRAMID: return 0;
|
||||
default:
|
||||
mfem_error ("RT0_3DFECollection: unknown geometry type.");
|
||||
}
|
||||
@@ -1730,6 +1749,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
H1_dof[Geometry::TETRAHEDRON] = (TriDof*pm3)/3;
|
||||
H1_dof[Geometry::CUBE] = QuadDof*pm1;
|
||||
H1_dof[Geometry::PRISM] = TriDof*pm1;
|
||||
H1_dof[Geometry::PYRAMID] = 0;
|
||||
if (b_type == BasisType::Positive)
|
||||
{
|
||||
H1_Elements[Geometry::TETRAHEDRON] = new H1Pos_TetrahedronElement(p);
|
||||
@@ -1743,6 +1763,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
H1_Elements[Geometry::CUBE] = new H1_HexahedronElement(p, btype);
|
||||
H1_Elements[Geometry::PRISM] = new H1_WedgeElement(p, btype);
|
||||
}
|
||||
H1_Elements[Geometry::PYRAMID] = new LinearPyramidFiniteElement;
|
||||
|
||||
const int &TetDof = H1_dof[Geometry::TETRAHEDRON];
|
||||
TetDofOrd[0] = new int[24*TetDof];
|
||||
@@ -1837,6 +1858,21 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
}
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
H1_FECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if (GeomType != Geometry::PYRAMID || this->GetOrder() == 1)
|
||||
{
|
||||
return H1_Elements[GeomType];
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("H1 Pyramid basis functions are not yet supported "
|
||||
"for order > 1.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const int *H1_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
@@ -2076,9 +2112,12 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
L2_Elements[Geometry::CUBE] = new L2_HexahedronElement(p, btype);
|
||||
L2_Elements[Geometry::PRISM] = new L2_WedgeElement(p, btype);
|
||||
}
|
||||
L2_Elements[Geometry::PYRAMID] = new P0PyrFiniteElement;
|
||||
|
||||
L2_Elements[Geometry::TETRAHEDRON]->SetMapType(map_type);
|
||||
L2_Elements[Geometry::CUBE]->SetMapType(map_type);
|
||||
L2_Elements[Geometry::PRISM]->SetMapType(map_type);
|
||||
L2_Elements[Geometry::PYRAMID]->SetMapType(map_type);
|
||||
// Trace element use the default Gauss-Legendre nodal points for positive basis
|
||||
if (b_type == BasisType::Positive)
|
||||
{
|
||||
@@ -2199,6 +2238,21 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
}
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
L2_FECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if (GeomType != Geometry::PYRAMID || this->GetOrder() == 0)
|
||||
{
|
||||
return L2_Elements[GeomType];
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("L2 Pyramid basis functions are not yet supported "
|
||||
"for order > 0.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const int *L2_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
@@ -2290,6 +2344,12 @@ RT_FECollection::RT_FECollection(const int order, const int dim,
|
||||
|
||||
RT_Elements[Geometry::CUBE] = new RT_HexahedronElement(p, cb_type, ob_type);
|
||||
RT_dof[Geometry::CUBE] = 3*p*pp1*pp1;
|
||||
|
||||
RT_Elements[Geometry::PRISM] = new RT0WdgFiniteElement;
|
||||
RT_dof[Geometry::PRISM] = 0;
|
||||
|
||||
RT_Elements[Geometry::PYRAMID] = new RT0PyrFiniteElement(false);
|
||||
RT_dof[Geometry::PYRAMID] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2433,6 +2493,22 @@ void RT_FECollection::InitFaces(const int p, const int dim,
|
||||
}
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
RT_FECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if ((GeomType != Geometry::PRISM && GeomType != Geometry::PYRAMID) ||
|
||||
this->GetOrder() == 1)
|
||||
{
|
||||
return RT_Elements[GeomType];
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("RT Wedge and Pyramid basis functions are not yet supported "
|
||||
"for order > 0.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const int *RT_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
@@ -2656,18 +2732,31 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
{
|
||||
for (int i = 0; i + j <= pm2; i++)
|
||||
{
|
||||
int k1 = p*pm1 - (p - j)*(pm1 - j) + 2*i;
|
||||
int k2 = p*pm1 - (p - i)*(pm1 - i) + 2*j;
|
||||
// (0,1,2)
|
||||
TriDofOrd[0][k1 ] = k1;
|
||||
TriDofOrd[0][k1+1] = k1 + 1;
|
||||
// (0,2,1)
|
||||
TriDofOrd[5][k1 ] = k2 + 1;
|
||||
TriDofOrd[5][k1+1] = k2;
|
||||
int k0 = p*pm1 - (p - j)*(pm1 - j) + 2*i;
|
||||
int k1 = 2*pm2 - 2*i + ((2*p-3)-j)*j;
|
||||
int k2 = 2*pm2 - 2*j + ((2*p-3)-i)*i;
|
||||
int k3 = p*pm1 - 2 - 3*j - i - (i+j)*(i+j);
|
||||
int k4 = p*pm1 - 2 - 3*i - j - (i+j)*(i+j);
|
||||
int k5 = p*pm1 - (p - i)*(pm1 - i) + 2*j;
|
||||
|
||||
// The other orientations can not be supported with the current
|
||||
// interface. The method Mesh::ReorientTetMesh will ensure that
|
||||
// only orientations 0 and 5 are generated.
|
||||
// (0,1,2)
|
||||
TriDofOrd[0][k0 ] = k0;
|
||||
TriDofOrd[0][k0+1] = k0 + 1;
|
||||
// (1,0,2)
|
||||
TriDofOrd[1][k0 ] = k1;
|
||||
TriDofOrd[1][k0+1] = k1 + 1;
|
||||
// (2,0,1)
|
||||
TriDofOrd[2][k0 ] = k2;
|
||||
TriDofOrd[2][k0+1] = k2 + 1;
|
||||
// (2,1,0)
|
||||
TriDofOrd[3][k0 ] = k3;
|
||||
TriDofOrd[3][k0+1] = k3 + 1;
|
||||
// (1,2,0)
|
||||
TriDofOrd[4][k0 ] = k4;
|
||||
TriDofOrd[4][k0+1] = k4 + 1;
|
||||
// (0,2,1)
|
||||
TriDofOrd[5][k0 ] = k5;
|
||||
TriDofOrd[5][k0+1] = k5 + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2680,6 +2769,28 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
// TODO: cb_type and ob_type for tets
|
||||
ND_Elements[Geometry::TETRAHEDRON] = new ND_TetrahedronElement(p);
|
||||
ND_dof[Geometry::TETRAHEDRON] = p*pm1*pm2/2;
|
||||
|
||||
ND_Elements[Geometry::PRISM] = new Nedelec1WdgFiniteElement;
|
||||
ND_dof[Geometry::PRISM] = 0;
|
||||
|
||||
ND_Elements[Geometry::PYRAMID] = new Nedelec1PyrFiniteElement;
|
||||
ND_dof[Geometry::PYRAMID] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
ND_FECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if ((GeomType != Geometry::PRISM && GeomType != Geometry::PYRAMID) ||
|
||||
this->GetOrder() == 1)
|
||||
{
|
||||
return ND_Elements[GeomType];
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("ND Wedge and Pyramid basis functions are not yet supported "
|
||||
"for order > 1.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2692,11 +2803,6 @@ const int *ND_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
}
|
||||
else if (GeomType == Geometry::TRIANGLE)
|
||||
{
|
||||
if (Or != 0 && Or != 5)
|
||||
{
|
||||
MFEM_ABORT("triangle face orientation " << Or << " is not supported! "
|
||||
"Use Mesh::ReorientTetMesh to fix it.");
|
||||
}
|
||||
return TriDofOrd[Or%6];
|
||||
}
|
||||
else if (GeomType == Geometry::SQUARE)
|
||||
|
||||
+16
-14
@@ -228,8 +228,7 @@ public:
|
||||
const int btype = BasisType::GaussLobatto);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{ return H1_Elements[GeomType]; }
|
||||
Geometry::Type GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{ return H1_dof[GeomType]; }
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
@@ -302,10 +301,7 @@ public:
|
||||
const int map_type = FiniteElement::VALUE);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
return L2_Elements[GeomType];
|
||||
}
|
||||
Geometry::Type GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if (L2_Elements[GeomType])
|
||||
@@ -371,8 +367,7 @@ public:
|
||||
const int ob_type = BasisType::GaussLegendre);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{ return RT_Elements[GeomType]; }
|
||||
Geometry::Type GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{ return RT_dof[GeomType]; }
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
@@ -430,8 +425,7 @@ public:
|
||||
const int ob_type = BasisType::GaussLegendre);
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{ return ND_Elements[GeomType]; }
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{ return ND_dof[GeomType]; }
|
||||
@@ -529,9 +523,10 @@ private:
|
||||
const BiLinear2DFiniteElement QuadrilateralFE;
|
||||
const Linear3DFiniteElement TetrahedronFE;
|
||||
const TriLinear3DFiniteElement ParallelepipedFE;
|
||||
const H1_WedgeElement WedgeFE;
|
||||
const LinearWedgeFiniteElement WedgeFE;
|
||||
const LinearPyramidFiniteElement PyramidFE;
|
||||
public:
|
||||
LinearFECollection() : FiniteElementCollection(1), WedgeFE(1) { }
|
||||
LinearFECollection() : FiniteElementCollection(1) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
@@ -936,10 +931,11 @@ class Const3DFECollection : public FiniteElementCollection
|
||||
private:
|
||||
const P0TetFiniteElement TetrahedronFE;
|
||||
const P0HexFiniteElement ParallelepipedFE;
|
||||
const L2_WedgeElement WedgeFE;
|
||||
const P0WdgFiniteElement WedgeFE;
|
||||
const P0PyrFiniteElement PyramidFE;
|
||||
|
||||
public:
|
||||
Const3DFECollection() : FiniteElementCollection(0), WedgeFE(0) { }
|
||||
Const3DFECollection() : FiniteElementCollection(0) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
@@ -960,6 +956,8 @@ class LinearDiscont3DFECollection : public FiniteElementCollection
|
||||
{
|
||||
private:
|
||||
const Linear3DFiniteElement TetrahedronFE;
|
||||
const LinearPyramidFiniteElement PyramidFE;
|
||||
const LinearWedgeFiniteElement WedgeFE;
|
||||
const TriLinear3DFiniteElement ParallelepipedFE;
|
||||
|
||||
public:
|
||||
@@ -1036,6 +1034,8 @@ class ND1_3DFECollection : public FiniteElementCollection
|
||||
private:
|
||||
const Nedelec1HexFiniteElement HexahedronFE;
|
||||
const Nedelec1TetFiniteElement TetrahedronFE;
|
||||
const Nedelec1WdgFiniteElement WedgeFE;
|
||||
const Nedelec1PyrFiniteElement PyramidFE;
|
||||
|
||||
public:
|
||||
ND1_3DFECollection() : FiniteElementCollection(1) { }
|
||||
@@ -1061,6 +1061,8 @@ private:
|
||||
const P0QuadFiniteElement QuadrilateralFE;
|
||||
const RT0HexFiniteElement HexahedronFE;
|
||||
const RT0TetFiniteElement TetrahedronFE;
|
||||
const RT0WdgFiniteElement WedgeFE;
|
||||
const RT0PyrFiniteElement PyramidFE;
|
||||
public:
|
||||
RT0_3DFECollection() : FiniteElementCollection(1) { }
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "geom.hpp"
|
||||
#include "fe.hpp"
|
||||
#include "fe_coll.hpp"
|
||||
#include "doftrans.hpp"
|
||||
#include "eltrans.hpp"
|
||||
#include "coefficient.hpp"
|
||||
#include "complex_fem.hpp"
|
||||
|
||||
+323
-50
@@ -58,9 +58,12 @@ DofsToVDofs<Ordering::byVDIM>(int ndofs, int vdim, Array<int> &dofs)
|
||||
|
||||
FiniteElementSpace::FiniteElementSpace()
|
||||
: mesh(NULL), fec(NULL), vdim(0), ordering(Ordering::byNODES),
|
||||
ndofs(0), nvdofs(0), nedofs(0), nfdofs(0), nbdofs(0), bdofs(NULL),
|
||||
elem_dof(NULL), bdr_elem_dof(NULL), face_dof(NULL),
|
||||
ndofs(0), nvdofs(0), nedofs(0), nfdofs(0), nbdofs(0),
|
||||
bdofs(NULL),
|
||||
elem_dof(NULL), elem_fos(NULL), bdr_elem_dof(NULL), bdr_elem_fos(NULL),
|
||||
face_dof(NULL),
|
||||
NURBSext(NULL), own_ext(false),
|
||||
DoFTrans(0), VDoFTrans(vdim, ordering),
|
||||
cP(NULL), cR(NULL), cR_hp(NULL), cP_is_set(false),
|
||||
Th(Operator::ANY_TYPE),
|
||||
sequence(0), mesh_sequence(0), orders_changed(false), relaxed_hp(false)
|
||||
@@ -69,6 +72,7 @@ FiniteElementSpace::FiniteElementSpace()
|
||||
FiniteElementSpace::FiniteElementSpace(const FiniteElementSpace &orig,
|
||||
Mesh *mesh,
|
||||
const FiniteElementCollection *fec)
|
||||
: VDoFTrans(orig.vdim, orig.ordering)
|
||||
{
|
||||
mesh = mesh ? mesh : orig.mesh;
|
||||
fec = fec ? fec : orig.fec;
|
||||
@@ -259,16 +263,36 @@ void FiniteElementSpace::AdjustVDofs (Array<int> &vdofs)
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetElementVDofs(int i, Array<int> &vdofs) const
|
||||
DofTransformation *
|
||||
FiniteElementSpace::GetElementVDofs(int i, Array<int> &vdofs) const
|
||||
{
|
||||
GetElementDofs(i, vdofs);
|
||||
DofTransformation * doftrans = GetElementDofs(i, vdofs);
|
||||
DofsToVDofs(vdofs);
|
||||
if (vdim == 1 || doftrans == NULL)
|
||||
{
|
||||
return doftrans;
|
||||
}
|
||||
else
|
||||
{
|
||||
VDoFTrans.SetDofTransformation(*doftrans);
|
||||
return &VDoFTrans;
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetBdrElementVDofs(int i, Array<int> &vdofs) const
|
||||
DofTransformation *
|
||||
FiniteElementSpace::GetBdrElementVDofs(int i, Array<int> &vdofs) const
|
||||
{
|
||||
GetBdrElementDofs(i, vdofs);
|
||||
DofTransformation * doftrans = GetBdrElementDofs(i, vdofs);
|
||||
DofsToVDofs(vdofs);
|
||||
if (vdim == 1 || doftrans == NULL)
|
||||
{
|
||||
return doftrans;
|
||||
}
|
||||
else
|
||||
{
|
||||
VDoFTrans.SetDofTransformation(*doftrans);
|
||||
return &VDoFTrans;
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetFaceVDofs(int i, Array<int> &vdofs) const
|
||||
@@ -307,21 +331,39 @@ void FiniteElementSpace::BuildElementToDofTable() const
|
||||
|
||||
// TODO: can we call GetElementDofs only once per element?
|
||||
Table *el_dof = new Table;
|
||||
Table *el_fos = (mesh->Dimension() > 2) ? (new Table) : NULL;
|
||||
Array<int> dofs;
|
||||
Array<int> F, Fo;
|
||||
el_dof -> MakeI (mesh -> GetNE());
|
||||
if (el_fos) { el_fos -> MakeI (mesh -> GetNE()); }
|
||||
for (int i = 0; i < mesh -> GetNE(); i++)
|
||||
{
|
||||
GetElementDofs (i, dofs);
|
||||
el_dof -> AddColumnsInRow (i, dofs.Size());
|
||||
|
||||
if (el_fos)
|
||||
{
|
||||
mesh->GetElementFaces(i, F, Fo);
|
||||
el_fos -> AddColumnsInRow (i, Fo.Size());
|
||||
}
|
||||
}
|
||||
el_dof -> MakeJ();
|
||||
if (el_fos) { el_fos -> MakeJ(); }
|
||||
for (int i = 0; i < mesh -> GetNE(); i++)
|
||||
{
|
||||
GetElementDofs (i, dofs);
|
||||
el_dof -> AddConnections (i, (int *)dofs, dofs.Size());
|
||||
|
||||
if (el_fos)
|
||||
{
|
||||
mesh->GetElementFaces(i, F, Fo);
|
||||
el_fos -> AddConnections (i, (int *)Fo, Fo.Size());
|
||||
}
|
||||
}
|
||||
el_dof -> ShiftUpI();
|
||||
if (el_fos) { el_fos -> ShiftUpI(); }
|
||||
elem_dof = el_dof;
|
||||
elem_fos = el_fos;
|
||||
}
|
||||
|
||||
void FiniteElementSpace::BuildBdrElementToDofTable() const
|
||||
@@ -375,7 +417,9 @@ void FiniteElementSpace::BuildFaceToDofTable() const
|
||||
void FiniteElementSpace::RebuildElementToDofTable()
|
||||
{
|
||||
delete elem_dof;
|
||||
delete elem_fos;
|
||||
elem_dof = NULL;
|
||||
elem_fos = NULL;
|
||||
BuildElementToDofTable();
|
||||
}
|
||||
|
||||
@@ -1315,8 +1359,10 @@ const FaceQuadratureInterpolator
|
||||
|
||||
SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
|
||||
const int coarse_ndofs, const Table &coarse_elem_dof,
|
||||
const DenseTensor localP[]) const
|
||||
const Table *coarse_elem_fos, const DenseTensor localP[]) const
|
||||
{
|
||||
/// TODO: Implement DofTransformation support
|
||||
|
||||
MFEM_VERIFY(mesh->GetLastOperation() == Mesh::REFINE, "");
|
||||
|
||||
Array<int> dofs, coarse_dofs, coarse_vdofs;
|
||||
@@ -1399,7 +1445,8 @@ void FiniteElementSpace::GetLocalRefinementMatrices(
|
||||
}
|
||||
|
||||
SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
|
||||
const Table* old_elem_dof)
|
||||
const Table* old_elem_dof,
|
||||
const Table* old_elem_fos)
|
||||
{
|
||||
MFEM_VERIFY(GetNE() >= old_elem_dof->Size(),
|
||||
"Previous mesh is not coarser.");
|
||||
@@ -1412,13 +1459,16 @@ SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
|
||||
GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
|
||||
}
|
||||
|
||||
return RefinementMatrix_main(old_ndofs, *old_elem_dof, localP);
|
||||
return RefinementMatrix_main(old_ndofs, *old_elem_dof, old_elem_fos,
|
||||
localP);
|
||||
}
|
||||
|
||||
FiniteElementSpace::RefinementOperator::RefinementOperator
|
||||
(const FiniteElementSpace* fespace, Table* old_elem_dof, int old_ndofs)
|
||||
(const FiniteElementSpace* fespace, Table* old_elem_dof, Table* old_elem_fos,
|
||||
int old_ndofs)
|
||||
: fespace(fespace)
|
||||
, old_elem_dof(old_elem_dof)
|
||||
, old_elem_fos(old_elem_fos)
|
||||
{
|
||||
MFEM_VERIFY(fespace->GetNE() >= old_elem_dof->Size(),
|
||||
"Previous mesh is not coarser.");
|
||||
@@ -1432,12 +1482,14 @@ FiniteElementSpace::RefinementOperator::RefinementOperator
|
||||
{
|
||||
fespace->GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
|
||||
}
|
||||
|
||||
ConstructDoFTrans();
|
||||
}
|
||||
|
||||
FiniteElementSpace::RefinementOperator::RefinementOperator(
|
||||
const FiniteElementSpace *fespace, const FiniteElementSpace *coarse_fes)
|
||||
: Operator(fespace->GetVSize(), coarse_fes->GetVSize()),
|
||||
fespace(fespace), old_elem_dof(NULL)
|
||||
fespace(fespace), old_elem_dof(NULL), old_elem_fos(NULL)
|
||||
{
|
||||
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
|
||||
|
||||
@@ -1449,11 +1501,50 @@ FiniteElementSpace::RefinementOperator::RefinementOperator(
|
||||
|
||||
// Make a copy of the coarse elem_dof Table.
|
||||
old_elem_dof = new Table(coarse_fes->GetElementToDofTable());
|
||||
|
||||
// Make a copy of the coarse elem_fos Table if it exists.
|
||||
if (coarse_fes->GetElementToFaceOrientationTable())
|
||||
{
|
||||
old_elem_fos = new Table(*coarse_fes->GetElementToFaceOrientationTable());
|
||||
}
|
||||
|
||||
ConstructDoFTrans();
|
||||
}
|
||||
|
||||
FiniteElementSpace::RefinementOperator::~RefinementOperator()
|
||||
{
|
||||
delete old_elem_dof;
|
||||
delete old_elem_fos;
|
||||
}
|
||||
|
||||
void FiniteElementSpace::RefinementOperator
|
||||
::ConstructDoFTrans()
|
||||
{
|
||||
old_DoFTrans.SetSize(Geometry::NUM_GEOMETRIES);
|
||||
for (int i=0; i<old_DoFTrans.Size(); i++)
|
||||
{
|
||||
old_DoFTrans[i] = NULL;
|
||||
}
|
||||
|
||||
const FiniteElementCollection *fec = fespace->FEColl();
|
||||
if (dynamic_cast<const ND_FECollection*>(fec))
|
||||
{
|
||||
const FiniteElement * nd_tri =
|
||||
fec->FiniteElementForGeometry(Geometry::TRIANGLE);
|
||||
if (nd_tri)
|
||||
{
|
||||
old_DoFTrans[Geometry::TRIANGLE] =
|
||||
new ND_TriDofTransformation(nd_tri->GetOrder());
|
||||
}
|
||||
|
||||
const FiniteElement * nd_tet =
|
||||
fec->FiniteElementForGeometry(Geometry::TETRAHEDRON);
|
||||
if (nd_tet)
|
||||
{
|
||||
old_DoFTrans[Geometry::TETRAHEDRON] =
|
||||
new ND_TetDofTransformation(nd_tet->GetOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteElementSpace::RefinementOperator
|
||||
@@ -1462,7 +1553,7 @@ void FiniteElementSpace::RefinementOperator
|
||||
Mesh* mesh = fespace->GetMesh();
|
||||
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
|
||||
|
||||
Array<int> dofs, vdofs, old_dofs, old_vdofs;
|
||||
Array<int> dofs, vdofs, old_dofs, old_vdofs, old_Fo;
|
||||
|
||||
int vdim = fespace->GetVDim();
|
||||
int old_ndofs = width / vdim;
|
||||
@@ -1477,18 +1568,53 @@ void FiniteElementSpace::RefinementOperator
|
||||
|
||||
subY.SetSize(lP.Height());
|
||||
|
||||
fespace->GetElementDofs(k, dofs);
|
||||
DofTransformation *doftrans = fespace->GetElementDofs(k, dofs);
|
||||
old_elem_dof->GetRow(emb.parent, old_dofs);
|
||||
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
if (!doftrans)
|
||||
{
|
||||
dofs.Copy(vdofs);
|
||||
fespace->DofsToVDofs(vd, vdofs);
|
||||
old_dofs.Copy(old_vdofs);
|
||||
fespace->DofsToVDofs(vd, old_vdofs, old_ndofs);
|
||||
x.GetSubVector(old_vdofs, subX);
|
||||
lP.Mult(subX, subY);
|
||||
y.SetSubVector(vdofs, subY);
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
{
|
||||
dofs.Copy(vdofs);
|
||||
fespace->DofsToVDofs(vd, vdofs);
|
||||
old_dofs.Copy(old_vdofs);
|
||||
fespace->DofsToVDofs(vd, old_vdofs, old_ndofs);
|
||||
x.GetSubVector(old_vdofs, subX);
|
||||
lP.Mult(subX, subY);
|
||||
y.SetSubVector(vdofs, subY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
old_elem_fos->GetRow(emb.parent, old_Fo);
|
||||
old_DoFTrans[geom]->SetFaceOrientations(old_Fo);
|
||||
|
||||
DofTransformation *new_doftrans = NULL;
|
||||
VDofTransformation *vdoftrans =
|
||||
dynamic_cast<VDofTransformation*>(doftrans);
|
||||
if (vdoftrans)
|
||||
{
|
||||
new_doftrans = doftrans;
|
||||
doftrans = vdoftrans->GetDofTransformation();
|
||||
}
|
||||
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
{
|
||||
dofs.Copy(vdofs);
|
||||
fespace->DofsToVDofs(vd, vdofs);
|
||||
old_dofs.Copy(old_vdofs);
|
||||
fespace->DofsToVDofs(vd, old_vdofs, old_ndofs);
|
||||
x.GetSubVector(old_vdofs, subX);
|
||||
old_DoFTrans[geom]->InvTransformPrimal(subX);
|
||||
lP.Mult(subX, subY);
|
||||
doftrans->TransformPrimal(subY);
|
||||
y.SetSubVector(vdofs, subY);
|
||||
}
|
||||
|
||||
if (vdoftrans)
|
||||
{
|
||||
doftrans = new_doftrans;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1504,12 +1630,12 @@ void FiniteElementSpace::RefinementOperator
|
||||
Array<char> processed(fespace->GetVSize());
|
||||
processed = 0;
|
||||
|
||||
Array<int> f_dofs, c_dofs, f_vdofs, c_vdofs;
|
||||
Array<int> f_dofs, c_dofs, f_vdofs, c_vdofs, old_Fo;
|
||||
|
||||
int vdim = fespace->GetVDim();
|
||||
int old_ndofs = width / vdim;
|
||||
|
||||
Vector subY, subX;
|
||||
Vector subY, subX, subYt, subXt;
|
||||
|
||||
for (int k = 0; k < mesh->GetNE(); k++)
|
||||
{
|
||||
@@ -1517,30 +1643,77 @@ void FiniteElementSpace::RefinementOperator
|
||||
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
|
||||
const DenseMatrix &lP = localP[geom](emb.matrix);
|
||||
|
||||
fespace->GetElementDofs(k, f_dofs);
|
||||
DofTransformation * doftrans = fespace->GetElementDofs(k, f_dofs);
|
||||
old_elem_dof->GetRow(emb.parent, c_dofs);
|
||||
|
||||
subY.SetSize(lP.Width());
|
||||
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
if (!doftrans)
|
||||
{
|
||||
f_dofs.Copy(f_vdofs);
|
||||
fespace->DofsToVDofs(vd, f_vdofs);
|
||||
c_dofs.Copy(c_vdofs);
|
||||
fespace->DofsToVDofs(vd, c_vdofs, old_ndofs);
|
||||
subY.SetSize(lP.Width());
|
||||
|
||||
x.GetSubVector(f_vdofs, subX);
|
||||
|
||||
for (int p = 0; p < f_dofs.Size(); ++p)
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
{
|
||||
if (processed[DecodeDof(f_dofs[p])])
|
||||
f_dofs.Copy(f_vdofs);
|
||||
fespace->DofsToVDofs(vd, f_vdofs);
|
||||
c_dofs.Copy(c_vdofs);
|
||||
fespace->DofsToVDofs(vd, c_vdofs, old_ndofs);
|
||||
|
||||
x.GetSubVector(f_vdofs, subX);
|
||||
|
||||
for (int p = 0; p < f_dofs.Size(); ++p)
|
||||
{
|
||||
subX[p] = 0.0;
|
||||
if (processed[DecodeDof(f_dofs[p])])
|
||||
{
|
||||
subX[p] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
lP.MultTranspose(subX, subY);
|
||||
y.AddElementVector(c_vdofs, subY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
subYt.SetSize(lP.Width());
|
||||
|
||||
old_elem_fos->GetRow(emb.parent, old_Fo);
|
||||
old_DoFTrans[geom]->SetFaceOrientations(old_Fo);
|
||||
|
||||
DofTransformation *new_doftrans = NULL;
|
||||
VDofTransformation *vdoftrans =
|
||||
dynamic_cast<VDofTransformation*>(doftrans);
|
||||
if (vdoftrans)
|
||||
{
|
||||
new_doftrans = doftrans;
|
||||
doftrans = vdoftrans->GetDofTransformation();
|
||||
}
|
||||
|
||||
lP.MultTranspose(subX, subY);
|
||||
y.AddElementVector(c_vdofs, subY);
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
{
|
||||
f_dofs.Copy(f_vdofs);
|
||||
fespace->DofsToVDofs(vd, f_vdofs);
|
||||
c_dofs.Copy(c_vdofs);
|
||||
fespace->DofsToVDofs(vd, c_vdofs, old_ndofs);
|
||||
|
||||
x.GetSubVector(f_vdofs, subX);
|
||||
old_DoFTrans[geom]->InvTransformPrimal(subX);
|
||||
|
||||
for (int p = 0; p < f_dofs.Size(); ++p)
|
||||
{
|
||||
if (processed[DecodeDof(f_dofs[p])])
|
||||
{
|
||||
subX[p] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
lP.MultTranspose(subX, subY);
|
||||
doftrans->TransformPrimal(subY);
|
||||
y.AddElementVector(c_vdofs, subY);
|
||||
}
|
||||
|
||||
if (vdoftrans)
|
||||
{
|
||||
doftrans = new_doftrans;
|
||||
}
|
||||
}
|
||||
|
||||
for (int p = 0; p < f_dofs.Size(); ++p)
|
||||
@@ -1550,6 +1723,7 @@ void FiniteElementSpace::RefinementOperator
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Implement DofTransformation support
|
||||
FiniteElementSpace::DerefinementOperator::DerefinementOperator(
|
||||
const FiniteElementSpace *f_fes, const FiniteElementSpace *c_fes,
|
||||
BilinearFormIntegrator *mass_integ)
|
||||
@@ -1707,8 +1881,11 @@ void FiniteElementSpace::GetLocalDerefinementMatrices(Geometry::Type geom,
|
||||
}
|
||||
|
||||
SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
|
||||
const Table* old_elem_dof)
|
||||
const Table* old_elem_dof,
|
||||
const Table* old_elem_fos)
|
||||
{
|
||||
/// TODO: Implement DofTransformation support
|
||||
|
||||
MFEM_VERIFY(Nonconforming(), "Not implemented for conforming meshes.");
|
||||
MFEM_VERIFY(old_ndofs, "Missing previous (finer) space.");
|
||||
MFEM_VERIFY(ndofs <= old_ndofs, "Previous space is not finer.");
|
||||
@@ -1814,6 +1991,7 @@ void FiniteElementSpace::Constructor(Mesh *mesh, NURBSExtension *NURBSext,
|
||||
this->ordering = (Ordering::Type) ordering;
|
||||
|
||||
elem_dof = NULL;
|
||||
elem_fos = NULL;
|
||||
face_dof = NULL;
|
||||
|
||||
sequence = 0;
|
||||
@@ -1841,6 +2019,8 @@ void FiniteElementSpace::Constructor(Mesh *mesh, NURBSExtension *NURBSext,
|
||||
UpdateNURBS();
|
||||
cP = cR = cR_hp = NULL;
|
||||
cP_is_set = false;
|
||||
|
||||
ConstructDoFTrans();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1848,9 +2028,41 @@ void FiniteElementSpace::Constructor(Mesh *mesh, NURBSExtension *NURBSext,
|
||||
own_ext = 0;
|
||||
Construct();
|
||||
}
|
||||
|
||||
BuildElementToDofTable();
|
||||
}
|
||||
|
||||
void FiniteElementSpace::ConstructDoFTrans()
|
||||
{
|
||||
DestroyDoFTrans();
|
||||
|
||||
VDoFTrans.SetVDim(vdim);
|
||||
DoFTrans.SetSize(Geometry::NUM_GEOMETRIES);
|
||||
for (int i=0; i<DoFTrans.Size(); i++)
|
||||
{
|
||||
DoFTrans[i] = NULL;
|
||||
}
|
||||
if (mesh->Dimension() < 3) { return; }
|
||||
if (dynamic_cast<const ND_FECollection*>(fec))
|
||||
{
|
||||
const FiniteElement * nd_tri =
|
||||
fec->FiniteElementForGeometry(Geometry::TRIANGLE);
|
||||
if (nd_tri)
|
||||
{
|
||||
DoFTrans[Geometry::TRIANGLE] =
|
||||
new ND_TriDofTransformation(nd_tri->GetOrder());
|
||||
}
|
||||
|
||||
const FiniteElement * nd_tet =
|
||||
fec->FiniteElementForGeometry(Geometry::TETRAHEDRON);
|
||||
if (nd_tet)
|
||||
{
|
||||
DoFTrans[Geometry::TETRAHEDRON] =
|
||||
new ND_TetDofTransformation(nd_tet->GetOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NURBSExtension *FiniteElementSpace::StealNURBSext()
|
||||
{
|
||||
if (NURBSext && !own_ext)
|
||||
@@ -1946,7 +2158,9 @@ void FiniteElementSpace::Construct()
|
||||
"Variable order space requires a nonconforming mesh.");
|
||||
|
||||
elem_dof = NULL;
|
||||
elem_fos = NULL;
|
||||
bdr_elem_dof = NULL;
|
||||
bdr_elem_fos = NULL;
|
||||
face_dof = NULL;
|
||||
|
||||
ndofs = 0;
|
||||
@@ -2044,6 +2258,8 @@ void FiniteElementSpace::Construct()
|
||||
|
||||
ndofs = nvdofs + nedofs + nfdofs + nbdofs;
|
||||
|
||||
ConstructDoFTrans();
|
||||
|
||||
// record the current mesh sequence number to detect refinement etc.
|
||||
mesh_sequence = mesh->GetSequence();
|
||||
|
||||
@@ -2295,14 +2511,22 @@ int FiniteElementSpace::GetNVariants(int entity, int index) const
|
||||
static const char* msg_orders_changed =
|
||||
"Element orders changed, you need to Update() the space first.";
|
||||
|
||||
void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
|
||||
DofTransformation *
|
||||
FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
|
||||
{
|
||||
MFEM_VERIFY(!orders_changed, msg_orders_changed);
|
||||
|
||||
if (elem_dof)
|
||||
{
|
||||
elem_dof->GetRow(elem, dofs);
|
||||
return;
|
||||
|
||||
if (DoFTrans[mesh->GetElementBaseGeometry(elem)])
|
||||
{
|
||||
Array<int> Fo;
|
||||
elem_fos -> GetRow (elem, Fo);
|
||||
DoFTrans[mesh->GetElementBaseGeometry(elem)]->SetFaceOrientations(Fo);
|
||||
}
|
||||
return DoFTrans[mesh->GetElementBaseGeometry(elem)];
|
||||
}
|
||||
|
||||
Array<int> V, E, Eo, F, Fo; // TODO: LocalArray
|
||||
@@ -2326,6 +2550,11 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
|
||||
{
|
||||
nfd += fec->GetNumDof(mesh->GetFaceGeometry(F[i]), order);
|
||||
}
|
||||
if (DoFTrans[mesh->GetElementBaseGeometry(elem)])
|
||||
{
|
||||
DoFTrans[mesh->GetElementBaseGeometry(elem)]
|
||||
-> SetFaceOrientations(Fo);
|
||||
}
|
||||
}
|
||||
|
||||
dofs.SetSize(0);
|
||||
@@ -2383,6 +2612,7 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
|
||||
dofs.Append(bbase + j);
|
||||
}
|
||||
}
|
||||
return DoFTrans[mesh->GetElementBaseGeometry(elem)];
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetFE(int i) const
|
||||
@@ -2415,18 +2645,27 @@ const FiniteElement *FiniteElementSpace::GetFE(int i) const
|
||||
return FE;
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs) const
|
||||
DofTransformation *
|
||||
FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs) const
|
||||
{
|
||||
MFEM_VERIFY(!orders_changed, msg_orders_changed);
|
||||
|
||||
if (bdr_elem_dof)
|
||||
{
|
||||
bdr_elem_dof->GetRow(bel, dofs);
|
||||
return;
|
||||
|
||||
if (DoFTrans[mesh->GetBdrElementBaseGeometry(bel)])
|
||||
{
|
||||
Array<int> Fo;
|
||||
bdr_elem_fos -> GetRow (bel, Fo);
|
||||
DoFTrans[mesh->GetBdrElementBaseGeometry(bel)]->
|
||||
SetFaceOrientations(Fo);
|
||||
}
|
||||
return DoFTrans[mesh->GetBdrElementBaseGeometry(bel)];
|
||||
}
|
||||
|
||||
Array<int> V, E, Eo; // TODO: LocalArray
|
||||
int F, Fo;
|
||||
Array<int> V, E, Eo, Fo; // TODO: LocalArray
|
||||
int F, oF;
|
||||
|
||||
int dim = mesh->Dimension();
|
||||
auto geom = mesh->GetBdrElementGeometry(bel);
|
||||
@@ -2445,7 +2684,17 @@ void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs) const
|
||||
|
||||
if (nv) { mesh->GetBdrElementVertices(bel, V); }
|
||||
if (ne) { mesh->GetBdrElementEdges(bel, E, Eo); }
|
||||
if (nf) { mesh->GetBdrElementFace(bel, &F, &Fo); }
|
||||
if (nf)
|
||||
{
|
||||
mesh->GetBdrElementFace(bel, &F, &oF);
|
||||
|
||||
if (DoFTrans[mesh->GetBdrElementBaseGeometry(bel)])
|
||||
{
|
||||
Fo.Append(oF);
|
||||
DoFTrans[mesh->GetBdrElementBaseGeometry(bel)]->
|
||||
SetFaceOrientations(Fo);
|
||||
}
|
||||
}
|
||||
|
||||
dofs.SetSize(0);
|
||||
dofs.Reserve(nv*V.Size() + ne*E.Size() + nf);
|
||||
@@ -2478,13 +2727,15 @@ void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs) const
|
||||
if (nf) // face DOFs
|
||||
{
|
||||
int fbase = (var_face_dofs.Size() > 0) ? FindFaceDof(F, nf) : F*nf;
|
||||
const int *ind = fec->GetDofOrdering(geom, order, Fo);
|
||||
const int *ind = fec->GetDofOrdering(geom, order, oF);
|
||||
|
||||
for (int j = 0; j < nf; j++)
|
||||
{
|
||||
dofs.Append(EncodeDof(nvdofs + nedofs + fbase, ind[j]));
|
||||
}
|
||||
}
|
||||
|
||||
return DoFTrans[mesh->GetBdrElementBaseGeometry(bel)];
|
||||
}
|
||||
|
||||
int FiniteElementSpace::GetFaceDofs(int face, Array<int> &dofs,
|
||||
@@ -2794,6 +3045,8 @@ void FiniteElementSpace::Destroy()
|
||||
}
|
||||
E2BFQ_array.SetSize(0);
|
||||
|
||||
DestroyDoFTrans();
|
||||
|
||||
dof_elem_array.DeleteAll();
|
||||
dof_ldof_array.DeleteAll();
|
||||
|
||||
@@ -2806,7 +3059,9 @@ void FiniteElementSpace::Destroy()
|
||||
else
|
||||
{
|
||||
delete elem_dof;
|
||||
delete elem_fos;
|
||||
delete bdr_elem_dof;
|
||||
delete bdr_elem_fos;
|
||||
delete face_dof;
|
||||
|
||||
delete [] bdofs;
|
||||
@@ -2814,6 +3069,15 @@ void FiniteElementSpace::Destroy()
|
||||
ceed::RemoveBasisAndRestriction(this);
|
||||
}
|
||||
|
||||
void FiniteElementSpace::DestroyDoFTrans()
|
||||
{
|
||||
for (int i = 0; i < DoFTrans.Size(); i++)
|
||||
{
|
||||
delete DoFTrans[i];
|
||||
}
|
||||
DoFTrans.SetSize(0);
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetTransferOperator(
|
||||
const FiniteElementSpace &coarse_fes, OperatorHandle &T) const
|
||||
{
|
||||
@@ -2831,6 +3095,8 @@ void FiniteElementSpace::GetTransferOperator(
|
||||
}
|
||||
T.Reset(RefinementMatrix_main(coarse_fes.GetNDofs(),
|
||||
coarse_fes.GetElementToDofTable(),
|
||||
coarse_fes.
|
||||
GetElementToFaceOrientationTable(),
|
||||
localP));
|
||||
}
|
||||
else
|
||||
@@ -2933,6 +3199,7 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
}
|
||||
|
||||
Table* old_elem_dof = NULL;
|
||||
Table* old_elem_fos = NULL;
|
||||
int old_ndofs;
|
||||
bool old_orders_changed = orders_changed;
|
||||
|
||||
@@ -2940,7 +3207,9 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
if (want_transform)
|
||||
{
|
||||
old_elem_dof = elem_dof;
|
||||
old_elem_fos = elem_fos;
|
||||
elem_dof = NULL;
|
||||
elem_fos = NULL;
|
||||
old_ndofs = ndofs;
|
||||
}
|
||||
|
||||
@@ -2966,15 +3235,18 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
{
|
||||
if (Th.Type() != Operator::MFEM_SPARSEMAT)
|
||||
{
|
||||
Th.Reset(new RefinementOperator(this, old_elem_dof, old_ndofs));
|
||||
Th.Reset(new RefinementOperator(this, old_elem_dof,
|
||||
old_elem_fos, old_ndofs));
|
||||
// The RefinementOperator takes ownership of 'old_elem_dof', so
|
||||
// we no longer own it:
|
||||
old_elem_dof = NULL;
|
||||
old_elem_fos = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate fully assembled matrix
|
||||
Th.Reset(RefinementMatrix(old_ndofs, old_elem_dof));
|
||||
Th.Reset(RefinementMatrix(old_ndofs, old_elem_dof,
|
||||
old_elem_fos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2982,7 +3254,7 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
case Mesh::DEREFINE:
|
||||
{
|
||||
BuildConformingInterpolation();
|
||||
Th.Reset(DerefinementMatrix(old_ndofs, old_elem_dof));
|
||||
Th.Reset(DerefinementMatrix(old_ndofs, old_elem_dof, old_elem_fos));
|
||||
if (cP && cR)
|
||||
{
|
||||
Th.SetOperatorOwner(false);
|
||||
@@ -2997,6 +3269,7 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
}
|
||||
|
||||
delete old_elem_dof;
|
||||
delete old_elem_fos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+30
-7
@@ -16,6 +16,7 @@
|
||||
#include "../linalg/sparsemat.hpp"
|
||||
#include "../mesh/mesh.hpp"
|
||||
#include "fe_coll.hpp"
|
||||
#include "doftrans.hpp"
|
||||
#include "restriction.hpp"
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
@@ -128,7 +129,9 @@ protected:
|
||||
|
||||
// precalculated DOFs for each element, boundary element, and face
|
||||
mutable Table *elem_dof; // owned (except in NURBS FE space)
|
||||
mutable Table *elem_fos; // face orientations by element index
|
||||
mutable Table *bdr_elem_dof; // owned (except in NURBS FE space)
|
||||
mutable Table *bdr_elem_fos; // bdr face orientations by bdr element index
|
||||
mutable Table *face_dof; // owned; in var-order space contains variant 0 DOFs
|
||||
|
||||
Array<int> dof_elem_array, dof_ldof_array;
|
||||
@@ -137,6 +140,9 @@ protected:
|
||||
int own_ext;
|
||||
mutable Array<int> face_to_be; // NURBS FE space only
|
||||
|
||||
Array<DofTransformation*> DoFTrans;
|
||||
mutable VDofTransformation VDoFTrans;
|
||||
|
||||
/** Matrix representing the prolongation from the global conforming dofs to
|
||||
a set of intermediate partially conforming dofs, e.g. the dofs associated
|
||||
with a "cut" space on a non-conforming mesh. */
|
||||
@@ -189,6 +195,9 @@ protected:
|
||||
void Construct();
|
||||
void Destroy();
|
||||
|
||||
void ConstructDoFTrans();
|
||||
void DestroyDoFTrans();
|
||||
|
||||
void BuildElementToDofTable() const;
|
||||
void BuildBdrElementToDofTable() const;
|
||||
void BuildFaceToDofTable() const;
|
||||
@@ -283,12 +292,19 @@ protected:
|
||||
const FiniteElementSpace* fespace;
|
||||
DenseTensor localP[Geometry::NumGeom];
|
||||
Table* old_elem_dof; // Owned.
|
||||
Table* old_elem_fos; // Owned.
|
||||
|
||||
Array<DofTransformation*> old_DoFTrans;
|
||||
mutable VDofTransformation old_VDoFTrans;
|
||||
|
||||
void ConstructDoFTrans();
|
||||
|
||||
public:
|
||||
/** Construct the operator based on the elem_dof table of the original
|
||||
(coarse) space. The class takes ownership of the table. */
|
||||
RefinementOperator(const FiniteElementSpace* fespace,
|
||||
Table *old_elem_dof/*takes ownership*/, int old_ndofs);
|
||||
Table *old_elem_dof/*takes ownership*/,
|
||||
Table *old_elem_fos/*takes ownership*/, int old_ndofs);
|
||||
RefinementOperator(const FiniteElementSpace *fespace,
|
||||
const FiniteElementSpace *coarse_fes);
|
||||
virtual void Mult(const Vector &x, Vector &y) const;
|
||||
@@ -302,6 +318,7 @@ protected:
|
||||
const FiniteElementSpace *fine_fes; // Not owned.
|
||||
DenseTensor localR[Geometry::NumGeom];
|
||||
Table *coarse_elem_dof; // Owned.
|
||||
// Table *coarse_elem_fos; // Owned.
|
||||
Table coarse_to_fine;
|
||||
Array<int> coarse_to_ref_type;
|
||||
Array<Geometry::Type> ref_type_to_geom;
|
||||
@@ -323,6 +340,7 @@ protected:
|
||||
the same vector dimension, vdim. */
|
||||
SparseMatrix *RefinementMatrix_main(const int coarse_ndofs,
|
||||
const Table &coarse_elem_dof,
|
||||
const Table *coarse_elem_fos,
|
||||
const DenseTensor localP[]) const;
|
||||
|
||||
void GetLocalRefinementMatrices(Geometry::Type geom,
|
||||
@@ -333,10 +351,12 @@ protected:
|
||||
/** Calculate explicit GridFunction interpolation matrix (after mesh
|
||||
refinement). NOTE: consider using the RefinementOperator class instead
|
||||
of the fully assembled matrix, which can take a lot of memory. */
|
||||
SparseMatrix* RefinementMatrix(int old_ndofs, const Table* old_elem_dof);
|
||||
SparseMatrix* RefinementMatrix(int old_ndofs, const Table* old_elem_dof,
|
||||
const Table* old_elem_fos);
|
||||
|
||||
/// Calculate GridFunction restriction matrix after mesh derefinement.
|
||||
SparseMatrix* DerefinementMatrix(int old_ndofs, const Table* old_elem_dof);
|
||||
SparseMatrix* DerefinementMatrix(int old_ndofs, const Table* old_elem_dof,
|
||||
const Table* old_elem_fos);
|
||||
|
||||
/** @brief Return in @a localP the local refinement matrices that map
|
||||
between fespaces after mesh refinement. */
|
||||
@@ -614,10 +634,11 @@ public:
|
||||
int GetBdrAttribute(int i) const { return mesh->GetBdrAttribute(i); }
|
||||
|
||||
/// Returns indices of degrees of freedom of element 'elem'.
|
||||
virtual void GetElementDofs(int elem, Array<int> &dofs) const;
|
||||
virtual DofTransformation *GetElementDofs(int elem, Array<int> &dofs) const;
|
||||
|
||||
/// Returns indices of degrees of freedom for boundary element 'bel'.
|
||||
virtual void GetBdrElementDofs(int bel, Array<int> &dofs) const;
|
||||
virtual DofTransformation *GetBdrElementDofs(int bel,
|
||||
Array<int> &dofs) const;
|
||||
|
||||
/** @brief Returns the indices of the degrees of freedom for the specified
|
||||
face, including the DOFs for the edges and the vertices of the face. */
|
||||
@@ -666,10 +687,10 @@ public:
|
||||
static void AdjustVDofs(Array<int> &vdofs);
|
||||
|
||||
/// Returns indexes of degrees of freedom in array dofs for i'th element.
|
||||
void GetElementVDofs(int i, Array<int> &vdofs) const;
|
||||
DofTransformation *GetElementVDofs(int i, Array<int> &vdofs) const;
|
||||
|
||||
/// Returns indexes of degrees of freedom for i'th boundary element.
|
||||
void GetBdrElementVDofs(int i, Array<int> &vdofs) const;
|
||||
DofTransformation *GetBdrElementVDofs(int i, Array<int> &vdofs) const;
|
||||
|
||||
/// Returns indexes of degrees of freedom for i'th face element (2D and 3D).
|
||||
void GetFaceVDofs(int i, Array<int> &vdofs) const;
|
||||
@@ -695,6 +716,8 @@ public:
|
||||
is preserved. */
|
||||
void ReorderElementToDofTable();
|
||||
|
||||
const Table *GetElementToFaceOrientationTable() const { return elem_fos; }
|
||||
|
||||
/** @brief Return a reference to the internal Table that stores the lists of
|
||||
scalar dofs, for each mesh element, as returned by GetElementDofs(). */
|
||||
const Table &GetElementToDofTable() const { return *elem_dof; }
|
||||
|
||||
+262
-7
@@ -11,15 +11,19 @@
|
||||
|
||||
#include "fem.hpp"
|
||||
#include "../mesh/wedge.hpp"
|
||||
#include "../mesh/pyramid.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
const char *Geometry::Name[NumGeom] =
|
||||
{ "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube", "Prism" };
|
||||
{
|
||||
"Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube", "Prism",
|
||||
"Pyramid"
|
||||
};
|
||||
|
||||
const double Geometry::Volume[NumGeom] =
|
||||
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5 };
|
||||
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5, 1./3 };
|
||||
|
||||
Geometry::Geometry()
|
||||
{
|
||||
@@ -139,6 +143,28 @@ Geometry::Geometry()
|
||||
GeomVert[6]->IntPoint(5).y = 1.0;
|
||||
GeomVert[6]->IntPoint(5).z = 1.0;
|
||||
|
||||
// Vertices for Geometry::PYRAMID
|
||||
GeomVert[7] = new IntegrationRule(5);
|
||||
GeomVert[7]->IntPoint(0).x = 0.0;
|
||||
GeomVert[7]->IntPoint(0).y = 0.0;
|
||||
GeomVert[7]->IntPoint(0).z = 0.0;
|
||||
|
||||
GeomVert[7]->IntPoint(1).x = 1.0;
|
||||
GeomVert[7]->IntPoint(1).y = 0.0;
|
||||
GeomVert[7]->IntPoint(1).z = 0.0;
|
||||
|
||||
GeomVert[7]->IntPoint(2).x = 1.0;
|
||||
GeomVert[7]->IntPoint(2).y = 1.0;
|
||||
GeomVert[7]->IntPoint(2).z = 0.0;
|
||||
|
||||
GeomVert[7]->IntPoint(3).x = 0.0;
|
||||
GeomVert[7]->IntPoint(3).y = 1.0;
|
||||
GeomVert[7]->IntPoint(3).z = 0.0;
|
||||
|
||||
GeomVert[7]->IntPoint(4).x = 0.0;
|
||||
GeomVert[7]->IntPoint(4).y = 0.0;
|
||||
GeomVert[7]->IntPoint(4).z = 1.0;
|
||||
|
||||
GeomCenter[POINT].x = 0.0;
|
||||
GeomCenter[POINT].y = 0.0;
|
||||
GeomCenter[POINT].z = 0.0;
|
||||
@@ -167,6 +193,10 @@ Geometry::Geometry()
|
||||
GeomCenter[PRISM].y = 1.0 / 3.0;
|
||||
GeomCenter[PRISM].z = 0.5;
|
||||
|
||||
GeomCenter[PYRAMID].x = 0.375;
|
||||
GeomCenter[PYRAMID].y = 0.375;
|
||||
GeomCenter[PYRAMID].z = 0.25;
|
||||
|
||||
GeomToPerfGeomJac[POINT] = NULL;
|
||||
GeomToPerfGeomJac[SEGMENT] = new DenseMatrix(1);
|
||||
GeomToPerfGeomJac[TRIANGLE] = new DenseMatrix(2);
|
||||
@@ -174,6 +204,7 @@ Geometry::Geometry()
|
||||
GeomToPerfGeomJac[TETRAHEDRON] = new DenseMatrix(3);
|
||||
GeomToPerfGeomJac[CUBE] = new DenseMatrix(3);
|
||||
GeomToPerfGeomJac[PRISM] = new DenseMatrix(3);
|
||||
GeomToPerfGeomJac[PYRAMID] = new DenseMatrix(3);
|
||||
|
||||
PerfGeomToGeomJac[POINT] = NULL;
|
||||
PerfGeomToGeomJac[SEGMENT] = NULL;
|
||||
@@ -182,6 +213,7 @@ Geometry::Geometry()
|
||||
PerfGeomToGeomJac[TETRAHEDRON] = new DenseMatrix(3);
|
||||
PerfGeomToGeomJac[CUBE] = NULL;
|
||||
PerfGeomToGeomJac[PRISM] = new DenseMatrix(3);
|
||||
PerfGeomToGeomJac[PYRAMID] = new DenseMatrix(3);
|
||||
|
||||
GeomToPerfGeomJac[SEGMENT]->Diag(1.0, 1);
|
||||
{
|
||||
@@ -210,6 +242,14 @@ Geometry::Geometry()
|
||||
*GeomToPerfGeomJac[PRISM] = pri_T.Jacobian();
|
||||
CalcInverse(pri_T.Jacobian(), *PerfGeomToGeomJac[PRISM]);
|
||||
}
|
||||
{
|
||||
IsoparametricTransformation pyr_T;
|
||||
pyr_T.SetFE(&PyramidFE);
|
||||
GetPerfPointMat (PYRAMID, pyr_T.GetPointMat());
|
||||
pyr_T.SetIntPoint(&GeomCenter[PYRAMID]);
|
||||
*GeomToPerfGeomJac[PYRAMID] = pyr_T.Jacobian();
|
||||
CalcInverse(pyr_T.Jacobian(), *PerfGeomToGeomJac[PYRAMID]);
|
||||
}
|
||||
}
|
||||
|
||||
Geometry::~Geometry()
|
||||
@@ -233,6 +273,7 @@ const IntegrationRule * Geometry::GetVertices(int GeomType)
|
||||
case Geometry::TETRAHEDRON: return GeomVert[4];
|
||||
case Geometry::CUBE: return GeomVert[5];
|
||||
case Geometry::PRISM: return GeomVert[6];
|
||||
case Geometry::PYRAMID: return GeomVert[7];
|
||||
default:
|
||||
mfem_error ("Geometry::GetVertices(...)");
|
||||
}
|
||||
@@ -310,6 +351,25 @@ void Geometry::GetRandomPoint(int GeomType, IntegrationPoint &ip)
|
||||
ip.y = 1.0 - ip.y;
|
||||
}
|
||||
break;
|
||||
case Geometry::PYRAMID:
|
||||
ip.x = double(rand()) / RAND_MAX;
|
||||
ip.y = double(rand()) / RAND_MAX;
|
||||
ip.z = double(rand()) / RAND_MAX;
|
||||
if (ip.x + ip.z > 1.0 && ip.y < ip.x)
|
||||
{
|
||||
double x = ip.x;
|
||||
ip.x = ip.y;
|
||||
ip.y = 1.0 - ip.z;
|
||||
ip.z = 1.0 - x;
|
||||
}
|
||||
else if (ip.y + ip.z > 1.0)
|
||||
{
|
||||
double z = ip.z;
|
||||
ip.z = 1.0 - ip.y;
|
||||
ip.y = ip.x;
|
||||
ip.x = 1.0 - z;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -371,6 +431,10 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip)
|
||||
if (ip.x < 0.0 || ip.y < 0.0 || ip.x+ip.y > 1.0 ||
|
||||
ip.z < 0.0 || ip.z > 1.0) { return false; }
|
||||
break;
|
||||
case Geometry::PYRAMID:
|
||||
if (ip.x < 0.0 || ip.y < 0.0 || ip.x+ip.z > 1.0 || ip.y+ip.z > 1.0 ||
|
||||
ip.z < 0.0 || ip.z > 1.0) { return false; }
|
||||
break;
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -441,6 +505,17 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip, double eps)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Geometry::PYRAMID:
|
||||
if (internal::FuzzyLT(ip.x, 0.0, eps)
|
||||
|| internal::FuzzyLT(ip.y, 0.0, eps)
|
||||
|| internal::FuzzyGT(ip.x+ip.z, 1.0, eps)
|
||||
|| internal::FuzzyGT(ip.y+ip.z, 1.0, eps)
|
||||
|| internal::FuzzyLT(ip.z, 0.0, eps)
|
||||
|| internal::FuzzyGT(ip.z, 1.0, eps) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -555,6 +630,16 @@ bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
|
||||
double lbeg[5] = { beg.x, beg.y, beg.z, 1.0-beg.x-beg.y, 1.0-beg.z };
|
||||
return internal::IntersectSegment<5,3>(lbeg, lend, end);
|
||||
}
|
||||
case Geometry::PYRAMID:
|
||||
{
|
||||
double lend[6] = { end.x, end.y, end.z,
|
||||
1.0-end.x-end.z, 1.0-end.y-end.z, 1.0-end.z
|
||||
};
|
||||
double lbeg[6] = { beg.x, beg.y, beg.z,
|
||||
1.0-beg.x-beg.z, 1.0-beg.y-beg.z, 1.0-beg.z
|
||||
};
|
||||
return internal::IntersectSegment<6,3>(lbeg, lend, end);
|
||||
}
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -652,6 +737,43 @@ bool Geometry::ProjectPoint(int GeomType, IntegrationPoint &ip)
|
||||
return in_tri && in_z;
|
||||
}
|
||||
|
||||
case PYRAMID:
|
||||
{
|
||||
if (ip.x < 0.0)
|
||||
{
|
||||
ip.x = 0.0;
|
||||
internal::ProjectTriangle(ip.y, ip.z);
|
||||
return false;
|
||||
}
|
||||
if (ip.y < 0.0)
|
||||
{
|
||||
ip.y = 0.0;
|
||||
internal::ProjectTriangle(ip.x, ip.z);
|
||||
return false;
|
||||
}
|
||||
if (ip.z < 0.0)
|
||||
{
|
||||
ip.z = 0.0;
|
||||
if (ip.x > 1.0) { ip.x = 1.0; }
|
||||
if (ip.y > 1.0) { ip.y = 1.0; }
|
||||
return false;
|
||||
}
|
||||
if (ip.x >= ip.y)
|
||||
{
|
||||
bool in_y = true;
|
||||
bool in_tri = internal::ProjectTriangle(ip.x, ip.z);
|
||||
if (ip.y > ip.z) { in_y = false; ip.y = ip.z; }
|
||||
return in_tri && in_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool in_x = true;
|
||||
bool in_tri = internal::ProjectTriangle(ip.y, ip.z);
|
||||
if (ip.x > ip.z) { in_x = false; ip.x = ip.z; }
|
||||
return in_tri && in_x;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
MFEM_ABORT("Reference element type is not supported!");
|
||||
}
|
||||
@@ -726,6 +848,17 @@ void Geometry::GetPerfPointMat(int GeomType, DenseMatrix &pm)
|
||||
}
|
||||
break;
|
||||
|
||||
case Geometry::PYRAMID:
|
||||
{
|
||||
pm.SetSize (3, 5);
|
||||
pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
|
||||
pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
|
||||
pm(0,2) = 1.0; pm(1,2) = 1.0; pm(2,2) = 0.0;
|
||||
pm(0,3) = 0.0; pm(1,3) = 1.0; pm(2,3) = 0.0;
|
||||
pm(0,4) = 0.5; pm(1,4) = 0.5; pm(2,4) = 0.7071067811865475;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
mfem_error ("Geometry::GetPerfPointMat (...)");
|
||||
}
|
||||
@@ -744,13 +877,13 @@ void Geometry::JacToPerfJac(int GeomType, const DenseMatrix &J,
|
||||
}
|
||||
}
|
||||
|
||||
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5 };
|
||||
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3, 3 };
|
||||
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5, 5 };
|
||||
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3, 3, 3 };
|
||||
const int Geometry::DimStart[MaxDim+2] =
|
||||
{ POINT, SEGMENT, TRIANGLE, TETRAHEDRON, NUM_GEOMETRIES };
|
||||
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8, 6 };
|
||||
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12, 9 };
|
||||
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6, 5 };
|
||||
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8, 6, 5 };
|
||||
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12, 9, 8 };
|
||||
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6, 5, 5 };
|
||||
|
||||
const int Geometry::
|
||||
Constants<Geometry::POINT>::Orient[1][1] = {{0}};
|
||||
@@ -897,6 +1030,30 @@ Constants<Geometry::PRISM>::VertToVert::J[9][2] =
|
||||
{5, 4} // 4,5:4
|
||||
};
|
||||
|
||||
const int Geometry::
|
||||
Constants<Geometry::PYRAMID>::Edges[8][2] =
|
||||
{{0, 1}, {1, 2}, {3, 2}, {0, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PYRAMID>::FaceTypes[5] =
|
||||
{
|
||||
Geometry::SQUARE,
|
||||
Geometry::TRIANGLE, Geometry::TRIANGLE,
|
||||
Geometry::TRIANGLE, Geometry::TRIANGLE
|
||||
};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PYRAMID>::FaceVert[5][4] =
|
||||
{{3, 2, 1, 0}, {0, 1, 4, -1}, {1, 2, 4, -1}, {2, 3, 4, -1}, {3, 0, 4, -1}};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PYRAMID>::VertToVert::I[5] = {0, 3, 5, 7, 8};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PYRAMID>::VertToVert::J[8][2] =
|
||||
{
|
||||
{1, 0}, {3, 3}, {4, 4}, // 0,1:0 0,3:3 0,4:4
|
||||
{2, 1}, {4, 5}, // 1,2:1 1,4:5
|
||||
{3,-3}, {4, 6}, // 2,3:-3 2,4:6
|
||||
{4, 7} // 3,4:7
|
||||
};
|
||||
|
||||
|
||||
GeometryRefiner::GeometryRefiner()
|
||||
{
|
||||
@@ -1262,6 +1419,104 @@ RefinedGeometry * GeometryRefiner::Refine(Geometry::Type Geom,
|
||||
return RG;
|
||||
}
|
||||
|
||||
case Geometry::PYRAMID:
|
||||
{
|
||||
const int n = Times;
|
||||
RG = new RefinedGeometry ((n+1)*(n+2)*(2*n+3)/6,
|
||||
5*n*(2*n-1)*(2*n+1)/3, 0);
|
||||
RG->Times = Times;
|
||||
RG->ETimes = ETimes;
|
||||
RG->Type = type;
|
||||
// enumerate and define the vertices
|
||||
m = 0;
|
||||
for (k = 0; k <= n; k++)
|
||||
{
|
||||
const double *cpij =
|
||||
poly1d.GetPoints(Times - k, BasisType::GetNodalBasis(type));
|
||||
for (j = 0; j <= n - k; j++)
|
||||
for (i = 0; i <= n - k; i++)
|
||||
{
|
||||
IntegrationPoint &ip = RG->RefPts.IntPoint(m);
|
||||
if (type == 0)
|
||||
{
|
||||
ip.x = (n > k) ? (double(i) / (n - k)) : 0.0;
|
||||
ip.y = (n > k) ? (double(j) / (n - k)) : 0.0;
|
||||
ip.z = double(k) / n;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip.x = cpij[i] * (1.0 - cp[k]);
|
||||
ip.y = cpij[j] * (1.0 - cp[k]);
|
||||
ip.z = cp[k];
|
||||
}
|
||||
m++;
|
||||
}
|
||||
}
|
||||
if (m != (n+1)*(n+2)*(2*n+3)/6)
|
||||
{
|
||||
mfem_error("GeometryRefiner::Refine() for PYRAMID #1");
|
||||
}
|
||||
// elements
|
||||
Array<int> &G = RG->RefGeoms;
|
||||
m = 0;
|
||||
for (k = 0; k < n; k++)
|
||||
{
|
||||
int lk = k * (k * (2 * k - 6 * n - 9) + 6 * n * (n + 3) + 13) / 6;
|
||||
int lkp1 = (k + 1) *
|
||||
(k * (2 * k - 6 * n -5) + 6 * n * (n + 2) + 6) / 6;
|
||||
for (j = 0; j < n - k; j++)
|
||||
{
|
||||
for (i = 0; i < n - k; i++)
|
||||
{
|
||||
G[m++] = lk + j * (n - k + 1) + i;
|
||||
G[m++] = lk + j * (n - k + 1) + i + 1;
|
||||
G[m++] = lk + (j + 1) * (n - k + 1) + i + 1;
|
||||
G[m++] = lk + (j + 1) * (n - k + 1) + i;
|
||||
G[m++] = lkp1 + j * (n - k) + i;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < n - k - 1; j++)
|
||||
{
|
||||
for (i = 0; i < n - k - 1; i++)
|
||||
{
|
||||
G[m++] = lkp1 + j * (n - k) + i;
|
||||
G[m++] = lkp1 + (j + 1) * (n - k) + i;
|
||||
G[m++] = lkp1 + (j + 1) * (n - k) + i + 1;
|
||||
G[m++] = lkp1 + j * (n - k) + i + 1;
|
||||
G[m++] = lk + (j + 1) * (n - k + 1) + i + 1;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < n - k; j++)
|
||||
{
|
||||
for (i = 0; i < n - k - 1; i++)
|
||||
{
|
||||
G[m++] = lk + j * (n - k + 1) + i + 1;
|
||||
G[m++] = lk + (j + 1) * (n - k + 1) + i + 1;
|
||||
G[m++] = lkp1 + j * (n - k) + i;
|
||||
G[m++] = lkp1 + j * (n - k) + i + 1;
|
||||
G[m++] = -1;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < n - k - 1; j++)
|
||||
{
|
||||
for (i = 0; i < n - k; i++)
|
||||
{
|
||||
G[m++] = lk + (j + 1) * (n - k + 1) + i;
|
||||
G[m++] = lk + (j + 1) * (n - k + 1) + i + 1;
|
||||
G[m++] = lkp1 + (j + 1) * (n - k) + i;
|
||||
G[m++] = lkp1 + j * (n - k) + i;
|
||||
G[m++] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m != 5*n*(2*n-1)*(2*n+1)/3)
|
||||
{
|
||||
mfem_error("GeometryRefiner::Refine() for PYRAMID #2");
|
||||
}
|
||||
RGeom[Geometry::PYRAMID].Append(RG);
|
||||
return RG;
|
||||
}
|
||||
|
||||
case Geometry::PRISM:
|
||||
{
|
||||
const int n = Times;
|
||||
|
||||
+22
-2
@@ -27,6 +27,7 @@ namespace mfem
|
||||
Geometry::TETRAHEDRON - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1)
|
||||
Geometry::CUBE - the unit cube
|
||||
Geometry::PRISM - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1),(1,0,1),(0,1,1)
|
||||
Geometry::PYRAMID - w/ vert. (0,0,0),(1,0,0),(1,1,0),(0,1,0),(0,0,1)
|
||||
*/
|
||||
class Geometry
|
||||
{
|
||||
@@ -34,7 +35,7 @@ public:
|
||||
enum Type
|
||||
{
|
||||
INVALID = -1,
|
||||
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM,
|
||||
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM, PYRAMID,
|
||||
NUM_GEOMETRIES
|
||||
};
|
||||
|
||||
@@ -251,7 +252,26 @@ template <> struct Geometry::Constants<Geometry::PRISM>
|
||||
};
|
||||
};
|
||||
|
||||
// Defined in fe.cpp to ensure construction after 'mfem::WedgeFE'.
|
||||
template <> struct Geometry::Constants<Geometry::PYRAMID>
|
||||
{
|
||||
static const int Dimension = 3;
|
||||
static const int NumVert = 5;
|
||||
static const int NumEdges = 8;
|
||||
static const int Edges[NumEdges][2];
|
||||
static const int NumFaces = 5;
|
||||
static const int FaceTypes[NumFaces];
|
||||
static const int MaxFaceVert = 4;
|
||||
static const int FaceVert[NumFaces][MaxFaceVert];
|
||||
// Upper-triangular part of the local vertex-to-vertex graph.
|
||||
struct VertToVert
|
||||
{
|
||||
static const int I[NumVert];
|
||||
static const int J[NumEdges][2]; // {end,edge_idx}
|
||||
};
|
||||
};
|
||||
|
||||
// Defined in fe.cpp to ensure construction after 'mfem::TriangleFE' and
|
||||
// `mfem::TetrahedronFE`.
|
||||
extern Geometry Geometries;
|
||||
|
||||
|
||||
|
||||
+166
-54
@@ -255,6 +255,8 @@ void GridFunction::SumFluxAndCount(BilinearFormIntegrator &blfi,
|
||||
GridFunction &u = *this;
|
||||
|
||||
ElementTransformation *Transf;
|
||||
DofTransformation *udoftrans;
|
||||
DofTransformation *fdoftrans;
|
||||
|
||||
FiniteElementSpace *ufes = u.FESpace();
|
||||
FiniteElementSpace *ffes = flux.FESpace();
|
||||
@@ -274,15 +276,23 @@ void GridFunction::SumFluxAndCount(BilinearFormIntegrator &blfi,
|
||||
continue;
|
||||
}
|
||||
|
||||
ufes->GetElementVDofs(i, udofs);
|
||||
ffes->GetElementVDofs(i, fdofs);
|
||||
udoftrans = ufes->GetElementVDofs(i, udofs);
|
||||
fdoftrans = ffes->GetElementVDofs(i, fdofs);
|
||||
|
||||
u.GetSubVector(udofs, ul);
|
||||
if (udoftrans)
|
||||
{
|
||||
udoftrans->InvTransformPrimal(ul);
|
||||
}
|
||||
|
||||
Transf = ufes->GetElementTransformation(i);
|
||||
blfi.ComputeElementFlux(*ufes->GetFE(i), *Transf, ul,
|
||||
*ffes->GetFE(i), fl, wcoef);
|
||||
|
||||
if (fdoftrans)
|
||||
{
|
||||
fdoftrans->TransformPrimal(fl);
|
||||
}
|
||||
flux.AddElementVector(fdofs, fl);
|
||||
|
||||
FiniteElementSpace::AdjustVDofs(fdofs);
|
||||
@@ -364,7 +374,7 @@ void GridFunction::GetNodalValues(int i, Array<double> &nval, int vdim) const
|
||||
|
||||
int k;
|
||||
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
const FiniteElement *FElem = fes->GetFE(i);
|
||||
const IntegrationRule *ElemVert =
|
||||
Geometries.GetVertices(FElem->GetGeomType());
|
||||
@@ -374,6 +384,10 @@ void GridFunction::GetNodalValues(int i, Array<double> &nval, int vdim) const
|
||||
vdim--;
|
||||
Vector loc_data;
|
||||
GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
|
||||
if (FElem->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
@@ -403,7 +417,7 @@ double GridFunction::GetValue(int i, const IntegrationPoint &ip, int vdim)
|
||||
const
|
||||
{
|
||||
Array<int> dofs;
|
||||
fes->GetElementDofs(i, dofs);
|
||||
DofTransformation * doftrans = fes->GetElementDofs(i, dofs);
|
||||
fes->DofsToVDofs(vdim-1, dofs);
|
||||
Vector DofVal(dofs.Size()), LocVec;
|
||||
const FiniteElement *fe = fes->GetFE(i);
|
||||
@@ -418,6 +432,10 @@ const
|
||||
fe->CalcPhysShape(*Tr, DofVal);
|
||||
}
|
||||
GetSubVector(dofs, LocVec);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(LocVec);
|
||||
}
|
||||
|
||||
return (DofVal * LocVec);
|
||||
}
|
||||
@@ -428,9 +446,13 @@ void GridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
|
||||
const FiniteElement *FElem = fes->GetFE(i);
|
||||
int dof = FElem->GetDof();
|
||||
Array<int> vdofs;
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
Vector loc_data;
|
||||
GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
if (FElem->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
Vector shape(dof);
|
||||
@@ -470,30 +492,35 @@ const
|
||||
Array<int> dofs;
|
||||
int n = ir.GetNPoints();
|
||||
vals.SetSize(n);
|
||||
fes->GetElementDofs(i, dofs);
|
||||
DofTransformation * doftrans = fes->GetElementDofs(i, dofs);
|
||||
fes->DofsToVDofs(vdim-1, dofs);
|
||||
const FiniteElement *FElem = fes->GetFE(i);
|
||||
int dof = FElem->GetDof();
|
||||
Vector DofVal(dof), loc_data(dof);
|
||||
GetSubVector(dofs, loc_data);
|
||||
if (FElem->GetMapType() == FiniteElement::VALUE)
|
||||
if (doftrans)
|
||||
{
|
||||
for (int k = 0; k < n; k++)
|
||||
{
|
||||
FElem->CalcShape(ir.IntPoint(k), DofVal);
|
||||
vals(k) = DofVal * loc_data;
|
||||
}
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ElementTransformation *Tr = fes->GetElementTransformation(i);
|
||||
for (int k = 0; k < n; k++)
|
||||
for (int k = 0; k < n; k++)
|
||||
if (FElem->GetMapType() == FiniteElement::VALUE)
|
||||
{
|
||||
Tr->SetIntPoint(&ir.IntPoint(k));
|
||||
FElem->CalcPhysShape(*Tr, DofVal);
|
||||
vals(k) = DofVal * loc_data;
|
||||
for (int k = 0; k < n; k++)
|
||||
{
|
||||
FElem->CalcShape(ir.IntPoint(k), DofVal);
|
||||
vals(k) = DofVal * loc_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ElementTransformation *Tr = fes->GetElementTransformation(i);
|
||||
for (int k = 0; k < n; k++)
|
||||
{
|
||||
Tr->SetIntPoint(&ir.IntPoint(k));
|
||||
FElem->CalcPhysShape(*Tr, DofVal);
|
||||
vals(k) = DofVal * loc_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GridFunction::GetValues(int i, const IntegrationRule &ir, Vector &vals,
|
||||
@@ -861,11 +888,12 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
|
||||
Array<int> vdofs;
|
||||
const FiniteElement *fe = NULL;
|
||||
DofTransformation * doftrans = NULL;
|
||||
|
||||
switch (T.ElementType)
|
||||
{
|
||||
case ElementTransformation::ELEMENT:
|
||||
fes->GetElementVDofs(T.ElementNo, vdofs);
|
||||
doftrans = fes->GetElementVDofs(T.ElementNo, vdofs);
|
||||
fe = fes->GetFE(T.ElementNo);
|
||||
break;
|
||||
case ElementTransformation::EDGE:
|
||||
@@ -956,6 +984,10 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
int dof = fe->GetDof();
|
||||
Vector loc_data;
|
||||
GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
if (fe->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
Vector shape(dof);
|
||||
@@ -998,10 +1030,14 @@ void GridFunction::GetVectorValues(ElementTransformation &T,
|
||||
int dof = FElem->GetDof();
|
||||
|
||||
Array<int> vdofs;
|
||||
fes->GetElementVDofs(T.ElementNo, vdofs);
|
||||
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(T.ElementNo, vdofs);
|
||||
Vector loc_data;
|
||||
GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
|
||||
int nip = ir.GetNPoints();
|
||||
|
||||
if (FElem->GetRangeType() == FiniteElement::SCALAR)
|
||||
@@ -1089,6 +1125,8 @@ void GridFunction::GetValuesFrom(const GridFunction &orig_func)
|
||||
// Without averaging ...
|
||||
|
||||
const FiniteElementSpace *orig_fes = orig_func.FESpace();
|
||||
DofTransformation * doftrans;
|
||||
DofTransformation * orig_doftrans;
|
||||
Array<int> vdofs, orig_vdofs;
|
||||
Vector shape, loc_values, orig_loc_values;
|
||||
int i, j, d, ne, dof, odof, vdim;
|
||||
@@ -1097,9 +1135,13 @@ void GridFunction::GetValuesFrom(const GridFunction &orig_func)
|
||||
vdim = fes->GetVDim();
|
||||
for (i = 0; i < ne; i++)
|
||||
{
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
orig_fes->GetElementVDofs(i, orig_vdofs);
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
orig_doftrans = orig_fes->GetElementVDofs(i, orig_vdofs);
|
||||
orig_func.GetSubVector(orig_vdofs, orig_loc_values);
|
||||
if (orig_doftrans)
|
||||
{
|
||||
orig_doftrans->InvTransformPrimal(orig_loc_values);
|
||||
}
|
||||
const FiniteElement *fe = fes->GetFE(i);
|
||||
const FiniteElement *orig_fe = orig_fes->GetFE(i);
|
||||
dof = fe->GetDof();
|
||||
@@ -1117,6 +1159,10 @@ void GridFunction::GetValuesFrom(const GridFunction &orig_func)
|
||||
shape * ((const double *)orig_loc_values + d * odof) ;
|
||||
}
|
||||
}
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformPrimal(loc_values);
|
||||
}
|
||||
SetSubVector(vdofs, loc_values);
|
||||
}
|
||||
}
|
||||
@@ -1126,8 +1172,10 @@ void GridFunction::GetBdrValuesFrom(const GridFunction &orig_func)
|
||||
// Without averaging ...
|
||||
|
||||
const FiniteElementSpace *orig_fes = orig_func.FESpace();
|
||||
// DofTransformation * doftrans;
|
||||
// DofTransformation * orig_doftrans;
|
||||
Array<int> vdofs, orig_vdofs;
|
||||
Vector shape, loc_values, orig_loc_values;
|
||||
Vector shape, loc_values, loc_values_t, orig_loc_values, orig_loc_values_t;
|
||||
int i, j, d, nbe, dof, odof, vdim;
|
||||
|
||||
nbe = fes->GetNBE();
|
||||
@@ -1165,37 +1213,33 @@ void GridFunction::GetVectorFieldValues(
|
||||
Array<int> vdofs;
|
||||
ElementTransformation *transf;
|
||||
|
||||
int d, j, k, n, sdim, dof, ind;
|
||||
int d, k, n, sdim, dof;
|
||||
|
||||
n = ir.GetNPoints();
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
const FiniteElement *fe = fes->GetFE(i);
|
||||
dof = fe->GetDof();
|
||||
sdim = fes->GetMesh()->SpaceDimension();
|
||||
int *dofs = &vdofs[comp*dof];
|
||||
// int *dofs = &vdofs[comp*dof];
|
||||
transf = fes->GetElementTransformation(i);
|
||||
transf->Transform(ir, tr);
|
||||
vals.SetSize(n, sdim);
|
||||
DenseMatrix vshape(dof, sdim);
|
||||
double a;
|
||||
Vector loc_data, val(sdim);
|
||||
GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
for (k = 0; k < n; k++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(k);
|
||||
transf->SetIntPoint(&ip);
|
||||
fe->CalcVShape(*transf, vshape);
|
||||
vshape.MultTranspose(loc_data, val);
|
||||
for (d = 0; d < sdim; d++)
|
||||
{
|
||||
a = 0.0;
|
||||
for (j = 0; j < dof; j++)
|
||||
if ( (ind=dofs[j]) >= 0 )
|
||||
{
|
||||
a += vshape(j, d) * data[ind];
|
||||
}
|
||||
else
|
||||
{
|
||||
a -= vshape(j, d) * data[-1-ind];
|
||||
}
|
||||
vals(k, d) = a;
|
||||
vals(k,d) = val(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1365,9 +1409,13 @@ void GridFunction::GetVectorGradientHat(
|
||||
const FiniteElement *FElem = fes->GetFE(elNo);
|
||||
int dim = FElem->GetDim(), dof = FElem->GetDof();
|
||||
Array<int> vdofs;
|
||||
fes->GetElementVDofs(elNo, vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(elNo, vdofs);
|
||||
Vector loc_data;
|
||||
GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
// assuming scalar FE
|
||||
int vdim = fes->GetVDim();
|
||||
DenseMatrix dshape(dof, dim);
|
||||
@@ -1406,9 +1454,13 @@ double GridFunction::GetDivergence(ElementTransformation &T) const
|
||||
{
|
||||
// Assuming RT-type space
|
||||
Array<int> dofs;
|
||||
fes->GetElementDofs(elNo, dofs);
|
||||
DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
|
||||
Vector loc_data, divshape(fe->GetDof());
|
||||
GetSubVector(dofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
fe->CalcDivShape(T.GetIntPoint(), divshape);
|
||||
return (loc_data * divshape) / T.Weight();
|
||||
}
|
||||
@@ -1499,9 +1551,13 @@ void GridFunction::GetCurl(ElementTransformation &T, Vector &curl) const
|
||||
{
|
||||
// Assuming ND-type space
|
||||
Array<int> dofs;
|
||||
fes->GetElementDofs(elNo, dofs);
|
||||
DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
|
||||
Vector loc_data;
|
||||
GetSubVector(dofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
DenseMatrix curl_shape(fe->GetDof(), fe->GetDim() == 3 ? 3 : 1);
|
||||
fe->CalcCurlShape(T.GetIntPoint(), curl_shape);
|
||||
curl.SetSize(curl_shape.Width());
|
||||
@@ -1643,8 +1699,12 @@ void GridFunction::GetGradients(ElementTransformation &tr,
|
||||
DenseMatrix dshape(fe->GetDof(), fe->GetDim());
|
||||
Vector lval, gh(fe->GetDim()), gcol;
|
||||
Array<int> dofs;
|
||||
fes->GetElementDofs(elNo, dofs);
|
||||
DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
|
||||
GetSubVector(dofs, lval);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(lval);
|
||||
}
|
||||
grad.SetSize(fe->GetDim(), ir.GetNPoints());
|
||||
for (int i = 0; i < ir.GetNPoints(); i++)
|
||||
{
|
||||
@@ -1724,6 +1784,8 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
|
||||
{
|
||||
MassIntegrator Mi;
|
||||
DenseMatrix loc_mass;
|
||||
DofTransformation * te_doftrans;
|
||||
DofTransformation * tr_doftrans;
|
||||
Array<int> te_dofs, tr_dofs;
|
||||
Vector loc_avgs, loc_this;
|
||||
Vector int_psi(avgs.Size());
|
||||
@@ -1734,11 +1796,19 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
|
||||
{
|
||||
Mi.AssembleElementMatrix2(*fes->GetFE(i), *avgs.FESpace()->GetFE(i),
|
||||
*fes->GetElementTransformation(i), loc_mass);
|
||||
fes->GetElementDofs(i, tr_dofs);
|
||||
avgs.FESpace()->GetElementDofs(i, te_dofs);
|
||||
tr_doftrans = fes->GetElementDofs(i, tr_dofs);
|
||||
te_doftrans = avgs.FESpace()->GetElementDofs(i, te_dofs);
|
||||
GetSubVector(tr_dofs, loc_this);
|
||||
if (tr_doftrans)
|
||||
{
|
||||
tr_doftrans->InvTransformPrimal(loc_this);
|
||||
}
|
||||
loc_avgs.SetSize(te_dofs.Size());
|
||||
loc_mass.Mult(loc_this, loc_avgs);
|
||||
if (te_doftrans)
|
||||
{
|
||||
te_doftrans->TransformPrimal(loc_avgs);
|
||||
}
|
||||
avgs.AddElementVector(te_dofs, loc_avgs);
|
||||
loc_this = 1.0; // assume the local basis for 'this' sums to 1
|
||||
loc_mass.Mult(loc_this, loc_avgs);
|
||||
@@ -1753,8 +1823,12 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
|
||||
void GridFunction::GetElementDofValues(int el, Vector &dof_vals) const
|
||||
{
|
||||
Array<int> dof_idx;
|
||||
fes->GetElementVDofs(el, dof_idx);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(el, dof_idx);
|
||||
GetSubVector(dof_idx, dof_vals);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(dof_vals);
|
||||
}
|
||||
}
|
||||
|
||||
void GridFunction::ProjectGridFunction(const GridFunction &src)
|
||||
@@ -1790,13 +1864,21 @@ void GridFunction::ProjectGridFunction(const GridFunction &src)
|
||||
cached_geom = geom;
|
||||
}
|
||||
|
||||
src.fes->GetElementVDofs(i, src_vdofs);
|
||||
DofTransformation * src_doftrans = src.fes->GetElementVDofs(i, src_vdofs);
|
||||
src.GetSubVector(src_vdofs, src_lvec);
|
||||
if (src_doftrans)
|
||||
{
|
||||
src_doftrans->InvTransformPrimal(src_lvec);
|
||||
}
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
{
|
||||
P.Mult(&src_lvec[vd*P.Width()], &dest_lvec[vd*P.Height()]);
|
||||
}
|
||||
fes->GetElementVDofs(i, dest_vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(i, dest_vdofs);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformPrimal(dest_lvec);
|
||||
}
|
||||
SetSubVector(dest_vdofs, dest_lvec);
|
||||
}
|
||||
}
|
||||
@@ -1805,10 +1887,15 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
|
||||
const Vector &lo_, const Vector &hi_)
|
||||
{
|
||||
Array<int> vdofs;
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
int size = vdofs.Size();
|
||||
Vector vals, new_vals(size);
|
||||
|
||||
GetSubVector(vdofs, vals);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(vals);
|
||||
}
|
||||
|
||||
MFEM_ASSERT(weights.Size() == size, "Different # of weights and dofs.");
|
||||
MFEM_ASSERT(lo_.Size() == size, "Different # of lower bounds and dofs.");
|
||||
@@ -1825,6 +1912,10 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
|
||||
slbqp.SetPrintLevel(0); // print messages only if not converged
|
||||
slbqp.Mult(vals, new_vals);
|
||||
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformPrimal(new_vals);
|
||||
}
|
||||
SetSubVector(vdofs, new_vals);
|
||||
}
|
||||
|
||||
@@ -1832,10 +1923,14 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
|
||||
double min_, double max_)
|
||||
{
|
||||
Array<int> vdofs;
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
int size = vdofs.Size();
|
||||
Vector vals, new_vals(size);
|
||||
GetSubVector(vdofs, vals);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(vals);
|
||||
}
|
||||
|
||||
double max_val = vals.Max();
|
||||
double min_val = vals.Min();
|
||||
@@ -1843,6 +1938,10 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
|
||||
if (max_val <= min_)
|
||||
{
|
||||
new_vals = min_;
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformPrimal(new_vals);
|
||||
}
|
||||
SetSubVector(vdofs, new_vals);
|
||||
return;
|
||||
}
|
||||
@@ -2278,6 +2377,7 @@ void GridFunction::ProjectDeltaCoefficient(DeltaCoefficient &delta_coeff,
|
||||
void GridFunction::ProjectCoefficient(Coefficient &coeff)
|
||||
{
|
||||
DeltaCoefficient *delta_c = dynamic_cast<DeltaCoefficient *>(&coeff);
|
||||
DofTransformation * doftrans = NULL;
|
||||
|
||||
if (delta_c == NULL)
|
||||
{
|
||||
@@ -2286,9 +2386,13 @@ void GridFunction::ProjectCoefficient(Coefficient &coeff)
|
||||
|
||||
for (int i = 0; i < fes->GetNE(); i++)
|
||||
{
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
vals.SetSize(vdofs.Size());
|
||||
fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformPrimal(vals);
|
||||
}
|
||||
SetSubVector(vdofs, vals);
|
||||
}
|
||||
}
|
||||
@@ -2334,11 +2438,17 @@ void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff)
|
||||
Array<int> vdofs;
|
||||
Vector vals;
|
||||
|
||||
DofTransformation * doftrans = NULL;
|
||||
|
||||
for (i = 0; i < fes->GetNE(); i++)
|
||||
{
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
vals.SetSize(vdofs.Size());
|
||||
fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformPrimal(vals);
|
||||
}
|
||||
SetSubVector(vdofs, vals);
|
||||
}
|
||||
}
|
||||
@@ -2401,6 +2511,7 @@ void GridFunction::ProjectCoefficient(Coefficient *coeff[])
|
||||
double val;
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *transf;
|
||||
// DofTransformation * doftrans;
|
||||
Array<int> vdofs;
|
||||
|
||||
vdim = fes->GetVDim();
|
||||
@@ -2410,6 +2521,7 @@ void GridFunction::ProjectCoefficient(Coefficient *coeff[])
|
||||
fdof = fe->GetDof();
|
||||
transf = fes->GetElementTransformation(i);
|
||||
const IntegrationRule &ir = fe->GetNodes();
|
||||
// doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
fes->GetElementVDofs(i, vdofs);
|
||||
for (j = 0; j < fdof; j++)
|
||||
{
|
||||
|
||||
@@ -910,6 +910,9 @@ IntegrationRules::IntegrationRules(int Ref, int type_):
|
||||
TetrahedronIntRules.SetSize(32, h_mt);
|
||||
TetrahedronIntRules = NULL;
|
||||
|
||||
PyramidIntRules.SetSize(32, h_mt);
|
||||
PyramidIntRules = NULL;
|
||||
|
||||
PrismIntRules.SetSize(32, h_mt);
|
||||
PrismIntRules = NULL;
|
||||
|
||||
@@ -930,6 +933,7 @@ const IntegrationRule &IntegrationRules::Get(int GeomType, int Order)
|
||||
case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
|
||||
case Geometry::CUBE: ir_array = &CubeIntRules; break;
|
||||
case Geometry::PRISM: ir_array = &PrismIntRules; break;
|
||||
case Geometry::PYRAMID: ir_array = &PyramidIntRules; break;
|
||||
default:
|
||||
mfem_error("IntegrationRules::Get(...) : Unknown geometry type!");
|
||||
ir_array = NULL;
|
||||
@@ -976,6 +980,7 @@ void IntegrationRules::Set(int GeomType, int Order, IntegrationRule &IntRule)
|
||||
case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
|
||||
case Geometry::CUBE: ir_array = &CubeIntRules; break;
|
||||
case Geometry::PRISM: ir_array = &PrismIntRules; break;
|
||||
case Geometry::PYRAMID: ir_array = &PyramidIntRules; break;
|
||||
default:
|
||||
mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
|
||||
ir_array = NULL;
|
||||
@@ -1019,6 +1024,7 @@ IntegrationRules::~IntegrationRules()
|
||||
DeleteIntRuleArray(TetrahedronIntRules);
|
||||
DeleteIntRuleArray(CubeIntRules);
|
||||
DeleteIntRuleArray(PrismIntRules);
|
||||
DeleteIntRuleArray(PyramidIntRules);
|
||||
}
|
||||
|
||||
|
||||
@@ -1041,6 +1047,8 @@ IntegrationRule *IntegrationRules::GenerateIntegrationRule(int GeomType,
|
||||
return CubeIntegrationRule(Order);
|
||||
case Geometry::PRISM:
|
||||
return PrismIntegrationRule(Order);
|
||||
case Geometry::PYRAMID:
|
||||
return PyramidIntegrationRule(Order);
|
||||
default:
|
||||
mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
|
||||
return NULL;
|
||||
@@ -1648,6 +1656,30 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
}
|
||||
}
|
||||
|
||||
// Integration rules for reference pyramid
|
||||
IntegrationRule *IntegrationRules::PyramidIntegrationRule(int Order)
|
||||
{
|
||||
// This is a simple integration rule adapted from an integration
|
||||
// rule for a cube which seems to be adequate for now. When we
|
||||
// implement high order finite elements for pyramids we should
|
||||
// revisit this and see if we can improve upon it.
|
||||
const IntegrationRule &irc = Get(Geometry::CUBE, Order);
|
||||
int npts = irc.GetNPoints();
|
||||
AllocIntRule(PyramidIntRules, Order);
|
||||
PyramidIntRules[Order] = new IntegrationRule(npts);
|
||||
|
||||
for (int k=0; k<npts; k++)
|
||||
{
|
||||
const IntegrationPoint & ipc = irc.IntPoint(k);
|
||||
IntegrationPoint & ipp = PyramidIntRules[Order]->IntPoint(k);
|
||||
ipp.x = ipc.x * (1.0 - ipc.z);
|
||||
ipp.y = ipc.y * (1.0 - ipc.z);
|
||||
ipp.z = ipc.z;
|
||||
ipp.weight = ipc.weight / 3.0;
|
||||
}
|
||||
return PyramidIntRules[Order];
|
||||
}
|
||||
|
||||
// Integration rules for reference prism
|
||||
IntegrationRule *IntegrationRules::PrismIntegrationRule(int Order)
|
||||
{
|
||||
|
||||
@@ -323,6 +323,7 @@ private:
|
||||
Array<IntegrationRule *> TriangleIntRules;
|
||||
Array<IntegrationRule *> SquareIntRules;
|
||||
Array<IntegrationRule *> TetrahedronIntRules;
|
||||
Array<IntegrationRule *> PyramidIntRules;
|
||||
Array<IntegrationRule *> PrismIntRules;
|
||||
Array<IntegrationRule *> CubeIntRules;
|
||||
|
||||
@@ -351,6 +352,7 @@ private:
|
||||
IntegrationRule *TriangleIntegrationRule(int Order);
|
||||
IntegrationRule *SquareIntegrationRule(int Order);
|
||||
IntegrationRule *TetrahedronIntegrationRule(int Order);
|
||||
IntegrationRule *PyramidIntegrationRule(int Order);
|
||||
IntegrationRule *PrismIntegrationRule(int Order);
|
||||
IntegrationRule *CubeIntegrationRule(int Order);
|
||||
|
||||
|
||||
+11
-2
@@ -103,6 +103,7 @@ void LinearForm::Assemble()
|
||||
{
|
||||
Array<int> vdofs;
|
||||
ElementTransformation *eltrans;
|
||||
DofTransformation *doftrans;
|
||||
Vector elemvect;
|
||||
|
||||
int i;
|
||||
@@ -134,10 +135,14 @@ void LinearForm::Assemble()
|
||||
if ( domain_integs_marker[k] == NULL ||
|
||||
(*(domain_integs_marker[k]))[elem_attr-1] == 1 )
|
||||
{
|
||||
fes -> GetElementVDofs (i, vdofs);
|
||||
doftrans = fes -> GetElementVDofs (i, vdofs);
|
||||
eltrans = fes -> GetElementTransformation (i);
|
||||
domain_integs[k]->AssembleRHSElementVect(*fes->GetFE(i),
|
||||
*eltrans, elemvect);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformDual(elemvect);
|
||||
}
|
||||
AddElementVector (vdofs, elemvect);
|
||||
}
|
||||
}
|
||||
@@ -174,7 +179,7 @@ void LinearForm::Assemble()
|
||||
{
|
||||
const int bdr_attr = mesh->GetBdrAttribute(i);
|
||||
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
|
||||
fes -> GetBdrElementVDofs (i, vdofs);
|
||||
doftrans = fes -> GetBdrElementVDofs (i, vdofs);
|
||||
eltrans = fes -> GetBdrElementTransformation (i);
|
||||
for (int k=0; k < boundary_integs.Size(); k++)
|
||||
{
|
||||
@@ -184,6 +189,10 @@ void LinearForm::Assemble()
|
||||
boundary_integs[k]->AssembleRHSElementVect(*fes->GetBE(i),
|
||||
*eltrans, elemvect);
|
||||
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformDual(elemvect);
|
||||
}
|
||||
AddElementVector (vdofs, elemvect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,15 +116,15 @@ void VectorConvectionNLFIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
|
||||
// PA Convection NL 2D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAConvectionNLApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &q_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAConvectionNLApply2D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &q_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -252,15 +252,15 @@ static void PAConvectionNLApply2D(const int NE,
|
||||
|
||||
// PA Convection NL 3D kernel
|
||||
template<int T_D1D = 0, int T_Q1D = 0>
|
||||
static void PAConvectionNLApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &q_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void PAConvectionNLApply3D(const int NE,
|
||||
const Array<double> &b,
|
||||
const Array<double> &g,
|
||||
const Array<double> &bt,
|
||||
const Vector &q_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
@@ -558,14 +558,14 @@ static void PAConvectionNLApply3D(const int NE,
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int T_MAX_D1D =0, int T_MAX_Q1D =0>
|
||||
static void SmemPAConvectionNLApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void SmemPAConvectionNLApply3D(const int NE,
|
||||
const Array<double> &b_,
|
||||
const Array<double> &g_,
|
||||
const Vector &d_,
|
||||
const Vector &x_,
|
||||
Vector &y_,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
|
||||
@@ -321,6 +321,7 @@ const
|
||||
{
|
||||
X.SetSpace(pfes);
|
||||
Y.SetSpace(pfes);
|
||||
Ytmp.SetSize(pfes->GetTrueVSize());
|
||||
}
|
||||
|
||||
X.Distribute(&x);
|
||||
@@ -335,7 +336,8 @@ const
|
||||
" implemented");
|
||||
mat->Mult(X, Y);
|
||||
}
|
||||
pfes->Dof_TrueDof_Matrix()->MultTranspose(a, Y, 1.0, y);
|
||||
pfes->GetProlongationMatrix()->MultTranspose(Y, Ytmp);
|
||||
y.Add(a,Ytmp);
|
||||
}
|
||||
|
||||
void ParBilinearForm::FormLinearSystem(
|
||||
|
||||
@@ -33,6 +33,7 @@ protected:
|
||||
|
||||
/// Auxiliary objects used in TrueAddMult().
|
||||
mutable ParGridFunction X, Y;
|
||||
mutable Vector Ytmp;
|
||||
|
||||
OperatorHandle p_mat, p_mat_e;
|
||||
|
||||
|
||||
+319
-53
@@ -128,6 +128,9 @@ void ParFiniteElementSpace::ParInit(ParMesh *pm)
|
||||
{
|
||||
ApplyLDofSigns(*elem_dof);
|
||||
}
|
||||
|
||||
// Check for shared trianglular faces with interior Nedelec DoFs
|
||||
CheckNDSTriaDofs();
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::Construct()
|
||||
@@ -464,32 +467,53 @@ void ParFiniteElementSpace::ApplyLDofSigns(Table &el_dof) const
|
||||
ApplyLDofSigns(all_dofs);
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetElementDofs(int i, Array<int> &dofs) const
|
||||
DofTransformation *
|
||||
ParFiniteElementSpace::GetElementDofs(int i, Array<int> &dofs) const
|
||||
{
|
||||
if (elem_dof)
|
||||
{
|
||||
elem_dof->GetRow(i, dofs);
|
||||
return;
|
||||
|
||||
if (DoFTrans[mesh->GetElementBaseGeometry(i)])
|
||||
{
|
||||
Array<int> Fo;
|
||||
elem_fos->GetRow(i, Fo);
|
||||
DoFTrans[mesh->GetElementBaseGeometry(i)]->SetFaceOrientations(Fo);
|
||||
return DoFTrans[mesh->GetElementBaseGeometry(i)];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
FiniteElementSpace::GetElementDofs(i, dofs);
|
||||
DofTransformation * doftrans = FiniteElementSpace::GetElementDofs(i, dofs);
|
||||
if (Conforming())
|
||||
{
|
||||
ApplyLDofSigns(dofs);
|
||||
}
|
||||
return doftrans;
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
|
||||
DofTransformation *
|
||||
ParFiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
|
||||
{
|
||||
if (bdr_elem_dof)
|
||||
{
|
||||
bdr_elem_dof->GetRow(i, dofs);
|
||||
return;
|
||||
|
||||
if (DoFTrans[mesh->GetBdrElementBaseGeometry(i)])
|
||||
{
|
||||
Array<int> Fo;
|
||||
bdr_elem_fos -> GetRow (i, Fo);
|
||||
DoFTrans[mesh->GetBdrElementBaseGeometry(i)]->SetFaceOrientations(Fo);
|
||||
return DoFTrans[mesh->GetBdrElementBaseGeometry(i)];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
FiniteElementSpace::GetBdrElementDofs(i, dofs);
|
||||
DofTransformation * doftrans =
|
||||
FiniteElementSpace::GetBdrElementDofs(i, dofs);
|
||||
if (Conforming())
|
||||
{
|
||||
ApplyLDofSigns(dofs);
|
||||
}
|
||||
return doftrans;
|
||||
}
|
||||
|
||||
int ParFiniteElementSpace::GetFaceDofs(int i, Array<int> &dofs,
|
||||
@@ -657,59 +681,266 @@ void ParFiniteElementSpace::GenerateGlobalOffsets() const
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::CheckNDSTriaDofs()
|
||||
{
|
||||
// Check for Nedelec basis
|
||||
bool nd_basis = dynamic_cast<const ND_FECollection*>(fec);
|
||||
if (!nd_basis)
|
||||
{
|
||||
nd_strias = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for interior face dofs on triangles (the use of TETRAHEDRON
|
||||
// is not an error)
|
||||
bool nd_fdof = fec->HasFaceDofs(Geometry::TETRAHEDRON,
|
||||
GetMaxElementOrder());
|
||||
if (!nd_fdof)
|
||||
{
|
||||
nd_strias = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for shared triangle faces
|
||||
bool strias = false;
|
||||
{
|
||||
int ngrps = pmesh->GetNGroups();
|
||||
for (int g = 1; g < ngrps; g++)
|
||||
{
|
||||
strias |= pmesh->GroupNTriangles(g);
|
||||
}
|
||||
}
|
||||
|
||||
// Combine results
|
||||
int loc_nd_strias = strias ? 1 : 0;
|
||||
int glb_nd_strias = 0;
|
||||
MPI_Allreduce(&loc_nd_strias, &glb_nd_strias, 1,
|
||||
MPI_INTEGER, MPI_SUM, MyComm);
|
||||
nd_strias = glb_nd_strias > 0;
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::Build_Dof_TrueDof_Matrix() const // matrix P
|
||||
{
|
||||
MFEM_ASSERT(Conforming(), "wrong code path");
|
||||
|
||||
if (P) { return; }
|
||||
|
||||
int ldof = GetVSize();
|
||||
int ltdof = TrueVSize();
|
||||
|
||||
HYPRE_Int *i_diag = Memory<HYPRE_Int>(ldof+1);
|
||||
HYPRE_Int *j_diag = Memory<HYPRE_Int>(ltdof);
|
||||
int diag_counter;
|
||||
|
||||
HYPRE_Int *i_offd = Memory<HYPRE_Int>(ldof+1);
|
||||
HYPRE_Int *j_offd = Memory<HYPRE_Int>(ldof-ltdof);
|
||||
int offd_counter;
|
||||
|
||||
HYPRE_BigInt *cmap = Memory<HYPRE_BigInt>(ldof-ltdof);
|
||||
|
||||
HYPRE_BigInt *col_starts = GetTrueDofOffsets();
|
||||
HYPRE_BigInt *row_starts = GetDofOffsets();
|
||||
|
||||
Array<Pair<HYPRE_BigInt, int> > cmap_j_offd(ldof-ltdof);
|
||||
|
||||
i_diag[0] = i_offd[0] = 0;
|
||||
diag_counter = offd_counter = 0;
|
||||
for (int i = 0; i < ldof; i++)
|
||||
if (!nd_strias)
|
||||
{
|
||||
int ltdof = GetLocalTDofNumber(i);
|
||||
if (ltdof >= 0)
|
||||
// Safe to assume 1-1 correspondence between shared dofs
|
||||
int ldof = GetVSize();
|
||||
int ltdof = TrueVSize();
|
||||
|
||||
HYPRE_Int *i_diag = Memory<HYPRE_Int>(ldof+1);
|
||||
HYPRE_Int *j_diag = Memory<HYPRE_Int>(ltdof);
|
||||
int diag_counter;
|
||||
|
||||
HYPRE_Int *i_offd = Memory<HYPRE_Int>(ldof+1);
|
||||
HYPRE_Int *j_offd = Memory<HYPRE_Int>(ldof-ltdof);
|
||||
int offd_counter;
|
||||
|
||||
HYPRE_BigInt *cmap = Memory<HYPRE_BigInt>(ldof-ltdof);
|
||||
|
||||
HYPRE_BigInt *col_starts = GetTrueDofOffsets();
|
||||
HYPRE_BigInt *row_starts = GetDofOffsets();
|
||||
|
||||
Array<Pair<HYPRE_BigInt, int> > cmap_j_offd(ldof-ltdof);
|
||||
|
||||
i_diag[0] = i_offd[0] = 0;
|
||||
diag_counter = offd_counter = 0;
|
||||
for (int i = 0; i < ldof; i++)
|
||||
{
|
||||
j_diag[diag_counter++] = ltdof;
|
||||
int ltdof = GetLocalTDofNumber(i);
|
||||
if (ltdof >= 0)
|
||||
{
|
||||
j_diag[diag_counter++] = ltdof;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmap_j_offd[offd_counter].one = GetGlobalTDofNumber(i);
|
||||
cmap_j_offd[offd_counter].two = offd_counter;
|
||||
offd_counter++;
|
||||
}
|
||||
i_diag[i+1] = diag_counter;
|
||||
i_offd[i+1] = offd_counter;
|
||||
}
|
||||
else
|
||||
|
||||
SortPairs<HYPRE_BigInt, int>(cmap_j_offd, offd_counter);
|
||||
|
||||
for (int i = 0; i < offd_counter; i++)
|
||||
{
|
||||
cmap_j_offd[offd_counter].one = GetGlobalTDofNumber(i);
|
||||
cmap_j_offd[offd_counter].two = offd_counter;
|
||||
offd_counter++;
|
||||
cmap[i] = cmap_j_offd[i].one;
|
||||
j_offd[cmap_j_offd[i].two] = i;
|
||||
}
|
||||
i_diag[i+1] = diag_counter;
|
||||
i_offd[i+1] = offd_counter;
|
||||
|
||||
P = new HypreParMatrix(MyComm, MyRank, NRanks, row_starts, col_starts,
|
||||
i_diag, j_diag, i_offd, j_offd,
|
||||
cmap, offd_counter);
|
||||
}
|
||||
|
||||
SortPairs<HYPRE_BigInt, int>(cmap_j_offd, offd_counter);
|
||||
|
||||
for (int i = 0; i < offd_counter; i++)
|
||||
else
|
||||
{
|
||||
cmap[i] = cmap_j_offd[i].one;
|
||||
j_offd[cmap_j_offd[i].two] = i;
|
||||
}
|
||||
// Some shared dofs will be linear combinations of others
|
||||
int ldof = GetVSize();
|
||||
int ltdof = TrueVSize();
|
||||
|
||||
P = new HypreParMatrix(MyComm, MyRank, NRanks, row_starts, col_starts,
|
||||
i_diag, j_diag, i_offd, j_offd, cmap, offd_counter);
|
||||
HYPRE_Int gdof = -1;
|
||||
HYPRE_Int gtdof = -1;
|
||||
|
||||
MPI_Allreduce(&ldof, &gdof, 1, HYPRE_MPI_INT, MPI_SUM, MyComm);
|
||||
MPI_Allreduce(<dof, >dof, 1, HYPRE_MPI_INT, MPI_SUM, MyComm);
|
||||
|
||||
// Ensure face orientations have been communicated
|
||||
pmesh->ExchangeFaceNbrData();
|
||||
|
||||
// Locate and count non-zeros in off-diagonal portion of P
|
||||
int nnz_offd = 0;
|
||||
Array<int> ldsize(ldof); ldsize = 0;
|
||||
Array<int> ltori(ldof); ltori = 0; // Local triangle orientations
|
||||
{
|
||||
int ngrps = pmesh->GetNGroups();
|
||||
int nedofs = fec->DofForGeometry(Geometry::SEGMENT);
|
||||
Array<int> sdofs;
|
||||
for (int g = 1; g < ngrps; g++)
|
||||
{
|
||||
if (pmesh->gtopo.IAmMaster(g))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int ei=0; ei<pmesh->GroupNEdges(g); ei++)
|
||||
{
|
||||
this->GetSharedEdgeDofs(g, ei, sdofs);
|
||||
for (int i=0; i<sdofs.Size(); i++)
|
||||
{
|
||||
int ind = (sdofs[i]>=0) ? sdofs[i] : (-sdofs[i]-1);
|
||||
if (ldsize[ind] == 0) { nnz_offd++; }
|
||||
ldsize[ind] = 1;
|
||||
}
|
||||
}
|
||||
for (int fi=0; fi<pmesh->GroupNTriangles(g); fi++)
|
||||
{
|
||||
int face, ori, info1, info2;
|
||||
pmesh->GroupTriangle(g, fi, face, ori);
|
||||
pmesh->GetFaceInfos(face, &info1, &info2);
|
||||
this->GetSharedTriangleDofs(g, fi, sdofs);
|
||||
for (int i=0; i<3*nedofs; i++)
|
||||
{
|
||||
int ind = (sdofs[i]>=0) ? sdofs[i] : (-sdofs[i]-1);
|
||||
if (ldsize[ind] == 0) { nnz_offd++; }
|
||||
ldsize[ind] = 1;
|
||||
}
|
||||
for (int i=3*nedofs; i<sdofs.Size(); i++)
|
||||
{
|
||||
if (ldsize[sdofs[i]] == 0) { nnz_offd += 2; }
|
||||
ldsize[sdofs[i]] = 2;
|
||||
ltori[sdofs[i]] = info2 % 64;
|
||||
}
|
||||
}
|
||||
for (int fi=0; fi<pmesh->GroupNQuadrilaterals(g); fi++)
|
||||
{
|
||||
this->GetSharedQuadrilateralDofs(g, fi, sdofs);
|
||||
for (int i=0; i<sdofs.Size(); i++)
|
||||
{
|
||||
int ind = (sdofs[i]>=0) ? sdofs[i] : (-sdofs[i]-1);
|
||||
if (ldsize[ind] == 0) { nnz_offd++; }
|
||||
ldsize[ind] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HYPRE_Int *i_diag = new HYPRE_Int[ldof+1];
|
||||
HYPRE_Int *j_diag = new HYPRE_Int[ltdof];
|
||||
double *d_diag = new double[ltdof];
|
||||
int diag_counter;
|
||||
|
||||
HYPRE_Int *i_offd = new HYPRE_Int[ldof+1];
|
||||
HYPRE_Int *j_offd = new HYPRE_Int[nnz_offd];
|
||||
double *d_offd = new double[nnz_offd];
|
||||
int offd_counter;
|
||||
|
||||
HYPRE_BigInt *cmap = new HYPRE_BigInt[ldof-ltdof];
|
||||
|
||||
HYPRE_BigInt *col_starts = GetTrueDofOffsets();
|
||||
HYPRE_BigInt *row_starts = GetDofOffsets();
|
||||
|
||||
Array<Pair<HYPRE_BigInt, int> > cmap_j_offd(ldof-ltdof);
|
||||
|
||||
i_diag[0] = i_offd[0] = 0;
|
||||
diag_counter = offd_counter = 0;
|
||||
int offd_col_counter = 0;
|
||||
for (int i = 0; i < ldof; i++)
|
||||
{
|
||||
int ltdof = GetLocalTDofNumber(i);
|
||||
if (ltdof >= 0)
|
||||
{
|
||||
j_diag[diag_counter] = ltdof;
|
||||
d_diag[diag_counter++] = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ldsize[i] == 1)
|
||||
{
|
||||
cmap_j_offd[offd_col_counter].one = GetGlobalTDofNumber(i);
|
||||
cmap_j_offd[offd_col_counter].two = offd_counter;
|
||||
offd_counter++;
|
||||
offd_col_counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmap_j_offd[offd_col_counter].one = GetGlobalTDofNumber(i);
|
||||
cmap_j_offd[offd_col_counter].two = offd_counter;
|
||||
offd_counter += 2;
|
||||
offd_col_counter++;
|
||||
i_diag[i+1] = diag_counter;
|
||||
i_offd[i+1] = offd_counter;
|
||||
i++;
|
||||
cmap_j_offd[offd_col_counter].one = GetGlobalTDofNumber(i);
|
||||
cmap_j_offd[offd_col_counter].two = offd_counter;
|
||||
offd_counter += 2;
|
||||
offd_col_counter++;
|
||||
}
|
||||
}
|
||||
i_diag[i+1] = diag_counter;
|
||||
i_offd[i+1] = offd_counter;
|
||||
}
|
||||
|
||||
SortPairs<HYPRE_BigInt, int>(cmap_j_offd, offd_col_counter);
|
||||
|
||||
for (int i = 0; i < nnz_offd; i++)
|
||||
{
|
||||
j_offd[i] = -1;
|
||||
d_offd[i] = 0.0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < offd_col_counter; i++)
|
||||
{
|
||||
cmap[i] = cmap_j_offd[i].one;
|
||||
j_offd[cmap_j_offd[i].two] = i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ldof; i++)
|
||||
{
|
||||
if (i_offd[i+1] == i_offd[i] + 1)
|
||||
{
|
||||
d_offd[i_offd[i]] = 1.0;
|
||||
}
|
||||
else if (i_offd[i+1] == i_offd[i] + 2)
|
||||
{
|
||||
const double * T = ND_DofTransformation
|
||||
::GetFaceTransform(ltori[i]).GetData();
|
||||
j_offd[i_offd[i] + 1] = j_offd[i_offd[i]] + 1;
|
||||
d_offd[i_offd[i]] = T[0]; d_offd[i_offd[i] + 1] = T[2];
|
||||
i++;
|
||||
j_offd[i_offd[i] + 1] = j_offd[i_offd[i]];
|
||||
j_offd[i_offd[i]] = j_offd[i_offd[i] + 1] - 1;
|
||||
d_offd[i_offd[i]] = T[1]; d_offd[i_offd[i] + 1] = T[3];
|
||||
}
|
||||
}
|
||||
|
||||
P = new HypreParMatrix(MyComm, gdof, gtdof, row_starts, col_starts,
|
||||
i_diag, j_diag, d_diag, i_offd, j_offd, d_offd,
|
||||
offd_col_counter, cmap);
|
||||
}
|
||||
|
||||
SparseMatrix Pdiag;
|
||||
P->GetDiag(Pdiag);
|
||||
@@ -913,6 +1144,8 @@ const Operator *ParFiniteElementSpace::GetProlongationMatrix() const
|
||||
{
|
||||
if (Pconf) { return Pconf; }
|
||||
|
||||
if (nd_strias) { return Dof_TrueDof_Matrix(); }
|
||||
|
||||
if (NRanks == 1)
|
||||
{
|
||||
Pconf = new IdentityOperator(GetTrueVSize());
|
||||
@@ -1216,10 +1449,29 @@ void ParFiniteElementSpace::ExchangeFaceNbrData()
|
||||
delete [] requests;
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetFaceNbrElementVDofs(
|
||||
DofTransformation *ParFiniteElementSpace::GetFaceNbrElementVDofs(
|
||||
int i, Array<int> &vdofs) const
|
||||
{
|
||||
face_nbr_element_dof.GetRow(i, vdofs);
|
||||
|
||||
DofTransformation *doftrans = NULL;
|
||||
Geometry::Type geom = GetFaceNbrFE(i)->GetGeomType();
|
||||
if (DoFTrans[geom])
|
||||
{
|
||||
Array<int> F, Fo;
|
||||
pmesh->GetFaceNbrElementFaces(pmesh->GetNE() + i, F, Fo);
|
||||
doftrans = DoFTrans[geom];
|
||||
doftrans->SetFaceOrientations(Fo);
|
||||
}
|
||||
if (vdim == 1 || doftrans == NULL)
|
||||
{
|
||||
return doftrans;
|
||||
}
|
||||
else
|
||||
{
|
||||
VDoFTrans.SetDofTransformation(*doftrans);
|
||||
return &VDoFTrans;
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetFaceNbrFaceVDofs(int i, Array<int> &vdofs) const
|
||||
@@ -1278,12 +1530,17 @@ const FiniteElement *ParFiniteElementSpace::GetFaceNbrFaceFE(int i) const
|
||||
|
||||
void ParFiniteElementSpace::Lose_Dof_TrueDof_Matrix()
|
||||
{
|
||||
P -> StealData();
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrix *csrP = (hypre_ParCSRMatrix*)(*P);
|
||||
hypre_ParCSRMatrixOwnsRowStarts(csrP) = 1;
|
||||
hypre_ParCSRMatrixOwnsColStarts(csrP) = 1;
|
||||
P -> StealData();
|
||||
dof_offsets.LoseData();
|
||||
tdof_offsets.LoseData();
|
||||
#else
|
||||
dof_offsets.DeleteAll();
|
||||
tdof_offsets.DeleteAll();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::ConstructTrueDofs()
|
||||
@@ -2526,7 +2783,8 @@ static int_type* make_j_array(int_type* I, int nrows)
|
||||
|
||||
HypreParMatrix*
|
||||
ParFiniteElementSpace::RebalanceMatrix(int old_ndofs,
|
||||
const Table* old_elem_dof)
|
||||
const Table* old_elem_dof,
|
||||
const Table* old_elem_fos)
|
||||
{
|
||||
MFEM_VERIFY(Nonconforming(), "Only supported for nonconforming meshes.");
|
||||
MFEM_VERIFY(old_dof_offsets.Size(), "ParFiniteElementSpace::Update needs to "
|
||||
@@ -2651,7 +2909,8 @@ struct DerefDofMessage
|
||||
|
||||
HypreParMatrix*
|
||||
ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
|
||||
const Table* old_elem_dof)
|
||||
const Table* old_elem_dof,
|
||||
const Table *old_elem_fos)
|
||||
{
|
||||
int nrk = HYPRE_AssumedPartitionCheck() ? 2 : NRanks;
|
||||
|
||||
@@ -3007,13 +3266,16 @@ void ParFiniteElementSpace::Update(bool want_transform)
|
||||
}
|
||||
|
||||
Table* old_elem_dof = NULL;
|
||||
Table* old_elem_fos = NULL;
|
||||
int old_ndofs;
|
||||
|
||||
// save old DOF table
|
||||
if (want_transform)
|
||||
{
|
||||
old_elem_dof = elem_dof;
|
||||
old_elem_fos = elem_fos;
|
||||
elem_dof = NULL;
|
||||
elem_fos = NULL;
|
||||
old_ndofs = ndofs;
|
||||
Swap(dof_offsets, old_dof_offsets);
|
||||
}
|
||||
@@ -3035,22 +3297,25 @@ void ParFiniteElementSpace::Update(bool want_transform)
|
||||
{
|
||||
if (Th.Type() != Operator::MFEM_SPARSEMAT)
|
||||
{
|
||||
Th.Reset(new RefinementOperator(this, old_elem_dof, old_ndofs));
|
||||
Th.Reset(new RefinementOperator(this, old_elem_dof,
|
||||
old_elem_fos, old_ndofs));
|
||||
// The RefinementOperator takes ownership of 'old_elem_dofs', so
|
||||
// we no longer own it:
|
||||
old_elem_dof = NULL;
|
||||
old_elem_fos = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate fully assembled matrix
|
||||
Th.Reset(RefinementMatrix(old_ndofs, old_elem_dof));
|
||||
Th.Reset(RefinementMatrix(old_ndofs, old_elem_dof, old_elem_fos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Mesh::DEREFINE:
|
||||
{
|
||||
Th.Reset(ParallelDerefinementMatrix(old_ndofs, old_elem_dof));
|
||||
Th.Reset(ParallelDerefinementMatrix(old_ndofs, old_elem_dof,
|
||||
old_elem_fos));
|
||||
if (Nonconforming())
|
||||
{
|
||||
Th.SetOperatorOwner(false);
|
||||
@@ -3062,7 +3327,7 @@ void ParFiniteElementSpace::Update(bool want_transform)
|
||||
|
||||
case Mesh::REBALANCE:
|
||||
{
|
||||
Th.Reset(RebalanceMatrix(old_ndofs, old_elem_dof));
|
||||
Th.Reset(RebalanceMatrix(old_ndofs, old_elem_dof, old_elem_fos));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3071,6 +3336,7 @@ void ParFiniteElementSpace::Update(bool want_transform)
|
||||
}
|
||||
|
||||
delete old_elem_dof;
|
||||
delete old_elem_fos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-5
@@ -87,6 +87,12 @@ private:
|
||||
this is a TransposeOperator wrapping R. */
|
||||
mutable Operator *R_transpose;
|
||||
|
||||
/// Flag indicating the existence of shared triangles with interior ND dofs
|
||||
bool nd_strias;
|
||||
|
||||
/// Resets nd_strias flag at constuction or after rebalancing
|
||||
void CheckNDSTriaDofs();
|
||||
|
||||
ParNURBSExtension *pNURBSext() const
|
||||
{ return dynamic_cast<ParNURBSExtension *>(NURBSext); }
|
||||
|
||||
@@ -174,14 +180,16 @@ private:
|
||||
The result is a parallel permutation matrix that can be used to update
|
||||
all grid functions defined on this space. */
|
||||
HypreParMatrix* RebalanceMatrix(int old_ndofs,
|
||||
const Table* old_elem_dof);
|
||||
const Table* old_elem_dof,
|
||||
const Table* old_elem_fos);
|
||||
|
||||
/** Calculate a GridFunction restriction matrix after mesh derefinement.
|
||||
The matrix is constructed so that the new grid function interpolates
|
||||
the original function, i.e., the original function is evaluated at the
|
||||
nodes of the coarse function. */
|
||||
HypreParMatrix* ParallelDerefinementMatrix(int old_ndofs,
|
||||
const Table *old_elem_dof);
|
||||
const Table *old_elem_dof,
|
||||
const Table *old_elem_fos);
|
||||
|
||||
/// Updates the internal mesh pointer. @warning @a new_mesh must be
|
||||
/// <b>topologically identical</b> to the existing mesh. Used if the address
|
||||
@@ -202,6 +210,8 @@ public:
|
||||
int num_face_nbr_dofs;
|
||||
// Face-neighbor-element to face-neighbor dof
|
||||
Table face_nbr_element_dof;
|
||||
// Face-neighbor-element face orientations
|
||||
Table face_nbr_element_fos;
|
||||
// Face-neighbor to ldof in the face-neighbor numbering
|
||||
Table face_nbr_ldof;
|
||||
// The global ldof indices of the face-neighbor dofs
|
||||
@@ -279,10 +289,10 @@ public:
|
||||
virtual int GetTrueVSize() const { return ltdof_size; }
|
||||
|
||||
/// Returns indexes of degrees of freedom in array dofs for i'th element.
|
||||
virtual void GetElementDofs(int i, Array<int> &dofs) const;
|
||||
virtual DofTransformation *GetElementDofs(int i, Array<int> &dofs) const;
|
||||
|
||||
/// Returns indexes of degrees of freedom for i'th boundary element.
|
||||
virtual void GetBdrElementDofs(int i, Array<int> &dofs) const;
|
||||
virtual DofTransformation *GetBdrElementDofs(int i, Array<int> &dofs) const;
|
||||
|
||||
/** Returns the indexes of the degrees of freedom for i'th face
|
||||
including the dofs for the edges and the vertices of the face. */
|
||||
@@ -382,7 +392,7 @@ public:
|
||||
// Face-neighbor functions
|
||||
void ExchangeFaceNbrData();
|
||||
int GetFaceNbrVSize() const { return num_face_nbr_dofs; }
|
||||
void GetFaceNbrElementVDofs(int i, Array<int> &vdofs) const;
|
||||
DofTransformation *GetFaceNbrElementVDofs(int i, Array<int> &vdofs) const;
|
||||
void GetFaceNbrFaceVDofs(int i, Array<int> &vdofs) const;
|
||||
const FiniteElement *GetFaceNbrFE(int i) const;
|
||||
const FiniteElement *GetFaceNbrFaceFE(int i) const;
|
||||
@@ -397,6 +407,8 @@ public:
|
||||
bool Conforming() const { return pmesh->pncmesh == NULL && !nonconf_P; }
|
||||
bool Nonconforming() const { return pmesh->pncmesh != NULL || nonconf_P; }
|
||||
|
||||
bool SharedNDTriangleDofs() const { return nd_strias; }
|
||||
|
||||
// Transfer parallel true-dof data from coarse_fes, defined on a coarse mesh,
|
||||
// to this FE space, defined on a refined mesh. See full documentation in the
|
||||
// base class, FiniteElementSpace::GetTrueTransferOperator.
|
||||
|
||||
+12
-2
@@ -325,9 +325,14 @@ void ParGridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
|
||||
if (nbr_el_no >= 0)
|
||||
{
|
||||
Array<int> dofs;
|
||||
pfes->GetFaceNbrElementVDofs(nbr_el_no, dofs);
|
||||
DofTransformation * doftrans = pfes->GetFaceNbrElementVDofs(nbr_el_no,
|
||||
dofs);
|
||||
Vector loc_data;
|
||||
face_nbr_data.GetSubVector(dofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
const FiniteElement *FElem = pfes->GetFaceNbrFE(nbr_el_no);
|
||||
int dof = FElem->GetDof();
|
||||
if (FElem->GetRangeType() == FiniteElement::SCALAR)
|
||||
@@ -437,12 +442,17 @@ void ParGridFunction::GetVectorValue(ElementTransformation &T,
|
||||
}
|
||||
|
||||
Array<int> vdofs;
|
||||
pfes->GetFaceNbrElementVDofs(nbr_el_no, vdofs);
|
||||
DofTransformation * doftrans = pfes->GetFaceNbrElementVDofs(nbr_el_no,
|
||||
vdofs);
|
||||
const FiniteElement *fe = pfes->GetFaceNbrFE(nbr_el_no);
|
||||
|
||||
int dof = fe->GetDof();
|
||||
Vector loc_data;
|
||||
face_nbr_data.GetSubVector(vdofs, loc_data);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->InvTransformPrimal(loc_data);
|
||||
}
|
||||
if (fe->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
Vector shape(dof);
|
||||
|
||||
+17
-17
@@ -27,14 +27,14 @@ namespace quadrature_interpolator
|
||||
{
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int MAX_D1D = 0, int MAX_Q1D = 0>
|
||||
static void Det2D(const int NE,
|
||||
const double *b,
|
||||
const double *g,
|
||||
const double *x,
|
||||
double *y,
|
||||
const int vdim = 1,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void Det2D(const int NE,
|
||||
const double *b,
|
||||
const double *g,
|
||||
const double *x,
|
||||
double *y,
|
||||
const int vdim = 1,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
constexpr int DIM = 2;
|
||||
static constexpr int NBZ = 1;
|
||||
@@ -79,15 +79,15 @@ static void Det2D(const int NE,
|
||||
|
||||
template<int T_D1D = 0, int T_Q1D = 0, int MAX_D1D = 0, int MAX_Q1D = 0,
|
||||
bool SMEM = true>
|
||||
static void Det3D(const int NE,
|
||||
const double *b,
|
||||
const double *g,
|
||||
const double *x,
|
||||
double *y,
|
||||
const int vdim = 1,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0,
|
||||
Vector *d_buff = nullptr) // used only with SMEM = false
|
||||
void Det3D(const int NE,
|
||||
const double *b,
|
||||
const double *g,
|
||||
const double *x,
|
||||
double *y,
|
||||
const int vdim = 1,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0,
|
||||
Vector *d_buff = nullptr) // used only with SMEM = false
|
||||
{
|
||||
constexpr int DIM = 3;
|
||||
static constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
+14
-14
@@ -31,13 +31,13 @@ namespace quadrature_interpolator
|
||||
template<QVectorLayout Q_LAYOUT,
|
||||
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
|
||||
int T_NBZ = 1, int MAX_D1D = 0, int MAX_Q1D = 0>
|
||||
static void Values2D(const int NE,
|
||||
const double *b_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void Values2D(const int NE,
|
||||
const double *b_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
static constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
|
||||
@@ -95,13 +95,13 @@ static void Values2D(const int NE,
|
||||
template<QVectorLayout Q_LAYOUT,
|
||||
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
|
||||
int MAX_D1D = 0, int MAX_Q1D = 0>
|
||||
static void Values3D(const int NE,
|
||||
const double *b_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void Values3D(const int NE,
|
||||
const double *b_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
+18
-18
@@ -31,15 +31,15 @@ namespace quadrature_interpolator
|
||||
template<QVectorLayout Q_LAYOUT, bool GRAD_PHYS,
|
||||
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
|
||||
int T_NBZ = 1, int MAX_D1D = 0, int MAX_Q1D = 0>
|
||||
static void Derivatives2D(const int NE,
|
||||
const double *b_,
|
||||
const double *g_,
|
||||
const double *j_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void Derivatives2D(const int NE,
|
||||
const double *b_,
|
||||
const double *g_,
|
||||
const double *j_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -139,15 +139,15 @@ static void Derivatives2D(const int NE,
|
||||
template<QVectorLayout Q_LAYOUT, bool GRAD_PHYS,
|
||||
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
|
||||
int MAX_D1D = 0, int MAX_Q1D = 0>
|
||||
static void Derivatives3D(const int NE,
|
||||
const double *b_,
|
||||
const double *g_,
|
||||
const double *j_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
void Derivatives3D(const int NE,
|
||||
const double *b_,
|
||||
const double *g_,
|
||||
const double *j_,
|
||||
const double *x_,
|
||||
double *y_,
|
||||
const int vdim = 0,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
+20
-20
@@ -61,16 +61,16 @@ namespace quadrature_interpolator
|
||||
// * assumes 'e_vec' is using ElementDofOrdering::NATIVE,
|
||||
// * assumes 'maps.mode == FULL'.
|
||||
template<const int T_VDIM, const int T_ND, const int T_NQ>
|
||||
static void Eval2D(const int NE,
|
||||
const int vdim,
|
||||
const QVectorLayout q_layout,
|
||||
const GeometricFactors *geom,
|
||||
const DofToQuad &maps,
|
||||
const Vector &e_vec,
|
||||
Vector &q_val,
|
||||
Vector &q_der,
|
||||
Vector &q_det,
|
||||
const int eval_flags)
|
||||
void Eval2D(const int NE,
|
||||
const int vdim,
|
||||
const QVectorLayout q_layout,
|
||||
const GeometricFactors *geom,
|
||||
const DofToQuad &maps,
|
||||
const Vector &e_vec,
|
||||
Vector &q_val,
|
||||
Vector &q_der,
|
||||
Vector &q_det,
|
||||
const int eval_flags)
|
||||
{
|
||||
using QI = QuadratureInterpolator;
|
||||
|
||||
@@ -209,16 +209,16 @@ static void Eval2D(const int NE,
|
||||
// * assumes 'e_vec' is using ElementDofOrdering::NATIVE,
|
||||
// * assumes 'maps.mode == FULL'.
|
||||
template<const int T_VDIM, const int T_ND, const int T_NQ>
|
||||
static void Eval3D(const int NE,
|
||||
const int vdim,
|
||||
const QVectorLayout q_layout,
|
||||
const GeometricFactors *geom,
|
||||
const DofToQuad &maps,
|
||||
const Vector &e_vec,
|
||||
Vector &q_val,
|
||||
Vector &q_der,
|
||||
Vector &q_det,
|
||||
const int eval_flags)
|
||||
void Eval3D(const int NE,
|
||||
const int vdim,
|
||||
const QVectorLayout q_layout,
|
||||
const GeometricFactors *geom,
|
||||
const DofToQuad &maps,
|
||||
const Vector &e_vec,
|
||||
Vector &q_val,
|
||||
Vector &q_der,
|
||||
Vector &q_det,
|
||||
const int eval_flags)
|
||||
{
|
||||
using QI = QuadratureInterpolator;
|
||||
|
||||
|
||||
+1
-1
@@ -1306,7 +1306,7 @@ namespace internal
|
||||
// MFEM_FORALL-based copy kernel -- used by protected methods below.
|
||||
// Needed as a workaround for the nvcc restriction that methods with MFEM_FORALL
|
||||
// in them must to be public.
|
||||
static inline void device_copy(double *d_dest, const double *d_src, int size)
|
||||
inline void device_copy(double *d_dest, const double *d_src, int size)
|
||||
{
|
||||
MFEM_FORALL(i, size, d_dest[i] = d_src[i];);
|
||||
}
|
||||
|
||||
+1
-1
@@ -234,7 +234,7 @@ void TMOPRefinerEstimator::SetTriIntRules()
|
||||
|
||||
// Reftype = 0 // original element
|
||||
const int Nvert = 3, NEsplit = 1;
|
||||
Mesh meshsplit(2, Nvert, NEsplit, 0 ,2);
|
||||
Mesh meshsplit(2, Nvert, NEsplit, 0,2);
|
||||
const double tri_v[3][2] =
|
||||
{
|
||||
{0, 0}, {1, 0}, {0, 1}
|
||||
|
||||
+2
-1
@@ -175,7 +175,8 @@ const Operator &InterpolationGridTransfer::ForwardOperator()
|
||||
localP[elem_geoms[i]]);
|
||||
}
|
||||
F.Reset(ran_fes.RefinementMatrix_main(
|
||||
dom_fes.GetNDofs(), dom_fes.GetElementToDofTable(), localP));
|
||||
dom_fes.GetNDofs(), dom_fes.GetElementToDofTable(),
|
||||
dom_fes.GetElementToFaceOrientationTable(), localP));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -21,12 +21,16 @@
|
||||
#define MFEM_PERF_FUNCTION CALI_CXX_MARK_FUNCTION
|
||||
#define MFEM_PERF_BEGIN(s) CALI_MARK_BEGIN(s)
|
||||
#define MFEM_PERF_END(s) CALI_MARK_END(s)
|
||||
#define MFEM_PERF_SCOPE(name) \
|
||||
cali::Annotation::Guard cali_autogenerated_guard_name(cali::Annotation("function").begin(std::string(name).c_str()))
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define MFEM_PERF_FUNCTION
|
||||
#define MFEM_PERF_BEGIN(s)
|
||||
#define MFEM_PERF_END(s)
|
||||
#define MFEM_PERF_SCOPE(name)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -164,7 +164,13 @@ __device__ void abort_msg(T & msg)
|
||||
#endif
|
||||
|
||||
// Abort inside a device kernel
|
||||
#if defined(__CUDA_ARCH__)
|
||||
#if defined(__CUDA_ARCH__) && defined(_WIN32)
|
||||
#define MFEM_ABORT_KERNEL(msg) \
|
||||
{ \
|
||||
printf(msg); \
|
||||
__debugbreak(); \
|
||||
}
|
||||
#elif defined(__CUDA_ARCH__)
|
||||
#define MFEM_ABORT_KERNEL(msg) \
|
||||
{ \
|
||||
printf(msg); \
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define MFEM_FORALL_HPP
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "annotation.hpp"
|
||||
#include "error.hpp"
|
||||
#include "backends.hpp"
|
||||
#include "device.hpp"
|
||||
|
||||
@@ -79,7 +79,13 @@ int isockstream::establish()
|
||||
int on=1;
|
||||
setsockopt(port, SOL_SOCKET, SO_REUSEADDR, (char *)(&on), sizeof(on));
|
||||
|
||||
if (bind(port,(const sockaddr*)&sa,(socklen_t)sizeof(struct sockaddr_in)) < 0)
|
||||
if (bind(
|
||||
#ifdef _WIN32
|
||||
(SOCKET)port
|
||||
#else
|
||||
port
|
||||
#endif
|
||||
,(const sockaddr*)&sa,(socklen_t)sizeof(struct sockaddr_in)) < 0)
|
||||
{
|
||||
mfem::err << "isockstream::establish(): bind() failed!" << endl;
|
||||
close(port);
|
||||
|
||||
@@ -118,6 +118,11 @@ int STable3D::Index (int r, int c, int f) const
|
||||
{
|
||||
STable3DNode *node;
|
||||
|
||||
if (r >= Size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Sort3 (r, c, f);
|
||||
|
||||
for (node = Rows[r]; node != NULL; node = node->Prev)
|
||||
|
||||
+3325
-2996
File diff suppressed because it is too large
Load Diff
@@ -787,10 +787,16 @@ HypreParMatrix * ComplexHypreParMatrix::GetSystemMatrix() const
|
||||
2 * num_cols_offd, cmap,
|
||||
true);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
// Give the new matrix ownership of row_starts and col_starts
|
||||
hypre_ParCSRMatrix *hA = (hypre_ParCSRMatrix*)(*A);
|
||||
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(hA,1);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(hA,1);
|
||||
#else
|
||||
mfem_hypre_TFree_host(row_starts);
|
||||
mfem_hypre_TFree_host(col_starts);
|
||||
#endif
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
@@ -763,6 +763,13 @@ public:
|
||||
tdata.New(i*j*k);
|
||||
}
|
||||
|
||||
DenseTensor(double *d, int i, int j, int k)
|
||||
: Mk(NULL, i, j)
|
||||
{
|
||||
nk = k;
|
||||
tdata.Wrap(d, i*j*k, false);
|
||||
}
|
||||
|
||||
DenseTensor(int i, int j, int k, MemoryType mt)
|
||||
: Mk(NULL, i, j)
|
||||
{
|
||||
|
||||
+63
-1
@@ -88,7 +88,9 @@ HypreParVector::HypreParVector(MPI_Comm comm, HYPRE_BigInt glob_size,
|
||||
{
|
||||
x = hypre_ParVectorCreate(comm,glob_size,col);
|
||||
hypre_ParVectorInitialize(x);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParVectorSetPartitioningOwner(x,0);
|
||||
#endif
|
||||
// The data will be destroyed by hypre (this is the default)
|
||||
hypre_ParVectorSetDataOwner(x,1);
|
||||
hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
|
||||
@@ -105,7 +107,9 @@ HypreParVector::HypreParVector(MPI_Comm comm, HYPRE_BigInt glob_size,
|
||||
hypre_ParVectorSetDataOwner(x,1); // owns the seq vector
|
||||
hypre_Vector *x_loc = hypre_ParVectorLocalVector(x);
|
||||
hypre_SeqVectorSetDataOwner(x_loc,0);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParVectorSetPartitioningOwner(x,0);
|
||||
#endif
|
||||
double tmp = 0.0;
|
||||
hypre_VectorData(x_loc) = &tmp;
|
||||
#ifdef HYPRE_USING_CUDA
|
||||
@@ -128,7 +132,9 @@ HypreParVector::HypreParVector(const HypreParVector &y) : Vector()
|
||||
x = hypre_ParVectorCreate(y.x -> comm, y.x -> global_size,
|
||||
y.x -> partitioning);
|
||||
hypre_ParVectorInitialize(x);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParVectorSetPartitioningOwner(x,0);
|
||||
#endif
|
||||
hypre_ParVectorSetDataOwner(x,1);
|
||||
hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
|
||||
_SetDataAndSize_();
|
||||
@@ -162,7 +168,9 @@ HypreParVector::HypreParVector(ParFiniteElementSpace *pfes)
|
||||
x = hypre_ParVectorCreate(pfes->GetComm(), pfes->GlobalTrueVSize(),
|
||||
pfes->GetTrueDofOffsets());
|
||||
hypre_ParVectorInitialize(x);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParVectorSetPartitioningOwner(x,0);
|
||||
#endif
|
||||
// The data will be destroyed by hypre (this is the default)
|
||||
hypre_ParVectorSetDataOwner(x,1);
|
||||
hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(x),1);
|
||||
@@ -683,8 +691,10 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm, HYPRE_BigInt glob_size,
|
||||
A = hypre_ParCSRMatrixCreate(comm, glob_size, glob_size, row_starts,
|
||||
row_starts, 0, diag->NumNonZeroElems(), 0);
|
||||
hypre_ParCSRMatrixSetDataOwner(A,1);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(A,0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(A,0);
|
||||
#endif
|
||||
|
||||
hypre_CSRMatrixSetDataOwner(A->diag,0);
|
||||
diagOwner = CopyCSR(diag, mem_diag, A->diag, false);
|
||||
@@ -726,8 +736,10 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm,
|
||||
row_starts, col_starts,
|
||||
0, diag->NumNonZeroElems(), 0);
|
||||
hypre_ParCSRMatrixSetDataOwner(A,1);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(A,0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(A,0);
|
||||
#endif
|
||||
|
||||
hypre_CSRMatrixSetDataOwner(A->diag,0);
|
||||
diagOwner = CopyCSR(diag, mem_diag, A->diag, false);
|
||||
@@ -770,8 +782,10 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm,
|
||||
offd->Width(), diag->NumNonZeroElems(),
|
||||
offd->NumNonZeroElems());
|
||||
hypre_ParCSRMatrixSetDataOwner(A,1);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(A,0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(A,0);
|
||||
#endif
|
||||
|
||||
hypre_CSRMatrixSetDataOwner(A->diag,0);
|
||||
diagOwner = CopyCSR(diag, mem_diag, A->diag, own_diag_offd);
|
||||
@@ -817,8 +831,10 @@ HypreParMatrix::HypreParMatrix(
|
||||
A = hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
|
||||
row_starts, col_starts, offd_num_cols, 0, 0);
|
||||
hypre_ParCSRMatrixSetDataOwner(A,1);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(A,0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(A,0);
|
||||
#endif
|
||||
|
||||
HYPRE_Int local_num_rows = hypre_CSRMatrixNumRows(A->diag);
|
||||
|
||||
@@ -931,8 +947,10 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm,
|
||||
A = hypre_ParCSRMatrixCreate(comm, global_num_rows, global_num_cols,
|
||||
row_starts, col_starts, 0, nnz, 0);
|
||||
hypre_ParCSRMatrixSetDataOwner(A,1);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(A,0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(A,0);
|
||||
#endif
|
||||
|
||||
hypre_CSRMatrixSetDataOwner(A->diag,0);
|
||||
diagOwner = CopyBoolCSR(diag, mem_diag, A->diag);
|
||||
@@ -989,8 +1007,10 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm, int id, int np,
|
||||
}
|
||||
|
||||
hypre_ParCSRMatrixSetDataOwner(A,1);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(A,0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(A,0);
|
||||
#endif
|
||||
|
||||
mem_diag.data.New(diag_nnz);
|
||||
for (HYPRE_Int i = 0; i < diag_nnz; i++)
|
||||
@@ -1177,6 +1197,13 @@ HypreParMatrix::HypreParMatrix(MPI_Comm comm, int nrows,
|
||||
{
|
||||
hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
|
||||
}
|
||||
#if MFEM_HYPRE_VERSION > 22200
|
||||
mfem_hypre_TFree_host(row_starts);
|
||||
if (rows != cols)
|
||||
{
|
||||
mfem_hypre_TFree_host(col_starts);
|
||||
}
|
||||
#endif
|
||||
hypre_MatvecCommPkgCreate(A);
|
||||
|
||||
height = GetNumRows();
|
||||
@@ -1263,6 +1290,7 @@ void HypreParMatrix::SetOwnerFlags(signed char diag, signed char offd,
|
||||
|
||||
void HypreParMatrix::CopyRowStarts()
|
||||
{
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
if (!A || hypre_ParCSRMatrixOwnsRowStarts(A) ||
|
||||
(hypre_ParCSRMatrixRowStarts(A) == hypre_ParCSRMatrixColStarts(A) &&
|
||||
hypre_ParCSRMatrixOwnsColStarts(A)))
|
||||
@@ -1297,10 +1325,12 @@ void HypreParMatrix::CopyRowStarts()
|
||||
hypre_ParCSRMatrixColStarts(A) = new_row_starts;
|
||||
hypre_ParCSRMatrixOwnsColStarts(A) = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HypreParMatrix::CopyColStarts()
|
||||
{
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
if (!A || hypre_ParCSRMatrixOwnsColStarts(A) ||
|
||||
(hypre_ParCSRMatrixRowStarts(A) == hypre_ParCSRMatrixColStarts(A) &&
|
||||
hypre_ParCSRMatrixOwnsRowStarts(A)))
|
||||
@@ -1339,6 +1369,7 @@ void HypreParMatrix::CopyColStarts()
|
||||
{
|
||||
hypre_ParCSRMatrixOwnsColStarts(A) = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HypreParMatrix::GetDiag(Vector &diag) const
|
||||
@@ -1791,9 +1822,14 @@ HypreParMatrix* HypreParMatrix::LeftDiagMult(const SparseMatrix &D,
|
||||
DA_diag, DA_offd, new_col_map_offd,
|
||||
own_diag_offd);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
// Give ownership of row_starts, col_starts, and col_map_offd to DA
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(DA->A, 1);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(DA->A, 1);
|
||||
#else
|
||||
mfem_hypre_TFree_host(new_row_starts);
|
||||
mfem_hypre_TFree_host(new_col_starts);
|
||||
#endif
|
||||
DA->colMapOwner = 1;
|
||||
|
||||
return DA;
|
||||
@@ -1948,18 +1984,22 @@ void HypreParMatrix::Threshold(double threshold)
|
||||
row_starts = hypre_ParCSRMatrixRowStarts(A);
|
||||
col_starts = hypre_ParCSRMatrixColStarts(A);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
bool old_owns_row = hypre_ParCSRMatrixOwnsRowStarts(A);
|
||||
bool old_owns_col = hypre_ParCSRMatrixOwnsColStarts(A);
|
||||
#endif
|
||||
HYPRE_BigInt global_num_rows = hypre_ParCSRMatrixGlobalNumRows(A);
|
||||
HYPRE_BigInt global_num_cols = hypre_ParCSRMatrixGlobalNumCols(A);
|
||||
parcsr_A_ptr = hypre_ParCSRMatrixCreate(comm, global_num_rows,
|
||||
global_num_cols,
|
||||
row_starts, col_starts,
|
||||
0, 0, 0);
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixOwnsRowStarts(parcsr_A_ptr) = old_owns_row;
|
||||
hypre_ParCSRMatrixOwnsColStarts(parcsr_A_ptr) = old_owns_col;
|
||||
hypre_ParCSRMatrixOwnsRowStarts(A) = 0;
|
||||
hypre_ParCSRMatrixOwnsColStarts(A) = 0;
|
||||
#endif
|
||||
|
||||
csr_A = hypre_MergeDiagAndOffd(A);
|
||||
|
||||
@@ -1994,7 +2034,12 @@ void HypreParMatrix::Threshold(double threshold)
|
||||
|
||||
hypre_ParCSRMatrixSetNumNonzeros(A);
|
||||
/* Make sure that the first entry in each row is the diagonal one. */
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
if (row_starts == col_starts)
|
||||
#else
|
||||
if ((row_starts[0] == col_starts[0]) &&
|
||||
(row_starts[1] == col_starts[1]))
|
||||
#endif
|
||||
{
|
||||
hypre_CSRMatrixReorder(hypre_ParCSRMatrixDiag(A));
|
||||
}
|
||||
@@ -2503,11 +2548,14 @@ HypreParMatrix * RAP(const HypreParMatrix *A, const HypreParMatrix *P)
|
||||
// hypre_ParCSRMatrixRAPKT
|
||||
}
|
||||
#else
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
HYPRE_Int P_owns_its_col_starts =
|
||||
hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*P));
|
||||
#endif
|
||||
|
||||
hypre_BoomerAMGBuildCoarseOperator(*P,*A,*P,&rap);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
/* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts
|
||||
from P (even if it does not own them)! */
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(rap,0);
|
||||
@@ -2516,6 +2564,7 @@ HypreParMatrix * RAP(const HypreParMatrix *A, const HypreParMatrix *P)
|
||||
{
|
||||
hypre_ParCSRMatrixSetColStartsOwner(*P, 1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
hypre_ParCSRMatrixSetNumNonzeros(rap);
|
||||
@@ -2536,13 +2585,16 @@ HypreParMatrix * RAP(const HypreParMatrix * Rt, const HypreParMatrix *A,
|
||||
hypre_ParCSRMatrixDestroy(Q);
|
||||
}
|
||||
#else
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
HYPRE_Int P_owns_its_col_starts =
|
||||
hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*P));
|
||||
HYPRE_Int Rt_owns_its_col_starts =
|
||||
hypre_ParCSRMatrixOwnsColStarts((hypre_ParCSRMatrix*)(*Rt));
|
||||
#endif
|
||||
|
||||
hypre_BoomerAMGBuildCoarseOperator(*Rt,*A,*P,&rap);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
/* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts
|
||||
from Rt and P (even if they do not own them)! */
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(rap,0);
|
||||
@@ -2555,6 +2607,7 @@ HypreParMatrix * RAP(const HypreParMatrix * Rt, const HypreParMatrix *A,
|
||||
{
|
||||
hypre_ParCSRMatrixSetColStartsOwner(*Rt, 1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
hypre_ParCSRMatrixSetNumNonzeros(rap);
|
||||
@@ -3144,8 +3197,12 @@ void HypreSmoother::SetOperator(const Operator &op)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
min_eig_est = 0;
|
||||
hypre_ParCSRMaxEigEstimate(*A, poly_scale, &max_eig_est);
|
||||
#else
|
||||
hypre_ParCSRMaxEigEstimate(*A, poly_scale, &max_eig_est, &min_eig_est);
|
||||
#endif
|
||||
}
|
||||
Z = new HypreParVector(*A);
|
||||
}
|
||||
@@ -3159,8 +3216,12 @@ void HypreSmoother::SetOperator(const Operator &op)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
min_eig_est = 0;
|
||||
hypre_ParCSRMaxEigEstimate(*A, poly_scale, &max_eig_est);
|
||||
#else
|
||||
hypre_ParCSRMaxEigEstimate(*A, poly_scale, &max_eig_est, &min_eig_est);
|
||||
#endif
|
||||
}
|
||||
|
||||
// The Taubin and FIR polynomials are defined on [0, 2]
|
||||
@@ -4997,11 +5058,11 @@ HypreADS::HypreADS(const HypreParMatrix &A, ParFiniteElementSpace *face_fespace)
|
||||
void HypreADS::Init(ParFiniteElementSpace *face_fespace)
|
||||
{
|
||||
int cycle_type = 11;
|
||||
int rlx_type = 2;
|
||||
int rlx_sweeps = 1;
|
||||
double rlx_weight = 1.0;
|
||||
double rlx_omega = 1.0;
|
||||
#ifndef HYPRE_USING_CUDA
|
||||
int rlx_type = 2;
|
||||
int amg_coarsen_type = 10;
|
||||
int amg_agg_levels = 1;
|
||||
int amg_rlx_type = 8;
|
||||
@@ -5009,6 +5070,7 @@ void HypreADS::Init(ParFiniteElementSpace *face_fespace)
|
||||
int amg_interp_type = 6;
|
||||
int amg_Pmax = 4;
|
||||
#else
|
||||
int rlx_type = 1;
|
||||
int amg_coarsen_type = 8;
|
||||
int amg_agg_levels = 0;
|
||||
int amg_rlx_type = 18;
|
||||
|
||||
@@ -508,8 +508,10 @@ void hypre_ParCSRMatrixEliminateAAe(hypre_ParCSRMatrix *A,
|
||||
hypre_ParCSRMatrixColStarts(A),
|
||||
0, 0, 0);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(*Ae, 0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(*Ae, 0);
|
||||
#endif
|
||||
|
||||
hypre_CSRMatrix *Ae_diag = hypre_ParCSRMatrixDiag(*Ae);
|
||||
hypre_CSRMatrix *Ae_offd = hypre_ParCSRMatrixOffd(*Ae);
|
||||
@@ -1002,10 +1004,17 @@ void hypre_ParCSRMatrixSplit(hypre_ParCSRMatrix *A,
|
||||
|
||||
hypre_ParCSRMatrixOwnsData(blocks[i]) = 1;
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
/* only the first block will own the row/col_starts */
|
||||
hypre_ParCSRMatrixOwnsRowStarts(blocks[i]) = !i;
|
||||
hypre_ParCSRMatrixOwnsColStarts(blocks[i]) = !i;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MFEM_HYPRE_VERSION > 22200
|
||||
mfem_hypre_TFree_host(row_starts);
|
||||
mfem_hypre_TFree_host(col_starts);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Based on hypre_CSRMatrixMatvec in hypre's csr_matvec.c */
|
||||
@@ -1916,9 +1925,12 @@ hypre_ParCSRMatrixAdd(hypre_ParCSRMatrix *A,
|
||||
|
||||
/* C owns diag, offd, and cmap. */
|
||||
hypre_ParCSRMatrixSetDataOwner(C, 1);
|
||||
|
||||
#if MFEM_HYPRE_VERSION <= 22200
|
||||
/* C does not own row and column starts. */
|
||||
hypre_ParCSRMatrixSetRowStartsOwner(C, 0);
|
||||
hypre_ParCSRMatrixSetColStartsOwner(C, 0);
|
||||
#endif
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
+1
-1
@@ -378,7 +378,7 @@ void Swap(T &a, T &b)
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
const double Epsilon = std::numeric_limits<double>::epsilon();
|
||||
constexpr double Epsilon = std::numeric_limits<double>::epsilon();
|
||||
|
||||
/// Utility function used in CalcSingularvalue<3>.
|
||||
MFEM_HOST_DEVICE static inline
|
||||
|
||||
+1
-1
@@ -1677,7 +1677,7 @@ int KINSolver::GradientMult(N_Vector v, N_Vector Jv, N_Vector u,
|
||||
|
||||
// Wrapper for evaluating linear systems J u = b
|
||||
int KINSolver::LinSysSetup(N_Vector u, N_Vector, SUNMatrix J,
|
||||
void *, N_Vector , N_Vector )
|
||||
void *, N_Vector, N_Vector )
|
||||
{
|
||||
const SundialsNVector mfem_u(u);
|
||||
KINSolver *self = static_cast<KINSolver*>(GET_CONTENT(J));
|
||||
|
||||
@@ -119,7 +119,7 @@ $(if $(word 2,$(SRC)),$(error Spaces in SRC = "$(SRC)" are not supported))
|
||||
MFEM_GIT_STRING = $(shell [ -d $(MFEM_DIR)/.git ] && git -C $(MFEM_DIR) \
|
||||
describe --all --long --abbrev=40 --dirty --always 2> /dev/null)
|
||||
|
||||
EXAMPLE_SUBDIRS = amgx ginkgo hiop petsc pumi sundials superlu
|
||||
EXAMPLE_SUBDIRS = amgx caliper ginkgo hiop petsc pumi sundials superlu
|
||||
EXAMPLE_DIRS := examples $(addprefix examples/,$(EXAMPLE_SUBDIRS))
|
||||
EXAMPLE_TEST_DIRS := examples
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ set(SRCS
|
||||
ncmesh.cpp
|
||||
nurbs.cpp
|
||||
point.cpp
|
||||
pyramid.cpp
|
||||
quadrilateral.cpp
|
||||
segment.cpp
|
||||
tetrahedron.cpp
|
||||
@@ -38,6 +39,7 @@ set(HDRS
|
||||
ncmesh.hpp
|
||||
nurbs.hpp
|
||||
point.hpp
|
||||
pyramid.hpp
|
||||
quadrilateral.hpp
|
||||
segment.hpp
|
||||
tetrahedron.hpp
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
/// Constants for the classes derived from Element.
|
||||
enum Type { POINT, SEGMENT, TRIANGLE, QUADRILATERAL,
|
||||
TETRAHEDRON, HEXAHEDRON, WEDGE
|
||||
TETRAHEDRON, HEXAHEDRON, WEDGE, PYRAMID
|
||||
};
|
||||
|
||||
/// Default element constructor.
|
||||
|
||||
+335
-36
@@ -335,6 +335,7 @@ FiniteElement *Mesh::GetTransformationFEforElementType(Element::Type ElemType)
|
||||
case Element::TETRAHEDRON : return &TetrahedronFE;
|
||||
case Element::HEXAHEDRON : return &HexahedronFE;
|
||||
case Element::WEDGE : return &WedgeFE;
|
||||
case Element::PYRAMID : return &PyramidFE;
|
||||
default:
|
||||
MFEM_ABORT("Unknown element type \"" << ElemType << "\"");
|
||||
break;
|
||||
@@ -735,6 +736,31 @@ void Mesh::GetLocalTriToWdgTransformation(
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::GetLocalTriToPyrTransformation(
|
||||
IsoparametricTransformation &Transf, int i)
|
||||
{
|
||||
DenseMatrix &locpm = Transf.GetPointMat();
|
||||
|
||||
Transf.SetFE(&TriangleFE);
|
||||
// (i/64) is the local face no. in the pyr
|
||||
MFEM_VERIFY(i >= 64, "Local face index " << i/64
|
||||
<< " is not a triangular face of a pyramid.");
|
||||
const int *pv = pyr_t::FaceVert[i/64];
|
||||
// (i%64) is the orientation of the pyramid face
|
||||
// w.r.t. the face element
|
||||
const int *to = tri_t::Orient[i%64];
|
||||
const IntegrationRule *PyrVert =
|
||||
Geometries.GetVertices(Geometry::PYRAMID);
|
||||
locpm.SetSize(3, 3);
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
const IntegrationPoint &vert = PyrVert->IntPoint(pv[to[j]]);
|
||||
locpm(0, j) = vert.x;
|
||||
locpm(1, j) = vert.y;
|
||||
locpm(2, j) = vert.z;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::GetLocalQuadToHexTransformation(
|
||||
IsoparametricTransformation &Transf, int i)
|
||||
{
|
||||
@@ -781,6 +807,29 @@ void Mesh::GetLocalQuadToWdgTransformation(
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::GetLocalQuadToPyrTransformation(
|
||||
IsoparametricTransformation &Transf, int i)
|
||||
{
|
||||
DenseMatrix &locpm = Transf.GetPointMat();
|
||||
|
||||
Transf.SetFE(&QuadrilateralFE);
|
||||
// (i/64) is the local face no. in the pyr
|
||||
MFEM_VERIFY(i < 64, "Local face index " << i/64
|
||||
<< " is not a quadrilateral face of a pyramid.");
|
||||
const int *pv = pyr_t::FaceVert[i/64];
|
||||
// (i%64) is the orientation of the quad
|
||||
const int *qo = quad_t::Orient[i%64];
|
||||
const IntegrationRule *PyrVert = Geometries.GetVertices(Geometry::PYRAMID);
|
||||
locpm.SetSize(3, 4);
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
const IntegrationPoint &vert = PyrVert->IntPoint(pv[qo[j]]);
|
||||
locpm(0, j) = vert.x;
|
||||
locpm(1, j) = vert.y;
|
||||
locpm(2, j) = vert.z;
|
||||
}
|
||||
}
|
||||
|
||||
const GeometricFactors* Mesh::GetGeometricFactors(const IntegrationRule& ir,
|
||||
const int flags,
|
||||
MemoryType d_mt)
|
||||
@@ -862,10 +911,19 @@ void Mesh::GetLocalFaceTransformation(
|
||||
{
|
||||
GetLocalTriToTetTransformation(Transf, info);
|
||||
}
|
||||
else if (elem_type == Element::WEDGE)
|
||||
{
|
||||
GetLocalTriToWdgTransformation(Transf, info);
|
||||
}
|
||||
else if (elem_type == Element::PYRAMID)
|
||||
{
|
||||
GetLocalTriToPyrTransformation(Transf, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ASSERT(elem_type == Element::WEDGE, "");
|
||||
GetLocalTriToWdgTransformation(Transf, info);
|
||||
MFEM_ABORT("Mesh::GetLocalFaceTransformation not defined for "
|
||||
"face type " << face_type
|
||||
<< " and element type " << elem_type << "\n");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -874,10 +932,19 @@ void Mesh::GetLocalFaceTransformation(
|
||||
{
|
||||
GetLocalQuadToHexTransformation(Transf, info);
|
||||
}
|
||||
else if (elem_type == Element::WEDGE)
|
||||
{
|
||||
GetLocalQuadToWdgTransformation(Transf, info);
|
||||
}
|
||||
else if (elem_type == Element::PYRAMID)
|
||||
{
|
||||
GetLocalQuadToPyrTransformation(Transf, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ASSERT(elem_type == Element::WEDGE, "");
|
||||
GetLocalQuadToWdgTransformation(Transf, info);
|
||||
MFEM_ABORT("Mesh::GetLocalFaceTransformation not defined for "
|
||||
"face type " << face_type
|
||||
<< " and element type " << elem_type << "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1370,6 +1437,20 @@ int Mesh::AddWedge(const int *vi, int attr)
|
||||
return NumOfElements++;
|
||||
}
|
||||
|
||||
int Mesh::AddPyramid(int v1, int v2, int v3, int v4, int v5, int attr)
|
||||
{
|
||||
CheckEnlarge(elements, NumOfElements);
|
||||
elements[NumOfElements] = new Pyramid(v1, v2, v3, v4, v5, attr);
|
||||
return NumOfElements++;
|
||||
}
|
||||
|
||||
int Mesh::AddPyramid(const int *vi, int attr)
|
||||
{
|
||||
CheckEnlarge(elements, NumOfElements);
|
||||
elements[NumOfElements] = new Pyramid(vi, attr);
|
||||
return NumOfElements++;
|
||||
}
|
||||
|
||||
int Mesh::AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8,
|
||||
int attr)
|
||||
{
|
||||
@@ -1423,6 +1504,25 @@ void Mesh::AddHexAsWedges(const int *vi, int attr)
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::AddHexAsPyramids(const int *vi, int attr)
|
||||
{
|
||||
static const int hex_to_pyr[6][5] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 8 }, { 0, 4, 5, 1, 8 }, { 1, 5, 6, 2, 8 },
|
||||
{ 2, 6, 7, 3, 8 }, { 3, 7, 4, 0, 8 }, { 7, 6, 5, 4, 8 }
|
||||
};
|
||||
int ti[5];
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
ti[j] = vi[hex_to_pyr[i][j]];
|
||||
}
|
||||
AddPyramid(ti, attr);
|
||||
}
|
||||
}
|
||||
|
||||
int Mesh::AddElement(Element *elem)
|
||||
{
|
||||
CheckEnlarge(elements, NumOfElements);
|
||||
@@ -2692,11 +2792,16 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
NElem *= 2;
|
||||
NBdrElem += 2*nx*ny;
|
||||
}
|
||||
else if (type == Element::PYRAMID)
|
||||
{
|
||||
NElem *= 6;
|
||||
NVert += nx * ny * nz;
|
||||
}
|
||||
|
||||
InitMesh(3, 3, NVert, NElem, NBdrElem);
|
||||
|
||||
double coord[3];
|
||||
int ind[8];
|
||||
int ind[9];
|
||||
|
||||
// Sets vertices and the corresponding coordinates
|
||||
for (z = 0; z <= nz; z++)
|
||||
@@ -2712,8 +2817,25 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == Element::PYRAMID)
|
||||
{
|
||||
for (z = 0; z < nz; z++)
|
||||
{
|
||||
coord[2] = (((double) z + 0.5) / nz) * sz;
|
||||
for (y = 0; y < ny; y++)
|
||||
{
|
||||
coord[1] = (((double) y + 0.5 ) / ny) * sy;
|
||||
for (x = 0; x < nx; x++)
|
||||
{
|
||||
coord[0] = (((double) x + 0.5 ) / nx) * sx;
|
||||
AddVertex(coord);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
|
||||
#define VTXP(XC, YC, ZC) ((nx+1)*(ny+1)*(nz+1)+(XC)+((YC)+(ZC)*ny)*nx)
|
||||
|
||||
// Sets elements and the corresponding indices of vertices
|
||||
if (sfc_ordering && type == Element::HEXAHEDRON)
|
||||
@@ -2728,14 +2850,14 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
y = sfc[3*k + 1];
|
||||
z = sfc[3*k + 2];
|
||||
|
||||
ind[0] = VTX(x , y , z );
|
||||
ind[1] = VTX(x+1, y , z );
|
||||
ind[0] = VTX(x, y, z );
|
||||
ind[1] = VTX(x+1, y, z );
|
||||
ind[2] = VTX(x+1, y+1, z );
|
||||
ind[3] = VTX(x , y+1, z );
|
||||
ind[4] = VTX(x , y , z+1);
|
||||
ind[5] = VTX(x+1, y , z+1);
|
||||
ind[3] = VTX(x, y+1, z );
|
||||
ind[4] = VTX(x, y, z+1);
|
||||
ind[5] = VTX(x+1, y, z+1);
|
||||
ind[6] = VTX(x+1, y+1, z+1);
|
||||
ind[7] = VTX(x , y+1, z+1);
|
||||
ind[7] = VTX(x, y+1, z+1);
|
||||
|
||||
AddHex(ind, 1);
|
||||
}
|
||||
@@ -2748,12 +2870,12 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (x = 0; x < nx; x++)
|
||||
{
|
||||
ind[0] = VTX(x , y , z );
|
||||
ind[1] = VTX(x+1, y , z );
|
||||
ind[0] = VTX(x, y, z );
|
||||
ind[1] = VTX(x+1, y, z );
|
||||
ind[2] = VTX(x+1, y+1, z );
|
||||
ind[3] = VTX(x , y+1, z );
|
||||
ind[4] = VTX(x , y , z+1);
|
||||
ind[5] = VTX(x+1, y , z+1);
|
||||
ind[3] = VTX(x, y+1, z );
|
||||
ind[4] = VTX(x, y, z+1);
|
||||
ind[5] = VTX(x+1, y, z+1);
|
||||
ind[6] = VTX(x+1, y+1, z+1);
|
||||
ind[7] = VTX( x, y+1, z+1);
|
||||
if (type == Element::TETRAHEDRON)
|
||||
@@ -2764,6 +2886,11 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
AddHexAsWedges(ind, 1);
|
||||
}
|
||||
else if (type == Element::PYRAMID)
|
||||
{
|
||||
ind[8] = VTXP( x, y, z);
|
||||
AddHexAsPyramids(ind, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddHex(ind, 1);
|
||||
@@ -2779,10 +2906,10 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (x = 0; x < nx; x++)
|
||||
{
|
||||
ind[0] = VTX(x , y , 0);
|
||||
ind[1] = VTX(x , y+1, 0);
|
||||
ind[0] = VTX(x, y, 0);
|
||||
ind[1] = VTX(x, y+1, 0);
|
||||
ind[2] = VTX(x+1, y+1, 0);
|
||||
ind[3] = VTX(x+1, y , 0);
|
||||
ind[3] = VTX(x+1, y, 0);
|
||||
if (type == Element::TETRAHEDRON)
|
||||
{
|
||||
AddBdrQuadAsTriangles(ind, 1);
|
||||
@@ -2802,10 +2929,10 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (x = 0; x < nx; x++)
|
||||
{
|
||||
ind[0] = VTX(x , y , nz);
|
||||
ind[1] = VTX(x+1, y , nz);
|
||||
ind[0] = VTX(x, y, nz);
|
||||
ind[1] = VTX(x+1, y, nz);
|
||||
ind[2] = VTX(x+1, y+1, nz);
|
||||
ind[3] = VTX(x , y+1, nz);
|
||||
ind[3] = VTX(x, y+1, nz);
|
||||
if (type == Element::TETRAHEDRON)
|
||||
{
|
||||
AddBdrQuadAsTriangles(ind, 6);
|
||||
@@ -2825,10 +2952,10 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (y = 0; y < ny; y++)
|
||||
{
|
||||
ind[0] = VTX(0 , y , z );
|
||||
ind[1] = VTX(0 , y , z+1);
|
||||
ind[2] = VTX(0 , y+1, z+1);
|
||||
ind[3] = VTX(0 , y+1, z );
|
||||
ind[0] = VTX(0, y, z );
|
||||
ind[1] = VTX(0, y, z+1);
|
||||
ind[2] = VTX(0, y+1, z+1);
|
||||
ind[3] = VTX(0, y+1, z );
|
||||
if (type == Element::TETRAHEDRON)
|
||||
{
|
||||
AddBdrQuadAsTriangles(ind, 5);
|
||||
@@ -2844,10 +2971,10 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (y = 0; y < ny; y++)
|
||||
{
|
||||
ind[0] = VTX(nx, y , z );
|
||||
ind[0] = VTX(nx, y, z );
|
||||
ind[1] = VTX(nx, y+1, z );
|
||||
ind[2] = VTX(nx, y+1, z+1);
|
||||
ind[3] = VTX(nx, y , z+1);
|
||||
ind[3] = VTX(nx, y, z+1);
|
||||
if (type == Element::TETRAHEDRON)
|
||||
{
|
||||
AddBdrQuadAsTriangles(ind, 3);
|
||||
@@ -2863,10 +2990,10 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (z = 0; z < nz; z++)
|
||||
{
|
||||
ind[0] = VTX(x , 0, z );
|
||||
ind[0] = VTX(x, 0, z );
|
||||
ind[1] = VTX(x+1, 0, z );
|
||||
ind[2] = VTX(x+1, 0, z+1);
|
||||
ind[3] = VTX(x , 0, z+1);
|
||||
ind[3] = VTX(x, 0, z+1);
|
||||
if (type == Element::TETRAHEDRON)
|
||||
{
|
||||
AddBdrQuadAsTriangles(ind, 2);
|
||||
@@ -2882,8 +3009,8 @@ void Mesh::Make3D(int nx, int ny, int nz, Element::Type type,
|
||||
{
|
||||
for (z = 0; z < nz; z++)
|
||||
{
|
||||
ind[0] = VTX(x , ny, z );
|
||||
ind[1] = VTX(x , ny, z+1);
|
||||
ind[0] = VTX(x, ny, z );
|
||||
ind[1] = VTX(x, ny, z+1);
|
||||
ind[2] = VTX(x+1, ny, z+1);
|
||||
ind[3] = VTX(x+1, ny, z );
|
||||
if (type == Element::TETRAHEDRON)
|
||||
@@ -3428,6 +3555,7 @@ Element *Mesh::NewElement(int geom)
|
||||
#endif
|
||||
case Geometry::CUBE: return (new Hexahedron);
|
||||
case Geometry::PRISM: return (new Wedge);
|
||||
case Geometry::PYRAMID: return (new Pyramid);
|
||||
default:
|
||||
MFEM_ABORT("invalid Geometry::Type, geom = " << geom);
|
||||
}
|
||||
@@ -3520,6 +3648,15 @@ void Mesh::SetMeshGen()
|
||||
meshgen |= 4;
|
||||
break;
|
||||
|
||||
case Element::PYRAMID:
|
||||
mesh_geoms |= (1 << Geometry::PYRAMID);
|
||||
mesh_geoms |= (1 << Geometry::SQUARE);
|
||||
mesh_geoms |= (1 << Geometry::TRIANGLE);
|
||||
mesh_geoms |= (1 << Geometry::SEGMENT);
|
||||
mesh_geoms |= (1 << Geometry::POINT);
|
||||
meshgen |= 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
MFEM_ABORT("invalid element type: " << type);
|
||||
break;
|
||||
@@ -3974,6 +4111,12 @@ void Mesh::MakeRefined_(Mesh &orig_mesh, const Array<int> ref_factors,
|
||||
}
|
||||
}
|
||||
|
||||
if (Dim > 2)
|
||||
{
|
||||
GetElementToFaceTable(false);
|
||||
GenerateFaces();
|
||||
}
|
||||
|
||||
// Add refined boundary elements
|
||||
for (int el = 0; el < orig_mesh.GetNBE(); el++)
|
||||
{
|
||||
@@ -5054,6 +5197,19 @@ int Mesh::CheckElementOrientation(bool fix_it)
|
||||
}
|
||||
break;
|
||||
|
||||
case Element::PYRAMID:
|
||||
// only check the Jacobian at the center of the element
|
||||
GetElementJacobian(i, J);
|
||||
if (J.Det() < 0.0)
|
||||
{
|
||||
wo++;
|
||||
if (fix_it)
|
||||
{
|
||||
// how?
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Element::HEXAHEDRON:
|
||||
// only check the Jacobian at the center of the element
|
||||
GetElementJacobian(i, J);
|
||||
@@ -6136,6 +6292,22 @@ void Mesh::GenerateFaces()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::PYRAMID:
|
||||
{
|
||||
for (int j = 0; j < 1; j++)
|
||||
{
|
||||
const int *fv = pyr_t::FaceVert[j];
|
||||
AddQuadFaceElement(j, ef[j], i,
|
||||
v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
|
||||
}
|
||||
for (int j = 1; j < 5; j++)
|
||||
{
|
||||
const int *fv = pyr_t::FaceVert[j];
|
||||
AddTriangleFaceElement(j, ef[j], i,
|
||||
v[fv[0]], v[fv[1]], v[fv[2]]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::HEXAHEDRON:
|
||||
{
|
||||
for (int j = 0; j < 6; j++)
|
||||
@@ -6228,6 +6400,20 @@ STable3D *Mesh::GetFacesTable()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::PYRAMID:
|
||||
{
|
||||
for (int j = 0; j < 1; j++)
|
||||
{
|
||||
const int *fv = pyr_t::FaceVert[j];
|
||||
faces_tbl->Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
|
||||
}
|
||||
for (int j = 1; j < 5; j++)
|
||||
{
|
||||
const int *fv = pyr_t::FaceVert[j];
|
||||
faces_tbl->Push(v[fv[0]], v[fv[1]], v[fv[2]]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::WEDGE:
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
@@ -6302,6 +6488,22 @@ STable3D *Mesh::GetElementToFaceTable(int ret_ftbl)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::PYRAMID:
|
||||
{
|
||||
for (int j = 0; j < 1; j++)
|
||||
{
|
||||
const int *fv = pyr_t::FaceVert[j];
|
||||
el_to_face->Push(
|
||||
i, faces_tbl->Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
|
||||
}
|
||||
for (int j = 1; j < 5; j++)
|
||||
{
|
||||
const int *fv = pyr_t::FaceVert[j];
|
||||
el_to_face->Push(
|
||||
i, faces_tbl->Push(v[fv[0]], v[fv[1]], v[fv[2]]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::HEXAHEDRON:
|
||||
{
|
||||
// find the face by the vertices with the smallest 3 numbers
|
||||
@@ -7638,8 +7840,22 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
}
|
||||
}
|
||||
|
||||
int pyr_counter = 0;
|
||||
if (HasGeometry(Geometry::PYRAMID))
|
||||
{
|
||||
for (int i = 0; i < elements.Size(); i++)
|
||||
{
|
||||
if (elements[i]->GetType() == Element::PYRAMID)
|
||||
{
|
||||
pyr_counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map from edge-index to vertex-index, needed for ReorientTetMesh() for
|
||||
// parallel meshes.
|
||||
// Note: with the removal of ReorientTetMesh() this may no longer
|
||||
// be needed. Unfortunately, it's hard to be sure.
|
||||
Array<int> e2v;
|
||||
if (HasGeometry(Geometry::TETRAHEDRON))
|
||||
{
|
||||
@@ -7695,7 +7911,7 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
Array<Element*> new_boundary;
|
||||
|
||||
vertices.SetSize(oelem + hex_counter);
|
||||
new_elements.SetSize(8 * NumOfElements);
|
||||
new_elements.SetSize(8 * NumOfElements + 2 * pyr_counter);
|
||||
CoarseFineTr.embeddings.SetSize(new_elements.Size());
|
||||
|
||||
hex_counter = 0;
|
||||
@@ -7961,6 +8177,73 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
}
|
||||
break;
|
||||
|
||||
case Element::PYRAMID:
|
||||
{
|
||||
const int *f = el_to_face->GetRow(i);
|
||||
// pyr_counter++;
|
||||
|
||||
for (int fi = 0; fi < 1; fi++)
|
||||
{
|
||||
for (int k = 0; k < 4; k++)
|
||||
{
|
||||
vv[k] = v[pyr_t::FaceVert[fi][k]];
|
||||
}
|
||||
AverageVertices(vv, 4, oface + f2qf[f[fi]]);
|
||||
}
|
||||
|
||||
for (int ei = 0; ei < 8; ei++)
|
||||
{
|
||||
for (int k = 0; k < 2; k++)
|
||||
{
|
||||
vv[k] = v[pyr_t::Edges[ei][k]];
|
||||
}
|
||||
AverageVertices(vv, 2, oedge+e[ei]);
|
||||
}
|
||||
|
||||
const int qf0 = f2qf[f[0]];
|
||||
|
||||
new_elements[j++] =
|
||||
new Pyramid(v[0], oedge+e[0], oface+qf0,
|
||||
oedge+e[3], oedge+e[4], attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Pyramid(oedge+e[0], v[1], oedge+e[1],
|
||||
oface+qf0, oedge+e[5], attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Pyramid(oface+qf0, oedge+e[1], v[2],
|
||||
oedge+e[2], oedge+e[6], attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Pyramid(oedge+e[3], oface+qf0, oedge+e[2],
|
||||
v[3], oedge+e[7], attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Pyramid(oedge+e[4], oedge+e[5], oedge+e[6],
|
||||
oedge+e[7], v[4], attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Pyramid(oedge+e[7], oedge+e[6], oedge+e[5],
|
||||
oedge+e[4], oface+qf0, attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Tetrahedron(oedge+e[0], oedge+e[4], oedge+e[5],
|
||||
oface+qf0, attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Tetrahedron(oedge+e[1], oedge+e[5], oedge+e[6],
|
||||
oface+qf0, attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Tetrahedron(oedge+e[2], oedge+e[6], oedge+e[7],
|
||||
oface+qf0, attr);
|
||||
|
||||
new_elements[j++] =
|
||||
new Tetrahedron(oedge+e[3], oedge+e[7], oedge+e[4],
|
||||
oface+qf0, attr);
|
||||
}
|
||||
break;
|
||||
|
||||
case Element::HEXAHEDRON:
|
||||
{
|
||||
const int *f = el_to_face->GetRow(i);
|
||||
@@ -8092,7 +8375,7 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
}
|
||||
mfem::Swap(boundary, new_boundary);
|
||||
|
||||
static const double A = 0.0, B = 0.5, C = 1.0;
|
||||
static const double A = 0.0, B = 0.5, C = 1.0, D = -1.0;
|
||||
static double tet_children[3*4*16] =
|
||||
{
|
||||
A,A,A, B,A,A, A,B,A, A,A,B,
|
||||
@@ -8118,6 +8401,19 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
A,A,B, A,B,B, B,A,B, B,B,A,
|
||||
A,A,B, B,A,B, B,A,A, B,B,A
|
||||
};
|
||||
static double pyr_children[3*5*10] =
|
||||
{
|
||||
A,A,A, B,A,A, B,B,A, A,B,A, A,A,B,
|
||||
B,A,A, C,A,A, C,B,A, B,B,A, B,A,B,
|
||||
B,B,A, C,B,A, C,C,A, B,C,A, B,B,B,
|
||||
A,B,A, B,B,A, B,C,A, A,C,A, A,B,B,
|
||||
A,A,B, B,A,B, B,B,B, A,B,B, A,A,C,
|
||||
A,B,B, B,B,B, B,A,B, A,A,B, B,B,A,
|
||||
B,A,A, A,A,B, B,A,B, B,B,A, D,D,D,
|
||||
C,B,A, B,A,B, B,B,B, B,B,A, D,D,D,
|
||||
B,C,A, B,B,B, A,B,B, B,B,A, D,D,D,
|
||||
A,B,A, A,B,B, A,A,B, B,B,A, D,D,D
|
||||
};
|
||||
static double pri_children[3*6*8] =
|
||||
{
|
||||
A,A,A, B,A,A, A,B,A, A,A,B, B,A,B, A,B,B,
|
||||
@@ -8143,6 +8439,8 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
|
||||
CoarseFineTr.point_matrices[Geometry::TETRAHEDRON]
|
||||
.UseExternalData(tet_children, 3, 4, 16);
|
||||
CoarseFineTr.point_matrices[Geometry::PYRAMID]
|
||||
.UseExternalData(pyr_children, 3, 5, 10);
|
||||
CoarseFineTr.point_matrices[Geometry::PRISM]
|
||||
.UseExternalData(pri_children, 3, 6, 8);
|
||||
CoarseFineTr.point_matrices[Geometry::CUBE]
|
||||
@@ -8159,7 +8457,7 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
|
||||
}
|
||||
|
||||
NumOfVertices = vertices.Size();
|
||||
NumOfElements = 8 * NumOfElements;
|
||||
NumOfElements = 8 * NumOfElements + 2 * pyr_counter;
|
||||
NumOfBdrElements = 4 * NumOfBdrElements;
|
||||
|
||||
GetElementToFaceTable();
|
||||
@@ -8743,7 +9041,7 @@ void Mesh::GeneralRefinement(const Array<Refinement> &refinements,
|
||||
else if (nonconforming < 0)
|
||||
{
|
||||
// determine if nonconforming refinement is suitable
|
||||
if ((meshgen & 2) || (meshgen & 4))
|
||||
if ((meshgen & 2) || (meshgen & 4) || (meshgen & 8))
|
||||
{
|
||||
nonconforming = 1; // tensor product elements and wedges
|
||||
}
|
||||
@@ -9527,6 +9825,7 @@ void Mesh::Printer(std::ostream &out, std::string section_delimiter) const
|
||||
"# TETRAHEDRON = 4\n"
|
||||
"# CUBE = 5\n"
|
||||
"# PRISM = 6\n"
|
||||
"# PYRAMID = 7\n"
|
||||
"#\n";
|
||||
|
||||
out << "\ndimension\n" << Dim;
|
||||
|
||||
+19
-1
@@ -177,6 +177,7 @@ protected:
|
||||
int own_nodes;
|
||||
|
||||
static const int vtk_quadratic_tet[10];
|
||||
static const int vtk_quadratic_pyramid[13];
|
||||
static const int vtk_quadratic_wedge[18];
|
||||
static const int vtk_quadratic_hex[27];
|
||||
|
||||
@@ -195,6 +196,7 @@ public:
|
||||
typedef Geometry::Constants<Geometry::TETRAHEDRON> tet_t;
|
||||
typedef Geometry::Constants<Geometry::CUBE> hex_t;
|
||||
typedef Geometry::Constants<Geometry::PRISM> pri_t;
|
||||
typedef Geometry::Constants<Geometry::PYRAMID> pyr_t;
|
||||
|
||||
enum Operation { NONE, REFINE, DEREFINE, REBALANCE };
|
||||
|
||||
@@ -373,11 +375,17 @@ protected:
|
||||
void GetLocalTriToWdgTransformation (IsoparametricTransformation &loc,
|
||||
int i);
|
||||
/// Used in GetFaceElementTransformations (...)
|
||||
void GetLocalTriToPyrTransformation (IsoparametricTransformation &loc,
|
||||
int i);
|
||||
/// Used in GetFaceElementTransformations (...)
|
||||
void GetLocalQuadToHexTransformation (IsoparametricTransformation &loc,
|
||||
int i);
|
||||
/// Used in GetFaceElementTransformations (...)
|
||||
void GetLocalQuadToWdgTransformation (IsoparametricTransformation &loc,
|
||||
int i);
|
||||
/// Used in GetFaceElementTransformations (...)
|
||||
void GetLocalQuadToPyrTransformation (IsoparametricTransformation &loc,
|
||||
int i);
|
||||
|
||||
/** Used in GetFaceElementTransformations to account for the fact that a
|
||||
slave face occupies only a portion of its master face. */
|
||||
@@ -657,11 +665,15 @@ public:
|
||||
int AddWedge(int v1, int v2, int v3, int v4, int v5, int v6, int attr = 1);
|
||||
int AddWedge(const int *vi, int attr = 1);
|
||||
|
||||
int AddPyramid(int v1, int v2, int v3, int v4, int v5, int attr = 1);
|
||||
int AddPyramid(const int *vi, int attr = 1);
|
||||
|
||||
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8,
|
||||
int attr = 1);
|
||||
int AddHex(const int *vi, int attr = 1);
|
||||
void AddHexAsTets(const int *vi, int attr = 1);
|
||||
void AddHexAsWedges(const int *vi, int attr = 1);
|
||||
void AddHexAsPyramids(const int *vi, int attr = 1);
|
||||
|
||||
/// The parameter @a elem should be allocated using the NewElement() method
|
||||
int AddElement(Element *elem);
|
||||
@@ -829,10 +841,16 @@ public:
|
||||
|
||||
/** @brief Get the mesh generator/type.
|
||||
|
||||
The purpose of this is to be able to quickly tell what type of elements
|
||||
one has in the mesh. Examination of this bitmask along with knowledge
|
||||
of the mesh dimension can be used to identify which element types are
|
||||
present.
|
||||
|
||||
@return A bitmask:
|
||||
- bit 0 - simplices are present in the mesh (triangles, tets),
|
||||
- bit 1 - tensor product elements are present in the mesh (quads, hexes),
|
||||
- bit 2 - the mesh has wedge elements.
|
||||
- bit 3 - the mesh has pyramid elements.
|
||||
|
||||
In parallel, the result takes into account elements on all processors.
|
||||
*/
|
||||
@@ -1227,7 +1245,7 @@ public:
|
||||
satisfy: v0 < min(v1, v2).
|
||||
|
||||
@note Refinement does not work after a call to this method! */
|
||||
virtual void ReorientTetMesh();
|
||||
MFEM_DEPRECATED virtual void ReorientTetMesh();
|
||||
|
||||
int *CartesianPartitioning(int nxyz[]);
|
||||
int *GeneratePartitioning(int nparts, int part_method = 1);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "mesh_operators.hpp"
|
||||
#include "nurbs.hpp"
|
||||
#include "wedge.hpp"
|
||||
#include "pyramid.hpp"
|
||||
|
||||
#ifdef MFEM_USE_MESQUITE
|
||||
#include "mesquite.hpp"
|
||||
|
||||
+18
-3
@@ -352,6 +352,11 @@ void Mesh::ReadTrueGridMesh(std::istream &input)
|
||||
const int Mesh::vtk_quadratic_tet[10] =
|
||||
{ 0, 1, 2, 3, 4, 7, 5, 6, 8, 9 };
|
||||
|
||||
// see Pyramid::edges & Mesh::GenerateFaces
|
||||
// https://www.vtk.org/doc/nightly/html/classvtkBiQuadraticQuadraticWedge.html
|
||||
const int Mesh::vtk_quadratic_pyramid[13] =
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
|
||||
// see Wedge::edges & Mesh::GenerateFaces
|
||||
// https://www.vtk.org/doc/nightly/html/classvtkBiQuadraticQuadraticWedge.html
|
||||
const int Mesh::vtk_quadratic_wedge[18] =
|
||||
@@ -514,8 +519,7 @@ void Mesh::CreateVTKMesh(const Vector &points, const Array<int> &cell_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generate faces and edges so that we can define
|
||||
// FE space on the mesh
|
||||
// Generate faces and edges so that we can define FE space on the mesh
|
||||
FinalizeTopology();
|
||||
|
||||
FiniteElementCollection *fec;
|
||||
@@ -546,6 +550,8 @@ void Mesh::CreateVTKMesh(const Vector &points, const Array<int> &cell_data,
|
||||
vtk_mfem = vtk_quadratic_hex; break;
|
||||
case Geometry::PRISM:
|
||||
vtk_mfem = vtk_quadratic_wedge; break;
|
||||
case Geometry::PYRAMID:
|
||||
vtk_mfem = vtk_quadratic_pyramid; break;
|
||||
default:
|
||||
vtk_mfem = NULL; // suppress a warning
|
||||
break;
|
||||
@@ -1394,6 +1400,10 @@ void Mesh::ReadInlineMesh(std::istream &input, bool generate_edges)
|
||||
{
|
||||
type = Element::WEDGE;
|
||||
}
|
||||
else if (eltype == "pyramid")
|
||||
{
|
||||
type = Element::PYRAMID;
|
||||
}
|
||||
else if (eltype == "tet")
|
||||
{
|
||||
type = Element::TETRAHEDRON;
|
||||
@@ -1448,7 +1458,7 @@ void Mesh::ReadInlineMesh(std::istream &input, bool generate_edges)
|
||||
Make2D(nx, ny, type, sx, sy, generate_edges, true);
|
||||
}
|
||||
else if (type == Element::TETRAHEDRON || type == Element::WEDGE ||
|
||||
type == Element::HEXAHEDRON)
|
||||
type == Element::HEXAHEDRON || type == Element::PYRAMID)
|
||||
{
|
||||
MFEM_VERIFY(nx > 0 && ny > 0 && nz > 0 &&
|
||||
sx > 0.0 && sy > 0.0 && sz > 0.0,
|
||||
@@ -2445,6 +2455,10 @@ void Mesh::ReadGmshMesh(std::istream &input, int &curved, int &read_gf)
|
||||
// initialize mesh_geoms so we can create Nodes FE space below
|
||||
this->SetMeshGen();
|
||||
|
||||
// Generate faces and edges so that we can define
|
||||
// FE space on the mesh
|
||||
this->FinalizeTopology();
|
||||
|
||||
// Construct GridFunction for uniformly spaced high order coords
|
||||
FiniteElementCollection* nfec;
|
||||
FiniteElementSpace* nfes;
|
||||
@@ -2666,6 +2680,7 @@ void Mesh::ReadGmshMesh(std::istream &input, int &curved, int &read_gf)
|
||||
// Convert nodes to discontinuous GridFunction (if they aren't already)
|
||||
if (mesh_order == 1)
|
||||
{
|
||||
this->FinalizeTopology();
|
||||
this->SetMeshGen();
|
||||
this->SetCurvature(1, true, spaceDim, Ordering::byVDIM);
|
||||
}
|
||||
|
||||
+1
-1
@@ -612,7 +612,7 @@ int NCMesh::NewSegment(int n0, int n1, int attr, int vattr1, int vattr2)
|
||||
// get (degenerate) faces and assign face attributes
|
||||
int v0 = el.node[0], v1 = el.node[1];
|
||||
faces.Get(v0, v0, v0, v0)->attribute = vattr1;
|
||||
faces.Get(v1, v1, v1 ,v1)->attribute = vattr2;
|
||||
faces.Get(v1, v1, v1,v1)->attribute = vattr2;
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
+243
-4
@@ -34,6 +34,7 @@ ParMesh::ParMesh(const ParMesh &pmesh, bool copy_nodes)
|
||||
group_sedge(pmesh.group_sedge),
|
||||
group_stria(pmesh.group_stria),
|
||||
group_squad(pmesh.group_squad),
|
||||
face_nbr_el_to_face(NULL),
|
||||
glob_elem_offset(-1),
|
||||
glob_offset_sequence(-1),
|
||||
gtopo(pmesh.gtopo)
|
||||
@@ -105,7 +106,8 @@ ParMesh& ParMesh::operator=(ParMesh &&mesh)
|
||||
|
||||
ParMesh::ParMesh(MPI_Comm comm, Mesh &mesh, int *partitioning_,
|
||||
int part_method)
|
||||
: glob_elem_offset(-1)
|
||||
: face_nbr_el_to_face(NULL)
|
||||
, glob_elem_offset(-1)
|
||||
, glob_offset_sequence(-1)
|
||||
, gtopo(comm)
|
||||
{
|
||||
@@ -852,6 +854,7 @@ ParMesh::ParMesh(const ParNCMesh &pncmesh)
|
||||
: MyComm(pncmesh.MyComm)
|
||||
, NRanks(pncmesh.NRanks)
|
||||
, MyRank(pncmesh.MyRank)
|
||||
, face_nbr_el_to_face(NULL)
|
||||
, glob_elem_offset(-1)
|
||||
, glob_offset_sequence(-1)
|
||||
, gtopo(MyComm)
|
||||
@@ -918,7 +921,8 @@ void ParMesh::FinalizeParTopo()
|
||||
}
|
||||
|
||||
ParMesh::ParMesh(MPI_Comm comm, istream &input, bool refine)
|
||||
: glob_elem_offset(-1)
|
||||
: face_nbr_el_to_face(NULL)
|
||||
, glob_elem_offset(-1)
|
||||
, glob_offset_sequence(-1)
|
||||
, gtopo(comm)
|
||||
{
|
||||
@@ -1129,6 +1133,7 @@ void ParMesh::MakeRefined_(ParMesh &orig_mesh, int ref_factor, int ref_type)
|
||||
MyComm = orig_mesh.GetComm();
|
||||
NRanks = orig_mesh.GetNRanks();
|
||||
MyRank = orig_mesh.GetMyRank();
|
||||
face_nbr_el_to_face = NULL;
|
||||
glob_elem_offset = -1;
|
||||
glob_offset_sequence = -1;
|
||||
gtopo = orig_mesh.gtopo;
|
||||
@@ -2073,6 +2078,11 @@ void ParMesh::ExchangeFaceNbrData()
|
||||
|
||||
ExchangeFaceNbrData(gr_sface, s2l_face);
|
||||
|
||||
if (Dim == 3)
|
||||
{
|
||||
GetFaceNbrElementToFaceTable();
|
||||
}
|
||||
|
||||
if (del_tables) { delete gr_sface; }
|
||||
|
||||
if ( have_face_nbr_data ) { return; }
|
||||
@@ -2141,6 +2151,8 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
|
||||
el_marker = -1;
|
||||
vertex_marker = -1;
|
||||
|
||||
Array<int> fcs, cor;
|
||||
|
||||
Table send_face_nbr_elemdata, send_face_nbr_facedata;
|
||||
|
||||
send_face_nbr_elements.MakeI(num_face_nbrs);
|
||||
@@ -2170,7 +2182,9 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
|
||||
send_face_nbr_vertices.AddAColumnInRow(fn);
|
||||
}
|
||||
|
||||
send_face_nbr_elemdata.AddColumnsInRow(fn, nv + 2);
|
||||
const int nf = elements[el]->GetNFaces();
|
||||
|
||||
send_face_nbr_elemdata.AddColumnsInRow(fn, nv + nf + 2);
|
||||
}
|
||||
}
|
||||
send_face_nbr_facedata.AddColumnsInRow(fn, 2*num_sfaces);
|
||||
@@ -2222,6 +2236,13 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
|
||||
send_face_nbr_elemdata.AddConnection(
|
||||
fn, GetElementBaseGeometry(el));
|
||||
send_face_nbr_elemdata.AddConnections(fn, v, nv);
|
||||
|
||||
if (Dim == 3)
|
||||
{
|
||||
const int nf = elements[el]->GetNFaces();
|
||||
GetElementFaces(el, fcs, cor);
|
||||
send_face_nbr_elemdata.AddConnections(fn, cor, nf);
|
||||
}
|
||||
}
|
||||
send_face_nbr_facedata.AddConnection(fn, el);
|
||||
int info = faces_info[lface].Elem1Inf;
|
||||
@@ -2267,12 +2288,13 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
|
||||
for (int el = 0; el < num_elems; el++)
|
||||
{
|
||||
const int nv = elements[elems[el]]->GetNVertices();
|
||||
const int nf = (Dim == 3) ? elements[elems[el]]->GetNFaces() : 0;
|
||||
elemdata += 2; // skip the attribute and the geometry type
|
||||
for (int j = 0; j < nv; j++)
|
||||
{
|
||||
elemdata[j] = vertex_marker[elemdata[j]];
|
||||
}
|
||||
elemdata += nv;
|
||||
elemdata += nv + nf;
|
||||
|
||||
el_marker[elems[el]] = el;
|
||||
}
|
||||
@@ -2323,6 +2345,8 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
|
||||
|
||||
// convert the element data into face_nbr_elements
|
||||
face_nbr_elements.SetSize(face_nbr_elements_offset[num_face_nbrs]);
|
||||
face_nbr_el_ori.Clear();
|
||||
face_nbr_el_ori.SetSize(face_nbr_elements_offset[num_face_nbrs], 6);
|
||||
while (true)
|
||||
{
|
||||
int fn;
|
||||
@@ -2350,9 +2374,20 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
|
||||
}
|
||||
el->SetVertices(recv_elemdata);
|
||||
recv_elemdata += nv;
|
||||
if (Dim == 3)
|
||||
{
|
||||
int nf = el->GetNFaces();
|
||||
int * fn_ori = face_nbr_el_ori.GetRow(elem_off);
|
||||
for (int j = 0; j < nf; j++)
|
||||
{
|
||||
fn_ori[j] = recv_elemdata[j];
|
||||
}
|
||||
recv_elemdata += nf;
|
||||
}
|
||||
face_nbr_elements[elem_off++] = el;
|
||||
}
|
||||
}
|
||||
face_nbr_el_ori.Finalize();
|
||||
|
||||
MPI_Waitall(num_face_nbrs, send_requests, statuses);
|
||||
|
||||
@@ -2511,6 +2546,179 @@ void ParMesh::ExchangeFaceNbrNodes()
|
||||
}
|
||||
}
|
||||
|
||||
STable3D *ParMesh::GetSharedFacesTable()
|
||||
{
|
||||
STable3D *sfaces_tbl = new STable3D(face_nbr_vertices.Size());
|
||||
for (int i = 0; i < face_nbr_elements.Size(); i++)
|
||||
{
|
||||
const int *v = face_nbr_elements[i]->GetVertices();
|
||||
switch (face_nbr_elements[i]->GetType())
|
||||
{
|
||||
case Element::TETRAHEDRON:
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
const int *fv = tet_t::FaceVert[j];
|
||||
sfaces_tbl->Push(v[fv[0]], v[fv[1]], v[fv[2]]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::WEDGE:
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
const int *fv = pri_t::FaceVert[j];
|
||||
sfaces_tbl->Push(v[fv[0]], v[fv[1]], v[fv[2]]);
|
||||
}
|
||||
for (int j = 2; j < 5; j++)
|
||||
{
|
||||
const int *fv = pri_t::FaceVert[j];
|
||||
sfaces_tbl->Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::HEXAHEDRON:
|
||||
{
|
||||
// find the face by the vertices with the smallest 3 numbers
|
||||
// z = 0, y = 0, x = 1, y = 1, x = 0, z = 1
|
||||
for (int j = 0; j < 6; j++)
|
||||
{
|
||||
const int *fv = hex_t::FaceVert[j];
|
||||
sfaces_tbl->Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MFEM_ABORT("Unexpected type of Element.");
|
||||
}
|
||||
}
|
||||
return sfaces_tbl;
|
||||
}
|
||||
|
||||
STable3D *ParMesh::GetFaceNbrElementToFaceTable(int ret_ftbl)
|
||||
{
|
||||
int i, *v;
|
||||
STable3D * faces_tbl = GetFacesTable();
|
||||
STable3D * sfaces_tbl = GetSharedFacesTable();
|
||||
|
||||
if (face_nbr_el_to_face != NULL)
|
||||
{
|
||||
delete face_nbr_el_to_face;
|
||||
}
|
||||
face_nbr_el_to_face = new Table(face_nbr_elements.Size(), 6);
|
||||
for (i = 0; i < face_nbr_elements.Size(); i++)
|
||||
{
|
||||
v = face_nbr_elements[i]->GetVertices();
|
||||
switch (face_nbr_elements[i]->GetType())
|
||||
{
|
||||
case Element::TETRAHEDRON:
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
const int *fv = tet_t::FaceVert[j];
|
||||
int lf = faces_tbl->Index(v[fv[0]], v[fv[1]], v[fv[2]]);
|
||||
if (lf < 0)
|
||||
{
|
||||
lf = sfaces_tbl->Index(v[fv[0]], v[fv[1]], v[fv[2]]);
|
||||
if (lf >= 0)
|
||||
{
|
||||
lf += NumOfFaces;
|
||||
}
|
||||
}
|
||||
face_nbr_el_to_face->Push(i, lf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::WEDGE:
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
const int *fv = pri_t::FaceVert[j];
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]], v[fv[1]], v[fv[2]]));
|
||||
}
|
||||
for (int j = 2; j < 5; j++)
|
||||
{
|
||||
const int *fv = pri_t::FaceVert[j];
|
||||
int k = 0;
|
||||
int max = v[fv[0]];
|
||||
|
||||
if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
|
||||
if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
|
||||
if (max < v[fv[3]]) { k = 3; }
|
||||
|
||||
switch (k)
|
||||
{
|
||||
case 0:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[1]],v[fv[2]],v[fv[3]]));
|
||||
break;
|
||||
case 1:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]],v[fv[2]],v[fv[3]]));
|
||||
break;
|
||||
case 2:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]],v[fv[1]],v[fv[3]]));
|
||||
break;
|
||||
case 3:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]],v[fv[1]],v[fv[2]]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Element::HEXAHEDRON:
|
||||
{
|
||||
// find the face by the vertices with the smallest 3 numbers
|
||||
// z = 0, y = 0, x = 1, y = 1, x = 0, z = 1
|
||||
for (int j = 0; j < 6; j++)
|
||||
{
|
||||
const int *fv = hex_t::FaceVert[j];
|
||||
int k = 0;
|
||||
int max = v[fv[0]];
|
||||
|
||||
if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
|
||||
if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
|
||||
if (max < v[fv[3]]) { k = 3; }
|
||||
|
||||
switch (k)
|
||||
{
|
||||
case 0:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[1]],v[fv[2]],v[fv[3]]));
|
||||
break;
|
||||
case 1:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]],v[fv[2]],v[fv[3]]));
|
||||
break;
|
||||
case 2:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]],v[fv[1]],v[fv[3]]));
|
||||
break;
|
||||
case 3:
|
||||
face_nbr_el_to_face->Push(
|
||||
i, faces_tbl->Index(v[fv[0]],v[fv[1]],v[fv[2]]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MFEM_ABORT("Unexpected type of Element.");
|
||||
}
|
||||
}
|
||||
face_nbr_el_to_face->Finalize();
|
||||
|
||||
if (ret_ftbl)
|
||||
{
|
||||
return faces_tbl;
|
||||
}
|
||||
delete faces_tbl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ParMesh::GetFaceNbrRank(int fn) const
|
||||
{
|
||||
if (Conforming())
|
||||
@@ -2528,6 +2736,37 @@ int ParMesh::GetFaceNbrRank(int fn) const
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ParMesh::GetFaceNbrElementFaces(int i, Array<int> &fcs, Array<int> &cor) const
|
||||
{
|
||||
int n, j;
|
||||
int el_nbr = i - GetNE();
|
||||
if (face_nbr_el_to_face)
|
||||
{
|
||||
face_nbr_el_to_face->GetRow(el_nbr, fcs);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("ParMesh::GetFaceNbrElementFaces(...) : "
|
||||
"face_nbr_el_to_face not generated.");
|
||||
}
|
||||
if (el_nbr < face_nbr_el_ori.Size())
|
||||
{
|
||||
const int * row = face_nbr_el_ori.GetRow(el_nbr);
|
||||
n = fcs.Size();
|
||||
cor.SetSize(n);
|
||||
for (j=0; j<n; j++)
|
||||
{
|
||||
cor[j] = row[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("ParMesh::GetFaceNbrElementFaces(...) : "
|
||||
"face_nbr_el_to_face not generated.");
|
||||
}
|
||||
}
|
||||
|
||||
Table *ParMesh::GetFaceToAllElementTable() const
|
||||
{
|
||||
const Array<int> *s2l_face;
|
||||
|
||||
+15
-3
@@ -75,6 +75,9 @@ protected:
|
||||
// sface ids: all triangles first, then all quads
|
||||
Array<int> sface_lface;
|
||||
|
||||
Table *face_nbr_el_to_face;
|
||||
Table face_nbr_el_ori; // orientations for each face (from nbr processor)
|
||||
|
||||
IsoparametricTransformation FaceNbrTransformation;
|
||||
|
||||
// glob_elem_offset + local element number defines a global element numbering
|
||||
@@ -103,6 +106,8 @@ protected:
|
||||
bool DecodeFaceSplittings(HashTable<Hashed2> &v_to_v, const int *v,
|
||||
const Array<unsigned> &codes, int &pos);
|
||||
|
||||
STable3D *GetFaceNbrElementToFaceTable(int ret_ftbl = 0);
|
||||
|
||||
void GetFaceNbrElementTransformation(
|
||||
int i, IsoparametricTransformation *ElTr);
|
||||
|
||||
@@ -196,6 +201,9 @@ protected:
|
||||
void BuildSharedVertMapping(int nvert, const Table* vert_element,
|
||||
const Array<int> &vert_global_local);
|
||||
|
||||
// Similar to Mesh::GetFacesTable()
|
||||
STable3D *GetSharedFacesTable();
|
||||
|
||||
/// Ensure that bdr_attributes and attributes agree across processors
|
||||
void DistributeAttributes(Array<int> &attr);
|
||||
|
||||
@@ -216,8 +224,9 @@ protected:
|
||||
|
||||
public:
|
||||
/// Default constructor. Create an empty @a ParMesh.
|
||||
ParMesh() : MyComm(0), NRanks(0), MyRank(-1), glob_elem_offset(-1),
|
||||
glob_offset_sequence(-1), have_face_nbr_data(false), pncmesh(NULL) { }
|
||||
ParMesh() : MyComm(0), NRanks(0), MyRank(-1), face_nbr_el_to_face(NULL),
|
||||
glob_elem_offset(-1), glob_offset_sequence(-1),
|
||||
have_face_nbr_data(false), pncmesh(NULL) { }
|
||||
|
||||
/// Create a parallel mesh by partitioning a serial Mesh.
|
||||
/** The mesh is partitioned automatically or using external partitioning
|
||||
@@ -341,6 +350,9 @@ public:
|
||||
int GetFaceNbrGroup(int fn) const { return face_nbr_group[fn]; }
|
||||
int GetFaceNbrRank(int fn) const;
|
||||
|
||||
/** Similar to Mesh::GetElementFaces */
|
||||
void GetFaceNbrElementFaces(int i, Array<int> &fcs, Array<int> &cor) const;
|
||||
|
||||
/** Similar to Mesh::GetFaceToElementTable with added face-neighbor elements
|
||||
with indices offset by the local number of elements. */
|
||||
Table *GetFaceToAllElementTable() const;
|
||||
@@ -370,7 +382,7 @@ public:
|
||||
int GetSharedFace(int sface) const;
|
||||
|
||||
/// See the remarks for the serial version in mesh.hpp
|
||||
virtual void ReorientTetMesh();
|
||||
MFEM_DEPRECATED virtual void ReorientTetMesh();
|
||||
|
||||
/// Utility function: sum integers from all processors (Allreduce).
|
||||
virtual long ReduceInt(int value) const;
|
||||
|
||||
+1
-2
@@ -84,8 +84,7 @@ public:
|
||||
the PUMI and MFEM meshes. E.g.,
|
||||
PUMI_tet{v0,v1,v2,v3} ---> MFEM_tet{v1,v0,v3,v2}
|
||||
* Note that change in the orientation can be caused by
|
||||
a) fixing wrong boundary element orientations
|
||||
b) a call to ReorientTetMesh() which is required for Nedelec */
|
||||
fixing wrong boundary element orientations */
|
||||
int RotationPUMItoMFEM(apf::Mesh2* apf_mesh,
|
||||
apf::MeshEntity* tet,
|
||||
int elemId);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
|
||||
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability visit https://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
// Implementation of class Pyramid
|
||||
|
||||
#include "mesh_headers.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
Pyramid::Pyramid(const int *ind, int attr)
|
||||
: Element(Geometry::PYRAMID)
|
||||
{
|
||||
attribute = attr;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
indices[i] = ind[i];
|
||||
}
|
||||
}
|
||||
|
||||
Pyramid::Pyramid(int ind1, int ind2, int ind3, int ind4, int ind5, int attr)
|
||||
: Element(Geometry::PYRAMID)
|
||||
{
|
||||
attribute = attr;
|
||||
indices[0] = ind1;
|
||||
indices[1] = ind2;
|
||||
indices[2] = ind3;
|
||||
indices[3] = ind4;
|
||||
indices[4] = ind5;
|
||||
}
|
||||
|
||||
void Pyramid::SetVertices(const int *ind)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
indices[i] = ind[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Pyramid::GetVertices(Array<int> &v) const
|
||||
{
|
||||
v.SetSize(5);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
v[i] = indices[i];
|
||||
}
|
||||
}
|
||||
|
||||
int Pyramid::GetNFaces(int &nFaceVertices) const
|
||||
{
|
||||
MFEM_ABORT("this method is not valid for Pyramid elements");
|
||||
nFaceVertices = 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
|
||||
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability visit https://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#ifndef MFEM_PYRAMID
|
||||
#define MFEM_PYRAMID
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "element.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/// Data type Pyramid element
|
||||
class Pyramid : public Element
|
||||
{
|
||||
protected:
|
||||
int indices[5];
|
||||
|
||||
public:
|
||||
typedef Geometry::Constants<Geometry::PYRAMID> geom_t;
|
||||
|
||||
Pyramid() : Element(Geometry::PYRAMID) { }
|
||||
|
||||
/// Constructs pyramid by specifying the indices and the attribute.
|
||||
Pyramid(const int *ind, int attr = 1);
|
||||
|
||||
/// Constructs pyramid by specifying the indices and the attribute.
|
||||
Pyramid(int ind1, int ind2, int ind3, int ind4, int ind5,
|
||||
int attr = 1);
|
||||
|
||||
/// Return element's type.
|
||||
virtual Type GetType() const { return Element::PYRAMID; }
|
||||
|
||||
/// Set the vertices according to the given input.
|
||||
virtual void SetVertices(const int *ind);
|
||||
|
||||
/// Returns the indices of the element's vertices.
|
||||
virtual void GetVertices(Array<int> &v) const;
|
||||
|
||||
virtual int *GetVertices() { return indices; }
|
||||
|
||||
virtual int GetNVertices() const { return 5; }
|
||||
|
||||
virtual int GetNEdges() const { return 8; }
|
||||
|
||||
virtual const int *GetEdgeVertices(int ei) const
|
||||
{ return geom_t::Edges[ei]; }
|
||||
|
||||
/// @deprecated Use GetNFaces(void) and GetNFaceVertices(int) instead.
|
||||
MFEM_DEPRECATED virtual int GetNFaces(int &nFaceVertices) const;
|
||||
|
||||
virtual int GetNFaces() const { return 5; }
|
||||
|
||||
virtual int GetNFaceVertices(int fi) const
|
||||
{ return ( ( fi < 1 ) ? 4 : 3); }
|
||||
|
||||
virtual const int *GetFaceVertices(int fi) const
|
||||
{ return geom_t::FaceVert[fi]; }
|
||||
|
||||
virtual Element *Duplicate(Mesh *m) const
|
||||
{ return new Pyramid(indices, attribute); }
|
||||
|
||||
virtual ~Pyramid() { }
|
||||
};
|
||||
|
||||
extern class LinearPyramidFiniteElement PyramidFE;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+1
-2
@@ -71,8 +71,7 @@ public:
|
||||
virtual ~Wedge() { }
|
||||
};
|
||||
|
||||
// Defined in fe.cpp to ensure construction after 'mfem::poly1d'.
|
||||
extern class H1_WedgeElement WedgeFE;
|
||||
extern class LinearWedgeFiniteElement WedgeFE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user