MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_vecmass_pa.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "../bilininteg.hpp"
15
16#include "./bilininteg_vecmass_pa.hpp" // IWYU pragma: keep
17
18namespace mfem
19{
20
22{
23 Mesh *mesh = fes.GetMesh();
24 const FiniteElement &el = *fes.GetTypicalFE();
25 MFEM_VERIFY(el.GetMapType() == FiniteElement::VALUE,
26 "Only value map type supported");
28 const auto *ir = IntRule ? IntRule : &MassIntegrator::GetRule(el, el, Trans);
29
30 if (DeviceCanUseCeed())
31 {
32 delete ceedOp;
33 const bool mixed =
34 mesh->GetNumGeometries(mesh->Dimension()) > 1 || fes.IsVariableOrder();
35 if (mixed) { ceedOp = new ceed::MixedPAMassIntegrator(*this, fes, Q); }
36 else { ceedOp = new ceed::PAMassIntegrator(fes, *ir, Q); }
37 return;
38 }
39
40 // If vdim is not set, set it to the space dimension
41 vdim = (vdim == -1) ? Trans.GetSpaceDim() : vdim;
42 MFEM_VERIFY(vdim == fes.GetVDim(), "vdim != fes.GetVDim()");
43 MFEM_VERIFY(vdim == mesh->Dimension(), "vdim != dim");
44
47 : pa_mt;
48
49 ne = mesh->GetNE();
50 dim = mesh->Dimension();
51 const int nq = ir->GetNPoints();
52 const int sdim = mesh->SpaceDimension();
55 dofs1D = maps->ndof;
56 quad1D = maps->nqpt;
57 const int q1d = quad1D;
58
59 if (!(dim == 2 || dim == 3)) { MFEM_ABORT("Dimension not supported."); }
60
61 QuadratureSpace qs(*mesh, *ir);
62 CoefficientVector coeff(qs);
63
64 if (Q)
65 {
66 coeff.Project(*Q);
67 }
68 else if (VQ)
69 {
70 coeff.Project(*VQ);
71 MFEM_VERIFY(VQ->GetVDim() == vdim, "VQ vdim vs. vdim error");
72 }
73 else if (MQ)
74 {
75 coeff.ProjectTranspose(*MQ);
76 MFEM_VERIFY(MQ->GetVDim() == vdim, "MQ dimension vs. vdim error");
77 MFEM_VERIFY(coeff.Size() == (vdim*vdim) * ne * nq, "MQ size error");
78 }
79 else { coeff.SetConstant(1.0); }
80
81 coeff_vdim = coeff.GetVDim();
82 const bool const_coeff = coeff_vdim == 1;
83 const bool vector_coeff = coeff_vdim == vdim;
84 const bool matrix_coeff = coeff_vdim == vdim * vdim;
85 MFEM_VERIFY(const_coeff + vector_coeff + matrix_coeff == 1, "");
86
87 pa_data.SetSize(coeff_vdim * nq * ne, mt);
88
89 const auto w_r = ir->GetWeights().Read();
90
91 if (dim == 2)
92 {
93 const auto W = Reshape(w_r, q1d, q1d);
94 const auto C = Reshape(coeff.Read(), coeff_vdim, q1d, q1d, ne);
95 const auto J = Reshape(geom->J.Read(), q1d, q1d, sdim, dim, ne);
96 auto D = Reshape(pa_data.Write(), q1d, q1d, coeff_vdim, ne);
97
98 mfem::forall_2D(ne, q1d, q1d, [=] MFEM_HOST_DEVICE(int e)
99 {
100 MFEM_FOREACH_THREAD(qy, y, q1d)
101 {
102 MFEM_FOREACH_THREAD(qx, x, q1d)
103 {
104 const real_t J11 = J(qx, qy, 0, 0, e), J12 = J(qx, qy, 1, 0, e);
105 const real_t J21 = J(qx, qy, 0, 1, e), J22 = J(qx, qy, 1, 1, e);
106 const real_t detJ = (J11 * J22) - (J21 * J12);
107 const real_t w_det = W(qx, qy) * detJ;
108 D(qx, qy, 0, e) = C(0, qx, qy, e) * w_det;
109 if (const_coeff) { continue; }
110 D(qx, qy, 1, e) = C(1, qx, qy, e) * w_det;
111 if (vector_coeff) { continue; }
112 assert(matrix_coeff);
113 D(qx, qy, 2, e) = C(2, qx, qy, e) * w_det;
114 D(qx, qy, 3, e) = C(3, qx, qy, e) * w_det;
115 }
116 }
117 });
118 }
119 else if (dim == 3)
120 {
121 const auto W = Reshape(w_r, q1d, q1d, q1d);
122 const auto C = Reshape(coeff.Read(), coeff_vdim, q1d, q1d, q1d, ne);
123 const auto J = Reshape(geom->J.Read(), q1d, q1d, q1d, sdim, dim, ne);
124 auto D = Reshape(pa_data.Write(), q1d, q1d, q1d, coeff_vdim, ne);
125
126 mfem::forall_3D(ne, q1d, q1d, q1d, [=] MFEM_HOST_DEVICE(int e)
127 {
128 MFEM_FOREACH_THREAD(qz, z, q1d)
129 {
130 MFEM_FOREACH_THREAD(qy, y, q1d)
131 {
132 MFEM_FOREACH_THREAD(qx, x, q1d)
133 {
134 const real_t J11 = J(qx, qy, qz, 0, 0, e),
135 J12 = J(qx, qy, qz, 0, 1, e),
136 J13 = J(qx, qy, qz, 0, 2, e);
137 const real_t J21 = J(qx, qy, qz, 1, 0, e),
138 J22 = J(qx, qy, qz, 1, 1, e),
139 J23 = J(qx, qy, qz, 1, 2, e);
140 const real_t J31 = J(qx, qy, qz, 2, 0, e),
141 J32 = J(qx, qy, qz, 2, 1, e),
142 J33 = J(qx, qy, qz, 2, 2, e);
143 const real_t detJ = J11 * (J22 * J33 - J32 * J23) -
144 J21 * (J12 * J33 - J32 * J13) +
145 J31 * (J12 * J23 - J22 * J13);
146 const real_t w_det = W(qx, qy, qz) * detJ;
147 D(qx, qy, qz, 0, e) = C(0, qx, qy, qz, e) * w_det;
148 if (const_coeff) { continue; }
149 D(qx, qy, qz, 1, e) = C(1, qx, qy, qz, e) * w_det;
150 D(qx, qy, qz, 2, e) = C(2, qx, qy, qz, e) * w_det;
151 if (vector_coeff) { continue; }
152 D(qx, qy, qz, 3, e) = C(3, qx, qy, qz, e) * w_det;
153 D(qx, qy, qz, 4, e) = C(4, qx, qy, qz, e) * w_det;
154 D(qx, qy, qz, 5, e) = C(5, qx, qy, qz, e) * w_det;
155 D(qx, qy, qz, 6, e) = C(6, qx, qy, qz, e) * w_det;
156 D(qx, qy, qz, 7, e) = C(7, qx, qy, qz, e) * w_det;
157 D(qx, qy, qz, 8, e) = C(8, qx, qy, qz, e) * w_det;
158 }
159 }
160 }
161 });
162 }
163 else
164 {
165 MFEM_ABORT("Unknown VectorMassIntegrator::AssemblePA kernel for"
166 << " dim:" << dim << ", vdim:" << vdim << ", sdim:" << sdim);
167 }
168}
169
171{
172 // Use CEED backend if available
173 if (DeviceCanUseCeed()) { return ceedOp->AddMult(x, y); }
174
175 // Add the VectorMassAddMultPA specializations
176 static const auto vector_mass_kernel_specializations =
177 ( // 2D
178 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 2,2>::Add(),
179 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 3,3>::Add(),
180 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 3,4>::Add(),
181 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 4,4>::Add(),
182 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 4,6>::Add(),
183 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 5,5>::Add(),
184 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 6,6>::Add(),
185 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 7,7>::Add(),
186 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 8,8>::Add(),
187 VectorMassIntegrator::VectorMassAddMultPA::Specialization<2, 9,9>::Add(),
188 // 3D
189 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 2,2>::Add(),
190 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 2,3>::Add(),
191 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 3,4>::Add(),
192 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 3,5>::Add(),
193 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 4,5>::Add(),
194 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 4,6>::Add(),
195 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 4,8>::Add(),
196 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 5,6>::Add(),
197 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 5,8>::Add(),
198 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 6,7>::Add(),
199 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 7,8>::Add(),
200 VectorMassIntegrator::VectorMassAddMultPA::Specialization<3, 8,9>::Add(),
201 true);
202 MFEM_CONTRACT_VAR(vector_mass_kernel_specializations);
203
204 VectorMassAddMultPA::Run(dim, dofs1D, quad1D,
205 ne, coeff_vdim, maps->B, pa_data, x, y,
206 dofs1D, quad1D);
207
208}
209
211{
212 if (DeviceCanUseCeed()) { return ceedOp->GetDiagonal(diag); }
213
214 MFEM_VERIFY(coeff_vdim == 1, "coeff_vdim != 1");
215 MFEM_VERIFY(!VQ && !MQ, "VQ and MQ not supported");
216
217 // Add the VectorMassAssembleDiagonalPA specializations
218 static const auto vector_mass_assemble_diagonal_kernel_specializations =
219 ( // 2D
220 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 2>::Add(),
221 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 3>::Add(),
222 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 4>::Add(),
223 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 5>::Add(),
224 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 6>::Add(),
225 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 7>::Add(),
226 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<2, 8>::Add(),
227 // 3D
228 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 2>::Add(),
229 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 3>::Add(),
230 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 4>::Add(),
231 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 5>::Add(),
232 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 6>::Add(),
233 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 7>::Add(),
234 VectorMassIntegrator::VectorMassAssembleDiagonalPA::Specialization<3, 8>::Add(),
235 true);
236 MFEM_CONTRACT_VAR(vector_mass_assemble_diagonal_kernel_specializations);
237
238 VectorMassAssembleDiagonalPA::Run(dim, quad1D, // templated arguments
239 ne, dofs1D, quad1D,
240 maps->B.Read(),
241 pa_data.Read(),
242 diag.ReadWrite());
243
244}
245
246} // namespace mfem
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:410
Class to represent a coefficient evaluated at quadrature points.
void SetConstant(real_t constant)
Set this vector to the given constant.
void Project(Coefficient &coeff)
Evaluate the given Coefficient at the quadrature points defined by qs.
int GetVDim() const
Return the number of values per quadrature point.
void ProjectTranspose(MatrixCoefficient &coeff)
Project the transpose of coeff.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Definition device.hpp:298
@ TENSOR
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
Definition fe_base.hpp:165
Array< real_t > B
Basis functions evaluated at quadrature points.
Definition fe_base.hpp:201
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:186
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:190
virtual int GetSpaceDim() const =0
Get the dimension of the target (physical) space.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition fespace.hpp:673
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:817
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Definition fespace.cpp:3896
Abstract class for all finite elements.
Definition fe_base.hpp:294
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
Definition fe_base.cpp:373
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition fe_base.hpp:436
Vector J
Jacobians of the element transformations at all quadrature points.
Definition mesh.hpp:3158
const IntegrationRule * IntRule
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans, const bool stroud=false)
int GetVDim() const
For backward compatibility get the width of the matrix.
Mesh data type.
Definition mesh.hpp:67
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
ElementTransformation * GetTypicalElementTransformation()
If the local mesh is not empty return GetElementTransformation(0); otherwise, return the identity tra...
Definition mesh.cpp:394
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1317
const GeometricFactors * GetGeometricFactors(const IntegrationRule &ir, const int flags, MemoryType d_mt=MemoryType::DEFAULT)
Return the mesh geometric factors corresponding to the given integration rule.
Definition mesh.cpp:958
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition mesh.cpp:8014
Class representing the storage layout of a QuadratureFunction.
Definition qspace.hpp:164
int GetVDim()
Returns dimension of the vector.
VectorCoefficient * VQ
void AssembleDiagonalPA(Vector &diag) override
Assemble diagonal and add it to Vector diag.
const DofToQuad * maps
Not owned.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
MatrixCoefficient * MQ
void AssemblePA(const FiniteElementSpace &fes) override
Method defining partial assembly.
const GeometricFactors * geom
Not owned.
Vector data type.
Definition vector.hpp:82
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:520
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:536
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:528
void GetDiagonal(mfem::Vector &diag) const
Definition operator.cpp:104
void AddMult(const mfem::Vector &x, mfem::Vector &y, const real_t a=1.0) const override
Operator application: y+=A(x) (default) or y+=a*A(x).
Definition operator.cpp:72
Represent a MassIntegrator with AssemblyLevel::Partial using libCEED.
Definition mass.hpp:27
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition dtensor.hpp:138
bool DeviceCanUseCeed()
Function that determines if a CEED kernel should be used, based on the current mfem::Device configura...
Definition util.cpp:33
void forall_2D(int N, int X, int Y, lambda &&body)
Definition forall.hpp:1220
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
Definition forall.hpp:1244
float real_t
Definition config.hpp:46
MemoryType
Memory types supported by MFEM.