MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
eval.hpp
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// Internal header, included only by .cpp files.
13// Template function implementations.
14
15#ifndef MFEM_QUADINTERP_EVAL
16#define MFEM_QUADINTERP_EVAL
17
22#include "../kernels.hpp"
23
24namespace mfem
25{
26
27namespace internal
28{
29
30namespace quadrature_interpolator
31{
32
33template<QVectorLayout Q_LAYOUT>
34static void Values1D(const int NE,
35 const real_t *b_,
36 const real_t *x_,
37 real_t *y_,
38 const int vdim,
39 const int d1d,
40 const int q1d)
41{
42 const auto b = Reshape(b_, q1d, d1d);
43 const auto x = Reshape(x_, d1d, vdim, NE);
44 auto y = Q_LAYOUT == QVectorLayout::byNODES ?
45 Reshape(y_, q1d, vdim, NE):
46 Reshape(y_, vdim, q1d, NE);
47
48 mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
49 {
50 for (int c = 0; c < vdim; c++)
51 {
52 for (int q = 0; q < q1d; q++)
53 {
54 real_t u = 0.0;
55 for (int d = 0; d < d1d; d++)
56 {
57 u += b(q, d) * x(d, c, e);
58 }
59 if (Q_LAYOUT == QVectorLayout::byVDIM) { y(c, q, e) = u; }
60 if (Q_LAYOUT == QVectorLayout::byNODES) { y(q, c, e) = u; }
61 }
62 }
63 });
64}
65
66// Template compute kernel for Values in 2D: tensor product version.
67template<QVectorLayout Q_LAYOUT,
68 int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
69 int T_NBZ = 1>
70static void Values2D(const int NE,
71 const real_t *b_,
72 const real_t *x_,
73 real_t *y_,
74 const int vdim = 0,
75 const int d1d = 0,
76 const int q1d = 0)
77{
78 static constexpr int NBZ = T_NBZ ? T_NBZ : 1;
79
80 const int D1D = T_D1D ? T_D1D : d1d;
81 const int Q1D = T_Q1D ? T_Q1D : q1d;
82 const int VDIM = T_VDIM ? T_VDIM : vdim;
83
84 const auto b = Reshape(b_, Q1D, D1D);
85 const auto x = Reshape(x_, D1D, D1D, VDIM, NE);
86 auto y = Q_LAYOUT == QVectorLayout::byNODES ?
87 Reshape(y_, Q1D, Q1D, VDIM, NE):
88 Reshape(y_, VDIM, Q1D, Q1D, NE);
89
90 mfem::forall_2D_batch(NE, Q1D, Q1D, NBZ, [=] MFEM_HOST_DEVICE (int e)
91 {
92 const int D1D = T_D1D ? T_D1D : d1d;
93 const int Q1D = T_Q1D ? T_Q1D : q1d;
94 const int VDIM = T_VDIM ? T_VDIM : vdim;
95 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
96 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
97 constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
98 const int tidz = MFEM_THREAD_ID(z);
99
100 MFEM_SHARED real_t sB[MQ1*MD1];
101 MFEM_SHARED real_t sm0[NBZ][MDQ*MDQ];
102 MFEM_SHARED real_t sm1[NBZ][MDQ*MDQ];
103
104 kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
105
106 ConstDeviceMatrix B(sB, D1D,Q1D);
107 DeviceMatrix DD(sm0[tidz], MD1, MD1);
108 DeviceMatrix DQ(sm1[tidz], MD1, MQ1);
109 DeviceMatrix QQ(sm0[tidz], MQ1, MQ1);
110
111 for (int c = 0; c < VDIM; c++)
112 {
113 kernels::internal::LoadX(e,D1D,c,x,DD);
114 kernels::internal::EvalX(D1D,Q1D,B,DD,DQ);
115 kernels::internal::EvalY(D1D,Q1D,B,DQ,QQ);
116 MFEM_FOREACH_THREAD(qy,y,Q1D)
117 {
118 MFEM_FOREACH_THREAD(qx,x,Q1D)
119 {
120 real_t u = QQ(qx,qy);
121 if (Q_LAYOUT == QVectorLayout::byVDIM) { y(c,qx,qy,e) = u; }
122 if (Q_LAYOUT == QVectorLayout::byNODES) { y(qx,qy,c,e) = u; }
123 }
124 }
125 MFEM_SYNC_THREAD;
126 }
127 });
128}
129
130// Template compute kernel for Values in 3D: tensor product version.
131template<QVectorLayout Q_LAYOUT,
132 int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0>
133static void Values3D(const int NE,
134 const real_t *b_,
135 const real_t *x_,
136 real_t *y_,
137 const int vdim = 0,
138 const int d1d = 0,
139 const int q1d = 0)
140{
141 const int D1D = T_D1D ? T_D1D : d1d;
142 const int Q1D = T_Q1D ? T_Q1D : q1d;
143 const int VDIM = T_VDIM ? T_VDIM : vdim;
144
145 const auto b = Reshape(b_, Q1D, D1D);
146 const auto x = Reshape(x_, D1D, D1D, D1D, VDIM, NE);
147 auto y = Q_LAYOUT == QVectorLayout:: byNODES ?
148 Reshape(y_, Q1D, Q1D, Q1D, VDIM, NE):
149 Reshape(y_, VDIM, Q1D, Q1D, Q1D, NE);
150
151 mfem::forall_3D(NE, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE (int e)
152 {
153 const int D1D = T_D1D ? T_D1D : d1d;
154 const int Q1D = T_Q1D ? T_Q1D : q1d;
155 const int VDIM = T_VDIM ? T_VDIM : vdim;
156 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_INTERP_1D;
157 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_INTERP_1D;
158 constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
159
160 MFEM_SHARED real_t sB[MQ1*MD1];
161 MFEM_SHARED real_t sm0[MDQ*MDQ*MDQ];
162 MFEM_SHARED real_t sm1[MDQ*MDQ*MDQ];
163
164 kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
165
166 ConstDeviceMatrix B(sB, D1D,Q1D);
167 DeviceCube DDD(sm0, MD1,MD1,MD1);
168 DeviceCube DDQ(sm1, MD1,MD1,MQ1);
169 DeviceCube DQQ(sm0, MD1,MQ1,MQ1);
170 DeviceCube QQQ(sm1, MQ1,MQ1,MQ1);
171
172 for (int c = 0; c < VDIM; c++)
173 {
174 kernels::internal::LoadX(e,D1D,c,x,DDD);
175 kernels::internal::EvalX(D1D,Q1D,B,DDD,DDQ);
176 kernels::internal::EvalY(D1D,Q1D,B,DDQ,DQQ);
177 kernels::internal::EvalZ(D1D,Q1D,B,DQQ,QQQ);
178 MFEM_FOREACH_THREAD(qz,z,Q1D)
179 {
180 MFEM_FOREACH_THREAD(qy,y,Q1D)
181 {
182 MFEM_FOREACH_THREAD(qx,x,Q1D)
183 {
184 const real_t u = QQQ(qz,qy,qx);
185 if (Q_LAYOUT == QVectorLayout::byVDIM) { y(c,qx,qy,qz,e) = u; }
186 if (Q_LAYOUT == QVectorLayout::byNODES) { y(qx,qy,qz,c,e) = u; }
187 }
188 }
189 }
190 MFEM_SYNC_THREAD;
191 }
192 });
193}
194
195} // namespace quadrature_interpolator
196
197} // namespace internal
198
199/// @cond Suppress_Doxygen_warnings
200
201template<int DIM, QVectorLayout Q_LAYOUT,
202 int VDIM, int D1D, int Q1D, int NBZ>
204QuadratureInterpolator::TensorEvalKernels::Kernel()
205{
206 if (DIM == 1) { return internal::quadrature_interpolator::Values1D<Q_LAYOUT>; }
207 else if (DIM == 2) { return internal::quadrature_interpolator::Values2D<Q_LAYOUT, VDIM, D1D, Q1D, NBZ>; }
208 else if (DIM == 3) { return internal::quadrature_interpolator::Values3D<Q_LAYOUT, VDIM, D1D, Q1D>; }
209 else { MFEM_ABORT(""); }
210}
211
212/// @endcond
213
214} // namespace mfem
215
216#endif
void(*)(const int, const real_t *, const real_t *, real_t *, const int, const int, const int) TensorEvalKernelType
real_t b
Definition lissajous.cpp:42
constexpr int DIM
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
DeviceTensor< 2, real_t > DeviceMatrix
Definition dtensor.hpp:143
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:131
void forall_2D_batch(int N, int X, int Y, int BZ, lambda &&body)
Definition forall.hpp:768
DeviceTensor< 2, const real_t > ConstDeviceMatrix
Definition dtensor.hpp:144
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
Definition forall.hpp:774
QVectorLayout
Type describing possible layouts for Q-vectors.
Definition fespace.hpp:53
float real_t
Definition config.hpp:43
DeviceTensor< 3, real_t > DeviceCube
Definition dtensor.hpp:146
void forall(int N, lambda &&body)
Definition forall.hpp:753