20DiffusionIntegrator::Kernels::Kernels()
90void PADiffusionSetup2D<2>(
const int Q1D,
99void PADiffusionSetup2D<3>(
const int Q1D,
107void PADiffusionSetup(
const int dim,
118 if (
dim == 1) { MFEM_ABORT(
"dim==1 not supported in PADiffusionSetup"); }
124 OccaPADiffusionSetup2D(D1D, Q1D, NE, W, J, C, D);
128 MFEM_CONTRACT_VAR(D1D);
130 if (sdim == 2) { PADiffusionSetup2D<2>(Q1D, coeffDim, NE, W, J, C, D); }
131 if (sdim == 3) { PADiffusionSetup2D<3>(Q1D, coeffDim, NE, W, J, C, D); }
138 OccaPADiffusionSetup3D(D1D, Q1D, NE, W, J, C, D);
142 PADiffusionSetup3D(Q1D, coeffDim, NE, W, J, C, D);
147void PADiffusionSetup2D<2>(
const int Q1D,
150 const Array<real_t> &w,
155 const bool symmetric = (coeffDim != 4);
156 const bool const_c = c.Size() == coeffDim;
157 const auto W =
Reshape(w.Read(), Q1D,Q1D);
158 const auto J =
Reshape(j.Read(), Q1D,Q1D,2,2,NE);
159 const auto C = const_c ?
Reshape(c.Read(), coeffDim,1,1,1) :
161 auto D =
Reshape(d.Write(), Q1D,Q1D, symmetric ? 3 : 4, NE);
163 auto get_coeff = [const_c] MFEM_HOST_DEVICE
164 (
const decltype(C) &C,
int i,
int qx,
int qy,
int e)
166 return const_c ? C(i,0,0,0) : C(i,qx,qy,e);
171 MFEM_FOREACH_THREAD(qx,x,Q1D)
173 MFEM_FOREACH_THREAD(qy,y,Q1D)
175 const real_t J11 = J(qx,qy,0,0,e);
176 const real_t J21 = J(qx,qy,1,0,e);
177 const real_t J12 = J(qx,qy,0,1,e);
178 const real_t J22 = J(qx,qy,1,1,e);
179 const real_t w_detJ = W(qx,qy) / ((J11*J22)-(J21*J12));
180 if (coeffDim == 3 || coeffDim == 4)
183 const real_t M11 = get_coeff(C,0,qx,qy,e);
184 const real_t M12 = get_coeff(C,1,qx,qy,e);
185 const real_t M21 = symmetric ? M12 : get_coeff(C,2,qx,qy,e);
186 const real_t M22 = symmetric ? get_coeff(C,2,qx,qy,e)
187 : get_coeff(C,3,qx,qy,e);
188 const real_t R11 = M11*J22 - M12*J12;
189 const real_t R21 = M21*J22 - M22*J12;
190 const real_t R12 = -M11*J21 + M12*J11;
191 const real_t R22 = -M21*J21 + M22*J11;
194 D(qx,qy,0,e) = w_detJ * ( J22*R11 - J12*R21);
195 D(qx,qy,1,e) = w_detJ * (-J21*R11 + J11*R21);
196 D(qx,qy,2,e) = w_detJ * (symmetric ? (-J21*R12 + J11*R22) :
197 (J22*R12 - J12*R22));
200 D(qx,qy,3,e) = w_detJ * (-J21*R12 + J11*R22);
205 const real_t C1 = get_coeff(C,0,qx,qy,e);
206 const real_t C2 = get_coeff(C,coeffDim==2?1:0,qx,qy,e);
208 D(qx,qy,0,e) = w_detJ * (C2*J12*J12 + C1*J22*J22);
209 D(qx,qy,1,e) = -w_detJ * (C2*J12*J11 + C1*J22*J21);
210 D(qx,qy,2,e) = w_detJ * (C2*J11*J11 + C1*J21*J21);
218void PADiffusionSetup2D<3>(
const int Q1D,
221 const Array<real_t> &w,
226 MFEM_VERIFY(coeffDim == 1,
"Matrix and vector coefficients not supported");
227 constexpr int DIM = 2;
228 constexpr int SDIM = 3;
229 const bool const_c = c.Size() == 1;
230 const auto W =
Reshape(w.Read(), Q1D,Q1D);
232 const auto C = const_c ?
Reshape(c.Read(), 1,1,1) :
234 auto D =
Reshape(d.Write(), Q1D,Q1D, 3, NE);
237 MFEM_FOREACH_THREAD(qx,x,Q1D)
239 MFEM_FOREACH_THREAD(qy,y,Q1D)
241 const real_t wq = W(qx,qy);
242 const real_t J11 = J(qx,qy,0,0,e);
243 const real_t J21 = J(qx,qy,1,0,e);
244 const real_t J31 = J(qx,qy,2,0,e);
245 const real_t J12 = J(qx,qy,0,1,e);
246 const real_t J22 = J(qx,qy,1,1,e);
247 const real_t J32 = J(qx,qy,2,1,e);
248 const real_t E = J11*J11 + J21*J21 + J31*J31;
249 const real_t G = J12*J12 + J22*J22 + J32*J32;
250 const real_t F = J11*J12 + J21*J22 + J31*J32;
251 const real_t iw = 1.0 / std::sqrt(E*G - F*F);
252 const real_t coeff = const_c ? C(0,0,0) : C(qx,qy,e);
254 D(qx,qy,0,e) =
alpha * G;
255 D(qx,qy,1,e) = -
alpha * F;
256 D(qx,qy,2,e) =
alpha * E;
262void PADiffusionSetup3D(
const int Q1D,
265 const Array<real_t> &w,
270 const bool symmetric = (coeffDim != 9);
271 const bool const_c = c.Size() == coeffDim;
272 const auto W =
Reshape(w.Read(), Q1D,Q1D,Q1D);
273 const auto J =
Reshape(j.Read(), Q1D,Q1D,Q1D,3,3,NE);
274 const auto C = const_c ?
Reshape(c.Read(), coeffDim,1,1,1,1) :
276 auto D =
Reshape(d.Write(), Q1D,Q1D,Q1D, symmetric ? 6 : 9, NE);
278 auto get_coeff = [const_c] MFEM_HOST_DEVICE
279 (
const decltype(C) &C,
int i,
int qx,
int qy,
int qz,
int e)
281 return const_c ? C(i,0,0,0,0) : C(i,qx,qy,qz,e);
286 MFEM_FOREACH_THREAD(qx,x,Q1D)
288 MFEM_FOREACH_THREAD(qy,y,Q1D)
290 MFEM_FOREACH_THREAD(qz,z,Q1D)
292 const real_t J11 = J(qx,qy,qz,0,0,e);
293 const real_t J21 = J(qx,qy,qz,1,0,e);
294 const real_t J31 = J(qx,qy,qz,2,0,e);
295 const real_t J12 = J(qx,qy,qz,0,1,e);
296 const real_t J22 = J(qx,qy,qz,1,1,e);
297 const real_t J32 = J(qx,qy,qz,2,1,e);
298 const real_t J13 = J(qx,qy,qz,0,2,e);
299 const real_t J23 = J(qx,qy,qz,1,2,e);
300 const real_t J33 = J(qx,qy,qz,2,2,e);
301 const real_t detJ = J11 * (J22 * J33 - J32 * J23) -
302 J21 * (J12 * J33 - J32 * J13) +
303 J31 * (J12 * J23 - J22 * J13);
304 const real_t w_detJ = W(qx,qy,qz) / detJ;
306 const real_t A11 = (J22 * J33) - (J23 * J32);
307 const real_t A12 = (J32 * J13) - (J12 * J33);
308 const real_t A13 = (J12 * J23) - (J22 * J13);
309 const real_t A21 = (J31 * J23) - (J21 * J33);
310 const real_t A22 = (J11 * J33) - (J13 * J31);
311 const real_t A23 = (J21 * J13) - (J11 * J23);
312 const real_t A31 = (J21 * J32) - (J31 * J22);
313 const real_t A32 = (J31 * J12) - (J11 * J32);
314 const real_t A33 = (J11 * J22) - (J12 * J21);
316 if (coeffDim == 6 || coeffDim == 9)
319 const real_t M11 = get_coeff(C, 0, qx,qy,qz, e);
320 const real_t M12 = get_coeff(C, 1, qx,qy,qz, e);
321 const real_t M13 = get_coeff(C, 2, qx,qy,qz, e);
322 const real_t M21 = (!symmetric) ? get_coeff(C, 3, qx,qy,qz, e) : M12;
323 const real_t M22 = (!symmetric) ? get_coeff(C, 4, qx,qy,qz, e)
324 : get_coeff(C, 3, qx,qy,qz, e);
325 const real_t M23 = (!symmetric) ? get_coeff(C, 5, qx,qy,qz, e)
326 : get_coeff(C, 4, qx,qy,qz, e);
327 const real_t M31 = (!symmetric) ? get_coeff(C, 6, qx,qy,qz, e) : M13;
328 const real_t M32 = (!symmetric) ? get_coeff(C, 7, qx,qy,qz, e) : M23;
329 const real_t M33 = (!symmetric) ? get_coeff(C, 8, qx,qy,qz, e)
330 : get_coeff(C, 5, qx,qy,qz, e);
332 const real_t R11 = M11*A11 + M12*A12 + M13*A13;
333 const real_t R12 = M11*A21 + M12*A22 + M13*A23;
334 const real_t R13 = M11*A31 + M12*A32 + M13*A33;
335 const real_t R21 = M21*A11 + M22*A12 + M23*A13;
336 const real_t R22 = M21*A21 + M22*A22 + M23*A23;
337 const real_t R23 = M21*A31 + M22*A32 + M23*A33;
338 const real_t R31 = M31*A11 + M32*A12 + M33*A13;
339 const real_t R32 = M31*A21 + M32*A22 + M33*A23;
340 const real_t R33 = M31*A31 + M32*A32 + M33*A33;
343 D(qx,qy,qz,0,e) = w_detJ * (A11*R11 + A12*R21 + A13*R31);
344 const real_t D12 = w_detJ * (A11*R12 + A12*R22 + A13*R32);
345 D(qx,qy,qz,1,e) = D12;
346 D(qx,qy,qz,2,e) = w_detJ * (A11*R13 + A12*R23 + A13*R33);
348 const real_t D22 = w_detJ * (A21*R12 + A22*R22 + A23*R32);
349 const real_t D23 = w_detJ * (A21*R13 + A22*R23 + A23*R33);
351 const real_t D33 = w_detJ * (A31*R13 + A32*R23 + A33*R33);
353 D(qx,qy,qz,4,e) = symmetric ? D23 : D22;
354 D(qx,qy,qz,5,e) = symmetric ? D33 : D23;
358 D(qx,qy,qz,3,e) = D22;
362 D(qx,qy,qz,3,e) = w_detJ * (A21*R11 + A22*R21 + A23*R31);
363 D(qx,qy,qz,6,e) = w_detJ * (A31*R11 + A32*R21 + A33*R31);
364 D(qx,qy,qz,7,e) = w_detJ * (A31*R12 + A32*R22 + A33*R32);
365 D(qx,qy,qz,8,e) = D33;
370 const real_t C1 = get_coeff(C,0,qx,qy,qz,e);
371 const real_t C2 = get_coeff(C,coeffDim==3?1:0,qx,qy,qz,e);
372 const real_t C3 = get_coeff(C,coeffDim==3?2:0,qx,qy,qz,e);
375 D(qx,qy,qz,0,e) = w_detJ * (C1*A11*A11 + C2*A12*A12 + C3*A13*A13);
376 D(qx,qy,qz,1,e) = w_detJ * (C1*A11*A21 + C2*A12*A22 + C3*A13*A23);
377 D(qx,qy,qz,2,e) = w_detJ * (C1*A11*A31 + C2*A12*A32 + C3*A13*A33);
378 D(qx,qy,qz,3,e) = w_detJ * (C1*A21*A21 + C2*A22*A22 + C3*A23*A23);
379 D(qx,qy,qz,4,e) = w_detJ * (C1*A21*A31 + C2*A22*A32 + C3*A23*A33);
380 D(qx,qy,qz,5,e) = w_detJ * (C1*A31*A31 + C2*A32*A32 + C3*A33*A33);
389void OccaPADiffusionSetup2D(
const int D1D,
392 const Array<real_t> &W,
397 occa::properties props;
398 props[
"defines/D1D"] = D1D;
399 props[
"defines/Q1D"] = Q1D;
404 const bool const_c = C.Size() == 1;
405 const occa_id_t id = std::make_pair(D1D,Q1D);
407 if (OccaDiffSetup2D_ker.find(
id) == OccaDiffSetup2D_ker.end())
409 const occa::kernel DiffusionSetup2D =
411 "DiffusionSetup2D", props);
412 OccaDiffSetup2D_ker.emplace(
id, DiffusionSetup2D);
414 OccaDiffSetup2D_ker.at(
id)(NE, o_W, o_J, o_C, o_op, const_c);
417void OccaPADiffusionSetup3D(
const int D1D,
420 const Array<real_t> &W,
425 occa::properties props;
426 props[
"defines/D1D"] = D1D;
427 props[
"defines/Q1D"] = Q1D;
432 const bool const_c = C.Size() == 1;
433 const occa_id_t id = std::make_pair(D1D,Q1D);
435 if (OccaDiffSetup3D_ker.find(
id) == OccaDiffSetup3D_ker.end())
437 const occa::kernel DiffusionSetup3D =
439 "DiffusionSetup3D", props);
440 OccaDiffSetup3D_ker.emplace(
id, DiffusionSetup3D);
442 OccaDiffSetup3D_ker.at(
id)(NE, o_W, o_J, o_C, o_op, const_c);
445void OccaPADiffusionApply2D(
const int D1D,
448 const Array<real_t> &B,
449 const Array<real_t> &G,
450 const Array<real_t> &Bt,
451 const Array<real_t> &Gt,
456 occa::properties props;
457 props[
"defines/D1D"] = D1D;
458 props[
"defines/Q1D"] = Q1D;
461 const occa::memory o_Bt =
OccaMemoryRead(Bt.GetMemory(), Bt.Size());
462 const occa::memory o_Gt =
OccaMemoryRead(Gt.GetMemory(), Gt.Size());
466 const occa_id_t id = std::make_pair(D1D,Q1D);
467 if (!Device::Allows(Backend::OCCA_CUDA))
470 if (OccaDiffApply2D_cpu.find(
id) == OccaDiffApply2D_cpu.end())
472 const occa::kernel DiffusionApply2D_CPU =
474 "DiffusionApply2D_CPU", props);
475 OccaDiffApply2D_cpu.emplace(
id, DiffusionApply2D_CPU);
477 OccaDiffApply2D_cpu.at(
id)(NE, o_B, o_G, o_Bt, o_Gt, o_D, o_X, o_Y);
482 if (OccaDiffApply2D_gpu.find(
id) == OccaDiffApply2D_gpu.end())
484 const occa::kernel DiffusionApply2D_GPU =
486 "DiffusionApply2D_GPU", props);
487 OccaDiffApply2D_gpu.emplace(
id, DiffusionApply2D_GPU);
489 OccaDiffApply2D_gpu.at(
id)(NE, o_B, o_G, o_Bt, o_Gt, o_D, o_X, o_Y);
493void OccaPADiffusionApply3D(
const int D1D,
496 const Array<real_t> &B,
497 const Array<real_t> &G,
498 const Array<real_t> &Bt,
499 const Array<real_t> &Gt,
504 occa::properties props;
505 props[
"defines/D1D"] = D1D;
506 props[
"defines/Q1D"] = Q1D;
509 const occa::memory o_Bt =
OccaMemoryRead(Bt.GetMemory(), Bt.Size());
510 const occa::memory o_Gt =
OccaMemoryRead(Gt.GetMemory(), Gt.Size());
514 const occa_id_t id = std::make_pair(D1D,Q1D);
515 if (!Device::Allows(Backend::OCCA_CUDA))
518 if (OccaDiffApply3D_cpu.find(
id) == OccaDiffApply3D_cpu.end())
520 const occa::kernel DiffusionApply3D_CPU =
522 "DiffusionApply3D_CPU", props);
523 OccaDiffApply3D_cpu.emplace(
id, DiffusionApply3D_CPU);
525 OccaDiffApply3D_cpu.at(
id)(NE, o_B, o_G, o_Bt, o_Gt, o_D, o_X, o_Y);
530 if (OccaDiffApply3D_gpu.find(
id) == OccaDiffApply3D_gpu.end())
532 const occa::kernel DiffusionApply3D_GPU =
534 "DiffusionApply3D_GPU", props);
535 OccaDiffApply3D_gpu.emplace(
id, DiffusionApply3D_GPU);
537 OccaDiffApply3D_gpu.at(
id)(NE, o_B, o_G, o_Bt, o_Gt, o_D, o_X, o_Y);
static void AddSimplexSpecialization()
static void AddSpecialization()
occa::memory OccaMemoryReadWrite(Memory< T > &mem, size_t size)
Wrap a Memory object as occa::memory for read-write access with the mfem::Device MemoryClass....
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,...
occa::memory OccaMemoryWrite(Memory< T > &mem, size_t size)
Wrap a Memory object as occa::memory for write only access with the mfem::Device MemoryClass....
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void forall_2D(int N, int X, int Y, lambda &&body)
std::map< occa_id_t, occa::kernel > occa_kernel_t
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
bool DeviceCanUseOcca()
Function that determines if an OCCA kernel should be used, based on the current mfem::Device configur...
const occa::memory OccaMemoryRead(const Memory< T > &mem, size_t size)
Wrap a Memory object as occa::memory for read only access with the mfem::Device MemoryClass....
occa::device & OccaDev()
Return the default occa::device used by MFEM.
std::pair< int, int > occa_id_t