MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_convection_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
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 ElementTransformation &Trans = *mesh->GetTypicalElementTransformation();
182 const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, Trans);
183 if (DeviceCanUseCeed())
184 {
185 delete ceedOp;
186 const bool mixed = mesh->GetNumGeometries(mesh->Dimension()) > 1 ||
187 fes.IsVariableOrder();
188 if (mixed)
189 {
190 ceedOp = new ceed::MixedPAConvectionIntegrator(*this, fes, Q, alpha);
191 }
192 else
193 {
194 ceedOp = new ceed::PAConvectionIntegrator(fes, *ir, Q, alpha);
195 }
196 return;
197 }
198 const int dims = el.GetDim();
199 const int symmDims = dims;
200 nq = ir->GetNPoints();
201 dim = mesh->Dimension();
202 ne = fes.GetNE();
203 geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS, mt);
204 maps = &el.GetDofToQuad(*ir, DofToQuad::TENSOR);
205 dofs1D = maps->ndof;
206 quad1D = maps->nqpt;
207 pa_data.SetSize(symmDims * nq * ne, mt);
208
209 QuadratureSpace qs(*mesh, *ir);
210 CoefficientVector vel(*Q, qs, CoefficientStorage::COMPRESSED);
211
212 PAConvectionSetup(dim, nq, ne, ir->GetWeights(), geom->J,
213 vel, alpha, pa_data);
214}
215
216void ConvectionIntegrator::AssembleDiagonalPA(Vector &diag)
217{
218 if (DeviceCanUseCeed())
219 {
220 ceedOp->GetDiagonal(diag);
221 }
222 else
223 {
224 MFEM_ABORT("AssembleDiagonalPA not yet implemented for"
225 " ConvectionIntegrator.");
226 }
227}
228
229inline ConvectionIntegrator::ApplyKernelType
230ConvectionIntegrator::ApplyPAKernels::Fallback(int DIM, int, int)
231{
232 if (DIM == 2)
233 {
234 return PAConvectionApply2D;
235 }
236 else if (DIM == 3)
237 {
238 return PAConvectionApply3D;
239 }
240 else
241 {
242 MFEM_ABORT("");
243 }
244}
245
246inline ConvectionIntegrator::ApplyKernelType
247ConvectionIntegrator::ApplyPATKernels::Fallback(int DIM, int, int)
248{
249 if (DIM == 2)
250 {
251 return PAConvectionApplyT2D;
252 }
253 else if (DIM == 3)
254 {
255 return PAConvectionApplyT3D;
256 }
257 else
258 {
259 MFEM_ABORT("");
260 }
261}
262
263void ConvectionIntegrator::AddMultPA(const Vector &x, Vector &y) const
264{
265 if (DeviceCanUseCeed())
266 {
267 ceedOp->AddMult(x, y);
268 }
269 else
270 {
271 ApplyPAKernels::Run(dim, dofs1D, quad1D, ne, maps->B, maps->G, maps->Bt,
272 maps->Gt, pa_data, x, y, dofs1D, quad1D);
273 }
274}
275
276void ConvectionIntegrator::AddMultTransposePA(const Vector &x, Vector &y) const
277{
278 if (DeviceCanUseCeed())
279 {
280 MFEM_ABORT("AddMultPA not yet implemented with libCEED for"
281 " ConvectionIntegrator.");
282 }
283 else
284 {
285 ApplyPATKernels::Run(dim, dofs1D, quad1D, ne, maps->B, maps->G, maps->Bt,
286 maps->Gt, pa_data, x, y, dofs1D, quad1D);
287 }
288}
289
290} // namespace mfem
291/// \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:348
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:839
void vel(const Vector &x, real_t t, Vector &u)