MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_convection_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
13#include "../bilininteg.hpp"
14#include "../gridfunc.hpp"
15#include "../qfunction.hpp"
17
19
20/// \cond DO_NOT_DOCUMENT
21namespace mfem
22{
23
25 : Q(&q), alpha(a)
26{
27 static Kernels kernels;
28}
29
30ConvectionIntegrator::Kernels::Kernels()
31{
32 // 2D
33 // Q = P + 1
34 ConvectionIntegrator::AddSpecialization<2, 2, 2>();
35 ConvectionIntegrator::AddSpecialization<2, 3, 3>();
36 ConvectionIntegrator::AddSpecialization<2, 4, 4>();
37 ConvectionIntegrator::AddSpecialization<2, 5, 5>();
38 ConvectionIntegrator::AddSpecialization<2, 6, 6>();
39 // Q = P + 2
40 ConvectionIntegrator::AddSpecialization<2, 2, 3>();
41 ConvectionIntegrator::AddSpecialization<2, 3, 4>();
42 ConvectionIntegrator::AddSpecialization<2, 4, 5>();
43 ConvectionIntegrator::AddSpecialization<2, 5, 6>();
44 ConvectionIntegrator::AddSpecialization<2, 6, 7>();
45 // 3D
46 // Q = P + 1
47 ConvectionIntegrator::AddSpecialization<3, 2, 2>();
48 ConvectionIntegrator::AddSpecialization<3, 3, 3>();
49 ConvectionIntegrator::AddSpecialization<3, 4, 4>();
50 ConvectionIntegrator::AddSpecialization<3, 5, 5>();
51 ConvectionIntegrator::AddSpecialization<3, 6, 6>();
52 // Q = P + 2
53 ConvectionIntegrator::AddSpecialization<3, 2, 3>();
54 ConvectionIntegrator::AddSpecialization<3, 3, 4>();
55 ConvectionIntegrator::AddSpecialization<3, 4, 5>();
56 ConvectionIntegrator::AddSpecialization<3, 5, 6>();
57 ConvectionIntegrator::AddSpecialization<3, 6, 7>();
58}
59
60// PA Convection Assemble 2D kernel
61static void PAConvectionSetup2D(const int NQ,
62 const int NE,
63 const Array<real_t> &w,
64 const Vector &j,
65 const Vector &vel,
66 const real_t alpha,
67 Vector &op)
68{
69 constexpr int DIM = 2;
70
71 const bool const_v = vel.Size() == DIM;
72
73 const auto W = w.Read();
74 const auto J = Reshape(j.Read(), NQ,DIM,DIM,NE);
75 const auto V = const_v ?
76 Reshape(vel.Read(), DIM,1,1) :
77 Reshape(vel.Read(), DIM,NQ,NE);
78 auto y = Reshape(op.Write(), NQ,DIM,NE);
79
80 mfem::forall(NE*NQ, [=] MFEM_HOST_DEVICE (int q_global)
81 {
82 const int e = q_global / NQ;
83 const int q = q_global % NQ;
84 const real_t J11 = J(q,0,0,e);
85 const real_t J21 = J(q,1,0,e);
86 const real_t J12 = J(q,0,1,e);
87 const real_t J22 = J(q,1,1,e);
88 const real_t w = alpha * W[q];
89 const real_t v0 = const_v ? V(0,0,0) : V(0,q,e);
90 const real_t v1 = const_v ? V(1,0,0) : V(1,q,e);
91 const real_t wx = w * v0;
92 const real_t wy = w * v1;
93 // y = alpha * W * det(J) * J^{-1} . v = adj(J) . { wx, wy }
94 y(q,0,e) = wx * J22 - wy * J12; // 1
95 y(q,1,e) = -wx * J21 + wy * J11; // 2
96 });
97}
98
99// PA Convection Assemble 3D kernel
100static void PAConvectionSetup3D(const int NQ,
101 const int NE,
102 const Array<real_t> &w,
103 const Vector &j,
104 const Vector &vel,
105 const real_t alpha,
106 Vector &op)
107{
108 constexpr int DIM = 3;
109 constexpr int SDIM = DIM;
110 const auto W = Reshape(w.Read(), NQ);
111 const auto J = Reshape(j.Read(), NQ,SDIM,DIM,NE);
112 const bool const_v = vel.Size() == DIM;
113 const auto V = const_v ?
114 Reshape(vel.Read(), 3,1,1) :
115 Reshape(vel.Read(), 3,NQ,NE);
116 auto y = Reshape(op.Write(), NQ,3,NE);
117 mfem::forall(NE*NQ, [=] MFEM_HOST_DEVICE (int q_global)
118 {
119 const int e = q_global / NQ;
120 const int q = q_global % NQ;
121 const real_t J11 = J(q,0,0,e);
122 const real_t J12 = J(q,0,1,e);
123 const real_t J13 = J(q,0,2,e);
124 const real_t J21 = J(q,1,0,e);
125 const real_t J22 = J(q,1,1,e);
126 const real_t J23 = J(q,1,2,e);
127 const real_t J31 = J(q,2,0,e);
128 const real_t J32 = J(q,2,1,e);
129 const real_t J33 = J(q,2,2,e);
130 const real_t w = alpha * W(q);
131 const real_t v0 = const_v ? V(0,0,0) : V(0,q,e);
132 const real_t v1 = const_v ? V(1,0,0) : V(1,q,e);
133 const real_t v2 = const_v ? V(2,0,0) : V(2,q,e);
134 const real_t wx = w * v0;
135 const real_t wy = w * v1;
136 const real_t wz = w * v2;
137 // A = adj(J)
138 const real_t A11 = (J22 * J33) - (J23 * J32);
139 const real_t A12 = (J32 * J13) - (J12 * J33);
140 const real_t A13 = (J12 * J23) - (J22 * J13);
141 const real_t A21 = (J31 * J23) - (J21 * J33);
142 const real_t A22 = (J11 * J33) - (J13 * J31);
143 const real_t A23 = (J21 * J13) - (J11 * J23);
144 const real_t A31 = (J21 * J32) - (J31 * J22);
145 const real_t A32 = (J31 * J12) - (J11 * J32);
146 const real_t A33 = (J11 * J22) - (J12 * J21);
147 // y = alpha * W * det(J) * J^{-1} . v = adj(J) . { wx, wy, wz }
148 y(q,0,e) = wx * A11 + wy * A12 + wz * A13;
149 y(q,1,e) = wx * A21 + wy * A22 + wz * A23;
150 y(q,2,e) = wx * A31 + wy * A32 + wz * A33;
151 });
152}
153
154static void PAConvectionSetup(const int dim,
155 const int NQ,
156 const int NE,
157 const Array<real_t> &W,
158 const Vector &J,
159 const Vector &coeff,
160 const real_t alpha,
161 Vector &op)
162{
163 if (dim == 1) { MFEM_ABORT("dim==1 not supported in PAConvectionSetup"); }
164 if (dim == 2)
165 {
166 PAConvectionSetup2D(NQ, NE, W, J, coeff, alpha, op);
167 }
168 if (dim == 3)
169 {
170 PAConvectionSetup3D(NQ, NE, W, J, coeff, alpha, op);
171 }
172}
173
174void ConvectionIntegrator::AssemblePA(const FiniteElementSpace &fes)
175{
176 const MemoryType mt = (pa_mt == MemoryType::DEFAULT) ?
177 Device::GetDeviceMemoryType() : pa_mt;
178 // Assumes tensor-product elements
179 Mesh *mesh = fes.GetMesh();
180 const FiniteElement &el = *fes.GetTypicalFE();
181 MFEM_VERIFY(el.GetMapType() == FiniteElement::VALUE,
182 "Only value map type currently supported");
183 ElementTransformation &Trans = *mesh->GetTypicalElementTransformation();
184 const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, Trans);
185 if (DeviceCanUseCeed())
186 {
187 delete ceedOp;
188 const bool mixed = mesh->GetNumGeometries(mesh->Dimension()) > 1 ||
189 fes.IsVariableOrder();
190 if (mixed)
191 {
192 ceedOp = new ceed::MixedPAConvectionIntegrator(*this, fes, Q, alpha);
193 }
194 else
195 {
196 ceedOp = new ceed::PAConvectionIntegrator(fes, *ir, Q, alpha);
197 }
198 return;
199 }
200 const int dims = el.GetDim();
201 const int symmDims = dims;
202 nq = ir->GetNPoints();
203 dim = mesh->Dimension();
204 ne = fes.GetNE();
205 geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS, mt);
206 maps = &el.GetDofToQuad(*ir, DofToQuad::TENSOR);
207 dofs1D = maps->ndof;
208 quad1D = maps->nqpt;
209 pa_data.SetSize(symmDims * nq * ne, mt);
210
211 QuadratureSpace qs(*mesh, *ir);
212 CoefficientVector vel(*Q, qs, CoefficientStorage::COMPRESSED);
213
214 PAConvectionSetup(dim, nq, ne, ir->GetWeights(), geom->J,
215 vel, alpha, pa_data);
216}
217
218void ConvectionIntegrator::AssembleDiagonalPA(Vector &diag)
219{
220 if (DeviceCanUseCeed())
221 {
222 ceedOp->GetDiagonal(diag);
223 }
224 else
225 {
226 MFEM_ABORT("AssembleDiagonalPA not yet implemented for"
227 " ConvectionIntegrator.");
228 }
229}
230
231inline ConvectionIntegrator::ApplyKernelType
232ConvectionIntegrator::ApplyPAKernels::Fallback(int DIM, int, int)
233{
234 if (DIM == 2)
235 {
236 return PAConvectionApply2D;
237 }
238 else if (DIM == 3)
239 {
240 return PAConvectionApply3D;
241 }
242 else
243 {
244 MFEM_ABORT("");
245 }
246}
247
248inline ConvectionIntegrator::ApplyKernelType
249ConvectionIntegrator::ApplyPATKernels::Fallback(int DIM, int, int)
250{
251 if (DIM == 2)
252 {
253 return PAConvectionApplyT2D;
254 }
255 else if (DIM == 3)
256 {
257 return PAConvectionApplyT3D;
258 }
259 else
260 {
261 MFEM_ABORT("");
262 }
263}
264
265void ConvectionIntegrator::AddMultPA(const Vector &x, Vector &y) const
266{
267 if (DeviceCanUseCeed())
268 {
269 ceedOp->AddMult(x, y);
270 }
271 else
272 {
273 ApplyPAKernels::Run(dim, dofs1D, quad1D, ne, maps->B, maps->G, maps->Bt,
274 maps->Gt, pa_data, x, y, dofs1D, quad1D);
275 }
276}
277
278void ConvectionIntegrator::AddMultTransposePA(const Vector &x, Vector &y) const
279{
280 if (DeviceCanUseCeed())
281 {
282 MFEM_ABORT("AddMultPA not yet implemented with libCEED for"
283 " ConvectionIntegrator.");
284 }
285 else
286 {
287 ApplyPATKernels::Run(dim, dofs1D, quad1D, ne, maps->B, maps->G, maps->Bt,
288 maps->Gt, pa_data, x, y, dofs1D, quad1D);
289 }
290}
291
292} // namespace mfem
293/// \endcond DO_NOT_DOCUMENT
ConvectionIntegrator(VectorCoefficient &q, real_t a=1.0)
const real_t alpha
Definition ex15.cpp:369
int dim
Definition ex24.cpp:53
real_t a
Definition lissajous.cpp:41
constexpr int SDIM
constexpr int DIM
mfem::real_t real_t
const IntegrationRule & GetRule(const Integrator &integ, const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans)
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:369
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
SchrodingerBaseKernels< ParMesh, ParFiniteElementSpace, ParComplexGridFunction, ParGridFunction, ParBilinearForm, ParMixedBilinearForm, ParLinearForm > Kernels
bool DeviceCanUseCeed()
Function that determines if a CEED kernel should be used, based on the current mfem::Device configura...
Definition util.cpp:33
MemoryType
Memory types supported by MFEM.
void forall(int N, lambda &&body)
Definition forall.hpp:1134
void vel(const Vector &x, real_t t, Vector &u)