Compare commits

..
Author SHA1 Message Date
bensworth d8501138bc Some mods for compiling 2021-08-18 09:42:36 -06:00
bensworth c679c99b35 minor mods for MFEM 2021-08-18 09:08:24 -06:00
bensworth 3f9a3658a6 Added framework for IMEX BDF and RK; not included in MFEM config/setup yet 2021-08-18 09:03:18 -06:00
115 changed files with 5748 additions and 9834 deletions
-1
View File
@@ -50,7 +50,6 @@ 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
-15
View File
@@ -12,21 +12,6 @@ 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
======================================
-66
View File
@@ -1,66 +0,0 @@
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
-4
View File
@@ -175,10 +175,6 @@ 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)
+1 -1
View File
@@ -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.1 (HYPRE built with CUDA)
HYPRE >= 2.22.0 (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).
-9
View File
@@ -1,9 +0,0 @@
MFEM INLINE mesh v1.0
type = pyramid
nx = 4
ny = 4
nz = 4
sx = 1.0
sy = 1.0
sz = 1.0
-43
View File
@@ -1,43 +0,0 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
# 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
-38
View File
@@ -1,38 +0,0 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
# 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
+2 -2
View File
@@ -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,7 +223,6 @@ 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);
@@ -234,6 +233,7 @@ 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);
+18 -19
View File
@@ -231,29 +231,28 @@ 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)
{
MFEM_PERF_SCOPE("Solve A X=B");
Solver *prec = NULL;
if (pa)
if (UsesTensorBasis(fespace))
{
if (UsesTensorBasis(fespace))
{
prec = new OperatorJacobiSmoother(a, ess_tdof_list);
}
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);
-1
View File
@@ -9,7 +9,6 @@
// 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
+1
View File
@@ -118,6 +118,7 @@ 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.
+4 -7
View File
@@ -24,10 +24,7 @@
// 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. 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.
// high-order implicit (SDIRK) time integration.
//
// We recommend viewing examples 2, 9 and 10 before viewing this
// example.
@@ -329,8 +326,8 @@ ConductionOperator::ConductionOperator(FiniteElementSpace &f, double al,
void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
{
// Compute:
// du_dt = M^{-1}*-Ku
// for du_dt, where K is linearized by using u from the previous timestep
// du_dt = M^{-1}*-K(u)
// for du_dt
Kmat.Mult(u, z);
z.Neg(); // z = -z
M_solver.Mult(z, du_dt);
@@ -341,7 +338,7 @@ void ConductionOperator::ImplicitSolve(const double dt,
{
// Solve the equation:
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
// for du_dt, where K is linearized by using u from the previous timestep
// for du_dt
if (!T)
{
T = Add(1.0, Mmat, dt, Kmat);
+5 -8
View File
@@ -24,11 +24,8 @@
// 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. 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.
// high-order implicit (SDIRK) time integration. Optional saving
// with ADIOS2 (adios2.readthedocs.io) is also illustrated.
//
// We recommend viewing examples 2, 9 and 10 before viewing this
// example.
@@ -423,8 +420,8 @@ ConductionOperator::ConductionOperator(ParFiniteElementSpace &f, double al,
void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
{
// Compute:
// du_dt = M^{-1}*-Ku
// for du_dt, where K is linearized by using u from the previous timestep
// du_dt = M^{-1}*-K(u)
// for du_dt
Kmat.Mult(u, z);
z.Neg(); // z = -z
M_solver.Mult(z, du_dt);
@@ -435,7 +432,7 @@ void ConductionOperator::ImplicitSolve(const double dt,
{
// Solve the equation:
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
// for du_dt, where K is linearized by using u from the previous timestep
// for du_dt
if (!T)
{
T = Add(1.0, Mmat, dt, Kmat);
-1
View File
@@ -9,7 +9,6 @@
// 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
-2
View File
@@ -13,8 +13,6 @@
// 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:
-2
View File
@@ -13,8 +13,6 @@
// 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:
+1
View File
@@ -113,6 +113,7 @@ 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.
+1
View File
@@ -141,6 +141,7 @@ 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.
+5 -3
View File
@@ -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,8 +277,10 @@ int main(int argc, char *argv[])
mesh->UniformRefinement();
}
// 6. Set element attributes in order to distinguish elements in the
// PML region
// 6. Reorient mesh in case of a tet mesh
mesh->ReorientTetMesh();
// 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
+4 -1
View File
@@ -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,6 +316,9 @@ 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);
+1 -2
View File
@@ -16,8 +16,6 @@
// 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
@@ -115,6 +113,7 @@ 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.
+4 -3
View File
@@ -16,8 +16,6 @@
// 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
@@ -141,7 +139,9 @@ 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.
// 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.
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
@@ -151,6 +151,7 @@ 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.
-2
View File
@@ -19,8 +19,6 @@
// 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:
+4 -3
View File
@@ -19,8 +19,6 @@
// 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:
@@ -137,7 +135,9 @@ 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.
// 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).
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
@@ -147,6 +147,7 @@ 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.
+1
View File
@@ -106,6 +106,7 @@ 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
+4 -1
View File
@@ -121,7 +121,9 @@ 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.
// 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.
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
@@ -131,6 +133,7 @@ int main(int argc, char *argv[])
pmesh->UniformRefinement();
}
}
pmesh->ReorientTetMesh();
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use the Nedelec finite elements of the specified order.
+4 -1
View File
@@ -122,7 +122,9 @@ 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.
// 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).
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
@@ -132,6 +134,7 @@ int main(int argc, char *argv[])
pmesh->UniformRefinement();
}
}
pmesh->ReorientTetMesh();
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use the Raviart-Thomas finite elements of the specified order.
-2
View File
@@ -39,7 +39,6 @@ set(SRCS
complex_fem.cpp
convergence.cpp
datacollection.cpp
doftrans.cpp
eltrans.cpp
estimators.cpp
fe.cpp
@@ -120,7 +119,6 @@ set(HDRS
complex_fem.hpp
convergence.hpp
datacollection.hpp
doftrans.hpp
eltrans.hpp
estimators.hpp
fe.hpp
+24 -58
View File
@@ -391,7 +391,6 @@ void BilinearForm::Assemble(int skip_zeros)
}
ElementTransformation *eltrans;
DofTransformation * doftrans;
Mesh *mesh = fes -> GetMesh();
DenseMatrix elmat, *elmat_p;
@@ -425,7 +424,7 @@ void BilinearForm::Assemble(int skip_zeros)
for (int i = 0; i < fes -> GetNE(); i++)
{
int elem_attr = fes->GetMesh()->GetAttribute(i);
doftrans = fes->GetElementVDofs(i, vdofs);
fes->GetElementVDofs(i, vdofs);
if (element_matrices)
{
elmat_p = &(*element_matrices)(i);
@@ -459,11 +458,6 @@ void BilinearForm::Assemble(int skip_zeros)
{
elmat_p = &elmat;
}
if (doftrans)
{
doftrans->TransformDual(elmat);
}
elmat_p = &elmat;
}
if (static_cond)
{
@@ -509,7 +503,7 @@ void BilinearForm::Assemble(int skip_zeros)
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
const FiniteElement &be = *fes->GetBE(i);
doftrans = fes -> GetBdrElementVDofs (i, vdofs);
fes -> GetBdrElementVDofs (i, vdofs);
eltrans = fes -> GetBdrElementTransformation (i);
int k = 0;
for (; k < boundary_integs.Size(); k++)
@@ -529,22 +523,17 @@ 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_p, skip_zeros);
mat->AddSubMatrix(vdofs, vdofs, elmat, skip_zeros);
if (hybridization)
{
hybridization->AssembleBdrMatrix(i, *elmat_p);
hybridization->AssembleBdrMatrix(i, elmat);
}
}
else
{
static_cond->AssembleBdrMatrix(i, *elmat_p);
static_cond->AssembleBdrMatrix(i, elmat);
}
}
}
@@ -1329,10 +1318,9 @@ void MixedBilinearForm::Assemble (int skip_zeros)
return;
}
Array<int> tr_vdofs, te_vdofs;
ElementTransformation *eltrans;
DofTransformation * dom_dof_trans;
DofTransformation * ran_dof_trans;
DenseMatrix elmat;
DenseMatrix elemmat;
Mesh *mesh = test_fes -> GetMesh();
@@ -1345,24 +1333,16 @@ void MixedBilinearForm::Assemble (int skip_zeros)
{
for (int i = 0; i < test_fes -> GetNE(); i++)
{
dom_dof_trans = trial_fes -> GetElementVDofs (i, trial_vdofs);
ran_dof_trans = test_fes -> GetElementVDofs (i, test_vdofs);
trial_fes -> GetElementVDofs (i, tr_vdofs);
test_fes -> GetElementVDofs (i, te_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);
elmat += elemmat;
mat -> AddSubMatrix (te_vdofs, tr_vdofs, elemmat, skip_zeros);
}
if (ran_dof_trans || dom_dof_trans)
{
TransformDual(ran_dof_trans, dom_dof_trans, elmat);
}
mat -> AddSubMatrix (test_vdofs, trial_vdofs, elmat, skip_zeros);
}
}
@@ -1394,12 +1374,9 @@ void MixedBilinearForm::Assemble (int skip_zeros)
const int bdr_attr = mesh->GetBdrAttribute(i);
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
dom_dof_trans = trial_fes -> GetBdrElementVDofs (i, trial_vdofs);
ran_dof_trans = test_fes -> GetBdrElementVDofs (i, test_vdofs);
trial_fes -> GetBdrElementVDofs (i, tr_vdofs);
test_fes -> GetBdrElementVDofs (i, te_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] &&
@@ -1408,34 +1385,29 @@ void MixedBilinearForm::Assemble (int skip_zeros)
boundary_integs[k]->AssembleElementMatrix2 (*trial_fes -> GetBE(i),
*test_fes -> GetBE(i),
*eltrans, elemmat);
elmat += elemmat;
mat -> AddSubMatrix (te_vdofs, tr_vdofs, elemmat, skip_zeros);
}
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> test_vdofs2;
Array<int> te_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, trial_vdofs);
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs);
trial_fes->GetFaceVDofs(i, tr_vdofs);
test_fes->GetElementVDofs(ftr->Elem1No, te_vdofs);
trial_face_fe = trial_fes->GetFaceElement(i);
test_fe1 = test_fes->GetFE(ftr->Elem1No);
if (ftr->Elem2No >= 0)
{
test_fes->GetElementVDofs(ftr->Elem2No, test_vdofs2);
test_vdofs.Append(test_vdofs2);
test_fes->GetElementVDofs(ftr->Elem2No, te_vdofs2);
te_vdofs.Append(te_vdofs2);
test_fe2 = test_fes->GetFE(ftr->Elem2No);
}
else
@@ -1449,7 +1421,7 @@ void MixedBilinearForm::Assemble (int skip_zeros)
{
trace_face_integs[k]->AssembleFaceMatrix(*trial_face_fe, *test_fe1,
*test_fe2, *ftr, elemmat);
mat->AddSubMatrix(test_vdofs, trial_vdofs, elemmat, skip_zeros);
mat->AddSubMatrix(te_vdofs, tr_vdofs, elemmat, skip_zeros);
}
}
}
@@ -1489,8 +1461,8 @@ void MixedBilinearForm::Assemble (int skip_zeros)
ftr = mesh->GetBdrFaceTransformations(i);
if (ftr)
{
trial_fes->GetFaceVDofs(ftr->ElementNo, trial_vdofs);
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs);
trial_fes->GetFaceVDofs(ftr->ElementNo, tr_vdofs);
test_fes->GetElementVDofs(ftr->Elem1No, te_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
@@ -1507,7 +1479,7 @@ void MixedBilinearForm::Assemble (int skip_zeros)
*test_fe1,
*test_fe2,
*ftr, elemmat);
mat->AddSubMatrix(test_vdofs, trial_vdofs, elemmat, skip_zeros);
mat->AddSubMatrix(te_vdofs, tr_vdofs, elemmat, skip_zeros);
}
}
}
@@ -1869,8 +1841,6 @@ 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;
@@ -1883,8 +1853,8 @@ void DiscreteLinearOperator::Assemble(int skip_zeros)
{
for (int i = 0; i < test_fes->GetNE(); i++)
{
dom_dof_trans = trial_fes->GetElementVDofs(i, dom_vdofs);
ran_dof_trans = test_fes->GetElementVDofs(i, ran_vdofs);
trial_fes->GetElementVDofs(i, dom_vdofs);
test_fes->GetElementVDofs(i, ran_vdofs);
T = test_fes->GetElementTransformation(i);
dom_fe = trial_fes->GetFE(i);
ran_fe = test_fes->GetFE(i);
@@ -1897,10 +1867,6 @@ 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);
}
}
+24 -24
View File
@@ -17,14 +17,14 @@ namespace mfem
{
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -69,14 +69,14 @@ void EAConvectionAssemble1D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -146,14 +146,14 @@ void EAConvectionAssemble2D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+18 -18
View File
@@ -21,13 +21,13 @@ namespace mfem
// PA Convection Integrator
// PA Convection Assemble 2D kernel
void PAConvectionSetup2D(const int NQ,
const int NE,
const Array<double> &w,
const Vector &j,
const Vector &vel,
const double alpha,
Vector &op)
static 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 @@ void PAConvectionSetup2D(const int NQ,
}
// PA Convection Assemble 3D kernel
void PAConvectionSetup3D(const int NQ,
const int NE,
const Array<double> &w,
const Vector &j,
const Vector &vel,
const double alpha,
Vector &op)
static 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>
template<int T_D1D = 0, int T_Q1D = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0> static
void SmemPAConvectionApply3D(const int ne,
const Array<double> &b,
const Array<double> &g,
+41 -41
View File
@@ -16,12 +16,12 @@
namespace mfem
{
void EADGTraceAssemble1DInt(const int NF,
const Array<double> &basis,
const Vector &padata,
Vector &eadata_int,
Vector &eadata_ext,
const bool add)
static 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 @@ void EADGTraceAssemble1DInt(const int NF,
});
}
void EADGTraceAssemble1DBdr(const int NF,
const Array<double> &basis,
const Vector &padata,
Vector &eadata_bdr,
const bool add)
static 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 @@ void EADGTraceAssemble1DBdr(const int NF,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -128,13 +128,13 @@ void EADGTraceAssemble2DInt(const int NF,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -170,14 +170,14 @@ void EADGTraceAssemble2DBdr(const int NF,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -268,13 +268,13 @@ void EADGTraceAssemble3DInt(const int NF,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+26 -26
View File
@@ -19,16 +19,16 @@ using namespace std;
namespace mfem
{
// PA DG Trace Integrator
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)
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)
{
const int VDIM = 2;
@@ -61,16 +61,16 @@ void PADGTraceSetup2D(const int Q1D,
});
}
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)
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)
{
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>
template<int T_D1D = 0, int T_Q1D = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0> static
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>
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0> static
void SmemPADGTraceApplyTranspose3D(const int NF,
const Array<double> &b,
const Array<double> &bt,
+24 -24
View File
@@ -17,14 +17,14 @@ namespace mfem
{
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -68,14 +68,14 @@ void EADiffusionAssemble1D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -145,14 +145,14 @@ void EADiffusionAssemble2D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+71 -71
View File
@@ -496,14 +496,14 @@ void DiffusionIntegrator::AssemblePA(const FiniteElementSpace &fes)
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -562,14 +562,14 @@ 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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -656,14 +656,14 @@ void SmemPADiffusionDiagonal2D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
constexpr int DIM = 3;
const int D1D = T_D1D ? T_D1D : d1d;
@@ -757,14 +757,14 @@ void PADiffusionDiagonal3D(const int NE,
// Shared memory PA Diffusion Diagonal 3D kernel
template<int T_D1D = 0, int T_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)
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)
{
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>
void PADiffusionApply2D(const int NE,
const bool symmetric,
const Array<double> &b_,
const Array<double> &g_,
const Array<double> &bt_,
const Array<double> &gt_,
const Vector &d_,
const Vector &x_,
Vector &y_,
const int d1d = 0,
const int 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> &gt_,
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 @@ 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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -1314,16 +1314,16 @@ void SmemPADiffusionApply2D(const int NE,
// PA Diffusion Apply 3D kernel
template<int T_D1D = 0, int T_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> &gt,
const Vector &d_,
const Vector &x_,
Vector &y_,
int d1d = 0, int 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> &gt,
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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+72 -72
View File
@@ -21,12 +21,12 @@ namespace mfem
// PA Divergence Integrator
// PA Divergence Assemble 2D kernel
void PADivergenceSetup2D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
const double COEFF,
Vector &op)
static 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 @@ void PADivergenceSetup2D(const int Q1D,
}
// PA Divergence Assemble 3D kernel
void PADivergenceSetup3D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
const double COEFF,
Vector &op)
static 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>
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)
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)
{
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 @@ 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>
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)
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)
{
// TODO
MFEM_ASSERT(false, "SHARED MEM NOT PROGRAMMED YET");
@@ -298,16 +298,16 @@ 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>
void PADivergenceApplyTranspose2D(const int NE,
const Array<double> &bt,
const Array<double> &gt,
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)
static void PADivergenceApplyTranspose2D(const int NE,
const Array<double> &bt,
const Array<double> &gt,
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 @@ 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>
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)
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)
{
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 @@ 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>
void PADivergenceApplyTranspose3D(const int NE,
const Array<double> &bt,
const Array<double> &gt,
const Array<double> &b,
const Vector &op_,
const Vector &x_,
Vector &y_,
int tr_d1d = 0,
int te_d1d = 0,
int q1d = 0)
static void PADivergenceApplyTranspose3D(const int NE,
const Array<double> &bt,
const Array<double> &gt,
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 @@ 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>
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)
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)
{
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
View File
@@ -70,12 +70,12 @@ namespace mfem
the \b MFEM_SHARED keyword for local arrays. */
// PA Gradient Assemble 2D kernel
void PAGradientSetup2D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
const Vector &c,
Vector &op)
static 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 @@ void PAGradientSetup2D(const int Q1D,
}
// PA Gradient Assemble 3D kernel
void PAGradientSetup3D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
const Vector &c,
Vector &op)
static 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>
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)
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)
{
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>
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)
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)
{
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>
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)
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)
{
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
View File
@@ -791,12 +791,12 @@ void SmemPAHcurlMassApply3D(const int D1D,
}
// PA H(curl) curl-curl assemble 2D kernel
void PACurlCurlSetup2D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
Vector &coeff,
Vector &op)
static 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 @@ void PACurlCurlSetup2D(const int Q1D,
}
// PA H(curl) curl-curl assemble 3D kernel
void PACurlCurlSetup3D(const int Q1D,
const int coeffDim,
const int NE,
const Array<double> &w,
const Vector &j,
Vector &coeff,
Vector &op)
static 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)
}
}
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)
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)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HCURL_MAX_D1D;
@@ -1166,19 +1166,19 @@ void PACurlCurlApply2D(const int D1D,
}
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
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)
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)
{
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
@@ -1677,19 +1677,19 @@ void PACurlCurlApply3D(const int D1D,
}
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
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)
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)
{
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
}
}
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)
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)
{
constexpr static int VDIM = 2;
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
@@ -2087,16 +2087,16 @@ void PACurlCurlAssembleDiagonal2D(const int D1D,
}
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
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)
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)
{
constexpr static int VDIM = 3;
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
@@ -2273,16 +2273,16 @@ void PACurlCurlAssembleDiagonal3D(const int D1D,
}
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
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)
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)
{
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>
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)
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)
{
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
@@ -3297,16 +3297,16 @@ 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>
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)
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)
{
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
@@ -3585,18 +3585,18 @@ 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>
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)
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)
{
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>
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)
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)
{
// See PAHcurlL2Apply3D for comments.
@@ -4413,16 +4413,16 @@ void PAHcurlL2Apply3DTranspose(const int D1D,
}
template<int MAX_D1D = HCURL_MAX_D1D, int MAX_Q1D = HCURL_MAX_Q1D>
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)
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)
{
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.
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_)
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_)
{
auto B = Reshape(B_.Read(), c_dofs1D, c_dofs1D);
auto G = Reshape(G_.Read(), o_dofs1D, c_dofs1D);
@@ -4753,12 +4753,12 @@ void PAHcurlApplyGradient2D(const int c_dofs1D,
}
// Specialization of PAHcurlApplyGradient2D to the case where B is identity
void PAHcurlApplyGradient2DBId(const int c_dofs1D,
const int o_dofs1D,
const int NE,
const Array<double> &G_,
const Vector &x_,
Vector &y_)
static 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 @@ void PAHcurlApplyGradient2DBId(const int c_dofs1D,
});
}
void PAHcurlApplyGradientTranspose2D(
static 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 @@ void PAHcurlApplyGradientTranspose2D(
// Specialization of PAHcurlApplyGradientTranspose2D to the case where
// B is identity
void PAHcurlApplyGradientTranspose2DBId(
static 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 @@ void PAHcurlApplyGradientTranspose2DBId(
});
}
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_)
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_)
{
auto B = Reshape(B_.Read(), c_dofs1D, c_dofs1D);
auto G = Reshape(G_.Read(), o_dofs1D, c_dofs1D);
@@ -5154,12 +5154,12 @@ void PAHcurlApplyGradient3D(const int c_dofs1D,
}
// Specialization of PAHcurlApplyGradient3D to the case where
void PAHcurlApplyGradient3DBId(const int c_dofs1D,
const int o_dofs1D,
const int NE,
const Array<double> &G_,
const Vector &x_,
Vector &y_)
static 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 @@ void PAHcurlApplyGradient3DBId(const int c_dofs1D,
});
}
void PAHcurlApplyGradientTranspose3D(
static 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 @@ void PAHcurlApplyGradientTranspose3D(
}
// Specialization of PAHcurlApplyGradientTranspose3D to the case where
void PAHcurlApplyGradientTranspose3DBId(
static 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
}
}
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_)
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_)
{
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
@@ -6002,14 +6002,14 @@ void PAHcurlVecH1IdentityApply3D(const int c_dofs1D,
});
}
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_)
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_)
{
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
@@ -6228,14 +6228,14 @@ void PAHcurlVecH1IdentityApplyTranspose3D(const int c_dofs1D,
});
}
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_)
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_)
{
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
@@ -6327,14 +6327,14 @@ void PAHcurlVecH1IdentityApply2D(const int c_dofs1D,
});
}
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_)
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_)
{
auto Bc = Reshape(Bclosed.Read(), c_dofs1D, c_dofs1D);
auto Bo = Reshape(Bopen.Read(), o_dofs1D, c_dofs1D);
+116 -116
View File
@@ -539,12 +539,12 @@ void PAHdivMassApply3D(const int D1D,
// PA H(div) div-div assemble 2D kernel
// NOTE: this is identical to PACurlCurlSetup3D
void PADivDivSetup2D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
Vector &coeff_,
Vector &op)
static 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 @@ void PADivDivSetup2D(const int Q1D,
});
}
void PADivDivSetup3D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
Vector &coeff_,
Vector &op)
static 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 @@ void PADivDivSetup3D(const int Q1D,
});
}
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_)
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_)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
@@ -718,16 +718,16 @@ void PADivDivApply2D(const int D1D,
}); // end of element loop
}
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_)
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_)
{
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
}
}
void PADivDivAssembleDiagonal2D(const int D1D,
const int Q1D,
const int NE,
const Array<double> &Bo_,
const Array<double> &Gc_,
const Vector &op_,
Vector &diag_)
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_)
{
constexpr static int VDIM = 2;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
@@ -1023,13 +1023,13 @@ void PADivDivAssembleDiagonal2D(const int D1D,
});
}
void PADivDivAssembleDiagonal3D(const int D1D,
const int Q1D,
const int NE,
const Array<double> &Bo_,
const Array<double> &Gc_,
const Vector &op_,
Vector &diag_)
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_)
{
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
void PADivL2Setup2D(const int Q1D,
const int NE,
const Array<double> &w,
Vector &coeff_,
Vector &op)
static 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 @@ void PADivL2Setup2D(const int Q1D,
});
}
void PADivL2Setup3D(const int Q1D,
const int NE,
const Array<double> &w,
Vector &coeff_,
Vector &op)
static 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.
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_)
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_)
{
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 @@ 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.
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_)
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_)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
@@ -1494,16 +1494,16 @@ void PAHdivL2Apply2D(const int D1D,
}); // end of element loop
}
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_)
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_)
{
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 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
}); // end of element loop
}
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_)
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_)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
@@ -1791,16 +1791,16 @@ void VectorFEDivergenceIntegrator::AddMultTransposePA(const Vector &x,
}
}
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_)
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_)
{
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 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
}); // end of element loop
}
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_)
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_)
{
constexpr static int VDIM = 2;
+21 -21
View File
@@ -17,13 +17,13 @@ namespace mfem
{
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -67,13 +67,13 @@ void EAMassAssemble1D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -139,13 +139,13 @@ void EAMassAssemble2D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+56 -56
View File
@@ -155,12 +155,12 @@ void MassIntegrator::AssemblePA(const FiniteElementSpace &fes)
}
template<int T_D1D = 0, int T_Q1D = 0>
void PAMassAssembleDiagonal2D(const int NE,
const Array<double> &b,
const Vector &d,
Vector &y,
const int d1d = 0,
const int 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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -201,12 +201,12 @@ void PAMassAssembleDiagonal2D(const int NE,
}
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 0>
void SmemPAMassAssembleDiagonal2D(const int NE,
const Array<double> &b_,
const Vector &d_,
Vector &y_,
const int d1d = 0,
const int q1d = 0)
static 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 @@ void SmemPAMassAssembleDiagonal2D(const int NE,
}
template<int T_D1D = 0, int T_Q1D = 0>
void PAMassAssembleDiagonal3D(const int NE,
const Array<double> &b,
const Vector &d,
Vector &y,
const int d1d = 0,
const int 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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -336,12 +336,12 @@ void PAMassAssembleDiagonal3D(const int NE,
}
template<int T_D1D = 0, int T_Q1D = 0>
void SmemPAMassAssembleDiagonal3D(const int NE,
const Array<double> &b_,
const Vector &d_,
Vector &y_,
const int d1d = 0,
const int 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)
{
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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -661,14 +661,14 @@ void PAMassApply2D(const int NE,
}
template<int T_D1D = 0, int T_Q1D = 0, int T_NBZ = 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)
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)
{
MFEM_CONTRACT_VAR(bt_);
const int D1D = T_D1D ? T_D1D : d1d;
@@ -784,14 +784,14 @@ void SmemPAMassApply2D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -925,14 +925,14 @@ void PAMassApply3D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
MFEM_CONTRACT_VAR(bt_);
const int D1D = T_D1D ? T_D1D : d1d;
+28 -28
View File
@@ -22,12 +22,12 @@ namespace mfem
// PA Vector Diffusion Integrator
// PA Diffusion Assemble 2D kernel
void PAVectorDiffusionSetup2D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
const Vector &c,
Vector &op)
static 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 @@ void PAVectorDiffusionSetup2D(const int Q1D,
}
// PA Diffusion Assemble 3D kernel
void PAVectorDiffusionSetup3D(const int Q1D,
const int NE,
const Array<double> &w,
const Vector &j,
const Vector &c,
Vector &op)
static 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>
template<int T_D1D = 0, int T_Q1D = 0, int T_VDIM = 0> static
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>
const int T_Q1D = 0> static
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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -673,13 +673,13 @@ void PAVectorDiffusionDiagonal2D(const int NE,
}
template<int T_D1D = 0, int T_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)
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)
{
constexpr int DIM = 3;
const int D1D = T_D1D ? T_D1D : d1d;
+30 -30
View File
@@ -104,14 +104,14 @@ void VectorMassIntegrator::AssemblePA(const FiniteElementSpace &fes)
template<const int T_D1D = 0,
const int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -201,14 +201,14 @@ void PAVectorMassApply2D(const int NE,
template<const int T_D1D = 0,
const int T_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)
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)
{
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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -431,13 +431,13 @@ void PAVectorMassAssembleDiagonal2D(const int NE,
}
template<const int T_D1D = 0, const int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
-358
View File
@@ -1,358 +0,0 @@
// 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
-277
View File
@@ -1,277 +0,0 @@
// 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
-1
View File
@@ -380,7 +380,6 @@ 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!");
}
+2 -3
View File
@@ -329,7 +329,7 @@ void KellyErrorEstimator::ComputeEstimates()
error_estimates(e) = sqrt(factor * error_estimates(e));
}
total_error = error_estimates.Norml2();
total_error = error_estimates.Sum();
delete flux;
return;
}
@@ -452,10 +452,9 @@ void KellyErrorEstimator::ComputeEstimates()
auto pfes = dynamic_cast<ParFiniteElementSpace*>(xfes);
MFEM_VERIFY(pfes, "xfes is not a ParFiniteElementSpace pointer");
double process_local_error = pow(error_estimates.Norml2(),2.0);
double process_local_error = error_estimates.Sum();
MPI_Allreduce(&process_local_error, &total_error, 1, MPI_DOUBLE,
MPI_SUM, pfes->GetComm());
total_error = sqrt(total_error);
#endif // MFEM_USE_MPI
}
+18 -1204
View File
File diff suppressed because it is too large Load Diff
-219
View File
@@ -1313,64 +1313,6 @@ 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
{
@@ -1748,32 +1690,6 @@ 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
@@ -1912,10 +1828,6 @@ 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;
};
@@ -1940,66 +1852,6 @@ 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;
};
@@ -2093,77 +1945,6 @@ 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:
+15 -121
View File
@@ -33,9 +33,6 @@ 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");
}
@@ -577,7 +574,6 @@ 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.");
}
@@ -595,7 +591,6 @@ 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.");
}
@@ -1245,7 +1240,6 @@ 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.");
}
@@ -1263,7 +1257,6 @@ 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.");
}
@@ -1284,8 +1277,6 @@ 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.");
@@ -1302,8 +1293,6 @@ 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.");
@@ -1405,8 +1394,6 @@ 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.");
}
@@ -1423,8 +1410,6 @@ 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.");
}
@@ -1454,8 +1439,6 @@ 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.");
}
@@ -1472,8 +1455,6 @@ 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.");
}
@@ -1749,7 +1730,6 @@ 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);
@@ -1763,7 +1743,6 @@ 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];
@@ -1858,21 +1837,6 @@ 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
{
@@ -2112,12 +2076,9 @@ 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)
{
@@ -2238,21 +2199,6 @@ 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
{
@@ -2344,12 +2290,6 @@ 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
{
@@ -2493,22 +2433,6 @@ 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
{
@@ -2732,31 +2656,18 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
{
for (int i = 0; i + j <= pm2; i++)
{
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;
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][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;
TriDofOrd[0][k1 ] = k1;
TriDofOrd[0][k1+1] = k1 + 1;
// (0,2,1)
TriDofOrd[5][k0 ] = k5;
TriDofOrd[5][k0+1] = k5 + 1;
TriDofOrd[5][k1 ] = k2 + 1;
TriDofOrd[5][k1+1] = k2;
// 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.
}
}
}
@@ -2769,28 +2680,6 @@ 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;
}
}
@@ -2803,6 +2692,11 @@ 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)
+14 -16
View File
@@ -228,7 +228,8 @@ public:
const int btype = BasisType::GaussLobatto);
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type GeomType) const;
Geometry::Type GeomType) const
{ return H1_Elements[GeomType]; }
virtual int DofForGeometry(Geometry::Type GeomType) const
{ return H1_dof[GeomType]; }
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
@@ -301,7 +302,10 @@ public:
const int map_type = FiniteElement::VALUE);
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type GeomType) const;
Geometry::Type GeomType) const
{
return L2_Elements[GeomType];
}
virtual int DofForGeometry(Geometry::Type GeomType) const
{
if (L2_Elements[GeomType])
@@ -367,7 +371,8 @@ public:
const int ob_type = BasisType::GaussLegendre);
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type GeomType) const;
Geometry::Type GeomType) const
{ return RT_Elements[GeomType]; }
virtual int DofForGeometry(Geometry::Type GeomType) const
{ return RT_dof[GeomType]; }
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
@@ -425,7 +430,8 @@ public:
const int ob_type = BasisType::GaussLegendre);
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const
{ return ND_Elements[GeomType]; }
virtual int DofForGeometry(Geometry::Type GeomType) const
{ return ND_dof[GeomType]; }
@@ -523,10 +529,9 @@ private:
const BiLinear2DFiniteElement QuadrilateralFE;
const Linear3DFiniteElement TetrahedronFE;
const TriLinear3DFiniteElement ParallelepipedFE;
const LinearWedgeFiniteElement WedgeFE;
const LinearPyramidFiniteElement PyramidFE;
const H1_WedgeElement WedgeFE;
public:
LinearFECollection() : FiniteElementCollection(1) { }
LinearFECollection() : FiniteElementCollection(1), WedgeFE(1) { }
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
@@ -931,11 +936,10 @@ class Const3DFECollection : public FiniteElementCollection
private:
const P0TetFiniteElement TetrahedronFE;
const P0HexFiniteElement ParallelepipedFE;
const P0WdgFiniteElement WedgeFE;
const P0PyrFiniteElement PyramidFE;
const L2_WedgeElement WedgeFE;
public:
Const3DFECollection() : FiniteElementCollection(0) { }
Const3DFECollection() : FiniteElementCollection(0), WedgeFE(0) { }
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
@@ -956,8 +960,6 @@ class LinearDiscont3DFECollection : public FiniteElementCollection
{
private:
const Linear3DFiniteElement TetrahedronFE;
const LinearPyramidFiniteElement PyramidFE;
const LinearWedgeFiniteElement WedgeFE;
const TriLinear3DFiniteElement ParallelepipedFE;
public:
@@ -1034,8 +1036,6 @@ class ND1_3DFECollection : public FiniteElementCollection
private:
const Nedelec1HexFiniteElement HexahedronFE;
const Nedelec1TetFiniteElement TetrahedronFE;
const Nedelec1WdgFiniteElement WedgeFE;
const Nedelec1PyrFiniteElement PyramidFE;
public:
ND1_3DFECollection() : FiniteElementCollection(1) { }
@@ -1061,8 +1061,6 @@ private:
const P0QuadFiniteElement QuadrilateralFE;
const RT0HexFiniteElement HexahedronFE;
const RT0TetFiniteElement TetrahedronFE;
const RT0WdgFiniteElement WedgeFE;
const RT0PyrFiniteElement PyramidFE;
public:
RT0_3DFECollection() : FiniteElementCollection(1) { }
-1
View File
@@ -16,7 +16,6 @@
#include "geom.hpp"
#include "fe.hpp"
#include "fe_coll.hpp"
#include "doftrans.hpp"
#include "eltrans.hpp"
#include "coefficient.hpp"
#include "complex_fem.hpp"
+50 -323
View File
@@ -58,12 +58,9 @@ 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), elem_fos(NULL), bdr_elem_dof(NULL), bdr_elem_fos(NULL),
face_dof(NULL),
ndofs(0), nvdofs(0), nedofs(0), nfdofs(0), nbdofs(0), bdofs(NULL),
elem_dof(NULL), bdr_elem_dof(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)
@@ -72,7 +69,6 @@ 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;
@@ -263,36 +259,16 @@ void FiniteElementSpace::AdjustVDofs (Array<int> &vdofs)
}
}
DofTransformation *
FiniteElementSpace::GetElementVDofs(int i, Array<int> &vdofs) const
void FiniteElementSpace::GetElementVDofs(int i, Array<int> &vdofs) const
{
DofTransformation * doftrans = GetElementDofs(i, vdofs);
GetElementDofs(i, vdofs);
DofsToVDofs(vdofs);
if (vdim == 1 || doftrans == NULL)
{
return doftrans;
}
else
{
VDoFTrans.SetDofTransformation(*doftrans);
return &VDoFTrans;
}
}
DofTransformation *
FiniteElementSpace::GetBdrElementVDofs(int i, Array<int> &vdofs) const
void FiniteElementSpace::GetBdrElementVDofs(int i, Array<int> &vdofs) const
{
DofTransformation * doftrans = GetBdrElementDofs(i, vdofs);
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
@@ -331,39 +307,21 @@ 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
@@ -417,9 +375,7 @@ void FiniteElementSpace::BuildFaceToDofTable() const
void FiniteElementSpace::RebuildElementToDofTable()
{
delete elem_dof;
delete elem_fos;
elem_dof = NULL;
elem_fos = NULL;
BuildElementToDofTable();
}
@@ -1359,10 +1315,8 @@ const FaceQuadratureInterpolator
SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
const int coarse_ndofs, const Table &coarse_elem_dof,
const Table *coarse_elem_fos, const DenseTensor localP[]) const
const DenseTensor localP[]) const
{
/// TODO: Implement DofTransformation support
MFEM_VERIFY(mesh->GetLastOperation() == Mesh::REFINE, "");
Array<int> dofs, coarse_dofs, coarse_vdofs;
@@ -1445,8 +1399,7 @@ void FiniteElementSpace::GetLocalRefinementMatrices(
}
SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
const Table* old_elem_dof,
const Table* old_elem_fos)
const Table* old_elem_dof)
{
MFEM_VERIFY(GetNE() >= old_elem_dof->Size(),
"Previous mesh is not coarser.");
@@ -1459,16 +1412,13 @@ SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
}
return RefinementMatrix_main(old_ndofs, *old_elem_dof, old_elem_fos,
localP);
return RefinementMatrix_main(old_ndofs, *old_elem_dof, localP);
}
FiniteElementSpace::RefinementOperator::RefinementOperator
(const FiniteElementSpace* fespace, Table* old_elem_dof, Table* old_elem_fos,
int old_ndofs)
(const FiniteElementSpace* fespace, Table* old_elem_dof, 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.");
@@ -1482,14 +1432,12 @@ 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), old_elem_fos(NULL)
fespace(fespace), old_elem_dof(NULL)
{
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
@@ -1501,50 +1449,11 @@ 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
@@ -1553,7 +1462,7 @@ void FiniteElementSpace::RefinementOperator
Mesh* mesh = fespace->GetMesh();
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
Array<int> dofs, vdofs, old_dofs, old_vdofs, old_Fo;
Array<int> dofs, vdofs, old_dofs, old_vdofs;
int vdim = fespace->GetVDim();
int old_ndofs = width / vdim;
@@ -1568,53 +1477,18 @@ void FiniteElementSpace::RefinementOperator
subY.SetSize(lP.Height());
DofTransformation *doftrans = fespace->GetElementDofs(k, dofs);
fespace->GetElementDofs(k, dofs);
old_elem_dof->GetRow(emb.parent, old_dofs);
if (!doftrans)
for (int vd = 0; vd < vdim; vd++)
{
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;
}
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);
}
}
}
@@ -1630,12 +1504,12 @@ void FiniteElementSpace::RefinementOperator
Array<char> processed(fespace->GetVSize());
processed = 0;
Array<int> f_dofs, c_dofs, f_vdofs, c_vdofs, old_Fo;
Array<int> f_dofs, c_dofs, f_vdofs, c_vdofs;
int vdim = fespace->GetVDim();
int old_ndofs = width / vdim;
Vector subY, subX, subYt, subXt;
Vector subY, subX;
for (int k = 0; k < mesh->GetNE(); k++)
{
@@ -1643,77 +1517,30 @@ void FiniteElementSpace::RefinementOperator
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
const DenseMatrix &lP = localP[geom](emb.matrix);
DofTransformation * doftrans = fespace->GetElementDofs(k, f_dofs);
fespace->GetElementDofs(k, f_dofs);
old_elem_dof->GetRow(emb.parent, c_dofs);
if (!doftrans)
subY.SetSize(lP.Width());
for (int vd = 0; vd < vdim; vd++)
{
subY.SetSize(lP.Width());
f_dofs.Copy(f_vdofs);
fespace->DofsToVDofs(vd, f_vdofs);
c_dofs.Copy(c_vdofs);
fespace->DofsToVDofs(vd, c_vdofs, old_ndofs);
for (int vd = 0; vd < vdim; vd++)
x.GetSubVector(f_vdofs, subX);
for (int p = 0; p < f_dofs.Size(); ++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)
if (processed[DecodeDof(f_dofs[p])])
{
if (processed[DecodeDof(f_dofs[p])])
{
subX[p] = 0.0;
}
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();
}
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;
}
lP.MultTranspose(subX, subY);
y.AddElementVector(c_vdofs, subY);
}
for (int p = 0; p < f_dofs.Size(); ++p)
@@ -1723,7 +1550,6 @@ void FiniteElementSpace::RefinementOperator
}
}
/// TODO: Implement DofTransformation support
FiniteElementSpace::DerefinementOperator::DerefinementOperator(
const FiniteElementSpace *f_fes, const FiniteElementSpace *c_fes,
BilinearFormIntegrator *mass_integ)
@@ -1881,11 +1707,8 @@ void FiniteElementSpace::GetLocalDerefinementMatrices(Geometry::Type geom,
}
SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
const Table* old_elem_dof,
const Table* old_elem_fos)
const Table* old_elem_dof)
{
/// 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.");
@@ -1991,7 +1814,6 @@ void FiniteElementSpace::Constructor(Mesh *mesh, NURBSExtension *NURBSext,
this->ordering = (Ordering::Type) ordering;
elem_dof = NULL;
elem_fos = NULL;
face_dof = NULL;
sequence = 0;
@@ -2019,8 +1841,6 @@ void FiniteElementSpace::Constructor(Mesh *mesh, NURBSExtension *NURBSext,
UpdateNURBS();
cP = cR = cR_hp = NULL;
cP_is_set = false;
ConstructDoFTrans();
}
else
{
@@ -2028,41 +1848,9 @@ 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)
@@ -2158,9 +1946,7 @@ 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;
@@ -2258,8 +2044,6 @@ void FiniteElementSpace::Construct()
ndofs = nvdofs + nedofs + nfdofs + nbdofs;
ConstructDoFTrans();
// record the current mesh sequence number to detect refinement etc.
mesh_sequence = mesh->GetSequence();
@@ -2511,22 +2295,14 @@ int FiniteElementSpace::GetNVariants(int entity, int index) const
static const char* msg_orders_changed =
"Element orders changed, you need to Update() the space first.";
DofTransformation *
FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
{
MFEM_VERIFY(!orders_changed, msg_orders_changed);
if (elem_dof)
{
elem_dof->GetRow(elem, dofs);
if (DoFTrans[mesh->GetElementBaseGeometry(elem)])
{
Array<int> Fo;
elem_fos -> GetRow (elem, Fo);
DoFTrans[mesh->GetElementBaseGeometry(elem)]->SetFaceOrientations(Fo);
}
return DoFTrans[mesh->GetElementBaseGeometry(elem)];
return;
}
Array<int> V, E, Eo, F, Fo; // TODO: LocalArray
@@ -2550,11 +2326,6 @@ 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);
@@ -2612,7 +2383,6 @@ FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
dofs.Append(bbase + j);
}
}
return DoFTrans[mesh->GetElementBaseGeometry(elem)];
}
const FiniteElement *FiniteElementSpace::GetFE(int i) const
@@ -2645,27 +2415,18 @@ const FiniteElement *FiniteElementSpace::GetFE(int i) const
return FE;
}
DofTransformation *
FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs) const
void 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);
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)];
return;
}
Array<int> V, E, Eo, Fo; // TODO: LocalArray
int F, oF;
Array<int> V, E, Eo; // TODO: LocalArray
int F, Fo;
int dim = mesh->Dimension();
auto geom = mesh->GetBdrElementGeometry(bel);
@@ -2684,17 +2445,7 @@ 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, &oF);
if (DoFTrans[mesh->GetBdrElementBaseGeometry(bel)])
{
Fo.Append(oF);
DoFTrans[mesh->GetBdrElementBaseGeometry(bel)]->
SetFaceOrientations(Fo);
}
}
if (nf) { mesh->GetBdrElementFace(bel, &F, &Fo); }
dofs.SetSize(0);
dofs.Reserve(nv*V.Size() + ne*E.Size() + nf);
@@ -2727,15 +2478,13 @@ 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, oF);
const int *ind = fec->GetDofOrdering(geom, order, Fo);
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,
@@ -3045,8 +2794,6 @@ void FiniteElementSpace::Destroy()
}
E2BFQ_array.SetSize(0);
DestroyDoFTrans();
dof_elem_array.DeleteAll();
dof_ldof_array.DeleteAll();
@@ -3059,9 +2806,7 @@ void FiniteElementSpace::Destroy()
else
{
delete elem_dof;
delete elem_fos;
delete bdr_elem_dof;
delete bdr_elem_fos;
delete face_dof;
delete [] bdofs;
@@ -3069,15 +2814,6 @@ 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
{
@@ -3095,8 +2831,6 @@ void FiniteElementSpace::GetTransferOperator(
}
T.Reset(RefinementMatrix_main(coarse_fes.GetNDofs(),
coarse_fes.GetElementToDofTable(),
coarse_fes.
GetElementToFaceOrientationTable(),
localP));
}
else
@@ -3199,7 +2933,6 @@ 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;
@@ -3207,9 +2940,7 @@ 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;
}
@@ -3235,18 +2966,15 @@ void FiniteElementSpace::Update(bool want_transform)
{
if (Th.Type() != Operator::MFEM_SPARSEMAT)
{
Th.Reset(new RefinementOperator(this, old_elem_dof,
old_elem_fos, old_ndofs));
Th.Reset(new RefinementOperator(this, old_elem_dof, 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,
old_elem_fos));
Th.Reset(RefinementMatrix(old_ndofs, old_elem_dof));
}
break;
}
@@ -3254,7 +2982,7 @@ void FiniteElementSpace::Update(bool want_transform)
case Mesh::DEREFINE:
{
BuildConformingInterpolation();
Th.Reset(DerefinementMatrix(old_ndofs, old_elem_dof, old_elem_fos));
Th.Reset(DerefinementMatrix(old_ndofs, old_elem_dof));
if (cP && cR)
{
Th.SetOperatorOwner(false);
@@ -3269,7 +2997,6 @@ void FiniteElementSpace::Update(bool want_transform)
}
delete old_elem_dof;
delete old_elem_fos;
}
}
+7 -30
View File
@@ -16,7 +16,6 @@
#include "../linalg/sparsemat.hpp"
#include "../mesh/mesh.hpp"
#include "fe_coll.hpp"
#include "doftrans.hpp"
#include "restriction.hpp"
#include <iostream>
#include <unordered_map>
@@ -129,9 +128,7 @@ 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;
@@ -140,9 +137,6 @@ 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. */
@@ -195,9 +189,6 @@ protected:
void Construct();
void Destroy();
void ConstructDoFTrans();
void DestroyDoFTrans();
void BuildElementToDofTable() const;
void BuildBdrElementToDofTable() const;
void BuildFaceToDofTable() const;
@@ -292,19 +283,12 @@ 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*/,
Table *old_elem_fos/*takes ownership*/, int old_ndofs);
Table *old_elem_dof/*takes ownership*/, int old_ndofs);
RefinementOperator(const FiniteElementSpace *fespace,
const FiniteElementSpace *coarse_fes);
virtual void Mult(const Vector &x, Vector &y) const;
@@ -318,7 +302,6 @@ 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;
@@ -340,7 +323,6 @@ 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,
@@ -351,12 +333,10 @@ 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,
const Table* old_elem_fos);
SparseMatrix* RefinementMatrix(int old_ndofs, const Table* old_elem_dof);
/// Calculate GridFunction restriction matrix after mesh derefinement.
SparseMatrix* DerefinementMatrix(int old_ndofs, const Table* old_elem_dof,
const Table* old_elem_fos);
SparseMatrix* DerefinementMatrix(int old_ndofs, const Table* old_elem_dof);
/** @brief Return in @a localP the local refinement matrices that map
between fespaces after mesh refinement. */
@@ -634,11 +614,10 @@ public:
int GetBdrAttribute(int i) const { return mesh->GetBdrAttribute(i); }
/// Returns indices of degrees of freedom of element 'elem'.
virtual DofTransformation *GetElementDofs(int elem, Array<int> &dofs) const;
virtual void GetElementDofs(int elem, Array<int> &dofs) const;
/// Returns indices of degrees of freedom for boundary element 'bel'.
virtual DofTransformation *GetBdrElementDofs(int bel,
Array<int> &dofs) const;
virtual void 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. */
@@ -687,10 +666,10 @@ public:
static void AdjustVDofs(Array<int> &vdofs);
/// Returns indexes of degrees of freedom in array dofs for i'th element.
DofTransformation *GetElementVDofs(int i, Array<int> &vdofs) const;
void GetElementVDofs(int i, Array<int> &vdofs) const;
/// Returns indexes of degrees of freedom for i'th boundary element.
DofTransformation *GetBdrElementVDofs(int i, Array<int> &vdofs) const;
void 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;
@@ -716,8 +695,6 @@ 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; }
+7 -262
View File
@@ -11,19 +11,15 @@
#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",
"Pyramid"
};
{ "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube", "Prism" };
const double Geometry::Volume[NumGeom] =
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5, 1./3 };
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5 };
Geometry::Geometry()
{
@@ -143,28 +139,6 @@ 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;
@@ -193,10 +167,6 @@ 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);
@@ -204,7 +174,6 @@ 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;
@@ -213,7 +182,6 @@ 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);
{
@@ -242,14 +210,6 @@ 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()
@@ -273,7 +233,6 @@ 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(...)");
}
@@ -351,25 +310,6 @@ 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!");
}
@@ -431,10 +371,6 @@ 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!");
}
@@ -505,17 +441,6 @@ 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!");
}
@@ -630,16 +555,6 @@ 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!");
}
@@ -737,43 +652,6 @@ 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!");
}
@@ -848,17 +726,6 @@ 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 (...)");
}
@@ -877,13 +744,13 @@ void Geometry::JacToPerfJac(int GeomType, const DenseMatrix &J,
}
}
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::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5 };
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 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, 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::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::
Constants<Geometry::POINT>::Orient[1][1] = {{0}};
@@ -1030,30 +897,6 @@ 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()
{
@@ -1419,104 +1262,6 @@ 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;
+2 -22
View File
@@ -27,7 +27,6 @@ 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
{
@@ -35,7 +34,7 @@ public:
enum Type
{
INVALID = -1,
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM, PYRAMID,
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM,
NUM_GEOMETRIES
};
@@ -252,26 +251,7 @@ template <> struct Geometry::Constants<Geometry::PRISM>
};
};
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`.
// Defined in fe.cpp to ensure construction after 'mfem::WedgeFE'.
extern Geometry Geometries;
+54 -166
View File
@@ -255,8 +255,6 @@ void GridFunction::SumFluxAndCount(BilinearFormIntegrator &blfi,
GridFunction &u = *this;
ElementTransformation *Transf;
DofTransformation *udoftrans;
DofTransformation *fdoftrans;
FiniteElementSpace *ufes = u.FESpace();
FiniteElementSpace *ffes = flux.FESpace();
@@ -276,23 +274,15 @@ void GridFunction::SumFluxAndCount(BilinearFormIntegrator &blfi,
continue;
}
udoftrans = ufes->GetElementVDofs(i, udofs);
fdoftrans = ffes->GetElementVDofs(i, fdofs);
ufes->GetElementVDofs(i, udofs);
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);
@@ -374,7 +364,7 @@ void GridFunction::GetNodalValues(int i, Array<double> &nval, int vdim) const
int k;
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
fes->GetElementVDofs(i, vdofs);
const FiniteElement *FElem = fes->GetFE(i);
const IntegrationRule *ElemVert =
Geometries.GetVertices(FElem->GetGeomType());
@@ -384,10 +374,6 @@ 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)
{
@@ -417,7 +403,7 @@ double GridFunction::GetValue(int i, const IntegrationPoint &ip, int vdim)
const
{
Array<int> dofs;
DofTransformation * doftrans = fes->GetElementDofs(i, dofs);
fes->GetElementDofs(i, dofs);
fes->DofsToVDofs(vdim-1, dofs);
Vector DofVal(dofs.Size()), LocVec;
const FiniteElement *fe = fes->GetFE(i);
@@ -432,10 +418,6 @@ const
fe->CalcPhysShape(*Tr, DofVal);
}
GetSubVector(dofs, LocVec);
if (doftrans)
{
doftrans->InvTransformPrimal(LocVec);
}
return (DofVal * LocVec);
}
@@ -446,13 +428,9 @@ void GridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
const FiniteElement *FElem = fes->GetFE(i);
int dof = FElem->GetDof();
Array<int> vdofs;
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
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);
@@ -492,35 +470,30 @@ const
Array<int> dofs;
int n = ir.GetNPoints();
vals.SetSize(n);
DofTransformation * doftrans = fes->GetElementDofs(i, dofs);
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 (doftrans)
if (FElem->GetMapType() == FiniteElement::VALUE)
{
doftrans->InvTransformPrimal(loc_data);
for (int k = 0; k < n; k++)
{
FElem->CalcShape(ir.IntPoint(k), DofVal);
vals(k) = DofVal * loc_data;
}
}
for (int k = 0; k < n; k++)
if (FElem->GetMapType() == FiniteElement::VALUE)
else
{
ElementTransformation *Tr = fes->GetElementTransformation(i);
for (int k = 0; k < n; k++)
{
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;
}
Tr->SetIntPoint(&ir.IntPoint(k));
FElem->CalcPhysShape(*Tr, DofVal);
vals(k) = DofVal * loc_data;
}
}
}
void GridFunction::GetValues(int i, const IntegrationRule &ir, Vector &vals,
@@ -888,12 +861,11 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
Array<int> vdofs;
const FiniteElement *fe = NULL;
DofTransformation * doftrans = NULL;
switch (T.ElementType)
{
case ElementTransformation::ELEMENT:
doftrans = fes->GetElementVDofs(T.ElementNo, vdofs);
fes->GetElementVDofs(T.ElementNo, vdofs);
fe = fes->GetFE(T.ElementNo);
break;
case ElementTransformation::EDGE:
@@ -984,10 +956,6 @@ 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);
@@ -1030,14 +998,10 @@ void GridFunction::GetVectorValues(ElementTransformation &T,
int dof = FElem->GetDof();
Array<int> vdofs;
DofTransformation * doftrans = fes->GetElementVDofs(T.ElementNo, vdofs);
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)
@@ -1125,8 +1089,6 @@ 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;
@@ -1135,13 +1097,9 @@ void GridFunction::GetValuesFrom(const GridFunction &orig_func)
vdim = fes->GetVDim();
for (i = 0; i < ne; i++)
{
doftrans = fes->GetElementVDofs(i, vdofs);
orig_doftrans = orig_fes->GetElementVDofs(i, orig_vdofs);
fes->GetElementVDofs(i, vdofs);
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();
@@ -1159,10 +1117,6 @@ 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);
}
}
@@ -1172,10 +1126,8 @@ 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, loc_values_t, orig_loc_values, orig_loc_values_t;
Vector shape, loc_values, orig_loc_values;
int i, j, d, nbe, dof, odof, vdim;
nbe = fes->GetNBE();
@@ -1213,33 +1165,37 @@ void GridFunction::GetVectorFieldValues(
Array<int> vdofs;
ElementTransformation *transf;
int d, k, n, sdim, dof;
int d, j, k, n, sdim, dof, ind;
n = ir.GetNPoints();
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
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);
Vector loc_data, val(sdim);
GetSubVector(vdofs, loc_data);
if (doftrans)
{
doftrans->InvTransformPrimal(loc_data);
}
double a;
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++)
{
vals(k,d) = val(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;
}
}
}
@@ -1409,13 +1365,9 @@ void GridFunction::GetVectorGradientHat(
const FiniteElement *FElem = fes->GetFE(elNo);
int dim = FElem->GetDim(), dof = FElem->GetDof();
Array<int> vdofs;
DofTransformation * doftrans = fes->GetElementVDofs(elNo, vdofs);
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);
@@ -1454,13 +1406,9 @@ double GridFunction::GetDivergence(ElementTransformation &T) const
{
// Assuming RT-type space
Array<int> dofs;
DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
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();
}
@@ -1551,13 +1499,9 @@ void GridFunction::GetCurl(ElementTransformation &T, Vector &curl) const
{
// Assuming ND-type space
Array<int> dofs;
DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
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());
@@ -1699,12 +1643,8 @@ void GridFunction::GetGradients(ElementTransformation &tr,
DenseMatrix dshape(fe->GetDof(), fe->GetDim());
Vector lval, gh(fe->GetDim()), gcol;
Array<int> dofs;
DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
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++)
{
@@ -1784,8 +1724,6 @@ 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());
@@ -1796,19 +1734,11 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
{
Mi.AssembleElementMatrix2(*fes->GetFE(i), *avgs.FESpace()->GetFE(i),
*fes->GetElementTransformation(i), loc_mass);
tr_doftrans = fes->GetElementDofs(i, tr_dofs);
te_doftrans = avgs.FESpace()->GetElementDofs(i, te_dofs);
fes->GetElementDofs(i, tr_dofs);
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);
@@ -1823,12 +1753,8 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
void GridFunction::GetElementDofValues(int el, Vector &dof_vals) const
{
Array<int> dof_idx;
DofTransformation * doftrans = fes->GetElementVDofs(el, dof_idx);
fes->GetElementVDofs(el, dof_idx);
GetSubVector(dof_idx, dof_vals);
if (doftrans)
{
doftrans->InvTransformPrimal(dof_vals);
}
}
void GridFunction::ProjectGridFunction(const GridFunction &src)
@@ -1864,21 +1790,13 @@ void GridFunction::ProjectGridFunction(const GridFunction &src)
cached_geom = geom;
}
DofTransformation * src_doftrans = src.fes->GetElementVDofs(i, src_vdofs);
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()]);
}
DofTransformation * doftrans = fes->GetElementVDofs(i, dest_vdofs);
if (doftrans)
{
doftrans->TransformPrimal(dest_lvec);
}
fes->GetElementVDofs(i, dest_vdofs);
SetSubVector(dest_vdofs, dest_lvec);
}
}
@@ -1887,15 +1805,10 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
const Vector &lo_, const Vector &hi_)
{
Array<int> vdofs;
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
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.");
@@ -1912,10 +1825,6 @@ 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);
}
@@ -1923,14 +1832,10 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
double min_, double max_)
{
Array<int> vdofs;
DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
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();
@@ -1938,10 +1843,6 @@ 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;
}
@@ -2377,7 +2278,6 @@ 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)
{
@@ -2386,13 +2286,9 @@ void GridFunction::ProjectCoefficient(Coefficient &coeff)
for (int i = 0; i < fes->GetNE(); i++)
{
doftrans = fes->GetElementVDofs(i, vdofs);
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);
}
}
@@ -2438,17 +2334,11 @@ void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff)
Array<int> vdofs;
Vector vals;
DofTransformation * doftrans = NULL;
for (i = 0; i < fes->GetNE(); i++)
{
doftrans = fes->GetElementVDofs(i, vdofs);
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);
}
}
@@ -2511,7 +2401,6 @@ void GridFunction::ProjectCoefficient(Coefficient *coeff[])
double val;
const FiniteElement *fe;
ElementTransformation *transf;
// DofTransformation * doftrans;
Array<int> vdofs;
vdim = fes->GetVDim();
@@ -2521,7 +2410,6 @@ 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++)
{
-32
View File
@@ -910,9 +910,6 @@ 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;
@@ -933,7 +930,6 @@ 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;
@@ -980,7 +976,6 @@ 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;
@@ -1024,7 +1019,6 @@ IntegrationRules::~IntegrationRules()
DeleteIntRuleArray(TetrahedronIntRules);
DeleteIntRuleArray(CubeIntRules);
DeleteIntRuleArray(PrismIntRules);
DeleteIntRuleArray(PyramidIntRules);
}
@@ -1047,8 +1041,6 @@ 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;
@@ -1656,30 +1648,6 @@ 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)
{
-2
View File
@@ -323,7 +323,6 @@ private:
Array<IntegrationRule *> TriangleIntRules;
Array<IntegrationRule *> SquareIntRules;
Array<IntegrationRule *> TetrahedronIntRules;
Array<IntegrationRule *> PyramidIntRules;
Array<IntegrationRule *> PrismIntRules;
Array<IntegrationRule *> CubeIntRules;
@@ -352,7 +351,6 @@ 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);
+2 -11
View File
@@ -103,7 +103,6 @@ void LinearForm::Assemble()
{
Array<int> vdofs;
ElementTransformation *eltrans;
DofTransformation *doftrans;
Vector elemvect;
int i;
@@ -135,14 +134,10 @@ void LinearForm::Assemble()
if ( domain_integs_marker[k] == NULL ||
(*(domain_integs_marker[k]))[elem_attr-1] == 1 )
{
doftrans = fes -> GetElementVDofs (i, vdofs);
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);
}
}
@@ -179,7 +174,7 @@ void LinearForm::Assemble()
{
const int bdr_attr = mesh->GetBdrAttribute(i);
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
doftrans = fes -> GetBdrElementVDofs (i, vdofs);
fes -> GetBdrElementVDofs (i, vdofs);
eltrans = fes -> GetBdrElementTransformation (i);
for (int k=0; k < boundary_integs.Size(); k++)
{
@@ -189,10 +184,6 @@ void LinearForm::Assemble()
boundary_integs[k]->AssembleRHSElementVect(*fes->GetBE(i),
*eltrans, elemvect);
if (doftrans)
{
doftrans->TransformDual(elemvect);
}
AddElementVector (vdofs, elemvect);
}
}
+26 -26
View File
@@ -116,15 +116,15 @@ void VectorConvectionNLFIntegrator::AssemblePA(const FiniteElementSpace &fes)
// PA Convection NL 2D kernel
template<int T_D1D = 0, int T_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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -252,15 +252,15 @@ void PAConvectionNLApply2D(const int NE,
// PA Convection NL 3D kernel
template<int T_D1D = 0, int T_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)
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)
{
constexpr int VDIM = 3;
const int D1D = T_D1D ? T_D1D : d1d;
@@ -558,14 +558,14 @@ void PAConvectionNLApply3D(const int NE,
}
template<int T_D1D = 0, int T_Q1D = 0, int T_MAX_D1D =0, int T_MAX_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)
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)
{
constexpr int VDIM = 3;
const int D1D = T_D1D ? T_D1D : d1d;
+1 -3
View File
@@ -321,7 +321,6 @@ const
{
X.SetSpace(pfes);
Y.SetSpace(pfes);
Ytmp.SetSize(pfes->GetTrueVSize());
}
X.Distribute(&x);
@@ -336,8 +335,7 @@ const
" implemented");
mat->Mult(X, Y);
}
pfes->GetProlongationMatrix()->MultTranspose(Y, Ytmp);
y.Add(a,Ytmp);
pfes->Dof_TrueDof_Matrix()->MultTranspose(a, Y, 1.0, y);
}
void ParBilinearForm::FormLinearSystem(
-1
View File
@@ -33,7 +33,6 @@ protected:
/// Auxiliary objects used in TrueAddMult().
mutable ParGridFunction X, Y;
mutable Vector Ytmp;
OperatorHandle p_mat, p_mat_e;
+53 -319
View File
@@ -128,9 +128,6 @@ void ParFiniteElementSpace::ParInit(ParMesh *pm)
{
ApplyLDofSigns(*elem_dof);
}
// Check for shared trianglular faces with interior Nedelec DoFs
CheckNDSTriaDofs();
}
void ParFiniteElementSpace::Construct()
@@ -467,53 +464,32 @@ void ParFiniteElementSpace::ApplyLDofSigns(Table &el_dof) const
ApplyLDofSigns(all_dofs);
}
DofTransformation *
ParFiniteElementSpace::GetElementDofs(int i, Array<int> &dofs) const
void ParFiniteElementSpace::GetElementDofs(int i, Array<int> &dofs) const
{
if (elem_dof)
{
elem_dof->GetRow(i, dofs);
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;
return;
}
DofTransformation * doftrans = FiniteElementSpace::GetElementDofs(i, dofs);
FiniteElementSpace::GetElementDofs(i, dofs);
if (Conforming())
{
ApplyLDofSigns(dofs);
}
return doftrans;
}
DofTransformation *
ParFiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
void ParFiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
{
if (bdr_elem_dof)
{
bdr_elem_dof->GetRow(i, dofs);
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;
return;
}
DofTransformation * doftrans =
FiniteElementSpace::GetBdrElementDofs(i, dofs);
FiniteElementSpace::GetBdrElementDofs(i, dofs);
if (Conforming())
{
ApplyLDofSigns(dofs);
}
return doftrans;
}
int ParFiniteElementSpace::GetFaceDofs(int i, Array<int> &dofs,
@@ -681,267 +657,60 @@ 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; }
if (!nd_strias)
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++)
{
// 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++)
int ltdof = GetLocalTDofNumber(i);
if (ltdof >= 0)
{
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;
j_diag[diag_counter++] = ltdof;
}
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;
cmap_j_offd[offd_counter].one = GetGlobalTDofNumber(i);
cmap_j_offd[offd_counter].two = offd_counter;
offd_counter++;
}
P = new HypreParMatrix(MyComm, MyRank, NRanks, row_starts, col_starts,
i_diag, j_diag, i_offd, j_offd,
cmap, 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++)
{
// Some shared dofs will be linear combinations of others
int ldof = GetVSize();
int ltdof = TrueVSize();
HYPRE_Int gdof = -1;
HYPRE_Int gtdof = -1;
MPI_Allreduce(&ldof, &gdof, 1, HYPRE_MPI_INT, MPI_SUM, MyComm);
MPI_Allreduce(&ltdof, &gtdof, 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);
cmap[i] = cmap_j_offd[i].one;
j_offd[cmap_j_offd[i].two] = i;
}
P = new HypreParMatrix(MyComm, MyRank, NRanks, row_starts, col_starts,
i_diag, j_diag, i_offd, j_offd, cmap, offd_counter);
SparseMatrix Pdiag;
P->GetDiag(Pdiag);
R = Transpose(Pdiag);
@@ -1144,8 +913,6 @@ const Operator *ParFiniteElementSpace::GetProlongationMatrix() const
{
if (Pconf) { return Pconf; }
if (nd_strias) { return Dof_TrueDof_Matrix(); }
if (NRanks == 1)
{
Pconf = new IdentityOperator(GetTrueVSize());
@@ -1449,29 +1216,10 @@ void ParFiniteElementSpace::ExchangeFaceNbrData()
delete [] requests;
}
DofTransformation *ParFiniteElementSpace::GetFaceNbrElementVDofs(
void 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
@@ -1530,17 +1278,12 @@ 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()
@@ -2783,8 +2526,7 @@ 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_fos)
const Table* old_elem_dof)
{
MFEM_VERIFY(Nonconforming(), "Only supported for nonconforming meshes.");
MFEM_VERIFY(old_dof_offsets.Size(), "ParFiniteElementSpace::Update needs to "
@@ -2909,8 +2651,7 @@ struct DerefDofMessage
HypreParMatrix*
ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
const Table* old_elem_dof,
const Table *old_elem_fos)
const Table* old_elem_dof)
{
int nrk = HYPRE_AssumedPartitionCheck() ? 2 : NRanks;
@@ -3266,16 +3007,13 @@ 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);
}
@@ -3297,25 +3035,22 @@ void ParFiniteElementSpace::Update(bool want_transform)
{
if (Th.Type() != Operator::MFEM_SPARSEMAT)
{
Th.Reset(new RefinementOperator(this, old_elem_dof,
old_elem_fos, old_ndofs));
Th.Reset(new RefinementOperator(this, old_elem_dof, 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, old_elem_fos));
Th.Reset(RefinementMatrix(old_ndofs, old_elem_dof));
}
break;
}
case Mesh::DEREFINE:
{
Th.Reset(ParallelDerefinementMatrix(old_ndofs, old_elem_dof,
old_elem_fos));
Th.Reset(ParallelDerefinementMatrix(old_ndofs, old_elem_dof));
if (Nonconforming())
{
Th.SetOperatorOwner(false);
@@ -3327,7 +3062,7 @@ void ParFiniteElementSpace::Update(bool want_transform)
case Mesh::REBALANCE:
{
Th.Reset(RebalanceMatrix(old_ndofs, old_elem_dof, old_elem_fos));
Th.Reset(RebalanceMatrix(old_ndofs, old_elem_dof));
break;
}
@@ -3336,7 +3071,6 @@ void ParFiniteElementSpace::Update(bool want_transform)
}
delete old_elem_dof;
delete old_elem_fos;
}
}
+5 -17
View File
@@ -87,12 +87,6 @@ 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); }
@@ -180,16 +174,14 @@ 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_fos);
const Table* old_elem_dof);
/** 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_fos);
const Table *old_elem_dof);
/// Updates the internal mesh pointer. @warning @a new_mesh must be
/// <b>topologically identical</b> to the existing mesh. Used if the address
@@ -210,8 +202,6 @@ 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
@@ -289,10 +279,10 @@ public:
virtual int GetTrueVSize() const { return ltdof_size; }
/// Returns indexes of degrees of freedom in array dofs for i'th element.
virtual DofTransformation *GetElementDofs(int i, Array<int> &dofs) const;
virtual void GetElementDofs(int i, Array<int> &dofs) const;
/// Returns indexes of degrees of freedom for i'th boundary element.
virtual DofTransformation *GetBdrElementDofs(int i, Array<int> &dofs) const;
virtual void 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. */
@@ -392,7 +382,7 @@ public:
// Face-neighbor functions
void ExchangeFaceNbrData();
int GetFaceNbrVSize() const { return num_face_nbr_dofs; }
DofTransformation *GetFaceNbrElementVDofs(int i, Array<int> &vdofs) const;
void 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;
@@ -407,8 +397,6 @@ 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.
+2 -12
View File
@@ -325,14 +325,9 @@ void ParGridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
if (nbr_el_no >= 0)
{
Array<int> dofs;
DofTransformation * doftrans = pfes->GetFaceNbrElementVDofs(nbr_el_no,
dofs);
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)
@@ -442,17 +437,12 @@ void ParGridFunction::GetVectorValue(ElementTransformation &T,
}
Array<int> vdofs;
DofTransformation * doftrans = pfes->GetFaceNbrElementVDofs(nbr_el_no,
vdofs);
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
View File
@@ -27,14 +27,14 @@ namespace quadrature_interpolator
{
template<int T_D1D = 0, int T_Q1D = 0, int MAX_D1D = 0, int MAX_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)
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)
{
constexpr int DIM = 2;
static constexpr int NBZ = 1;
@@ -79,15 +79,15 @@ 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>
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
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
{
constexpr int DIM = 3;
static constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
+14 -14
View File
@@ -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>
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 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 @@ 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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+18 -18
View File
@@ -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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
@@ -139,15 +139,15 @@ 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>
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)
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)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
+20 -20
View File
@@ -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>
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)
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)
{
using QI = QuadratureInterpolator;
@@ -209,16 +209,16 @@ 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>
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)
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)
{
using QI = QuadratureInterpolator;
+1 -1
View File
@@ -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.
inline void device_copy(double *d_dest, const double *d_src, int size)
static 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
View File
@@ -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}
+1 -2
View File
@@ -175,8 +175,7 @@ const Operator &InterpolationGridTransfer::ForwardOperator()
localP[elem_geoms[i]]);
}
F.Reset(ran_fes.RefinementMatrix_main(
dom_fes.GetNDofs(), dom_fes.GetElementToDofTable(),
dom_fes.GetElementToFaceOrientationTable(), localP));
dom_fes.GetNDofs(), dom_fes.GetElementToDofTable(), localP));
}
else
{
-4
View File
@@ -21,16 +21,12 @@
#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
+1 -7
View File
@@ -164,13 +164,7 @@ __device__ void abort_msg(T & msg)
#endif
// Abort inside a device kernel
#if defined(__CUDA_ARCH__) && defined(_WIN32)
#define MFEM_ABORT_KERNEL(msg) \
{ \
printf(msg); \
__debugbreak(); \
}
#elif defined(__CUDA_ARCH__)
#if defined(__CUDA_ARCH__)
#define MFEM_ABORT_KERNEL(msg) \
{ \
printf(msg); \
-1
View File
@@ -13,7 +13,6 @@
#define MFEM_FORALL_HPP
#include "../config/config.hpp"
#include "annotation.hpp"
#include "error.hpp"
#include "backends.hpp"
#include "device.hpp"
+1 -7
View File
@@ -79,13 +79,7 @@ int isockstream::establish()
int on=1;
setsockopt(port, SOL_SOCKET, SO_REUSEADDR, (char *)(&on), sizeof(on));
if (bind(
#ifdef _WIN32
(SOCKET)port
#else
port
#endif
,(const sockaddr*)&sa,(socklen_t)sizeof(struct sockaddr_in)) < 0)
if (bind(port,(const sockaddr*)&sa,(socklen_t)sizeof(struct sockaddr_in)) < 0)
{
mfem::err << "isockstream::establish(): bind() failed!" << endl;
close(port);
-5
View File
@@ -118,11 +118,6 @@ 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)
+2996 -3325
View File
File diff suppressed because it is too large Load Diff
-6
View File
@@ -787,16 +787,10 @@ 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;
}
-7
View File
@@ -763,13 +763,6 @@ 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)
{
+1 -63
View File
@@ -88,9 +88,7 @@ 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);
@@ -107,9 +105,7 @@ 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
@@ -132,9 +128,7 @@ 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_();
@@ -168,9 +162,7 @@ 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);
@@ -691,10 +683,8 @@ 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);
@@ -736,10 +726,8 @@ 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);
@@ -782,10 +770,8 @@ 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);
@@ -831,10 +817,8 @@ 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);
@@ -947,10 +931,8 @@ 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);
@@ -1007,10 +989,8 @@ 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++)
@@ -1197,13 +1177,6 @@ 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();
@@ -1290,7 +1263,6 @@ 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)))
@@ -1325,12 +1297,10 @@ 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)))
@@ -1369,7 +1339,6 @@ void HypreParMatrix::CopyColStarts()
{
hypre_ParCSRMatrixOwnsColStarts(A) = 1;
}
#endif
}
void HypreParMatrix::GetDiag(Vector &diag) const
@@ -1822,14 +1791,9 @@ 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;
@@ -1984,22 +1948,18 @@ 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);
@@ -2034,12 +1994,7 @@ 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));
}
@@ -2548,14 +2503,11 @@ 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);
@@ -2564,7 +2516,6 @@ HypreParMatrix * RAP(const HypreParMatrix *A, const HypreParMatrix *P)
{
hypre_ParCSRMatrixSetColStartsOwner(*P, 1);
}
#endif
#endif
hypre_ParCSRMatrixSetNumNonzeros(rap);
@@ -2585,16 +2536,13 @@ 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);
@@ -2607,7 +2555,6 @@ HypreParMatrix * RAP(const HypreParMatrix * Rt, const HypreParMatrix *A,
{
hypre_ParCSRMatrixSetColStartsOwner(*Rt, 1);
}
#endif
#endif
hypre_ParCSRMatrixSetNumNonzeros(rap);
@@ -3197,12 +3144,8 @@ 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);
}
@@ -3216,12 +3159,8 @@ 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]
@@ -5058,11 +4997,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;
@@ -5070,7 +5009,6 @@ 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;
-12
View File
@@ -508,10 +508,8 @@ 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);
@@ -1004,17 +1002,10 @@ 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 */
@@ -1925,12 +1916,9 @@ 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;
}
+1169
View File
File diff suppressed because it is too large Load Diff
+244
View File
@@ -0,0 +1,244 @@
#ifndef MFEM_IMEX
#define MFEM_IMEX
#include "../config/config.hpp"
#include "operator.hpp"
#include "ode.hpp"
#include <vector>
namespace mfem
{
/** Class for spatial discretizations of a PDE resulting in the time-dependent,
nonlinear set of ODEs with implicit-explicit additive partition
M*du/dt = N_E(u,t) + N_I(u,t).
MFEM typically treats time integration as
du/dt = F^{-1} G(u),
Here F represents what MFEM calls the implicit part, and G represents the
explicit part; in simpler terms, F is typically just a mass matrix.
For BDF schemes, the ImplicitSolve function is a bit different, and it is
more natural to apply M and M^{-1} separate from the Mult functions, so we
include MassMult and MassInv as functions to be provided, and do not include
such actions in the Mult functions. */
class IMEXTimeDependentOperator : public TimeDependentOperator
{
protected:
mutable Vector temp; // Auxillary vector
public:
// Sets linearly implicit to false by default
IMEXTimeDependentOperator(int n, double t=0.0, Type type=EXPLICIT)
: TimeDependentOperator(n, t, type) { };
~IMEXTimeDependentOperator() { };
/** Apply action of implicit part of operator y <- N_I(x,y). For fully
implicit schemes, this just corresponds to applying the time-dependent
(nonlinear) operator.
PREVIOUSLY CALLED ExplicitMult */
virtual void ImplicitMult(const Vector &x, Vector &y) const = 0;
/** Apply action of explicit part of operator y <- N_E(x,y) */
virtual void ExplicitMult(const Vector &x, Vector &y) const { y = 0.0; };
/** Solve k = f(x+dt*k) for stage k, where f() is the implicit part of
the operator. Used in Runge-Kutta methods. */
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k)
{ mfem::mfem_error("IMEXTimeDependentOperator::ImplicitSolve() is not overridden!"); };
/** Solve M*x - dtf(x, t) = b for solution x, where f() is the implicit
part of the operator. Used in BDF methods. */
virtual void ImplicitSolve2(const double dt, const Vector &b, Vector &x)
{ mfem::mfem_error("IMEXTimeDependentOperator::ImplicitSolve2() is not overridden!"); };
/** Apply action mass matrix, y = M*x.
If not re-implemented, this method simply generates an error.
PREVIOUSLY CALLED ImplictMult */
virtual void MassMult(const Vector &x, Vector &y) const = 0;
/** Apply action of inverse of mass matrix, y = M^{-1}*x.
If not re-implemented, this method simply generates an error.
NOTE : only necessary for PolyIMEX methods. */
virtual void MassInv(const Vector &x, Vector &y) const = 0;
};
/** Class holding RK Butcher tableau, and associated data required by
implicit and explicit splitting. */
class IMEXRKData
{
public:
// Implicit Runge Kutta type. Enumeration (s, \sigma, p):
// - s = number of implicit stages
// - \sigma = number of explicit stages
// - p = order
// In this notation, when s = \sigma, we satisfy (2.3)/(2.4) in
// Ascher et al., and do not need to compute the final explicit
// stage. This is represented in the stiffly_accurate boolean.
enum Type {
IMEX111 = 111,
IMEX121 = 121,
IMEX122 = 122,
IMEX222 = 222,
IMEX232 = 232,
IMEX233 = 233,
IMEX443 = 443,
// ARK ESDIRK-ERK schemes: enumeration (s,p), for total number of
// stages s.
ARK43 = -43
};
IMEXRKData() : s(-1) { };
IMEXRKData(Type ID_) : ID(ID_) { SetData(); };
~IMEXRKData() { };
/// Set explicit RK data
void SetExplicitData(DenseMatrix Ae_, Vector be_, Vector ce_);
/// Set implicit RK data
void SetImplicitData(DenseMatrix Ai_, Vector bi_, Vector ci_, bool esdirk_=false);
void SetID(Type ID_) { ID=ID_; SetData(); };
bool esdirk;
bool stiffly_accurate;
bool use_final_exp_stage;
int s;
DenseMatrix Ai; // Implicit Butcher matrix
Vector bi; // Implicit Butcher tableau weights
DenseMatrix Ae; // Explicit Butcher matrix
Vector be; // Explicit Butcher tableau weights
Vector c0; // Butcher tableau nodes (same for implicit and explicit!)
private:
Type ID;
void SetData();
void InitData();
};
/** Class for two-part additive IMEX RK method, where explicit and implicit
stage vectors are stored. Assume same abscissae, {c}, for both schemes.
Butcher Data must be provided either in a custom IMEXRKData object, or
using the IMEXRKData::Type for predefined tableaux. */
class IMEXRK : public ODESolver
{
protected:
IMEXRKData tableaux;
std::vector< Vector *> exp_stages;
std::vector< Vector *> imp_stages;
IMEXTimeDependentOperator *imex; // Spatial discretization.
public:
IMEXRK(IMEXRKData tableaux_) : ODESolver(), tableaux(tableaux_) { };
IMEXRK(IMEXRKData::Type type_) : ODESolver(), tableaux(type_) { };
~IMEXRK();
void Init(IMEXTimeDependentOperator &_imex);
void Step(Vector &x, double &t, double &dt) override;
};
/** Class holding BDF integrator data. Setting alpha < 0 (the default
constructor) defines alpha = 2/(q-1), corresponding to classical BDF
of order q. */
class BDFData
{
public:
enum Type {
BDF1 = 01, BDF2 = 02, BDF3 = 03, BDF4 = 04,
IMEX_BDF1 = 11, IMEX_BDF2 = 12, IMEX_BDF3 = 13,
IMEX_BDF4 = 14
};
BDFData() { };
BDFData(Type ID_, double alpha_=-1) : ID(ID_), alpha(alpha_) { SetData(); };
~BDFData() { };
int GetID() { return static_cast<int>(ID); };
void SetID(Type ID_, double alpha_=-1)
{
ID=ID_;
alpha = alpha_;
SetData();
};
void Print()
{
std::cout << "q = " << q << "\n";
std::cout << "alpha = " << alpha << "\n";
std::cout << "A:\n";
A.PrintMatlab();
std::cout << "Be:\n";
Be.PrintMatlab();
std::cout << "Bi:\n";
Bi.Print();
std::cout << "z:\n";
z0.Print();
};
double alpha;
int q; // Number of previous values stored
bool shifted_nodes; // false = clssical BDF, true = Polynomial BDF w/ shifted nodes
DenseMatrix A; // Previous solution coefficients
Vector Bi; // Implicit coefficients
DenseMatrix Be; // Explicit coefficients
Vector z0;
private:
Type ID;
void SetData();
void InitData();
};
/** Class for IMEX-BDF methods, including classical IMEX-BDF and IMEX-
Polynomial-BDF (IMEX-PBDF). IMEX-PBDF methods have an additional
alpha parameter, where larger alpha leads to smaller stability
regions and a smaller leading accuracy constant, while smaller
alpha leads to larger stabiltiy regions and a larger accuracy
constant. For classical methods, there are two implementations:
- ClassicalStep() stores previous solutions and the explicit
part of the operator evaluated on the solution, and
- ClassicalStepNoStore() does not store the explicit
component, but must re-evaluate q times during each time
step.
This option can be set via the recompute_exp input. The type of
scheme must be set through the BDFData structure or BDFData::Type.
There is also an option to use pointwise Lagrange interpolating
polynomials to provide an initial guess for the ImplicitSolve. This
is set via InterpolateGuess(). This option is only implemented for
PBDF. */
class IMEXBDF : public ODESolver
{
private:
BDFData data;
bool recompute_exp;
bool interpolate;
int initialized;
double dt_prev;
std::vector< Vector*> sols;
std::vector< Vector*> exp_sols;
IMEXTimeDependentOperator *imex; // Spatial discretization
IMEXRK *RKsolver;
std::vector<double> exp_nodes;
void AlphaStep(Vector &x, double &t, double &dt);
void ClassicalStep(Vector &x, double &t, double &dt);
void ClassicalStepNoStore(Vector &x, double &t, double &dt);
public:
IMEXBDF(BDFData data_, bool recompute_exp_=false) :
ODESolver(), data(data_), recompute_exp(recompute_exp_),
interpolate(false) { };
IMEXBDF(BDFData::Type scheme, bool recompute_exp_=false) :
ODESolver(), recompute_exp(recompute_exp_), interpolate(false)
{ data.SetID(scheme); };
IMEXBDF(BDFData::Type scheme, double alpha) :
ODESolver(), interpolate(false), recompute_exp(false)
{ data.SetID(scheme, alpha); };
~IMEXBDF();
void Init(IMEXTimeDependentOperator &_imex);
void Step(Vector &x, double &t, double &dt);
void InterpolateGuess() {interpolate = true; };
};
}
#endif
+1 -1
View File
@@ -378,7 +378,7 @@ void Swap(T &a, T &b)
b = tmp;
}
constexpr double Epsilon = std::numeric_limits<double>::epsilon();
const double Epsilon = std::numeric_limits<double>::epsilon();
/// Utility function used in CalcSingularvalue<3>.
MFEM_HOST_DEVICE static inline
+1
View File
@@ -31,6 +31,7 @@
#include "invariants.hpp"
#include "constraints.hpp"
#include "auxiliary.hpp"
#include "imex.hpp"
#ifdef MFEM_USE_AMGX
#include "amgxsolver.hpp"
+1 -1
View File
@@ -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));
+1 -1
View File
@@ -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 caliper ginkgo hiop petsc pumi sundials superlu
EXAMPLE_SUBDIRS = amgx ginkgo hiop petsc pumi sundials superlu
EXAMPLE_DIRS := examples $(addprefix examples/,$(EXAMPLE_SUBDIRS))
EXAMPLE_TEST_DIRS := examples
-2
View File
@@ -19,7 +19,6 @@ set(SRCS
ncmesh.cpp
nurbs.cpp
point.cpp
pyramid.cpp
quadrilateral.cpp
segment.cpp
tetrahedron.cpp
@@ -39,7 +38,6 @@ set(HDRS
ncmesh.hpp
nurbs.hpp
point.hpp
pyramid.hpp
quadrilateral.hpp
segment.hpp
tetrahedron.hpp
+1 -1
View File
@@ -39,7 +39,7 @@ public:
/// Constants for the classes derived from Element.
enum Type { POINT, SEGMENT, TRIANGLE, QUADRILATERAL,
TETRAHEDRON, HEXAHEDRON, WEDGE, PYRAMID
TETRAHEDRON, HEXAHEDRON, WEDGE
};
/// Default element constructor.
+36 -335
View File
@@ -335,7 +335,6 @@ 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;
@@ -736,31 +735,6 @@ 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)
{
@@ -807,29 +781,6 @@ 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)
@@ -911,19 +862,10 @@ 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_ABORT("Mesh::GetLocalFaceTransformation not defined for "
"face type " << face_type
<< " and element type " << elem_type << "\n");
MFEM_ASSERT(elem_type == Element::WEDGE, "");
GetLocalTriToWdgTransformation(Transf, info);
}
break;
@@ -932,19 +874,10 @@ 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_ABORT("Mesh::GetLocalFaceTransformation not defined for "
"face type " << face_type
<< " and element type " << elem_type << "\n");
MFEM_ASSERT(elem_type == Element::WEDGE, "");
GetLocalQuadToWdgTransformation(Transf, info);
}
break;
}
@@ -1437,20 +1370,6 @@ 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)
{
@@ -1504,25 +1423,6 @@ 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);
@@ -2792,16 +2692,11 @@ 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[9];
int ind[8];
// Sets vertices and the corresponding coordinates
for (z = 0; z <= nz; z++)
@@ -2817,25 +2712,8 @@ 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)
@@ -2850,14 +2728,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);
}
@@ -2870,12 +2748,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)
@@ -2886,11 +2764,6 @@ 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);
@@ -2906,10 +2779,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);
@@ -2929,10 +2802,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);
@@ -2952,10 +2825,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);
@@ -2971,10 +2844,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);
@@ -2990,10 +2863,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);
@@ -3009,8 +2882,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)
@@ -3555,7 +3428,6 @@ 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);
}
@@ -3648,15 +3520,6 @@ 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;
@@ -4111,12 +3974,6 @@ 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++)
{
@@ -5197,19 +5054,6 @@ 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);
@@ -6292,22 +6136,6 @@ 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++)
@@ -6400,20 +6228,6 @@ 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++)
@@ -6488,22 +6302,6 @@ 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
@@ -7840,22 +7638,8 @@ 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))
{
@@ -7911,7 +7695,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 + 2 * pyr_counter);
new_elements.SetSize(8 * NumOfElements);
CoarseFineTr.embeddings.SetSize(new_elements.Size());
hex_counter = 0;
@@ -8177,73 +7961,6 @@ 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);
@@ -8375,7 +8092,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, D = -1.0;
static const double A = 0.0, B = 0.5, C = 1.0;
static double tet_children[3*4*16] =
{
A,A,A, B,A,A, A,B,A, A,A,B,
@@ -8401,19 +8118,6 @@ 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,
@@ -8439,8 +8143,6 @@ 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]
@@ -8457,7 +8159,7 @@ void Mesh::UniformRefinement3D_base(Array<int> *f2qf_ptr, DSTable *v_to_v_p,
}
NumOfVertices = vertices.Size();
NumOfElements = 8 * NumOfElements + 2 * pyr_counter;
NumOfElements = 8 * NumOfElements;
NumOfBdrElements = 4 * NumOfBdrElements;
GetElementToFaceTable();
@@ -9041,7 +8743,7 @@ void Mesh::GeneralRefinement(const Array<Refinement> &refinements,
else if (nonconforming < 0)
{
// determine if nonconforming refinement is suitable
if ((meshgen & 2) || (meshgen & 4) || (meshgen & 8))
if ((meshgen & 2) || (meshgen & 4))
{
nonconforming = 1; // tensor product elements and wedges
}
@@ -9825,7 +9527,6 @@ 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;
+1 -19
View File
@@ -177,7 +177,6 @@ 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];
@@ -196,7 +195,6 @@ 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 };
@@ -375,17 +373,11 @@ 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. */
@@ -665,15 +657,11 @@ 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);
@@ -841,16 +829,10 @@ 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.
*/
@@ -1245,7 +1227,7 @@ public:
satisfy: v0 < min(v1, v2).
@note Refinement does not work after a call to this method! */
MFEM_DEPRECATED virtual void ReorientTetMesh();
virtual void ReorientTetMesh();
int *CartesianPartitioning(int nxyz[]);
int *GeneratePartitioning(int nparts, int part_method = 1);
-1
View File
@@ -27,7 +27,6 @@
#include "mesh_operators.hpp"
#include "nurbs.hpp"
#include "wedge.hpp"
#include "pyramid.hpp"
#ifdef MFEM_USE_MESQUITE
#include "mesquite.hpp"
+3 -18
View File
@@ -352,11 +352,6 @@ 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] =
@@ -519,7 +514,8 @@ 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;
@@ -550,8 +546,6 @@ 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;
@@ -1400,10 +1394,6 @@ 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;
@@ -1458,7 +1448,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::PYRAMID)
type == Element::HEXAHEDRON)
{
MFEM_VERIFY(nx > 0 && ny > 0 && nz > 0 &&
sx > 0.0 && sy > 0.0 && sz > 0.0,
@@ -2455,10 +2445,6 @@ 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;
@@ -2680,7 +2666,6 @@ 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
View File
@@ -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;
}
+4 -243
View File
@@ -34,7 +34,6 @@ 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)
@@ -106,8 +105,7 @@ ParMesh& ParMesh::operator=(ParMesh &&mesh)
ParMesh::ParMesh(MPI_Comm comm, Mesh &mesh, int *partitioning_,
int part_method)
: face_nbr_el_to_face(NULL)
, glob_elem_offset(-1)
: glob_elem_offset(-1)
, glob_offset_sequence(-1)
, gtopo(comm)
{
@@ -854,7 +852,6 @@ 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)
@@ -921,8 +918,7 @@ void ParMesh::FinalizeParTopo()
}
ParMesh::ParMesh(MPI_Comm comm, istream &input, bool refine)
: face_nbr_el_to_face(NULL)
, glob_elem_offset(-1)
: glob_elem_offset(-1)
, glob_offset_sequence(-1)
, gtopo(comm)
{
@@ -1133,7 +1129,6 @@ 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;
@@ -2078,11 +2073,6 @@ void ParMesh::ExchangeFaceNbrData()
ExchangeFaceNbrData(gr_sface, s2l_face);
if (Dim == 3)
{
GetFaceNbrElementToFaceTable();
}
if (del_tables) { delete gr_sface; }
if ( have_face_nbr_data ) { return; }
@@ -2151,8 +2141,6 @@ 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);
@@ -2182,9 +2170,7 @@ void ParMesh::ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
send_face_nbr_vertices.AddAColumnInRow(fn);
}
const int nf = elements[el]->GetNFaces();
send_face_nbr_elemdata.AddColumnsInRow(fn, nv + nf + 2);
send_face_nbr_elemdata.AddColumnsInRow(fn, nv + 2);
}
}
send_face_nbr_facedata.AddColumnsInRow(fn, 2*num_sfaces);
@@ -2236,13 +2222,6 @@ 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;
@@ -2288,13 +2267,12 @@ 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 + nf;
elemdata += nv;
el_marker[elems[el]] = el;
}
@@ -2345,8 +2323,6 @@ 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;
@@ -2374,20 +2350,9 @@ 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);
@@ -2546,179 +2511,6 @@ 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())
@@ -2736,37 +2528,6 @@ 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;
+3 -15
View File
@@ -75,9 +75,6 @@ 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
@@ -106,8 +103,6 @@ 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);
@@ -201,9 +196,6 @@ 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);
@@ -224,9 +216,8 @@ protected:
public:
/// Default constructor. Create an empty @a ParMesh.
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) { }
ParMesh() : MyComm(0), NRanks(0), MyRank(-1), 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
@@ -350,9 +341,6 @@ 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;
@@ -382,7 +370,7 @@ public:
int GetSharedFace(int sface) const;
/// See the remarks for the serial version in mesh.hpp
MFEM_DEPRECATED virtual void ReorientTetMesh();
virtual void ReorientTetMesh();
/// Utility function: sum integers from all processors (Allreduce).
virtual long ReduceInt(int value) const;
+2 -1
View File
@@ -84,7 +84,8 @@ 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
fixing wrong boundary element orientations */
a) fixing wrong boundary element orientations
b) a call to ReorientTetMesh() which is required for Nedelec */
int RotationPUMItoMFEM(apf::Mesh2* apf_mesh,
apf::MeshEntity* tet,
int elemId);

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