MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
quadinterpolator.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 "quadinterpolator.hpp"
13#include "qinterp/grad.hpp"
14#include "qinterp/eval.hpp"
15#include "qspace.hpp"
16#include "../general/forall.hpp"
17#include "../linalg/dtensor.hpp"
18#include "../linalg/kernels.hpp"
19
20namespace mfem
21{
22
23namespace internal
24{
25namespace quadrature_interpolator
26{
27void InitEvalByNodesKernels();
28void InitEvalByVDimKernels();
29void InitEvalKernels();
30void InitDetKernels();
31template <bool P> void InitGradByNodesKernels();
32template <bool P> void InitGradByVDimKernels();
33void InitTensorEvalHDivKernels();
34struct Kernels
35{
36 Kernels()
37 {
38 using namespace internal::quadrature_interpolator;
39
40 InitEvalByNodesKernels();
41 InitEvalByVDimKernels();
42 // Non-phys grad kernels
43 InitGradByNodesKernels<false>();
44 InitGradByVDimKernels<false>();
45 // Phys grad kernels
46 InitGradByNodesKernels<true>();
47 InitGradByVDimKernels<true>();
48 // Determinants
49 InitDetKernels();
50 // Non-tensor
51 InitEvalKernels();
52 // Tensor (quad,hex) H(div)
53 InitTensorEvalHDivKernels();
54 }
55};
56}
57}
58
60 const IntegrationRule &ir):
61
62 fespace(&fes),
63 qspace(nullptr),
64 IntRule(&ir),
65 q_layout(QVectorLayout::byNODES),
66 use_tensor_products(UsesTensorBasis(fes))
67{
68 static internal::quadrature_interpolator::Kernels kernels;
69
70 d_buffer.UseDevice(true);
71 if (fespace->GetNE() == 0) { return; }
72 MFEM_VERIFY(
73 SupportsFESpace(fes),
74 "Only elements with MapType VALUE, INTEGRAL, or H_DIV are supported!");
75}
76
78 const QuadratureSpace &qs):
79
80 fespace(&fes),
81 qspace(&qs),
82 IntRule(nullptr),
83 q_layout(QVectorLayout::byNODES),
84 use_tensor_products(UsesTensorBasis(fes))
85{
86 d_buffer.UseDevice(true);
87 if (fespace->GetNE() == 0) { return; }
88 MFEM_VERIFY(
89 SupportsFESpace(fes),
90 "Only elements with MapType VALUE, INTEGRAL, or H_DIV are supported!");
91}
92
102
103namespace internal
104{
105
106namespace quadrature_interpolator
107{
108
109// Compute kernel for 1D quadrature interpolation:
110// * non-tensor product version,
111// * assumes 'e_vec' is using ElementDofOrdering::NATIVE,
112// * assumes 'maps.mode == FULL'.
113template <bool Integral>
114void ImplEval1D(const int NE, const int vdim, const QVectorLayout q_layout,
115 const real_t *detJ_, const GeometricFactors *geom,
116 const DofToQuad &maps, const Vector &e_vec, Vector &q_val,
117 Vector &q_der, Vector &q_det, const int eval_flags)
118{
119 using QI = QuadratureInterpolator;
120
121 const int nd = maps.ndof;
122 const int nq = maps.nqpt;
123 MFEM_ASSERT(maps.mode == DofToQuad::FULL, "internal error");
124 MFEM_ASSERT(!geom || geom->mesh->SpaceDimension() == 1, "");
125 MFEM_VERIFY(vdim == 1 || !(eval_flags & QI::DETERMINANTS), "");
126 if constexpr(Integral)
127 {
128 MFEM_VERIFY(!(eval_flags & (QI::DERIVATIVES | QI::PHYSICAL_DERIVATIVES |
129 QI::DETERMINANTS)),
130 "Integral FE does not support computing derivatives");
131 }
132 const auto B_ = maps.B.Read();
133 const auto G_ = maps.G.Read();
134 const auto J = Reshape(geom ? geom->J.Read() : nullptr, nq, NE);
135 const auto E_ = e_vec.Read();
136 auto val = q_layout == QVectorLayout::byNODES ?
137 Reshape(q_val.Write(), nq, vdim, NE):
138 Reshape(q_val.Write(), vdim, nq, NE);
139 auto der = q_layout == QVectorLayout::byNODES ?
140 Reshape(q_der.Write(), nq, vdim, NE):
141 Reshape(q_der.Write(), vdim, nq, NE);
142 auto det = Reshape(q_det.Write(), nq, NE);
143 mfem::forall(NE, [=] MFEM_HOST_DEVICE(int e)
144 {
145 const auto B = Reshape(B_, nq, nd);
146 const auto G = Reshape(G_, nq, nd);
147 const auto E = Reshape(E_, nd, vdim, NE);
148 const auto detJ = Reshape(detJ_, nq, NE);
149 for (int q = 0; q < nq; ++q)
150 {
151 if (eval_flags & (QI::VALUES | QI::PHYSICAL_VALUES))
152 {
153 for (int c = 0; c < vdim; c++)
154 {
155 real_t q_val = 0.0;
156 for (int d = 0; d < nd; ++d)
157 {
158 q_val += B(q, d) * E(d, c, e);
159 }
160 if constexpr (Integral)
161 {
162 q_val /= detJ(q, e);
163 }
164 if (q_layout == QVectorLayout::byVDIM)
165 {
166 val(c, q, e) = q_val;
167 }
168 if (q_layout == QVectorLayout::byNODES)
169 {
170 val(q, c, e) = q_val;
171 }
172 }
173 }
174 if ((eval_flags & QI::DERIVATIVES) ||
175 (eval_flags & QI::PHYSICAL_DERIVATIVES) ||
176 (eval_flags & QI::DETERMINANTS))
177 {
178 for (int c = 0; c < vdim; c++)
179 {
180 real_t q_d = 0.0;
181 for (int d = 0; d < nd; ++d)
182 {
183 q_d += G(q, d) * E(d, c, e);
184 }
185 if (eval_flags & QI::PHYSICAL_DERIVATIVES)
186 {
187 q_d /= J(q,e);
188 }
189 if (eval_flags & QI::DERIVATIVES || eval_flags & QI::PHYSICAL_DERIVATIVES)
190 {
191 if (q_layout == QVectorLayout::byVDIM)
192 {
193 der(c, q, e) = q_d;
194 }
195 if (q_layout == QVectorLayout::byNODES)
196 {
197 der(q, c, e) = q_d;
198 }
199 }
200 if (vdim == 1 && (eval_flags & QI::DETERMINANTS))
201 {
202 det(q,e) = q_d;
203 }
204 }
205 }
206 }
207 });
208}
209
210template void
211ImplEval1D<true>(const int NE, const int vdim, const QVectorLayout q_layout,
212 const real_t *detJ, const GeometricFactors *geom,
213 const DofToQuad &maps, const Vector &e_vec, Vector &q_val,
214 Vector &q_der, Vector &q_det, const int eval_flags);
215
216template void
217ImplEval1D<false>(const int NE, const int vdim, const QVectorLayout q_layout,
218 const real_t *detJ, const GeometricFactors *geom,
219 const DofToQuad &maps, const Vector &e_vec, Vector &q_val,
220 Vector &q_der, Vector &q_det, const int eval_flags);
221
222} // namespace quadrature_interpolator
223
224} // namespace internal
225
227 unsigned eval_flags,
228 Vector &q_val,
229 Vector &q_der,
230 Vector &q_det) const
231{
232 using namespace internal::quadrature_interpolator;
233
234 const int ne = fespace->GetNE();
235 if (ne == 0) { return; }
236 const FiniteElement *fe = fespace->GetFE(0);
237
239 {
240 // q_der == q_div
241 return MultHDiv(e_vec, eval_flags, q_val, q_der);
242 }
243
244 const int vdim = fespace->GetVDim();
245 const int sdim = fespace->GetMesh()->SpaceDimension();
246 const bool use_tensor_eval =
248 dynamic_cast<const TensorBasisElement*>(fe) != nullptr;
249 const IntegrationRule *ir =
251 const DofToQuad::Mode mode =
252 use_tensor_eval ? DofToQuad::TENSOR : DofToQuad::FULL;
253 const DofToQuad &maps = fe->GetDofToQuad(*ir, mode);
254 const int dim = maps.FE->GetDim();
255 const int nd = maps.ndof;
256 const int nq = maps.nqpt;
257 const GeometricFactors *geom = nullptr;
258 {
259 int jac_factors = 0;
260 if (eval_flags & PHYSICAL_DERIVATIVES)
261 {
262 jac_factors = GeometricFactors::JACOBIANS;
263 }
265 {
266 jac_factors |= GeometricFactors::DETERMINANTS;
267 }
268 if (jac_factors)
269 {
270 geom = fespace->GetMesh()->GetGeometricFactors(*ir, jac_factors);
271 }
272 }
273
274 MFEM_ASSERT(!(eval_flags & DETERMINANTS) || dim == vdim ||
275 (dim == 2 && vdim == 3) || (dim == 1 && vdim == 2) ||
276 (dim == 1 && vdim == 3), "Invalid dimensions for determinants.");
277 MFEM_ASSERT(fespace->GetMesh()->GetNumGeometries(
278 fespace->GetMesh()->Dimension()) == 1,
279 "mixed meshes are not supported");
280
281 if (use_tensor_eval)
282 {
283 if (eval_flags & (VALUES | PHYSICAL_VALUES))
284 {
286 {
287 IntTensorEvalKernels::Run(dim, q_layout, vdim, nd, nq, ne,
288 maps.B.Read(), geom->detJ.Read(),
289 e_vec.Read(), q_val.Write(), vdim, nd, nq);
290 }
291 else
292 {
293 TensorEvalKernels::Run(dim, q_layout, vdim, nd, nq, ne,
294 maps.B.Read(), e_vec.Read(), q_val.Write(),
295 vdim, nd, nq);
296 }
297 }
298 if (eval_flags & (DERIVATIVES | PHYSICAL_DERIVATIVES))
299 {
300 const bool phys = (eval_flags & PHYSICAL_DERIVATIVES);
301 const real_t *J = phys ? geom->J.Read() : nullptr;
302 const int s_dim = phys ? sdim : dim;
304 {
305 MFEM_ABORT("");
306 }
307 else
308 {
309 GradKernels::Run(dim, q_layout, phys, vdim, nd, nq, ne,
310 maps.B.Read(), maps.G.Read(), J, e_vec.Read(),
311 q_der.Write(), s_dim, vdim, nd, nq);
312 }
313 }
314 if (eval_flags & DETERMINANTS)
315 {
317 {
318 MFEM_ABORT("");
319 }
320 else
321 {
322 DetKernels::Run(dim, vdim, nd, nq, ne, maps.B.Read(), maps.G.Read(),
323 e_vec.Read(), q_det.Write(), nd, nq, &d_buffer);
324 }
325 }
326 }
327 else // use_tensor_eval == false
328 {
330 {
331 IntEvalKernels::Run(dim, vdim, maps.ndof, maps.nqpt, ne, vdim,
332 q_layout, geom->detJ.Read(), geom, maps, e_vec,
333 q_val, q_der, q_det, eval_flags);
334 }
335 else
336 {
337 EvalKernels::Run(dim, vdim, maps.ndof, maps.nqpt, ne, vdim, q_layout,
338 geom, maps, e_vec, q_val, q_der, q_det, eval_flags);
339 }
340 }
341}
342
344 unsigned eval_flags,
345 Vector &q_val,
346 Vector &q_div) const
347{
348 const int ne = fespace->GetNE();
349 if (ne == 0) { return; }
350 MFEM_VERIFY(fespace->IsVariableOrder() == false,
351 "variable order spaces are not supported yet!");
352 const FiniteElement *fe = fespace->GetFE(0);
353 MFEM_VERIFY(fe->GetMapType() == FiniteElement::MapType::H_DIV,
354 "this method can be used only for H(div) spaces");
355 MFEM_VERIFY((eval_flags &
357 "only VALUES, PHYSICAL_VALUES, and PHYSICAL_MAGNITUDES"
358 " evaluations are implemented!");
359 const int dim = fespace->GetMesh()->Dimension();
360 const int sdim = fespace->GetMesh()->SpaceDimension();
361 MFEM_VERIFY((dim == 2 || dim == 3) && dim == sdim,
362 "dim = " << dim << ", sdim = " << sdim
363 << " is not supported yet!");
364 MFEM_VERIFY(fespace->GetMesh()->GetNumGeometries(dim) <= 1,
365 "mixed meshes are not supported yet!");
366 const int vdim = fespace->GetVDim();
367 MFEM_VERIFY(vdim == 1, "vdim != 1 is not supported yet!");
368 auto tfe = dynamic_cast<const VectorTensorFiniteElement *>(fe);
369 MFEM_VERIFY(tfe != nullptr, "only quad and hex elements are supported!");
370 MFEM_VERIFY(use_tensor_products,
371 "non-tensor-product evaluation are not supported yet!");
372 const bool use_tensor_eval = use_tensor_products && (tfe != nullptr);
373 const IntegrationRule *ir =
375 const DofToQuad::Mode mode =
376 use_tensor_eval ? DofToQuad::TENSOR : DofToQuad::FULL;
377 const DofToQuad &maps_c = tfe->GetDofToQuad(*ir, mode);
378 const DofToQuad &maps_o = tfe->GetDofToQuadOpen(*ir, mode);
379 const int nd = maps_c.ndof;
380 const int nq = maps_c.nqpt;
381 const GeometricFactors *geom = nullptr;
382 if (eval_flags & (PHYSICAL_VALUES | PHYSICAL_MAGNITUDES))
383 {
384 const int jacobians = GeometricFactors::JACOBIANS;
385 geom = fespace->GetMesh()->GetGeometricFactors(*ir, jacobians);
386 }
387 // Check that at most one of VALUES, PHYSICAL_VALUES, and PHYSICAL_MAGNITUDES
388 // is specified:
389 MFEM_VERIFY(bool(eval_flags & VALUES) + bool(eval_flags & PHYSICAL_VALUES) +
390 bool(eval_flags & PHYSICAL_MAGNITUDES) <= 1,
391 "only one of VALUES, PHYSICAL_VALUES, and PHYSICAL_MAGNITUDES"
392 " can be requested at a time!");
393 const unsigned value_eval_mode =
394 eval_flags & (VALUES | PHYSICAL_VALUES | PHYSICAL_MAGNITUDES);
395 if (value_eval_mode)
396 {
397 // For PHYSICAL_MAGNITUDES the QVectorLayouts are the same and we
398 // instantiate only QVectorLayout::byNODES:
399 const auto q_l = (eval_flags & PHYSICAL_MAGNITUDES) ?
401 TensorEvalHDivKernels::Run(
402 // dispatch params: dim + the template params of EvalHDiv2D/3D:
403 dim, q_l, value_eval_mode, nd, nq,
404 // runtime params, see the arguments of EvalHDiv2D/3D:
405 ne, maps_o.B.Read(), maps_c.B.Read(), geom ? geom->J.Read() : nullptr,
406 e_vec.Read(), q_val.Write(), nd, nq);
407 }
408 MFEM_CONTRACT_VAR(q_div);
409}
410
412 const Vector &q_val,
413 const Vector &q_der,
414 Vector &e_vec) const
415{
416 MFEM_CONTRACT_VAR(eval_flags);
417 MFEM_CONTRACT_VAR(q_val);
418 MFEM_CONTRACT_VAR(q_der);
419 MFEM_CONTRACT_VAR(e_vec);
420 MFEM_ABORT("this method is not implemented yet");
421}
422
424 Vector &q_val) const
425{
426 Vector empty;
427 Mult(e_vec, VALUES, q_val, empty, empty);
428}
429
431 Vector &q_val) const
432{
433 Vector empty;
434 Mult(e_vec, PHYSICAL_VALUES, q_val, empty, empty);
435}
436
438 Vector &q_der) const
439{
440 Vector empty;
441 Mult(e_vec, DERIVATIVES, empty, q_der, empty);
442}
443
445 Vector &q_der) const
446{
447 Vector empty;
448 Mult(e_vec, PHYSICAL_DERIVATIVES, empty, q_der, empty);
449}
450
452 Vector &q_det) const
453{
454 Vector empty;
455 Mult(e_vec, DETERMINANTS, empty, empty, q_det);
456}
457
458/// @cond Suppress_Doxygen_warnings
459
460namespace
461{
462
463using namespace internal::quadrature_interpolator;
464
465template <QVectorLayout Q_LAYOUT> auto IntFallbackTensorEvalKernel(int DIM)
466{
467 if (DIM == 1)
468 {
469 return ImplValues1D<Q_LAYOUT, true>;
470 }
471 else if (DIM == 2)
472 {
473 return ImplValues2D<Q_LAYOUT, true>;
474 }
475 else if (DIM == 3)
476 {
477 return ImplValues3D<Q_LAYOUT, true>;
478 }
479 MFEM_ABORT("");
480}
481
482template <QVectorLayout Q_LAYOUT> auto FallbackTensorEvalKernel(int DIM)
483{
484 if (DIM == 1)
485 {
486 return Values1D<Q_LAYOUT>;
487 }
488 else if (DIM == 2)
489 {
490 return Values2D<Q_LAYOUT>;
491 }
492 else if (DIM == 3)
493 {
494 return Values3D<Q_LAYOUT>;
495 }
496 MFEM_ABORT("");
497}
498
499template <QVectorLayout Q_LAYOUT, bool GRAD_PHYS> auto GetGradKernel(int DIM)
500{
501 if (DIM == 1) { return Derivatives1D<Q_LAYOUT, GRAD_PHYS>; }
502 else if (DIM == 2) { return Derivatives2D<Q_LAYOUT, GRAD_PHYS>; }
503 else if (DIM == 3) { return Derivatives3D<Q_LAYOUT, GRAD_PHYS>; }
504 else { MFEM_ABORT(""); }
505}
506
507template <QVectorLayout Q_LAYOUT> auto GetGradKernel(int DIM, bool GRAD_PHYS)
508{
509 if (GRAD_PHYS) { return GetGradKernel<Q_LAYOUT, true>(DIM); }
510 else { return GetGradKernel<Q_LAYOUT, false>(DIM); }
511}
512
513template<QVectorLayout Q_LAYOUT, bool GRAD_PHYS>
514auto GetCollocatedGradKernel(int DIM)
515{
516 if (DIM == 1)
517 {
518 return CollocatedDerivatives1D<Q_LAYOUT, GRAD_PHYS>;
519 }
520 else if (DIM == 2)
521 {
522 return CollocatedDerivatives2D<Q_LAYOUT, GRAD_PHYS>;
523 }
524 else if (DIM == 3)
525 {
526 return CollocatedDerivatives3D<Q_LAYOUT, GRAD_PHYS>;
527 }
528 MFEM_ABORT("");
529}
530
531template <QVectorLayout Q_LAYOUT>
532auto GetCollocatedGradKernel(int DIM, bool GRAD_PHYS)
533{
534 if (GRAD_PHYS) { return GetCollocatedGradKernel<Q_LAYOUT, true>(DIM); }
535 else { return GetCollocatedGradKernel<Q_LAYOUT, false>(DIM); }
536}
537
538auto GetCollocatedGradKernel(int DIM, bool GRAD_PHYS, QVectorLayout Q_LAYOUT)
539{
540 if (Q_LAYOUT == QVectorLayout::byNODES)
541 {
542 return GetCollocatedGradKernel<QVectorLayout::byNODES>(
543 DIM, GRAD_PHYS);
544 }
545 else
546 {
547 return GetCollocatedGradKernel<QVectorLayout::byVDIM>(
548 DIM, GRAD_PHYS);
549 }
550}
551} // namespace
552
553template <int DIM, bool Integral>
554auto GetEvalKernelVDimFallback(int VDIM)
555{
556 if constexpr (Integral)
557 {
558 using EvalKernels = QuadratureInterpolator::IntEvalKernels;
559 if (VDIM == 1)
560 {
561 return EvalKernels::Kernel<DIM, 1, 0, 0>();
562 }
563 else if (VDIM == 2)
564 {
565 return EvalKernels::Kernel<DIM, 2, 0, 0>();
566 }
567 else if (VDIM == 3)
568 {
569 return EvalKernels::Kernel<DIM, 3, 0, 0>();
570 }
571 }
572 if constexpr (!Integral)
573 {
574 using EvalKernels = QuadratureInterpolator::EvalKernels;
575 if (VDIM == 1)
576 {
577 return EvalKernels::Kernel<DIM, 1, 0, 0>();
578 }
579 else if (VDIM == 2)
580 {
581 return EvalKernels::Kernel<DIM, 2, 0, 0>();
582 }
583 else if (VDIM == 3)
584 {
585 return EvalKernels::Kernel<DIM, 3, 0, 0>();
586 }
587 }
588 MFEM_ABORT("");
589}
590
591template auto GetEvalKernelVDimFallback<1, true>(int VDIM);
592template auto GetEvalKernelVDimFallback<1, false>(int VDIM);
593template auto GetEvalKernelVDimFallback<2, true>(int VDIM);
594template auto GetEvalKernelVDimFallback<2, false>(int VDIM);
595template auto GetEvalKernelVDimFallback<3, true>(int VDIM);
596template auto GetEvalKernelVDimFallback<3, false>(int VDIM);
597
599QuadratureInterpolator::IntEvalKernels::Fallback(int DIM, int VDIM, int ND,
600 int NQ)
601{
602 if (DIM == 1)
603 {
604 return GetEvalKernelVDimFallback<1, true>(VDIM);
605 }
606 else if (DIM == 2)
607 {
608 return GetEvalKernelVDimFallback<2, true>(VDIM);
609 }
610 else if (DIM == 3)
611 {
612 return GetEvalKernelVDimFallback<3, true>(VDIM);
613 }
614 else
615 {
616 MFEM_ABORT("");
617 }
618}
619
621QuadratureInterpolator::EvalKernels::Fallback(int DIM, int VDIM, int ND, int NQ)
622{
623 if (DIM == 1)
624 {
625 return GetEvalKernelVDimFallback<1, false>(VDIM);
626 }
627 else if (DIM == 2)
628 {
629 return GetEvalKernelVDimFallback<2, false>(VDIM);
630 }
631 else if (DIM == 3)
632 {
633 return GetEvalKernelVDimFallback<3, false>(VDIM);
634 }
635 else
636 {
637 MFEM_ABORT("");
638 }
639}
640
642QuadratureInterpolator::IntTensorEvalKernels::Fallback(int DIM,
643 QVectorLayout Q_LAYOUT,
644 int, int, int)
645{
646 if (Q_LAYOUT == QVectorLayout::byNODES)
647 {
648 return IntFallbackTensorEvalKernel<QVectorLayout::byNODES>(DIM);
649 }
650 else
651 {
652 return IntFallbackTensorEvalKernel<QVectorLayout::byVDIM>(DIM);
653 }
654}
655
657QuadratureInterpolator::TensorEvalKernels::Fallback(int DIM,
658 QVectorLayout Q_LAYOUT, int,
659 int, int)
660{
661 if (Q_LAYOUT == QVectorLayout::byNODES)
662 {
663 return FallbackTensorEvalKernel<QVectorLayout::byNODES>(DIM);
664 }
665 else
666 {
667 return FallbackTensorEvalKernel<QVectorLayout::byVDIM>(DIM);
668 }
669}
670
672QuadratureInterpolator::GradKernels::Fallback(int DIM, QVectorLayout Q_LAYOUT,
673 bool GRAD_PHYS, int, int, int)
674{
675 if (Q_LAYOUT == QVectorLayout::byNODES) { return GetGradKernel<QVectorLayout::byNODES>(DIM, GRAD_PHYS); }
676 else { return GetGradKernel<QVectorLayout::byVDIM>(DIM, GRAD_PHYS); }
677}
678
680QuadratureInterpolator::CollocatedGradKernels::Fallback(int DIM,
681 QVectorLayout Q_LAYOUT,
682 bool GRAD_PHYS, int,
683 int)
684{
685 return GetCollocatedGradKernel(DIM, GRAD_PHYS, Q_LAYOUT);
686}
687
688/// @endcond
689
690namespace internal
691{
692namespace quadrature_interpolator
693{
694void InitEvalKernels()
695{
696 // 2D, VDIM = 1
699 // Q1
702 // Q2
705 // Q3
709 // Q4
714
715 // 3D, VDIM = 1
716 // Q0
719 // Q1
722 // Q2
725 // Q3
729 // Q4
732
733 // 2D, VDIM = 3
734 // Q0
737 // Q1
740 // Q2
745 // Q3
749 // Q4
754
755 // 2D, VDIM = 2
756 // Q1
759 // Q2
762 // Q3
766 // Q4
771
772 // 3D, VDIM = 3
773 // Q1
776 // Q2
780 // Q3
784 // Q4
787}
788
789} // namespace quadrature_Interpolator
790} // namespace internal
791
792} // namespace mfem
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:410
Structure representing the matrices/tensors needed to evaluate (in reference space) the values,...
Definition fe_base.hpp:141
Mode mode
Describes the contents of the B, Bt, G, and Gt arrays, see Mode.
Definition fe_base.hpp:182
Array< real_t > G
Gradients/divergences/curls of basis functions evaluated at quadrature points.
Definition fe_base.hpp:222
Mode
Type of data stored in the arrays B, Bt, G, and Gt.
Definition fe_base.hpp:154
@ FULL
Full multidimensional representation which does not use tensor product structure. The ordering of the...
Definition fe_base.hpp:158
@ 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
const class FiniteElement * FE
The FiniteElement that created and owns this object.
Definition fe_base.hpp:145
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Definition fe_base.hpp:190
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
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition fespace.cpp:3860
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:867
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 GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:381
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition fe_base.hpp:436
Structure for storing mesh geometric factors: coordinates, Jacobians, and determinants of the Jacobia...
Definition mesh.hpp:3119
const Mesh * mesh
Definition mesh.hpp:3125
Vector detJ
Determinants of the Jacobians at all quadrature points.
Definition mesh.hpp:3164
Vector J
Jacobians of the element transformations at all quadrature points.
Definition mesh.hpp:3158
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
Mesh data type.
Definition mesh.hpp:67
bool IsMixedMesh() const
Returns true if the mesh is a mixed mesh, false otherwise.
Definition mesh.cpp:8038
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
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
A class that performs interpolation from an E-vector to quadrature point values and/or derivatives (Q...
bool use_tensor_products
Tensor product evaluation mode.
@ VALUES
Evaluate the values at quadrature points.
@ DERIVATIVES
Evaluate the derivatives at quadrature points.
@ PHYSICAL_DERIVATIVES
Evaluate the physical derivatives.
@ DETERMINANTS
Assuming the derivative at quadrature points form a matrix, this flag can be used to compute and stor...
QuadratureInterpolator(const FiniteElementSpace &fes, const IntegrationRule &ir)
void Mult(const Vector &e_vec, unsigned eval_flags, Vector &q_val, Vector &q_der, Vector &q_det) const
Interpolate the E-vector e_vec to quadrature points.
void(*)(const int ne, const real_t *B, const real_t *e_vec, real_t *q_val, const int vdim, const int nd, const int nq) TensorEvalKernelType
void Determinants(const Vector &e_vec, Vector &q_det) const
Compute the determinants of the derivatives (with respect to reference coordinates) of the E-vector e...
void(*)(const int ne, const real_t *B, const real_t *G, const real_t *J, const real_t *e_vec, real_t *q_der, const int s_dim, const int v_dim, const int nd, const int nq) GradKernelType
void MultTranspose(unsigned eval_flags, const Vector &q_val, const Vector &q_der, Vector &e_vec) const
Perform the transpose operation of Mult(). (TODO)
void(*)(const int NE, const int vdim, const QVectorLayout q_layout, const GeometricFactors *geom, const DofToQuad &maps, const Vector &e_vec, Vector &q_val, Vector &q_der, Vector &q_det, const int eval_flags) EvalKernelType
void(*)(const int NE, const int vdim, const QVectorLayout q_layout, const real_t *detJ, const GeometricFactors *geom, const DofToQuad &maps, const Vector &e_vec, Vector &q_val, Vector &q_der, Vector &q_det, const int eval_flags) IntEvalKernelType
void Values(const Vector &e_vec, Vector &q_val) const
Interpolate the values of the E-vector e_vec at quadrature points.
void PhysValues(const Vector &e_vec, Vector &q_val) const
Interpolate the physical values of the E-vector e_vec at quadrature points.
void Derivatives(const Vector &e_vec, Vector &q_der) const
Interpolate the derivatives (with respect to reference coordinates) of the E-vector e_vec at quadratu...
QVectorLayout q_layout
Output Q-vector layout.
void PhysDerivatives(const Vector &e_vec, Vector &q_der) const
Interpolate the derivatives in physical space of the E-vector e_vec at quadrature points.
static bool SupportsFESpace(const FiniteElementSpace &fespace)
Returns true if the given finite element space is supported by QuadratureInterpolator.
static void AddEvalSpecializations()
Adds specializations for EvalKernels.
const IntegrationRule * IntRule
Not owned.
void(*)(const int ne, const real_t *B, const real_t *detJ, const real_t *e_vec, real_t *q_val, const int vdim, const int nd, const int nq) IntTensorEvalKernelType
Vector d_buffer
Auxiliary device buffer.
const FiniteElementSpace * fespace
Not owned.
const QuadratureSpace * qspace
Not owned.
void MultHDiv(const Vector &e_vec, unsigned eval_flags, Vector &q_val, Vector &q_div) const
Auxiliary method called by Mult() when using H(div)-conforming space.
void(*)(const int ne, const real_t *G, const real_t *J, const real_t *e_vec, real_t *q_der, const int sdim, const int vdim, const int d1d) CollocatedGradKernelType
Class representing the storage layout of a QuadratureFunction.
Definition qspace.hpp:164
const IntegrationRule & GetElementIntRule(int idx) const
Get the IntegrationRule associated with mesh element idx.
Definition qspace.hpp:193
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 void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition vector.hpp:145
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:528
int dim
Definition ex24.cpp:53
constexpr int DIM
mfem::real_t real_t
MFEM_HOST_DEVICE T det(const tensor< T, 1, 1 > &A)
Returns the determinant of a matrix.
Definition tensor.hpp:1406
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:386
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 UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.
Definition fespace.hpp:1644
QVectorLayout
Type describing possible layouts for Q-vectors.
Definition fespace.hpp:33
float real_t
Definition config.hpp:46
void forall(int N, lambda &&body)
Definition forall.hpp:1134