MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_dgdiffusion_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
15#include "../gridfunc.hpp"
16#include "../qfunction.hpp"
17
19
20namespace mfem
21{
22
23static void PADGDiffusionSetup2D(const int Q1D, const int NE, const int NF,
24 const Array<real_t> &w,
25 const GeometricFactors &el_geom,
26 const FaceGeometricFactors &face_geom,
27 const FaceNeighborGeometricFactors *nbr_geom,
28 const Vector &q, const int coeff_dim,
29 const real_t sigma, const real_t kappa,
30 Vector &pa_data, const Array<int> &face_info_)
31{
32 const auto J_loc = Reshape(el_geom.J.Read(), Q1D, Q1D, 2, 2, NE);
33 const auto detJe_loc = Reshape(el_geom.detJ.Read(), Q1D, Q1D, NE);
34
35 const int n_nbr = nbr_geom ? nbr_geom->num_neighbor_elems : 0;
36 const auto J_shared =
37 Reshape(nbr_geom ? nbr_geom->J.Read() : nullptr, Q1D, Q1D, 2, 2, n_nbr);
38 const auto detJ_shared =
39 Reshape(nbr_geom ? nbr_geom->detJ.Read() : nullptr, Q1D, Q1D, n_nbr);
40
41 const auto detJf = Reshape(face_geom.detJ.Read(), Q1D, NF);
42 const auto n = Reshape(face_geom.normal.Read(), Q1D, 2, NF);
43
44 const bool const_q = (q.Size() == coeff_dim);
45 const auto Q = const_q ? Reshape(q.Read(), coeff_dim, 1, 1)
46 : Reshape(q.Read(), coeff_dim, Q1D, NF);
47
48 const auto W = w.Read();
49
50 // (normal0, normal1, e0, e1, fid0, fid1)
51 const auto face_info = Reshape(face_info_.Read(), 6, NF);
52
53 // (q, 1/h, J0_0, J0_1, J1_0, J1_1)
54 auto pa = Reshape(pa_data.Write(), 6, Q1D, NF);
55
56 auto get_coeff = [const_q] MFEM_HOST_DEVICE (const decltype(Q) &Q, int i,
57 int qx, int e)
58 {
59 return const_q ? Q(i,0,0) : Q(i,qx,e);
60 };
61
62 mfem::forall(NF, [=] MFEM_HOST_DEVICE(int f) -> void
63 {
64 const int normal_dir[] = {face_info(0, f), face_info(1, f)};
65 const int fid[] = {face_info(4, f), face_info(5, f)};
66
67 int el[] = {face_info(2, f), face_info(3, f)};
68 const bool interior = el[1] >= 0;
69 const int nsides = (interior) ? 2 : 1;
70 const real_t factor = interior ? 0.5 : 1.0;
71
72 const bool shared = el[1] >= NE;
73 el[1] = shared ? el[1] - NE : el[1];
74
75 const int sgn0 = (fid[0] == 0 || fid[0] == 1) ? 1 : -1;
76 const int sgn1 = (fid[1] == 0 || fid[1] == 1) ? 1 : -1;
77
78 for (int p = 0; p < Q1D; ++p)
79 {
80 real_t qh = 0.0;
81 real_t hi = 0.0;
82
83 real_t Qtn[2];
84 if (coeff_dim > 1)
85 {
86 // matrix coefficient
87 Qtn[0] = get_coeff(Q,0,p,f)*n(p,0,f) + get_coeff(Q,1,p,f)*n(p,1,f);
88 Qtn[1] = get_coeff(Q,2,p,f)*n(p,0,f) + get_coeff(Q,3,p,f)*n(p,1,f);
89 qh = Qtn[0]*n(p,0,f) + Qtn[1]*n(p,1,f);
90 }
91 else
92 {
93 qh = get_coeff(Q, 0, p, f);
94 Qtn[0] = qh*n(p,0,f);
95 Qtn[1] = qh*n(p,1,f);
96 }
97
98 pa(0, p, f) = kappa * qh * W[p] * detJf(p, f);
99
100 for (int side = 0; side < nsides; ++side)
101 {
102 int i, j;
103 internal::FaceIdxToVolIdx2D(p, Q1D, fid[0], fid[1], side, i, j);
104
105 // Always opposite direction in "native" ordering
106 // Need to multiply the native=>lex0 with native=>lex1 and negate
107 const int sgn = (side == 1) ? -1 * sgn0 * sgn1 : 1;
108
109 const int e = el[side];
110 const auto &J = (side == 1 && shared) ? J_shared : J_loc;
111 const auto &detJ = (side == 1 && shared) ? detJ_shared : detJe_loc;
112
113 real_t nJi[2];
114 nJi[0] = Qtn[0]*J(i, j, 1, 1, e) - Qtn[1]*J(i, j, 0, 1, e);
115 nJi[1] = -Qtn[0]*J(i, j, 1, 0, e) + Qtn[1]*J(i, j, 0, 0, e);
116
117 const real_t dJe = detJ(i, j, e);
118 const real_t dJf = detJf(p, f);
119
120 const real_t w = factor * W[p] * dJf / dJe;
121
122 const int ni = normal_dir[side];
123 const int ti = 1 - ni;
124
125 // Normal
126 pa(2 + 2 * side + 0, p, f) = w * nJi[ni];
127 // Tangential
128 pa(2 + 2 * side + 1, p, f) = sgn * w * nJi[ti];
129
130 hi += factor * dJf / dJe;
131 }
132
133 if (nsides == 1)
134 {
135 pa(4, p, f) = 0.0;
136 pa(5, p, f) = 0.0;
137 }
138
139 pa(1, p, f) = hi;
140 }
141 });
142}
143
144static void PADGDiffusionSetup3D(const int Q1D, const int NE, const int NF,
145 const Array<real_t> &w,
146 const GeometricFactors &el_geom,
147 const FaceGeometricFactors &face_geom,
148 const FaceNeighborGeometricFactors *nbr_geom,
149 const Vector &q, const int coeff_dim,
150 const real_t sigma, const real_t kappa,
151 Vector &pa_data, const Array<int> &face_info_)
152{
153 const auto J_loc = Reshape(el_geom.J.Read(), Q1D, Q1D, Q1D, 3, 3, NE);
154 const auto detJe_loc = Reshape(el_geom.detJ.Read(), Q1D, Q1D, Q1D, NE);
155
156 const int n_nbr = nbr_geom ? nbr_geom->num_neighbor_elems : 0;
157 const auto J_shared = Reshape(nbr_geom ? nbr_geom->J.Read() : nullptr, Q1D,
158 Q1D, Q1D, 3, 3, n_nbr);
159 const auto detJ_shared =
160 Reshape(nbr_geom ? nbr_geom->detJ.Read() : nullptr, Q1D, Q1D, Q1D, n_nbr);
161
162 const auto detJf = Reshape(face_geom.detJ.Read(), Q1D, Q1D, NF);
163 const auto n = Reshape(face_geom.normal.Read(), Q1D, Q1D, 3, NF);
164
165 const bool const_q = (q.Size() == coeff_dim);
166 const auto Q = const_q ? Reshape(q.Read(), coeff_dim, 1, 1, 1)
167 : Reshape(q.Read(), coeff_dim, Q1D, Q1D, NF);
168
169 const auto W = Reshape(w.Read(), Q1D, Q1D);
170
171 // (perm[0], perm[1], perm[2], element_index, local_face_id, orientation)
172 const auto face_info = Reshape(face_info_.Read(), 6, 2, NF);
173 constexpr int _el_ = 3; // offset in face_info for element index
174 constexpr int _fid_ = 4; // offset in face_info for local face id
175 constexpr int _or_ = 5; // offset in face_info for orientation
176
177 // (J00, J01, J02, J10, J11, J12, q/h)
178 const auto pa = Reshape(pa_data.Write(), 7, Q1D, Q1D, NF);
179
180 auto get_coeff = [const_q] MFEM_HOST_DEVICE (const decltype(Q) &Q, int i,
181 int qx, int qy, int e)
182 {
183 return const_q ? Q(i,0,0,0) : Q(i,qx,qy,e);
184 };
185
186 mfem::forall_2D(NF, Q1D, Q1D, [=] MFEM_HOST_DEVICE(int f) -> void
187 {
188 MFEM_SHARED int perm[2][3];
189 MFEM_SHARED int el[2];
190 MFEM_SHARED bool shared[2];
191 MFEM_SHARED int fid[2];
192 MFEM_SHARED int ortn[2];
193
194 MFEM_FOREACH_THREAD(side, x, 2)
195 {
196 MFEM_FOREACH_THREAD(i, y, 3) { perm[side][i] = face_info(i, side, f); }
197
198 if (MFEM_THREAD_ID(y) == 0)
199 {
200 el[side] = face_info(_el_, side, f);
201 fid[side] = face_info(_fid_, side, f);
202 ortn[side] = face_info(_or_, side, f);
203
204 // If the element index is beyond the local partition NE, then the
205 // element is a "face neighbor" element.
206 shared[side] = (el[side] >= NE);
207 el[side] = shared[side] ? el[side] - NE : el[side];
208 }
209 }
210
211 MFEM_SYNC_THREAD;
212
213 const bool interior = el[1] >= 0;
214 const int nsides = interior ? 2 : 1;
215 const real_t factor = interior ? 0.5 : 1.0;
216
217 MFEM_FOREACH_THREAD(p1, x, Q1D)
218 {
219 MFEM_FOREACH_THREAD(p2, y, Q1D)
220 {
221 const real_t dJf = detJf(p1, p2, f);
222
223 real_t hi = 0.0;
224
225 real_t Qtn[3];
226 real_t qh = 0.0;
227
228 if (coeff_dim > 1)
229 {
230 // matrix coefficient
231 for (int d = 0; d < 3; ++d)
232 {
233 Qtn[d] = get_coeff(Q,0+3*d,p1,p2,f)*n(p1,p2,0,f)
234 + get_coeff(Q,1+3*d,p1,p2,f)*n(p1,p2,1,f)
235 + get_coeff(Q,2+3*d,p1,p2,f)*n(p1,p2,2,f);
236 qh += Qtn[d] * n(p1,p2,d,f);
237 }
238 }
239 else
240 {
241 qh = get_coeff(Q,0,p1,p2,f);
242 Qtn[0] = qh * n(p1,p2,0,f);
243 Qtn[1] = qh * n(p1,p2,1,f);
244 Qtn[2] = qh * n(p1,p2,2,f);
245 }
246
247 for (int side = 0; side < nsides; ++side)
248 {
249 int i, j, k;
250 internal::FaceIdxToVolIdx3D(p1 + Q1D * p2, Q1D, fid[0], fid[1],
251 side, ortn[1], i, j, k);
252
253 const int e = el[side];
254 const auto &J = shared[side] ? J_shared : J_loc;
255 const auto &detJe = shared[side] ? detJ_shared : detJe_loc;
256
257 // *INDENT-OFF*
258 real_t nJi[3];
259 nJi[0] = (-J(i, j, k, 1, 2, e) * J(i, j, k, 2, 1, e) +
260 J(i, j, k, 1, 1, e) * J(i, j, k, 2, 2, e)) * Qtn[0] +
261 (J(i, j, k, 0, 2, e) * J(i, j, k, 2, 1, e) -
262 J(i, j, k, 0, 1, e) * J(i, j, k, 2, 2, e)) * Qtn[1] +
263 (-J(i, j, k, 0, 2, e) * J(i, j, k, 1, 1, e) +
264 J(i, j, k, 0, 1, e) * J(i, j, k, 1, 2, e)) * Qtn[2];
265
266 nJi[1] = (J(i, j, k, 1, 2, e) * J(i, j, k, 2, 0, e) -
267 J(i, j, k, 1, 0, e) * J(i, j, k, 2, 2, e)) * Qtn[0] +
268 (-J(i, j, k, 0, 2, e) * J(i, j, k, 2, 0, e) +
269 J(i, j, k, 0, 0, e) * J(i, j, k, 2, 2, e)) * Qtn[1] +
270 (J(i, j, k, 0, 2, e) * J(i, j, k, 1, 0, e) -
271 J(i, j, k, 0, 0, e) * J(i, j, k, 1, 2, e)) * Qtn[2];
272
273 nJi[2] = (-J(i, j, k, 1, 1, e) * J(i, j, k, 2, 0, e) +
274 J(i, j, k, 1, 0, e) * J(i, j, k, 2, 1, e)) * Qtn[0] +
275 (J(i, j, k, 0, 1, e) * J(i, j, k, 2, 0, e) -
276 J(i, j, k, 0, 0, e) * J(i, j, k, 2, 1, e)) * Qtn[1] +
277 (-J(i, j, k, 0, 1, e) * J(i, j, k, 1, 0, e) +
278 J(i, j, k, 0, 0, e) * J(i, j, k, 1, 1, e)) * Qtn[2];
279 // *INDENT-ON*
280
281 const real_t dJe = detJe(i, j, k, e);
282 const real_t val = factor * W(p1, p2) * dJf / dJe;
283
284 for (int d = 0; d < 3; ++d)
285 {
286 const int idx = std::abs(perm[side][d]) - 1;
287 const int sgn = (perm[side][d] < 0) ? -1 : 1;
288 pa(3 * side + d, p1, p2, f) = sgn * val * nJi[idx];
289 }
290
291 hi += factor * dJf / dJe;
292 }
293
294 if (nsides == 1)
295 {
296 pa(3, p1, p2, f) = 0.0;
297 pa(4, p1, p2, f) = 0.0;
298 pa(5, p1, p2, f) = 0.0;
299 }
300
301 pa(6, p1, p2, f) = kappa * hi * qh * W(p1, p2) * dJf;
302 }
303 }
304 });
305}
306
307static void PADGDiffusionSetupFaceInfo2D(const int nf, const Mesh &mesh,
308 const FaceType type,
309 Array<int> &face_info_)
310{
311 const int ne = mesh.GetNE();
312
313 int fidx = 0;
314 face_info_.SetSize(nf * 6);
315
316 // normal0 and normal1 are the indices of the face normal direction relative
317 // to the element in reference coordinates, i.e. if the face is normal to the
318 // x-vector (left or right face), then it will be 0, otherwise 1.
319
320 // 2d: (normal0, normal1, e0, e1, fid0, fid1)
321 auto face_info = Reshape(face_info_.HostWrite(), 6, nf);
322 for (int f = 0; f < mesh.GetNumFaces(); ++f)
323 {
324 auto f_info = mesh.GetFaceInformation(f);
325
326 if (f_info.IsOfFaceType(type))
327 {
328 const int face_id_1 = f_info.element[0].local_face_id;
329 face_info(0, fidx) = (face_id_1 == 1 || face_id_1 == 3) ? 0 : 1;
330 face_info(2, fidx) = f_info.element[0].index;
331 face_info(4, fidx) = face_id_1;
332
333 if (f_info.IsInterior())
334 {
335 const int face_id_2 = f_info.element[1].local_face_id;
336 face_info(1, fidx) = (face_id_2 == 1 || face_id_2 == 3) ? 0 : 1;
337 if (f_info.IsShared())
338 {
339 face_info(3, fidx) = ne + f_info.element[1].index;
340 }
341 else
342 {
343 face_info(3, fidx) = f_info.element[1].index;
344 }
345 face_info(5, fidx) = face_id_2;
346 }
347 else
348 {
349 face_info(1, fidx) = -1;
350 face_info(3, fidx) = -1;
351 face_info(5, fidx) = -1;
352 }
353
354 fidx++;
355 }
356 }
357}
358
359// Assigns to perm the permutation:
360// perm[0] <- normal component
361// perm[1] <- first tangential component
362// perm[2] <- second tangential component
363//
364// (Tangential components are ordering lexicographically).
365inline void FaceNormalPermutation(int perm[3], const int face_id)
366{
367 const bool xy_plane = (face_id == 0 || face_id == 5);
368 const bool xz_plane = (face_id == 1 || face_id == 3);
369 // const bool yz_plane = (face_id == 2 || face_id == 4);
370
371 perm[0] = (xy_plane) ? 3 : (xz_plane) ? 2 : 1;
372 perm[1] = (xy_plane || xz_plane) ? 1 : 2;
373 perm[2] = (xy_plane) ? 2 : 3;
374}
375
376// Assigns to perm the permutation as in FaceNormalPermutation for the second
377// element on the face but signed to indicate the sign of the normal derivative.
378inline void SignedFaceNormalPermutation(int perm[3], const int face_id1,
379 const int face_id2,
380 const int orientation)
381{
382 FaceNormalPermutation(perm, face_id2);
383
384 // Sets perm according to the inverse of PermuteFace3D
385 if (face_id2 == 3 || face_id2 == 4)
386 {
387 perm[1] *= -1;
388 }
389 else if (face_id2 == 0)
390 {
391 perm[2] *= -1;
392 }
393
394 switch (orientation)
395 {
396 case 1:
397 std::swap(perm[1], perm[2]);
398 break;
399 case 2:
400 std::swap(perm[1], perm[2]);
401 perm[1] *= -1;
402 break;
403 case 3:
404 perm[1] *= -1;
405 break;
406 case 4:
407 perm[1] *= -1;
408 perm[2] *= -1;
409 break;
410 case 5:
411 std::swap(perm[1], perm[2]);
412 perm[1] *= -1;
413 perm[2] *= -1;
414 break;
415 case 6:
416 std::swap(perm[1], perm[2]);
417 perm[2] *= -1;
418 break;
419 case 7:
420 perm[2] *= -1;
421 break;
422 default:
423 break;
424 }
425
426 if (face_id1 == 3 || face_id1 == 4)
427 {
428 perm[1] *= -1;
429 }
430 else if (face_id1 == 0)
431 {
432 perm[2] *= -1;
433 }
434}
435
436static void PADGDiffusionSetupFaceInfo3D(const int nf, const Mesh &mesh,
437 const FaceType type,
438 Array<int> &face_info_)
439{
440 const int ne = mesh.GetNE();
441
442 int fidx = 0;
443 // face_info array has 12 entries per face, 6 for each of the adjacent
444 // elements: (perm[0], perm[1], perm[2], element_index, local_face_id,
445 // orientation)
446 face_info_.SetSize(nf * 12);
447 constexpr int _e_ = 3; // offset for element index
448 constexpr int _fid_ = 4; // offset for local face id
449 constexpr int _or_ = 5; // offset for orientation
450
451 auto face_info = Reshape(face_info_.HostWrite(), 6, 2, nf);
452 for (int f = 0; f < mesh.GetNumFaces(); ++f)
453 {
454 auto f_info = mesh.GetFaceInformation(f);
455
456 if (f_info.IsOfFaceType(type))
457 {
458 const int fid0 = f_info.element[0].local_face_id;
459 const int or0 = f_info.element[0].orientation;
460
461 face_info(_e_, 0, fidx) = f_info.element[0].index;
462 face_info(_fid_, 0, fidx) = fid0;
463 face_info(_or_, 0, fidx) = or0;
464
465 FaceNormalPermutation(&face_info(0, 0, fidx), fid0);
466
467 if (f_info.IsInterior())
468 {
469 const int fid1 = f_info.element[1].local_face_id;
470 const int or1 = f_info.element[1].orientation;
471
472 if (f_info.IsShared())
473 {
474 face_info(_e_, 1, fidx) = ne + f_info.element[1].index;
475 }
476 else
477 {
478 face_info(_e_, 1, fidx) = f_info.element[1].index;
479 }
480 face_info(_fid_, 1, fidx) = fid1;
481 face_info(_or_, 1, fidx) = or1;
482
483 SignedFaceNormalPermutation(&face_info(0, 1, fidx), fid0, fid1,
484 or1);
485 }
486 else
487 {
488 for (int i = 0; i < 6; ++i)
489 {
490 face_info(i, 1, fidx) = -1;
491 }
492 }
493
494 fidx++;
495 }
496 }
497}
498
499void DGDiffusionIntegrator::SetupPA(const FiniteElementSpace &fes,
500 FaceType type)
501{
502 const MemoryType mt =
504
505 const int ne = fes.GetNE();
506 nf = fes.GetNFbyType(type);
507
508 // Assumes tensor-product elements
509 Mesh &mesh = *fes.GetMesh();
510 const Geometry::Type face_geom_type = mesh.GetTypicalFaceGeometry();
511 const FiniteElement &el = *fes.GetTypicalTraceElement();
512 const int ir_order = IntRule
513 ? IntRule->GetOrder()
514 : GetRule(el.GetOrder(), face_geom_type).GetOrder();
515 const IntegrationRule &ir = irs.Get(face_geom_type, ir_order);
516 dim = mesh.Dimension();
517 const int q1d = (ir.GetOrder() + 3) / 2;
518 MFEM_ASSERT(q1d == pow(real_t(ir.Size()), 1.0 / (dim - 1)), "");
519
520 const auto vol_ir = irs.Get(mesh.GetTypicalElementGeometry(), ir_order);
521 const auto geom_flags =
523 const auto el_geom = mesh.GetGeometricFactors(vol_ir, geom_flags, mt);
524
525 std::unique_ptr<FaceNeighborGeometricFactors> nbr_geom;
526 if (type == FaceType::Interior)
527 {
528 nbr_geom.reset(new FaceNeighborGeometricFactors(*el_geom));
529 }
530
531 const auto face_geom_flags =
533 auto face_geom = mesh.GetFaceGeometricFactors(ir, face_geom_flags, type, mt);
534 maps = &el.GetDofToQuad(ir, DofToQuad::TENSOR);
535 dofs1D = maps->ndof;
536 quad1D = maps->nqpt;
537
538 const int pa_size = (dim == 2) ? (6 * q1d * nf) : (7 * q1d * q1d * nf);
540
541 // Evaluate the coefficient at the face quadrature points.
542 FaceQuadratureSpace fqs(mesh, ir, type);
543 CoefficientVector q(fqs, CoefficientStorage::CONSTANTS);
544 if (Q) { q.Project(*Q); }
545 else if (MQ) { q.Project(*MQ); }
546 else { q.SetConstant(1.0); }
547
548 const int coeff_dim = q.GetVDim();
549
550 Array<int> face_info;
551 if (dim == 1)
552 {
553 MFEM_ABORT("dim==1 not supported in PADGTraceSetup");
554 }
555 else if (dim == 2)
556 {
557 PADGDiffusionSetupFaceInfo2D(nf, mesh, type, face_info);
558 PADGDiffusionSetup2D(quad1D, ne, nf, ir.GetWeights(), *el_geom,
559 *face_geom, nbr_geom.get(), q, coeff_dim, sigma,
560 kappa, pa_data, face_info);
561 }
562 else if (dim == 3)
563 {
564 PADGDiffusionSetupFaceInfo3D(nf, mesh, type, face_info);
565 PADGDiffusionSetup3D(quad1D, ne, nf, ir.GetWeights(), *el_geom,
566 *face_geom, nbr_geom.get(), q, coeff_dim, sigma,
567 kappa, pa_data, face_info);
568 }
569}
570
576
582
584 const Vector &dxdn,
585 Vector &y,
586 Vector &dydn) const
587{
588 ApplyPAKernels::Run(dim, dofs1D, quad1D, nf, maps->B, maps->Bt, maps->G,
589 maps->Gt, sigma, pa_data, x, dxdn, y, dydn, dofs1D,
590 quad1D);
591}
592
594 : sigma(s), kappa(k)
595{
596 static Kernels kernels;
597}
598
600 const real_t k)
602{
603 Q = &q;
604}
605
612
613/// \cond DO_NOT_DOCUMENT
614
616DGDiffusionIntegrator::ApplyPAKernels::Fallback(int dim, int, int)
617{
618 if (dim == 2)
619 {
620 return internal::PADGDiffusionApply2D;
621 }
622 else if (dim == 3)
623 {
624 return internal::PADGDiffusionApply3D;
625 }
626 else
627 {
628 MFEM_ABORT("");
629 }
630}
631
632DGDiffusionIntegrator::Kernels::Kernels()
633{
642
651}
652
653/// \endcond DO_NOT_DOCUMENT
654
655} // namespace mfem
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
void AssemblePAInteriorFaces(const FiniteElementSpace &fes) override
const IntegrationRule & GetRule(int order, FaceElementTransformations &T)
DGDiffusionIntegrator(const real_t s, const real_t k)
void AddMultPAFaceNormalDerivatives(const Vector &x, const Vector &dxdn, Vector &y, Vector &dydn) const override
Method for partially assembled action.
void AssemblePABoundaryFaces(const FiniteElementSpace &fes) override
void(*)(const int, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const real_t, const Vector &, const Vector &_, const Vector &, Vector &, Vector &, const int, const int) ApplyKernelType
const DofToQuad * maps
Not owned.
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:281
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Definition device.hpp:277
Array< real_t > G
Gradients/divergences/curls of basis functions evaluated at quadrature points.
Definition fe_base.hpp:214
@ 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
Array< real_t > Gt
Transpose of G.
Definition fe_base.hpp:221
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:208
int GetOrder() const
Returns the order of the integration rule.
Definition intrules.hpp:249
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
const IntegrationRule * IntRule
Base class for Matrix Coefficients that optionally depend on time and space.
Vector data type.
Definition vector.hpp:82
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:584
real_t sigma(const Vector &x)
Definition maxwell.cpp:91
real_t kappa
Definition ex24.cpp:54
int dim
Definition ex24.cpp:53
mfem::real_t real_t
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
Definition dual.hpp:374
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
void SignedFaceNormalPermutation(int perm[3], const int face_id1, const int face_id2, const int orientation)
void FaceNormalPermutation(int perm[3], const int face_id)
@ CONSTANTS
Store constants using only vdim entries.
void forall_2D(int N, int X, int Y, lambda &&body)
Definition forall.hpp:925
float real_t
Definition config.hpp:46
MemoryType
Memory types supported by MFEM.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void forall(int N, lambda &&body)
Definition forall.hpp:839
FaceType
Definition mesh.hpp:49
real_t p(const Vector &x, real_t t)