14 #include "../../linalg/dtensor.hpp" 15 #include "../../general/forall.hpp" 25 static constexpr
int nv = 4;
26 static constexpr
int ne = 4;
27 static constexpr
int dim = 2;
28 static constexpr
int ddm2 = (
dim*(
dim+1))/2;
29 static constexpr
int ngeom = ddm2 + 1;
30 static constexpr
int o = ORDER;
31 static constexpr
int op1 = ORDER + 1;
32 static constexpr
int ndof_per_el =
dim*o*op1;
33 static constexpr
int nnz_per_row = 7;
34 static constexpr
int sz_local_mat = ne*ne;
36 const bool const_mq =
c1.
Size() == 1;
37 const auto MQ = const_mq
40 const bool const_dq =
c2.
Size() == 1;
41 const auto DQ = const_dq
52 MFEM_FOREACH_THREAD(iy,y,o)
54 MFEM_FOREACH_THREAD(ix,x,op1)
56 for (
int c=0; c<2; ++c)
58 for (
int j=0; j<nnz_per_row; ++j)
60 V(j,ix+iy*op1,c,iel_ho) = 0.0;
68 MFEM_FOREACH_THREAD(ky,y,ORDER)
70 MFEM_FOREACH_THREAD(kx,x,ORDER)
74 double local_mat_[sz_local_mat];
80 for (
int i=0; i<sz_local_mat; ++i) { local_mat[i] = 0.0; }
83 LORVertexCoordinates2D<ORDER>(X, iel_ho, kx, ky, vx, vy);
85 for (
int iqx=0; iqx<2; ++iqx)
87 for (
int iqy=0; iqy<2; ++iqy)
91 const double w = 1.0/4.0;
98 const double detJ =
Det2D(J);
99 const double w_detJ = w/detJ;
101 Q(0,iqy,iqx) = w_detJ * (J(0,0)*J(0,0) + J(1,0)*J(1,0));
102 Q(1,iqy,iqx) = w_detJ * (J(0,0)*J(0,1) + J(1,0)*J(1,1));
103 Q(2,iqy,iqx) = w_detJ * (J(0,1)*J(0,1) + J(1,1)*J(1,1));
104 Q(3,iqy,iqx) = w_detJ;
107 for (
int iqx=0; iqx<2; ++iqx)
109 for (
int iqy=0; iqy<2; ++iqy)
111 const double mq = const_mq ? MQ(0,0,0) : MQ(kx+iqx, ky+iqy, iel_ho);
112 const double dq = const_dq ? DQ(0,0,0) : DQ(kx+iqx, ky+iqy, iel_ho);
114 for (
int cj=0; cj<
dim; ++cj)
116 for (
int bj=0; bj<2; ++bj)
118 const double bxj = (cj == 0 && bj == iqx) ? 1 : 0;
119 const double byj = (cj == 1 && bj == iqy) ? 1 : 0;
120 const double div_j = (bj == 0) ? -1 : 1;
122 const double jj_loc = bj + 2*cj;
124 for (
int ci=0; ci<
dim; ++ci)
126 for (
int bi=0; bi<2; ++bi)
128 const double bxi = (ci == 0 && bi == iqx) ? 1 : 0;
129 const double byi = (ci == 1 && bi == iqy) ? 1 : 0;
130 const double div_i = (bi == 0) ? -1 : 1;
132 const double ii_loc = bi + 2*ci;
136 if (jj_loc > ii_loc) {
continue; }
139 val += bxi*bxj*Q(0,iqy,iqx);
140 val += byi*bxj*Q(1,iqy,iqx);
141 val += bxi*byj*Q(1,iqy,iqx);
142 val += byi*byj*Q(2,iqy,iqx);
144 val += dq*div_j*div_i*Q(3,iqy,iqx);
146 local_mat(ii_loc, jj_loc) += val;
156 for (
int ii_loc=0; ii_loc<ne; ++ii_loc)
158 const int ci = ii_loc/2;
159 const int bi = ii_loc%2;
160 const int ix = (ci == 0) ? bi : 0;
161 const int iy = (ci == 1) ? bi : 0;
163 int ii = kx+ix + (ky+iy)*((ci == 0) ? op1 : o);
165 for (
int jj_loc=0; jj_loc<ne; ++jj_loc)
167 const int cj = jj_loc/2;
168 const int bj = jj_loc%2;
170 const int jj_off = (ci == cj) ? (bj - bi + 1) : (3 + 1-bi + 2*bj);
173 const double val = (jj_loc <= ii_loc)
174 ? local_mat(ii_loc, jj_loc)
175 : local_mat(jj_loc, ii_loc);
176 AtomicAdd(V(jj_off, ii, ci, iel_ho), val);
186 for (
int ci=0; ci<2; ++ci)
188 const int i_off = (ci == 0) ? 0 : o*op1;
190 const int id1 = (ci+1)%2;
192 const int nxi = (ci == 0) ? op1 : o;
194 for (
int i0=0; i0<op1; ++i0)
196 for (
int i1=0; i1<o; ++i1)
201 const int ii_el = i_off + ii_lex[0] + ii_lex[1]*nxi;
203 for (
int cj_rel=0; cj_rel<2; ++cj_rel)
205 const int cj = (ci + cj_rel) % 2;
206 const int j_off = (cj == 0) ? 0 : o*op1;
207 const int nxj = (cj == 0) ? op1 : o;
209 const int j0_begin = (i0 > 0) ? i0-1 : i0;
210 const int j0_end = (cj_rel == 0)
211 ? ((i0 < o) ? i0+1 : i0)
212 : ((i0 < o) ? i0 : i0-1);
213 const int j1_begin = i1;
214 const int j1_end = (cj_rel == 0) ? i1 : i1+1;
216 for (
int j0=j0_begin; j0<=j0_end; ++j0)
218 const int d0 = 1 + j0 - i0;
219 for (
int j1=j1_begin; j1<=j1_end; ++j1)
221 const int d1 = j1 - i1;
225 const int jj_el = j_off + jj_lex[0] + jj_lex[1]*nxj;
226 const int jj_off = (cj_rel == 0) ? d0 : 3 + d0 + 2*d1;
227 map(jj_off, ii_el) = jj_el;
241 static constexpr
int nv = 8;
242 static constexpr
int nf = 6;
243 static constexpr
int dim = 3;
244 static constexpr
int ddm2 = (
dim*(
dim+1))/2;
245 static constexpr
int ngeom = ddm2 + 1;
246 static constexpr
int o = ORDER;
247 static constexpr
int op1 = ORDER + 1;
248 static constexpr
int ndof_per_el =
dim*o*o*op1;
249 static constexpr
int nnz_per_row = 11;
250 static constexpr
int sz_local_mat = nf*nf;
252 const bool const_mq =
c1.
Size() == 1;
253 const auto MQ = const_mq
256 const bool const_dq =
c2.
Size() == 1;
257 const auto DQ = const_dq
268 [=] MFEM_HOST_DEVICE (
int iel_ho)
270 MFEM_FOREACH_THREAD(iz,z,o)
272 MFEM_FOREACH_THREAD(iy,y,o)
274 MFEM_FOREACH_THREAD(ix,x,op1)
276 for (
int c=0; c<
dim; ++c)
278 for (
int j=0; j<nnz_per_row; ++j)
280 V(j,ix+iy*op1+iz*o*op1,c,iel_ho) = 0.0;
289 MFEM_FOREACH_THREAD(kz,z,ORDER)
291 MFEM_FOREACH_THREAD(ky,y,ORDER)
293 MFEM_FOREACH_THREAD(kx,x,ORDER)
299 double local_mat_[sz_local_mat];
301 for (
int i=0; i<sz_local_mat; ++i) { local_mat[i] = 0.0; }
303 double vx[8], vy[8], vz[8];
304 LORVertexCoordinates3D<ORDER>(X, iel_ho, kx, ky, kz, vx, vy, vz);
306 for (
int iqz=0; iqz<2; ++iqz)
308 for (
int iqy=0; iqy<2; ++iqy)
310 for (
int iqx=0; iqx<2; ++iqx)
312 const double x = iqx;
313 const double y = iqy;
314 const double z = iqz;
315 const double w = 1.0/8.0;
322 const double detJ =
Det3D(J);
323 const double w_detJ = w/detJ;
325 Q(0,iqz,iqy,iqx) = w_detJ*(J(0,0)*J(0,0)+J(1,0)*J(1,0)+J(2,0)*J(2,0));
326 Q(1,iqz,iqy,iqx) = w_detJ*(J(0,1)*J(0,0)+J(1,1)*J(1,0)+J(2,1)*J(2,0));
327 Q(2,iqz,iqy,iqx) = w_detJ*(J(0,2)*J(0,0)+J(1,2)*J(1,0)+J(2,2)*J(2,0));
328 Q(3,iqz,iqy,iqx) = w_detJ*(J(0,1)*J(0,1)+J(1,1)*J(1,1)+J(2,1)*J(2,1));
329 Q(4,iqz,iqy,iqx) = w_detJ*(J(0,2)*J(0,1)+J(1,2)*J(1,1)+J(2,2)*J(2,1));
330 Q(5,iqz,iqy,iqx) = w_detJ*(J(0,2)*J(0,2)+J(1,2)*J(1,2)+J(2,2)*J(2,2));
331 Q(6,iqz,iqy,iqx) = w_detJ;
335 for (
int iqz=0; iqz<2; ++iqz)
337 for (
int iqy=0; iqy<2; ++iqy)
339 for (
int iqx=0; iqx<2; ++iqx)
341 const double mq = const_mq ? MQ(0,0,0,0) : MQ(kx+iqx, ky+iqy, kz+iqz, iel_ho);
342 const double dq = const_dq ? DQ(0,0,0,0) : DQ(kx+iqx, ky+iqy, kz+iqz, iel_ho);
344 for (
int cj=0; cj<
dim; ++cj)
346 const double jq0 = (cj == 0) ? iqx : ((cj == 1) ? iqy : iqz);
349 const int jd_1 = (cj + 1)%3;
350 const int jd_2 = (cj + 2)%3;
352 for (
int bj=0; bj<2; ++bj)
354 const double div_j = (bj == 0) ? -1 : 1;
357 basis_j[jd_0] = (bj == jq0) ? 1 : 0;
361 const int jj_loc = bj + 2*cj;
363 for (
int ci=0; ci<
dim; ++ci)
365 const double iq0 = (ci == 0) ? iqx : ((ci == 1) ? iqy : iqz);
368 const int id_1 = (ci + 1)%3;
369 const int id_2 = (ci + 2)%3;
371 for (
int bi=0; bi<2; ++bi)
373 const double div_i = (bi == 0) ? -1 : 1;
376 basis_i[id_0] = (bi == iq0) ? 1 : 0;
380 const int ii_loc = bi + 2*ci;
384 if (jj_loc > ii_loc) {
continue; }
386 const double div_div = Q(6,iqz,iqy,iqx)*div_i*div_j;
388 double basis_basis = 0.0;
389 basis_basis += Q(0,iqz,iqy,iqx)*basis_i[0]*basis_j[0];
390 basis_basis += Q(1,iqz,iqy,iqx)*(basis_i[0]*basis_j[1] + basis_i[1]*basis_j[0]);
391 basis_basis += Q(2,iqz,iqy,iqx)*(basis_i[0]*basis_j[2] + basis_i[2]*basis_j[0]);
392 basis_basis += Q(3,iqz,iqy,iqx)*basis_i[1]*basis_j[1];
393 basis_basis += Q(4,iqz,iqy,iqx)*(basis_i[1]*basis_j[2] + basis_i[2]*basis_j[1]);
394 basis_basis += Q(5,iqz,iqy,iqx)*basis_i[2]*basis_j[2];
396 const double val = dq*div_div + mq*basis_basis;
399 local_mat(ii_loc, jj_loc) += val;
418 for (
int ii_loc=0; ii_loc<nf; ++ii_loc)
420 const int ci = ii_loc/2;
421 const int bi = ii_loc%2;
424 const int id1 = (ci+1)%3;
425 const int id2 = (ci+2)%3;
436 const int nx = (ci == 0) ? op1 : o;
437 const int ny = (ci == 1) ? op1 : o;
439 const int ii = kx+ii_lex[0] + (ky+ii_lex[1])*nx + (kz+ii_lex[2])*nx*ny;
441 for (
int jj_loc=0; jj_loc<nf; ++jj_loc)
443 const int cj = jj_loc/2;
446 const int cj_rel = (3 + cj - ci)%3;
448 const int bj = jj_loc%2;
450 const int jd0 = cj_rel;
451 const int jd1 = (cj_rel+1)%3;
452 const int jd2 = (cj_rel+2)%3;
459 const int d0 = jj_rel[0] - i0 + 1;
460 const int d1 = jj_rel[1] - i1;
461 const int d2 = jj_rel[2] - i2;
463 if (cj_rel == 0) { jj_off = d0; }
464 else if (cj_rel == 1) { jj_off = 3 + d0 + 2*d1; }
465 else { jj_off = 7 + d0 + 2*d2; }
468 const double val = (jj_loc <= ii_loc)
469 ? local_mat(ii_loc, jj_loc)
470 : local_mat(jj_loc, ii_loc);
471 AtomicAdd(V(jj_off, ii, ci, iel_ho), val);
482 for (
int ci=0; ci<
dim; ++ci)
484 const int i_off = ci*o*o*op1;
486 const int id1 = (ci+1)%3;
487 const int id2 = (ci+2)%3;
489 const int nxi = (ci == 0) ? op1 : o;
490 const int nyi = (ci == 1) ? op1 : o;
492 for (
int i0=0; i0<op1; ++i0)
494 for (
int i1=0; i1<o; ++i1)
496 for (
int i2=0; i2<o; ++i2)
502 const int ii_el = i_off + ii_lex[0] + ii_lex[1]*nxi + ii_lex[2]*nxi*nyi;
504 for (
int cj_rel=0; cj_rel<
dim; ++cj_rel)
506 const int cj = (ci + cj_rel) % 3;
507 const int j_off = cj*o*o*op1;
509 const int nxj = (cj == 0) ? op1 : o;
510 const int nyj = (cj == 1) ? op1 : o;
512 const int j0_begin = (i0 > 0) ? i0-1 : i0;
513 const int j0_end = (cj_rel == 0)
514 ? ((i0 < o) ? i0+1 : i0)
515 : ((i0 < o) ? i0 : i0-1);
516 const int j1_begin = i1;
517 const int j1_end = (cj_rel == 1) ? i1+1 : i1;
518 const int j2_begin = i2;
519 const int j2_end = (cj_rel == 2) ? i2+1 : i2;
521 for (
int j0=j0_begin; j0<=j0_end; ++j0)
523 const int d0 = 1 + j0 - i0;
524 for (
int j1=j1_begin; j1<=j1_end; ++j1)
526 const int d1 = j1 - i1;
527 for (
int j2=j2_begin; j2<=j2_end; ++j2)
529 const int d2 = j2 - i2;
534 const int jj_el = j_off + jj_lex[0] + jj_lex[1]*nxj + jj_lex[2]*nxj*nyj;
536 if (cj_rel == 0) { jj_off = d0; }
537 else if (cj_rel == 1) { jj_off = 3 + d0 + 2*d1; }
538 else { jj_off = 7 + d0 + 2*d2; }
539 map(jj_off, ii_el) = jj_el;
551 template void BatchedLOR_RT::Assemble2D<1>();
552 template void BatchedLOR_RT::Assemble2D<2>();
553 template void BatchedLOR_RT::Assemble2D<3>();
554 template void BatchedLOR_RT::Assemble2D<4>();
555 template void BatchedLOR_RT::Assemble2D<5>();
556 template void BatchedLOR_RT::Assemble2D<6>();
557 template void BatchedLOR_RT::Assemble2D<7>();
558 template void BatchedLOR_RT::Assemble2D<8>();
560 template void BatchedLOR_RT::Assemble3D<1>();
561 template void BatchedLOR_RT::Assemble3D<2>();
562 template void BatchedLOR_RT::Assemble3D<3>();
563 template void BatchedLOR_RT::Assemble3D<4>();
564 template void BatchedLOR_RT::Assemble3D<5>();
565 template void BatchedLOR_RT::Assemble3D<6>();
566 template void BatchedLOR_RT::Assemble3D<7>();
567 template void BatchedLOR_RT::Assemble3D<8>();
576 ProjectLORCoefficient<VectorFEMassIntegrator>(
a,
c1);
577 ProjectLORCoefficient<DivDivIntegrator>(
a,
c2);
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
Abstract base class for the batched LOR assembly kernels.
void forall_2D(int N, int X, int Y, lambda &&body)
Array< int > & sparse_mapping
Local element sparsity pattern.
void SetSize(int s)
Resize the vector to size s.
MFEM_HOST_DEVICE T AtomicAdd(T &add, const T val)
int Size() const
Returns the size of the vector.
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
CoefficientVector c2
Coefficient of second integrator.
BatchedLOR_RT(BilinearForm &a, FiniteElementSpace &fes_ho_, Vector &X_vert_, Vector &sparse_ij_, Array< int > &sparse_mapping_)
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Vector & sparse_ij
Local element sparsity matrix data.
MFEM_HOST_DEVICE double Det3D(DeviceMatrix &J)
MFEM_HOST_DEVICE double Det2D(DeviceMatrix &J)
MFEM_HOST_DEVICE void Jacobian3D(const double x, const double y, const double z, const double vx[8], const double vy[8], const double vz[8], DeviceMatrix &J)
FiniteElementSpace & fes_ho
The associated high-order space.
A basic generic Tensor class, appropriate for use on the GPU.
int GetNE() const
Returns number of elements in the mesh.
MFEM_HOST_DEVICE void Jacobian2D(const double x, const double y, const double vx[4], const double vy[4], DeviceMatrix &J)
Vector & X_vert
Mesh coordinate vector.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
CoefficientVector c1
Coefficient of first integrator.