13 #include "../../general/forall.hpp"
14 #include "../../fem/pbilinearform.hpp"
24 if (dynamic_cast<const ND_FECollection*>(fec))
28 else if (dynamic_cast<const RT_FECollection*>(fec))
34 MFEM_ABORT(
"Bad finite element type.")
41 const int op1 = o + 1;
42 const int nedge =
static_cast<int>(
dim*o*pow(op1,
dim-1));
47 for (
int c=0; c<
dim; ++c)
49 const int nx = (c == 0) ? o : op1;
50 for (
int i2=0; i2<op1; ++i2)
52 for (
int i1=0; i1<o; ++i1)
54 const int ix = (c == 0) ? i1 : i2;
55 const int iy = (c == 0) ? i2 : i1;
57 const int iedge = ix + iy*nx + c*o*op1;
59 const int ix1 = (c == 0) ? ix + 1 : ix;
60 const int iy1 = (c == 1) ? iy + 1 : iy;
62 const int iv0 = ix + iy*op1;
63 const int iv1 = ix1 + iy1*op1;
75 const int op1 = o + 1;
76 const int nedge =
static_cast<int>(
dim*o*pow(op1,
dim-1));
81 for (
int c=0; c<
dim; ++c)
83 const int nx = (c == 0) ? op1 : o;
84 for (
int i=0; i<o*op1; ++i)
89 const int iedge = ix + iy*nx + c*o*op1;
91 const int ix1 = (c == 0) ? ix : ix + 1;
92 const int iy1 = (c == 1) ? iy : iy + 1;
94 const int iv0 = ix + iy*op1;
95 const int iv1 = ix1 + iy1*op1;
99 e2v(0, iedge) = (c == 1) ? iv0 : iv1;
100 e2v(1, iedge) = (c == 1) ? iv1 : iv0;
108 const int op1 = o + 1;
109 const int nedge =
static_cast<int>(
dim*o*pow(op1,
dim-1));
114 for (
int c=0; c<
dim; ++c)
116 const int nx = (c == 0) ? o : op1;
117 const int ny = (c == 1) ? o : op1;
118 for (
int i=0; i<o*op1*op1; ++i)
121 const int iy = (i/nx)%ny;
122 const int iz = i/nx/ny;
124 const int iedge = ix + iy*nx + iz*nx*ny + c*o*op1*op1;
126 const int ix1 = (c == 0) ? ix + 1 : ix;
127 const int iy1 = (c == 1) ? iy + 1 : iy;
128 const int iz1 = (c == 2) ? iz + 1 : iz;
130 const int iv0 = ix + iy*op1 + iz*op1*op1;
131 const int iv1 = ix1 + iy1*op1 + iz1*op1*op1;
153 const int nnz = 2*nedge_dof;
154 auto I = G_local.
WriteI();
155 MFEM_FORALL(i, nedge_dof+1, I[i] = 2*i;);
170 MFEM_VERIFY(R_v != NULL && R_e != NULL,
"");
173 const int nedge_per_el =
static_cast<int>(
dim*
order*pow(
order + 1,
dim - 1));
174 const int nvert_per_el =
static_cast<int>(pow(
order + 1,
dim));
176 const auto offsets_e = R_e->Offsets().Read();
177 const auto indices_e = R_e->Indices().Read();
178 const auto gather_v =
Reshape(R_v->GatherMap().Read(), nvert_per_el, nel_ho);
180 const auto e2v =
Reshape(edge2vertex.Read(), 2, nedge_per_el);
186 auto J = G_local.
WriteJ();
190 MFEM_FORALL(i, nedge_dof,
192 const int sj = indices_e[offsets_e[i]];
193 const int j = (sj >= 0) ? sj : -1 - sj;
194 const int sgn = (sj >= 0) ? 1 : -1;
195 const int j_loc = j%nedge_per_el;
196 const int j_el = j/nedge_per_el;
198 const int jv0_loc = e2v(0, j_loc);
199 const int jv1_loc = e2v(1, j_loc);
201 J[i*2 + 0] = gather_v(jv0_loc, j_el);
202 J[i*2 + 1] = gather_v(jv1_loc, j_el);
221 G_diag.SetOperatorOwner(
false);
242 template <
typename T>
243 static inline const T *HypreRead(
const Memory<T> &mem)
248 template <
typename T>
249 static inline T *HypreWrite(Memory<T> &mem)
272 MFEM_VERIFY(el_restr != NULL,
"");
276 const int ndp1 =
order + 1;
277 const int ndof_per_el =
static_cast<int>(pow(ndp1,
dim));
278 const int sdim =
dim;
279 const int ntdofs = R->
Height();
289 const auto d_offsets = HypreRead(el_restr->Offsets().GetMemory());
290 const auto d_indices = HypreRead(el_restr->Indices().GetMemory());
291 const auto ltdof_ldof = HypreRead(R->
GetMemoryJ());
294 MFEM_HYPRE_FORALL(i, ntdofs,
296 const int j = d_offsets[ltdof_ldof[i]];
297 for (
int c = 0; c < sdim; ++c)
299 const int idx_j = d_indices[j];
300 xyz_tv(i,c) = xyz_e(c, idx_j%ndof_per_el, idx_j/ndof_per_el);
308 double *d_x_ptr = xyz_tv + 0*ntdofs;
310 double *d_y_ptr = xyz_tv + 1*ntdofs;
314 double *d_z_ptr = xyz_tv + 2*ntdofs;
359 : edge_fes(pfes_ho_),
360 dim(edge_fes.GetParMesh()->Dimension()),
361 order(edge_fes.GetMaxElementOrder()),
362 vert_fec(order,
dim),
363 vert_fes(edge_fes.GetParMesh(), &vert_fec)
376 batched_lor.
Assemble(a_ho, ess_tdof_list, A);
380 lor_ams.StealGradientMatrix(),
381 lor_ams.StealXCoordinate(),
382 lor_ams.StealYCoordinate(),
383 lor_ams.StealZCoordinate());
const OperatorHandle & GetAssembledSystem() const
Returns the assembled LOR system (const version).
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
Create and assemble a low-order refined version of a ParBilinearForm.
HypreParVector * StealZCoordinate()
int GetNDofs() const
Returns number of degrees of freedom.
The Auxiliary-space Maxwell Solver in hypre.
BatchedLOR_AMS(ParFiniteElementSpace &pfes_ho_, const Vector &X_vert)
Construct the BatchedLOR_AMS object associated with the Nedelec space (or RT in 2D) pfes_ho_...
ParFiniteElementSpace & edge_fes
The Nedelec space.
Device memory; using CUDA or HIP *Malloc and *Free.
virtual const Operator * GetProlongationMatrix() const
The returned Operator is owned by the FiniteElementSpace.
Efficient batched assembly of LOR discretizations on device.
Pointer to an Operator of a specified type.
void Form2DEdgeToVertex_ND(Array< int > &edge2vert)
HYPRE_BigInt GlobalTrueVSize() const
Abstract parallel finite element space.
void FormGradientMatrix()
Construct the discrete gradient matrix (not part of the public API).
HypreParMatrix & GetAssembledMatrix() const
Return the assembled LOR operator as a HypreParMatrix.
Memory< double > & GetMemoryData()
int Capacity() const
Return the size of the allocated memory.
Memory< double > & GetMemory()
Return a reference to the Memory object used by the Vector.
static bool FormIsSupported(BilinearForm &a)
Returns true if the form a supports batched assembly, false otherwise.
Memory< int > & GetMemoryI()
Memory< int > & GetMemoryJ()
int GetNE() const
Returns number of elements in the mesh.
HYPRE_BigInt GlobalVSize() const
ParFiniteElementSpace vert_fes
The corresponding H1 space.
void HypreStealOwnership(HypreParMatrix &A_hyp, SparseMatrix &A_diag)
Make A_hyp steal ownership of its diagonal part A_diag.
Vector * StealCoordinateVector()
Vector * xyz_tvec
Mesh vertex coordinates in true-vector format.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
void Form2DEdgeToVertex(Array< int > &edge2vert)
HypreParMatrix * Dof_TrueDof_Matrix() const
The true dof-to-dof interpolation matrix.
HypreParMatrix * G
Discrete gradient matrix.
const int dim
Spatial dimension.
void Form3DEdgeToVertex(Array< int > &edge2vert)
int * WriteI(bool on_dev=true)
void FormCoordinateVectors(const Vector &X_vert)
Construct the mesh coordinate vectors (not part of the public API).
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
HYPRE_BigInt * GetDofOffsets() const
void SetOperator(const Operator &op)
Set/update the solver for the given operator.
HypreParVector * StealYCoordinate()
Operator * Ptr() const
Access the underlying Operator pointer.
void MakeRectangularBlockDiag(MPI_Comm comm, HYPRE_BigInt glob_num_rows, HYPRE_BigInt glob_num_cols, HYPRE_BigInt *row_starts, HYPRE_BigInt *col_starts, SparseMatrix *diag)
Reset the OperatorHandle to hold a parallel rectangular block-diagonal matrix using the currently set...
Wrapper for hypre's parallel vector class.
const Vector & GetLORVertexCoordinates()
Return the vertices of the LOR mesh in E-vector format.
HYPRE_BigInt * GetTrueDofOffsets() const
bool IsIdentityProlongation(const Operator *P)
SolverType & GetSolver()
Access the underlying solver.
Operator that converts FiniteElementSpace L-vectors to E-vectors.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void Assemble(BilinearForm &a, const Array< int > ess_dofs, OperatorHandle &A)
Assemble the given form as a matrix and place the result in A.
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
const int order
Polynomial degree.
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
int height
Dimension of the output / number of rows in the matrix.
int * WriteJ(bool on_dev=true)
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
void SetOperatorOwner(bool own=true)
Set the ownership flag for the held Operator.
ParFiniteElementSpace & GetParFESpace() const
Return the LOR ParFiniteElementSpace.
constexpr MemoryClass GetHypreMemoryClass()
The MemoryClass used by Hypre objects.
virtual const SparseMatrix * GetRestrictionMatrix() const
Get the R matrix which restricts a local dof vector to true dof vector.
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
HypreParVector * StealXCoordinate()
void Form2DEdgeToVertex_RT(Array< int > &edge2vert)
void OverrideSize(int height_, int width_)
Sets the height and width of the matrix.
Class used by MFEM to store pointers to host and/or device memory.
LORSolver(BilinearForm &a_ho, const Array< int > &ess_tdof_list, int ref_type=BasisType::GaussLobatto)
Create a solver of type SolverType, formed using the assembled SparseMatrix of the LOR version of a_h...
Lexicographic ordering for tensor-product FiniteElements.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
const FiniteElementCollection * FEColl() const
ID for class HypreParMatrix.
T * StealPointer(T *&ptr)
Wrapper for hypre's ParCSR matrix class.
HypreParMatrix * StealGradientMatrix()
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
MemoryClass
Memory classes identify sets of memory types.
int width
Dimension of the input / number of columns in the matrix.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
double * WriteData(bool on_dev=true)