13 #include "../fem/kernels.hpp"
14 #include "../general/forall.hpp"
19 template<
int T_D1D = 0,
int T_Q1D = 0>
static
20 void DLFGradAssemble2D(
const int vdim,
const int ne,
const int d,
const int q,
21 const int *markers,
const double *
b,
const double *g,
22 const double *jacobians,
23 const double *weights,
const Vector &coeff,
double *y)
25 const auto F = coeff.Read();
26 const auto M =
Reshape(markers, ne);
27 const auto B =
Reshape(b, q, d);
28 const auto G =
Reshape(g, q, d);
29 const auto J =
Reshape(jacobians, q, q, 2,2, ne);
30 const auto W =
Reshape(weights, q, q);
31 const bool cst = coeff.Size() == vdim*2;
32 const auto C = cst ?
Reshape(F,2,vdim,1,1,1) : Reshape(F,2,vdim,q,q,ne);
33 auto Y =
Reshape(y, d,d, vdim, ne);
35 MFEM_FORALL_2D(e, ne, q, q, 1,
37 if (M(e) == 0) {
return; }
39 constexpr
int Q = T_Q1D ? T_Q1D :
MAX_Q1D;
40 constexpr
int D = T_D1D ? T_D1D :
MAX_D1D;
42 MFEM_SHARED
double sBGt[2][Q*D];
43 MFEM_SHARED
double sQQ[2][Q*Q];
44 MFEM_SHARED
double sDQ[2][D*Q];
48 kernels::internal::LoadBGt<D,Q>(d, q, B, G, sBGt);
56 for (
int c = 0; c < vdim; ++c)
58 const double cst_val0 = C(0,c,0,0,0);
59 const double cst_val1 = C(1,c,0,0,0);
61 MFEM_FOREACH_THREAD(x,x,q)
63 MFEM_FOREACH_THREAD(y,y,q)
65 const double w = W(x,y);
66 const double J11 = J(x,y,0,0,e);
67 const double J21 = J(x,y,1,0,e);
68 const double J12 = J(x,y,0,1,e);
69 const double J22 = J(x,y,1,1,e);
70 const double u = cst ? cst_val0 : C(0,c,x,y,e);
71 const double v = cst ? cst_val1 : C(1,c,x,y,e);
73 QQ0(y,x) = w * (J22*u - J12*v);
74 QQ1(y,x) = w * (J11*v - J21*
u);
78 MFEM_FOREACH_THREAD(qx,x,q)
80 MFEM_FOREACH_THREAD(dy,y,d)
82 double u = 0.0, v = 0.0;
83 for (
int qy = 0; qy < q; ++qy)
85 u += QQ0(qy,qx) * Bt(qy,dy);
86 v += QQ1(qy,qx) * Gt(qy,dy);
93 MFEM_FOREACH_THREAD(dx,x,d)
95 MFEM_FOREACH_THREAD(dy,y,d)
97 double u = 0.0, v = 0.0;
98 for (
int qx = 0; qx < q; ++qx)
100 u += DQ0(dy,qx) * Gt(qx,dx);
101 v += DQ1(dy,qx) * Bt(qx,dx);
103 Y(dx,dy,c,e) += u + v;
111 template<
int T_D1D = 0,
int T_Q1D = 0>
static
112 void DLFGradAssemble3D(
const int vdim,
const int ne,
const int d,
const int q,
113 const int *markers,
const double *b,
const double *g,
114 const double *jacobians,
115 const double *weights,
const Vector &coeff,
118 const auto F = coeff.Read();
119 const auto M =
Reshape(markers, ne);
120 const auto B =
Reshape(b, q,d);
121 const auto G =
Reshape(g, q,d);
122 const auto J =
Reshape(jacobians, q,q,q, 3,3, ne);
123 const auto W =
Reshape(weights, q,q,q);
124 const bool cst = coeff.Size() == vdim*3;
125 const auto C = cst ?
Reshape(F,3,vdim,1,1,1,1) : Reshape(F,3,vdim,q,q,q,ne);
127 auto Y =
Reshape(output, d,d,d, vdim, ne);
129 MFEM_FORALL_2D(e, ne, q, q, 1,
131 if (M(e) == 0) {
return; }
133 constexpr
int Q = T_Q1D ? T_Q1D :
MAX_Q1D;
134 constexpr
int D = T_D1D ? T_D1D :
MAX_D1D;
138 MFEM_SHARED
double sBGt[2][Q*D];
139 MFEM_SHARED
double sQQQ[Q*Q*Q];
142 kernels::internal::LoadBGt<D,Q>(d,q,B,G,sBGt);
148 for (
int c = 0; c < vdim; ++c)
150 const double cst_val_0 = C(0,c,0,0,0,0);
151 const double cst_val_1 = C(1,c,0,0,0,0);
152 const double cst_val_2 = C(2,c,0,0,0,0);
154 for (
int k = 0; k < 3; ++k)
156 for (
int z = 0; z < q; ++z)
158 MFEM_FOREACH_THREAD(y,y,q)
160 MFEM_FOREACH_THREAD(x,x,q)
162 const double J11 = J(x,y,z,0,0,e);
163 const double J21 = J(x,y,z,1,0,e);
164 const double J31 = J(x,y,z,2,0,e);
165 const double J12 = J(x,y,z,0,1,e);
166 const double J22 = J(x,y,z,1,1,e);
167 const double J32 = J(x,y,z,2,1,e);
168 const double J13 = J(x,y,z,0,2,e);
169 const double J23 = J(x,y,z,1,2,e);
170 const double J33 = J(x,y,z,2,2,e);
172 const double u = cst ? cst_val_0 : C(0,c,x,y,z,e);
173 const double v = cst ? cst_val_1 : C(1,c,x,y,z,e);
174 const double w = cst ? cst_val_2 : C(2,c,x,y,z,e);
178 const double A11 = (J22 * J33) - (J23 * J32);
179 const double A12 = (J32 * J13) - (J12 * J33);
180 const double A13 = (J12 * J23) - (J22 * J13);
181 QQQ(z,y,x) = A11*u + A12*v + A13*w;
187 const double A21 = (J31 * J23) - (J21 * J33);
188 const double A22 = (J11 * J33) - (J13 * J31);
189 const double A23 = (J21 * J13) - (J11 * J23);
190 QQQ(z,y,x) = A21*u + A22*v + A23*w;
195 const double A31 = (J21 * J32) - (J31 * J22);
196 const double A32 = (J31 * J12) - (J11 * J32);
197 const double A33 = (J11 * J22) - (J12 * J21);
198 QQQ(z,y,x) = A31*u + A32*v + A33*w;
201 QQQ(z,y,x) *= W(x,y,z);
206 MFEM_FOREACH_THREAD(qz,x,q)
208 MFEM_FOREACH_THREAD(qy,y,q)
210 for (
int dx = 0; dx < d; ++dx) { r_u[dx] = 0.0; }
211 for (
int qx = 0; qx < q; ++qx)
213 const double r_v = QQQ(qz,qy,qx);
214 for (
int dx = 0; dx < d; ++dx)
216 r_u[dx] += (k == 0 ? Gt(qx,dx) : Bt(qx,dx)) * r_v;
219 for (
int dx = 0; dx < d; ++dx) { QQD(qz,qy,dx) = r_u[dx]; }
223 MFEM_FOREACH_THREAD(qz,y,q)
225 MFEM_FOREACH_THREAD(dx,x,d)
227 for (
int dy = 0; dy < d; ++dy) { r_u[dy] = 0.0; }
228 for (
int qy = 0; qy < q; ++qy)
230 const double r_v = QQD(qz,qy,dx);
231 for (
int dy = 0; dy < d; ++dy)
233 r_u[dy] += (k == 1 ? Gt(qy,dy) : Bt(qy,dy)) * r_v;
236 for (
int dy = 0; dy < d; ++dy) { QDD(qz,dy,dx) = r_u[dy]; }
240 MFEM_FOREACH_THREAD(dy,y,d)
242 MFEM_FOREACH_THREAD(dx,x,d)
244 for (
int dz = 0; dz < d; ++dz) { r_u[dz] = 0.0; }
245 for (
int qz = 0; qz < q; ++qz)
247 const double r_v = QDD(qz,dy,dx);
248 for (
int dz = 0; dz < d; ++dz)
250 r_u[dz] += (k == 2 ? Gt(qz,dz) : Bt(qz,dz)) * r_v;
253 for (
int dz = 0; dz < d; ++dz) { Y(dx,dy,dz,c,e) += r_u[dz]; }
262 static void DLFGradAssemble(
const FiniteElementSpace &fes,
263 const IntegrationRule *ir,
264 const Array<int> &markers,
268 Mesh *mesh = fes.GetMesh();
269 const int dim = mesh->Dimension();
270 const FiniteElement &el = *fes.GetFE(0);
273 const int d = maps.ndof, q = maps.nqpt;
275 const GeometricFactors *geom = mesh->GetGeometricFactors(*ir, flags, mt);
276 decltype(&DLFGradAssemble2D<>) ker =
277 dim == 2 ? DLFGradAssemble2D<> : DLFGradAssemble3D<>;
281 if (d==1 && q==1) { ker=DLFGradAssemble2D<1,1>; }
282 if (d==2 && q==2) { ker=DLFGradAssemble2D<2,2>; }
283 if (d==3 && q==3) { ker=DLFGradAssemble2D<3,3>; }
284 if (d==4 && q==4) { ker=DLFGradAssemble2D<4,4>; }
285 if (d==5 && q==5) { ker=DLFGradAssemble2D<5,5>; }
286 if (d==2 && q==3) { ker=DLFGradAssemble2D<2,3>; }
287 if (d==3 && q==4) { ker=DLFGradAssemble2D<3,4>; }
288 if (d==4 && q==5) { ker=DLFGradAssemble2D<4,5>; }
289 if (d==5 && q==6) { ker=DLFGradAssemble2D<5,6>; }
294 if (d==1 && q==1) { ker=DLFGradAssemble3D<1,1>; }
295 if (d==2 && q==2) { ker=DLFGradAssemble3D<2,2>; }
296 if (d==3 && q==3) { ker=DLFGradAssemble3D<3,3>; }
297 if (d==4 && q==4) { ker=DLFGradAssemble3D<4,4>; }
298 if (d==5 && q==5) { ker=DLFGradAssemble3D<5,5>; }
299 if (d==2 && q==3) { ker=DLFGradAssemble3D<2,3>; }
300 if (d==3 && q==4) { ker=DLFGradAssemble3D<3,4>; }
301 if (d==4 && q==5) { ker=DLFGradAssemble3D<4,5>; }
302 if (d==5 && q==6) { ker=DLFGradAssemble3D<5,6>; }
305 MFEM_VERIFY(ker,
"No kernel ndof " << d <<
" nqpt " << q);
307 const int vdim = fes.GetVDim();
308 const int ne = fes.GetMesh()->GetNE();
309 const int *M = markers.Read();
310 const double *B = maps.B.Read();
311 const double *G = maps.G.Read();
312 const double *J = geom->J.Read();
313 const double *W = ir->GetWeights().Read();
314 double *Y = y.ReadWrite();
315 ker(vdim, ne, d, q, M, B, G, J, W, coeff, Y);
324 const int qorder = 2 * fe.
GetOrder();
330 DLFGradAssemble(fes, ir, markers, coeff, b);
338 const int qorder = 2 * fe.
GetOrder();
344 DLFGradAssemble(fes, ir, markers, coeff, b);
Abstract class for all finite elements.
Class for an integration rule - an Array of IntegrationPoint.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Class to represent a coefficient evaluated at quadrature points.
DeviceTensor< 2, double > DeviceMatrix
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Mesh * GetMesh() const
Returns the mesh.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Enable all above compressions.
DeviceTensor< 3, double > DeviceCube
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
MemoryType
Memory types supported by MFEM.
virtual void AssembleDevice(const FiniteElementSpace &fes, const Array< int > &markers, Vector &b) override
Method defining assembly on device.
virtual void AssembleDevice(const FiniteElementSpace &fes, const Array< int > &markers, Vector &b)
Method defining assembly on device.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Class representing the storage layout of a QuadratureFunction.
double u(const Vector &xvec)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.