MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_vectorfemass_pa.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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"
13#include "../gridfunc.hpp"
14#include "../qfunction.hpp"
19
20namespace mfem
21{
22
27
29 const FiniteElementSpace &test_fes)
30{
31 // Assumes tensor-product elements
32 Mesh *mesh = trial_fes.GetMesh();
33
34 const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
35 const VectorTensorFiniteElement *trial_el =
36 dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
37 MFEM_VERIFY(trial_el != NULL, "Only VectorTensorFiniteElement is supported!");
38
39 const FiniteElement *test_fel = test_fes.GetTypicalFE();
40 const VectorTensorFiniteElement *test_el =
41 dynamic_cast<const VectorTensorFiniteElement*>(test_fel);
42 MFEM_VERIFY(test_el != NULL, "Only VectorTensorFiniteElement is supported!");
43
44 const IntegrationRule *ir
45 = IntRule ? IntRule : &MassIntegrator::GetRule(*trial_el, *trial_el,
47 const int dims = trial_el->GetDim();
48 MFEM_VERIFY(dims == 2 || dims == 3, "");
49
50 const int symmDims = (dims * (dims + 1)) / 2; // 1x1: 1, 2x2: 3, 3x3: 6
51 nq = ir->GetNPoints();
52 dim = mesh->Dimension();
53 MFEM_VERIFY(dim == 2 || dim == 3, "");
54
55 ne = trial_fes.GetNE();
56 MFEM_VERIFY(ne == test_fes.GetNE(),
57 "Different meshes for test and trial spaces");
59 mapsC = &trial_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
60 mapsO = &trial_el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
61 dofs1D = mapsC->ndof;
62 quad1D = mapsC->nqpt;
63
67
68 MFEM_VERIFY(dofs1D == mapsO->ndof + 1 && quad1D == mapsO->nqpt, "");
69
70 trial_fetype = trial_el->GetDerivType();
71 test_fetype = test_el->GetDerivType();
72
73 const bool trial_curl = (trial_fetype == mfem::FiniteElement::CURL);
74 const bool trial_div = (trial_fetype == mfem::FiniteElement::DIV);
75 const bool test_curl = (test_fetype == mfem::FiniteElement::CURL);
76 const bool test_div = (test_fetype == mfem::FiniteElement::DIV);
77
78 QuadratureSpace qs(*mesh, *ir);
80 if (Q) { coeff.Project(*Q); }
81 else if (MQ) { coeff.ProjectTranspose(*MQ); }
82 else if (DQ) { coeff.Project(*DQ); }
83 else { coeff.SetConstant(1.0); }
84
85 const int coeff_dim = coeff.GetVDim();
86 symmetric = (coeff_dim != dim*dim);
87
88 if ((trial_curl && test_div) || (trial_div && test_curl))
89 {
90 pa_data.SetSize((coeff_dim == 1 ? 1 : dim*dim) * nq * ne,
92 }
93 else
94 {
95 pa_data.SetSize((symmetric ? symmDims : dims*dims) * nq * ne,
97 }
98 if (trial_curl && test_curl && dim == 3)
99 {
100 internal::PADiffusionSetup3D(quad1D, coeff_dim, ne, ir->GetWeights(), geom->J,
101 coeff, pa_data);
102 }
103 else if (trial_curl && test_curl && dim == 2)
104 {
105 internal::PADiffusionSetup2D<2>(quad1D, coeff_dim, ne, ir->GetWeights(),
106 geom->J, coeff, pa_data);
107 }
108 else if (trial_div && test_div && dim == 3)
109 {
110 internal::PAHdivMassSetup3D(quad1D, coeff_dim, ne, ir->GetWeights(), geom->J,
111 coeff, pa_data);
112 }
113 else if (trial_div && test_div && dim == 2)
114 {
115 internal::PAHdivMassSetup2D(quad1D, coeff_dim, ne, ir->GetWeights(), geom->J,
116 coeff, pa_data);
117 }
118 else if (((trial_curl && test_div) || (trial_div && test_curl)) &&
119 test_fel->GetOrder() == trial_fel->GetOrder())
120 {
121 if (coeff_dim == 1)
122 {
123 internal::PAHcurlL2Setup3D(nq, coeff_dim, ne, ir->GetWeights(), coeff, pa_data);
124 }
125 else
126 {
127 const bool tr = (trial_div && test_curl);
128 if (dim == 3)
129 {
130 internal::PAHcurlHdivMassSetup3D(quad1D, coeff_dim, ne, tr, ir->GetWeights(),
131 geom->J, coeff, pa_data);
132 }
133 else
134 {
135 internal::PAHcurlHdivMassSetup2D(quad1D, coeff_dim, ne, tr, ir->GetWeights(),
136 geom->J, coeff, pa_data);
137 }
138 }
139 }
140 else
141 {
142 MFEM_ABORT("Unknown kernel.");
143 }
144}
145
147{
148 if (dim == 3)
149 {
151 {
153 {
154 const int ID = (dofs1D << 4) | quad1D;
155 switch (ID)
156 {
157 case 0x23:
158 return internal::SmemPAHcurlMassAssembleDiagonal3D<2,3>(
160 mapsO->B, mapsC->B, pa_data, diag);
161 case 0x34:
162 return internal::SmemPAHcurlMassAssembleDiagonal3D<3,4>(
164 mapsO->B, mapsC->B, pa_data, diag);
165 case 0x45:
166 return internal::SmemPAHcurlMassAssembleDiagonal3D<4,5>(
168 mapsO->B, mapsC->B, pa_data, diag);
169 case 0x56:
170 return internal::SmemPAHcurlMassAssembleDiagonal3D<5,6>(
172 mapsO->B, mapsC->B, pa_data, diag);
173 default:
174 return internal::SmemPAHcurlMassAssembleDiagonal3D(
176 mapsO->B, mapsC->B, pa_data, diag);
177 }
178 }
179 else
180 {
181 internal::PAHcurlMassAssembleDiagonal3D(dofs1D, quad1D, ne, symmetric,
182 mapsO->B, mapsC->B, pa_data, diag);
183 }
184 }
187 {
188 internal::PAHdivMassAssembleDiagonal3D(dofs1D, quad1D, ne, symmetric,
189 mapsO->B, mapsC->B, pa_data, diag);
190 }
191 else
192 {
193 MFEM_ABORT("Unknown kernel.");
194 }
195 }
196 else // 2D
197 {
199 {
200 internal::PAHcurlMassAssembleDiagonal2D(dofs1D, quad1D, ne, symmetric,
201 mapsO->B, mapsC->B, pa_data, diag);
202 }
205 {
206 internal::PAHdivMassAssembleDiagonal2D(dofs1D, quad1D, ne, symmetric,
207 mapsO->B, mapsC->B, pa_data, diag);
208 }
209 else
210 {
211 MFEM_ABORT("Unknown kernel.");
212 }
213 }
214}
215
217{
218 const bool trial_curl = (trial_fetype == mfem::FiniteElement::CURL);
219 const bool trial_div = (trial_fetype == mfem::FiniteElement::DIV);
220 const bool test_curl = (test_fetype == mfem::FiniteElement::CURL);
221 const bool test_div = (test_fetype == mfem::FiniteElement::DIV);
222
223 if (dim == 3)
224 {
225 if (trial_curl && test_curl)
226 {
228 {
229 const int ID = (dofs1D << 4) | quad1D;
230 switch (ID)
231 {
232 case 0x23:
233 return internal::SmemPAHcurlMassApply3D<2,3>(
235 mapsO->B, mapsC->B, mapsO->Bt,
236 mapsC->Bt, pa_data, x, y);
237 case 0x34:
238 return internal::SmemPAHcurlMassApply3D<3,4>(
240 mapsO->B, mapsC->B, mapsO->Bt,
241 mapsC->Bt, pa_data, x, y);
242 case 0x45:
243 return internal::SmemPAHcurlMassApply3D<4,5>(
245 mapsO->B, mapsC->B, mapsO->Bt,
246 mapsC->Bt, pa_data, x, y);
247 case 0x56:
248 return internal::SmemPAHcurlMassApply3D<5,6>(
250 mapsO->B, mapsC->B, mapsO->Bt,
251 mapsC->Bt, pa_data, x, y);
252 default:
253 return internal::SmemPAHcurlMassApply3D(
255 mapsO->B, mapsC->B, mapsO->Bt,
256 mapsC->Bt, pa_data, x, y);
257 }
258 }
259 else
260 {
261 internal::PAHcurlMassApply3D(dofs1D, quad1D, ne, symmetric, mapsO->B, mapsC->B,
262 mapsO->Bt, mapsC->Bt, pa_data, x, y);
263 }
264 }
265 else if (trial_div && test_div)
266 {
267 internal::PAHdivMassApply(3, dofs1D, quad1D, ne, symmetric, mapsO->B, mapsC->B,
268 mapsO->Bt, mapsC->Bt, pa_data, x, y);
269 }
270 else if (trial_curl && test_div)
271 {
272 const bool scalarCoeff = !(DQ || MQ);
273 internal::PAHcurlHdivMassApply3D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
274 true, false, mapsO->B, mapsC->B, mapsOtest->Bt,
275 mapsCtest->Bt, pa_data, x, y);
276 }
277 else if (trial_div && test_curl)
278 {
279 const bool scalarCoeff = !(DQ || MQ);
280 internal::PAHcurlHdivMassApply3D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
281 false, false, mapsO->B, mapsC->B, mapsOtest->Bt,
282 mapsCtest->Bt, pa_data, x, y);
283 }
284 else
285 {
286 MFEM_ABORT("Unknown kernel.");
287 }
288 }
289 else // 2D
290 {
291 if (trial_curl && test_curl)
292 {
293 internal::PAHcurlMassApply2D(dofs1D, quad1D, ne, symmetric, mapsO->B, mapsC->B,
294 mapsO->Bt, mapsC->Bt, pa_data, x, y);
295 }
296 else if (trial_div && test_div)
297 {
298 internal::PAHdivMassApply(2, dofs1D, quad1D, ne, symmetric, mapsO->B, mapsC->B,
299 mapsO->Bt,
300 mapsC->Bt, pa_data, x, y);
301 }
302 else if ((trial_curl && test_div) || (trial_div && test_curl))
303 {
304 const bool scalarCoeff = !(DQ || MQ);
305 internal::PAHcurlHdivMassApply2D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
306 trial_curl, false, mapsO->B, mapsC->B,
307 mapsOtest->Bt, mapsCtest->Bt, pa_data, x, y);
308 }
309 else
310 {
311 MFEM_ABORT("Unknown kernel.");
312 }
313 }
314}
315
317 Vector &y) const
318{
319 const bool trial_curl = (trial_fetype == mfem::FiniteElement::CURL);
320 const bool trial_div = (trial_fetype == mfem::FiniteElement::DIV);
321 const bool test_curl = (test_fetype == mfem::FiniteElement::CURL);
322 const bool test_div = (test_fetype == mfem::FiniteElement::DIV);
323
324 bool symmetricSpaces = true;
325 if (dim == 3 && ((trial_div && test_curl) || (trial_curl && test_div)))
326 {
327 const bool scalarCoeff = !(DQ || MQ);
328 internal::PAHcurlHdivMassApply3D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
329 trial_div, true, mapsO->B, mapsC->B,
330 mapsOtest->Bt, mapsCtest->Bt, pa_data, x, y);
331 symmetricSpaces = false;
332 }
333 else if (dim == 2 && ((trial_curl && test_div) || (trial_div && test_curl)))
334 {
335 const bool scalarCoeff = !(DQ || MQ);
336 internal::PAHcurlHdivMassApply2D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
337 !trial_curl, true, mapsO->B, mapsC->B,
338 mapsOtest->Bt, mapsCtest->Bt, pa_data, x, y);
339 symmetricSpaces = false;
340 }
341 if (symmetricSpaces)
342 {
343 if (MQ && dynamic_cast<SymmetricMatrixCoefficient*>(MQ) == NULL)
344 {
345 MFEM_ABORT("VectorFEMassIntegrator transpose not implemented for asymmetric MatrixCoefficient");
346 }
347 AddMultPA(x, y);
348 }
349}
350
351} // namespace mfem
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 GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:278
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
Definition device.hpp:259
@ 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:193
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:178
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:182
Array< real_t > Bt
Transpose of B.
Definition fe_base.hpp:199
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:891
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:679
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:3871
Abstract class for all finite elements.
Definition fe_base.hpp:244
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:338
int GetDerivType() const
Returns the FiniteElement::DerivType of the element describing the spatial derivative method implemen...
Definition fe_base.hpp:365
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:321
@ DIV
Implements CalcDivShape methods.
Definition fe_base.hpp:306
@ CURL
Implements CalcCurlShape methods.
Definition fe_base.hpp:307
Vector J
Jacobians of the element transformations at all quadrature points.
Definition mesh.hpp:2976
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
const Array< real_t > & GetWeights() const
Return the quadrature weights in a contiguous array.
Definition intrules.cpp:86
const IntegrationRule * IntRule
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans)
Mesh data type.
Definition mesh.hpp:64
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
ElementTransformation * GetTypicalElementTransformation()
If the local mesh is not empty return GetElementTransformation(0); otherwise, return the identity tra...
Definition mesh.cpp:390
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:880
Class representing the storage layout of a QuadratureFunction.
Definition qspace.hpp:120
Base class for symmetric matrix coefficients that optionally depend on time and space.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
void AssembleDiagonalPA(Vector &diag) override
Assemble diagonal and add it to Vector diag.
const DofToQuad * mapsO
Not owned. DOF-to-quad map, open.
const DofToQuad * mapsOtest
Not owned. DOF-to-quad map, open.
void AssemblePA(const FiniteElementSpace &fes) override
Method defining partial assembly.
bool symmetric
False if using a nonsymmetric matrix coefficient.
void AddMultTransposePA(const Vector &x, Vector &y) const override
Method for partially assembled transposed action.
DiagonalMatrixCoefficient * DQ
const DofToQuad * mapsCtest
Not owned. DOF-to-quad map, closed.
const GeometricFactors * geom
Not owned.
const DofToQuad * mapsC
Not owned. DOF-to-quad map, closed.
const DofToQuad & GetDofToQuadOpen(const IntegrationRule &ir, DofToQuad::Mode mode) const
Definition fe_base.hpp:1362
const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const override
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
Definition fe_base.hpp:1354
Vector data type.
Definition vector.hpp:82
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:558
@ SYMMETRIC
Store the triangular part of symmetric matrices.
@ DEVICE_MASK
Biwise-OR of all device backends.
Definition device.hpp:97