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);
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);
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...
Class to represent a coefficient evaluated at quadrature points.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
DeviceTensor< 2, double > DeviceMatrix
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Enable all above compressions.
Mesh * GetMesh() const
Returns the mesh.
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.
Class representing the storage layout of a QuadratureFunction.
double u(const Vector &xvec)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...