35 const bool const_c = (c.
Size() == 1);
36 MFEM_VERIFY(coeffDim < 6 ||
37 !const_c,
"Constant matrix coefficient not supported");
40 const auto J =
Reshape(j.
Read(), Q1Dx,Q1Dy,Q1Dz,3,3);
41 const auto C = const_c ?
Reshape(c.
Read(), 1,1,1,1) :
43 d.
SetSize(Q1Dx * Q1Dy * Q1Dz * (symmetric ? 6 : 9));
44 auto D =
Reshape(d.
Write(), Q1Dx,Q1Dy,Q1Dz, symmetric ? 6 : 9);
46 MFEM_FORALL_3D(e, NE, Q1Dx, Q1Dy, Q1Dz,
48 MFEM_FOREACH_THREAD(qx,x,Q1Dx)
50 MFEM_FOREACH_THREAD(qy,y,Q1Dy)
52 MFEM_FOREACH_THREAD(qz,z,Q1Dz)
54 const real_t J11 = J(qx,qy,qz,0,0);
55 const real_t J21 = J(qx,qy,qz,1,0);
56 const real_t J31 = J(qx,qy,qz,2,0);
57 const real_t J12 = J(qx,qy,qz,0,1);
58 const real_t J22 = J(qx,qy,qz,1,1);
59 const real_t J32 = J(qx,qy,qz,2,1);
60 const real_t J13 = J(qx,qy,qz,0,2);
61 const real_t J23 = J(qx,qy,qz,1,2);
62 const real_t J33 = J(qx,qy,qz,2,2);
63 const real_t detJ = J11 * (J22 * J33 - J32 * J23) -
64 J21 * (J12 * J33 - J32 * J13) +
65 J31 * (J12 * J23 - J22 * J13);
66 const real_t w_detJ = W(qx,qy,qz) / detJ;
68 const real_t A11 = (J22 * J33) - (J23 * J32);
69 const real_t A12 = (J32 * J13) - (J12 * J33);
70 const real_t A13 = (J12 * J23) - (J22 * J13);
71 const real_t A21 = (J31 * J23) - (J21 * J33);
72 const real_t A22 = (J11 * J33) - (J13 * J31);
73 const real_t A23 = (J21 * J13) - (J11 * J23);
74 const real_t A31 = (J21 * J32) - (J31 * J22);
75 const real_t A32 = (J31 * J12) - (J11 * J32);
76 const real_t A33 = (J11 * J22) - (J12 * J21);
78 if (coeffDim == 6 || coeffDim == 9)
81 const real_t M11 = C(0, qx,qy,qz);
82 const real_t M12 = C(1, qx,qy,qz);
83 const real_t M13 = C(2, qx,qy,qz);
84 const real_t M21 = (!symmetric) ? C(3, qx,qy,qz) : M12;
85 const real_t M22 = (!symmetric) ? C(4, qx,qy,qz) : C(3, qx,qy,qz);
86 const real_t M23 = (!symmetric) ? C(5, qx,qy,qz) : C(4, qx,qy,qz);
87 const real_t M31 = (!symmetric) ? C(6, qx,qy,qz) : M13;
88 const real_t M32 = (!symmetric) ? C(7, qx,qy,qz) : M23;
89 const real_t M33 = (!symmetric) ? C(8, qx,qy,qz) : C(5, qx,qy,qz);
91 const real_t R11 = M11*A11 + M12*A12 + M13*A13;
92 const real_t R12 = M11*A21 + M12*A22 + M13*A23;
93 const real_t R13 = M11*A31 + M12*A32 + M13*A33;
94 const real_t R21 = M21*A11 + M22*A12 + M23*A13;
95 const real_t R22 = M21*A21 + M22*A22 + M23*A23;
96 const real_t R23 = M21*A31 + M22*A32 + M23*A33;
97 const real_t R31 = M31*A11 + M32*A12 + M33*A13;
98 const real_t R32 = M31*A21 + M32*A22 + M33*A23;
99 const real_t R33 = M31*A31 + M32*A32 + M33*A33;
102 D(qx,qy,qz,0) = w_detJ * (A11*R11 + A12*R21 + A13*R31);
103 const real_t D12 = w_detJ * (A11*R12 + A12*R22 + A13*R32);
105 D(qx,qy,qz,2) = w_detJ * (A11*R13 + A12*R23 + A13*R33);
107 const real_t D21 = w_detJ * (A21*R11 + A22*R21 + A23*R31);
108 const real_t D22 = w_detJ * (A21*R12 + A22*R22 + A23*R32);
109 const real_t D23 = w_detJ * (A21*R13 + A22*R23 + A23*R33);
111 const real_t D33 = w_detJ * (A31*R13 + A32*R23 + A33*R33);
113 D(qx,qy,qz,3) = symmetric ? D22 : D21;
114 D(qx,qy,qz,4) = symmetric ? D23 : D22;
115 D(qx,qy,qz,5) = symmetric ? D33 : D23;
119 D(qx,qy,qz,6) = w_detJ * (A31*R11 + A32*R21 + A33*R31);
120 D(qx,qy,qz,7) = w_detJ * (A31*R12 + A32*R22 + A33*R32);
126 const real_t C1 = const_c ? C(0,0,0,0) : C(0,qx,qy,qz);
127 const real_t C2 = const_c ? C(0,0,0,0) :
128 (coeffDim == 3 ? C(1,qx,qy,qz) : C(0,qx,qy,qz));
129 const real_t C3 = const_c ? C(0,0,0,0) :
130 (coeffDim == 3 ? C(2,qx,qy,qz) : C(0,qx,qy,qz));
133 D(qx,qy,qz,0) = w_detJ * (C1*A11*A11 + C2*A12*A12 + C3*A13*A13);
134 D(qx,qy,qz,1) = w_detJ * (C1*A11*A21 + C2*A12*A22 + C3*A13*A23);
135 D(qx,qy,qz,2) = w_detJ * (C1*A11*A31 + C2*A12*A32 + C3*A13*A33);
136 D(qx,qy,qz,3) = w_detJ * (C1*A21*A21 + C2*A22*A22 + C3*A23*A23);
137 D(qx,qy,qz,4) = w_detJ * (C1*A21*A31 + C2*A22*A32 + C3*A23*A33);
138 D(qx,qy,qz,5) = w_detJ * (C1*A31*A31 + C2*A32*A32 + C3*A33*A33);
151 std::vector<int> minQ,
152 std::vector<int> maxQ,
153 std::vector<int> minD,
154 std::vector<int> maxD,
155 std::vector<int> minDD,
156 std::vector<int> maxDD,
158 const bool zeroOrder,
159 std::vector<Vector> & reducedWeights,
160 std::vector<std::vector<int>> & reducedIDs)
162 MFEM_VERIFY(B.
NumRows() == nq,
"");
163 MFEM_VERIFY(B.
NumCols() == nd,
"");
164 MFEM_VERIFY(G.
NumRows() == nq,
"");
165 MFEM_VERIFY(G.
NumCols() == nd,
"");
168 for (
int dof=0; dof<nd; ++dof)
172 const int nc_dof = maxDD[dof] - minDD[dof] + 1;
173 const int nw_dof = maxD[dof] - minD[dof] + 1;
176 MFEM_VERIFY(nc_dof <= nw_dof,
"The NNLS system for the reduced "
177 "integration rule requires more full integration points. Try"
178 " increasing the order of the full integration rule.");
185 for (
int qx = minD[dof]; qx <= maxD[dof]; ++qx)
187 const real_t Bq = zeroOrder ? B(qx,dof) : G(qx,dof);
191 w[qx - minD[dof]] = w_qx;
193 for (
int dx = minQ[qx]; dx <= maxQ[qx]; ++dx)
195 const real_t Bd = zeroOrder ? B(qx,dx) : G(qx,dx);
197 Gmat(dx - minDD[dof], qx - minD[dof]) = Bq * Bd;
203#ifdef MFEM_USE_LAPACK
209 MFEM_ABORT(
"NNLSSolver requires building with LAPACK");
213 for (
int i=0; i<sol.
Size(); ++i)
221 MFEM_VERIFY(nnz > 0,
"");
224 std::vector<int> idnnz(nnz);
226 for (
int i=0; i<sol.
Size(); ++i)
236 reducedWeights.push_back(wred);
237 reducedIDs.push_back(idnnz);
242void DiffusionIntegrator::SetupPatchPA(
const int patch, Mesh *mesh,
245 const Array<int>& Q1D = pQ1D[patch];
246 const Array<int>& D1D = pD1D[patch];
247 const std::vector<Array2D<real_t>>& B = pB[patch];
248 const std::vector<Array2D<real_t>>& G = pG[patch];
250 const IntArrayVar2D& minD = pminD[patch];
251 const IntArrayVar2D& maxD = pmaxD[patch];
252 const IntArrayVar2D& minQ = pminQ[patch];
253 const IntArrayVar2D& maxQ = pmaxQ[patch];
255 const IntArrayVar2D& minDD = pminDD[patch];
256 const IntArrayVar2D& maxDD = pmaxDD[patch];
258 const Array<const IntegrationRule*>& ir1d = pir1d[patch];
260 MFEM_VERIFY(Q1D.Size() == 3,
"");
262 const int dims = dim;
263 const int symmDims = (dims * (dims + 1)) / 2;
266 for (
int i=1; i<dim; ++i)
273 Array<real_t> weights(nq);
277 Vector jac(dim * dim * nq);
279 for (
int qz=0; qz<Q1D[2]; ++qz)
281 for (
int qy=0; qy<Q1D[1]; ++qy)
283 for (
int qx=0; qx<Q1D[0]; ++qx)
285 const int p = qx + (qy * Q1D[0]) + (qz * Q1D[0] * Q1D[1]);
288 ElementTransformation *tr = mesh->GetElementTransformation(e);
290 weights[
p] = ip.weight;
292 tr->SetIntPoint(&ip);
294 const DenseMatrix& Jp = tr->Jacobian();
295 for (
int i=0; i<
dim; ++i)
296 for (
int j=0; j<
dim; ++j)
298 jac[
p + ((i + (j *
dim)) * nq)] = Jp(i,j);
304 if (
auto *SMQ =
dynamic_cast<SymmetricMatrixCoefficient *
>(
MQ))
306 MFEM_VERIFY(SMQ->GetSize() == dim,
"");
308 coeff.SetSize(symmDims * nq);
310 DenseSymmetricMatrix sym_mat;
311 sym_mat.SetSize(dim);
313 auto C =
Reshape(coeff.HostWrite(), symmDims, nq);
314 for (
int qz=0; qz<Q1D[2]; ++qz)
316 for (
int qy=0; qy<Q1D[1]; ++qy)
318 for (
int qx=0; qx<Q1D[0]; ++qx)
320 const int p = qx + (qy * Q1D[0]) + (qz * Q1D[0] * Q1D[1]);
322 ElementTransformation *tr = mesh->GetElementTransformation(e);
325 SMQ->Eval(sym_mat, *tr, ip);
327 for (
int i=0; i<
dim; ++i)
328 for (
int j=i; j<
dim; ++j, ++cnt)
330 C(cnt,
p) = sym_mat(i,j);
341 coeffDim = MQfullDim;
343 coeff.SetSize(MQfullDim * nq);
348 auto C =
Reshape(coeff.HostWrite(), MQfullDim, nq);
349 for (
int qz=0; qz<Q1D[2]; ++qz)
351 for (
int qy=0; qy<Q1D[1]; ++qy)
353 for (
int qx=0; qx<Q1D[0]; ++qx)
355 const int p = qx + (qy * Q1D[0]) + (qz * Q1D[0] * Q1D[1]);
357 ElementTransformation *tr = mesh->GetElementTransformation(e);
361 for (
int i=0; i<
dim; ++i)
362 for (
int j=0; j<
dim; ++j)
364 C(j+(i*dim),
p) = mat(i,j);
374 coeff.SetSize(coeffDim * nq);
375 auto C =
Reshape(coeff.HostWrite(), coeffDim, nq);
377 for (
int qz=0; qz<Q1D[2]; ++qz)
379 for (
int qy=0; qy<Q1D[1]; ++qy)
381 for (
int qx=0; qx<Q1D[0]; ++qx)
383 const int p = qx + (qy * Q1D[0]) + (qz * Q1D[0] * Q1D[1]);
385 ElementTransformation *tr = mesh->GetElementTransformation(e);
389 for (
int i=0; i<coeffDim; ++i)
397 else if (
Q ==
nullptr)
402 else if (ConstantCoefficient* cQ =
dynamic_cast<ConstantCoefficient*
>(
Q))
405 coeff(0) = cQ->constant;
407 else if (
dynamic_cast<QuadratureFunctionCoefficient*
>(
Q))
409 MFEM_ABORT(
"QuadratureFunction not supported yet\n");
414 auto C =
Reshape(coeff.HostWrite(), nq);
415 for (
int qz=0; qz<Q1D[2]; ++qz)
417 for (
int qy=0; qy<Q1D[1]; ++qy)
419 for (
int qx=0; qx<Q1D[0]; ++qx)
421 const int p = qx + (qy * Q1D[0]) + (qz * Q1D[0] * Q1D[1]);
423 ElementTransformation *tr = mesh->GetElementTransformation(e);
437 SetupPatch3D(Q1D[0], Q1D[1], Q1D[2], coeffDim, symmetric, weights, jac,
440 numPatches = mesh->NURBSext->GetNP();
448 const int totalDim = numPatches *
dim * numTypes;
449 reducedWeights.resize(totalDim);
450 reducedIDs.resize(totalDim);
452 auto rw =
Reshape(reducedWeights.data(), numTypes, dim, numPatches);
453 auto rid =
Reshape(reducedIDs.data(), numTypes, dim, numPatches);
455 for (
int d=0; d<
dim; ++d)
462 minDD[d], maxDD[d], ir1d[d],
true,
463 rw(0,d,patch), rid(0,d,patch));
467 minDD[d], maxDD[d], ir1d[d],
false,
468 rw(1,d,patch), rid(1,d,patch));
474void DiffusionIntegrator::AssemblePatchMatrix_fullQuadrature(
475 const int patch,
const FiniteElementSpace &fes, SparseMatrix*& smat)
477 MFEM_VERIFY(
patchRules,
"patchRules must be defined");
479 const int spaceDim =
dim;
481 Mesh *mesh = fes.GetMesh();
486 "Unexpected dimension for VectorCoefficient");
491 "Unexpected width for MatrixCoefficient");
493 "Unexpected height for MatrixCoefficient");
496#ifdef MFEM_THREAD_SAFE
497 DenseMatrix M(
MQ ? spaceDim : 0);
504 SetupPatchBasisData(mesh, patch);
506 SetupPatchPA(patch, mesh);
508 const Array<int>& Q1D = pQ1D[patch];
509 const Array<int>& D1D = pD1D[patch];
510 const std::vector<Array2D<real_t>>& B = pB[patch];
511 const std::vector<Array2D<real_t>>& G = pG[patch];
513 const IntArrayVar2D& minD = pminD[patch];
514 const IntArrayVar2D& maxD = pmaxD[patch];
515 const IntArrayVar2D& minQ = pminQ[patch];
516 const IntArrayVar2D& maxQ = pmaxQ[patch];
518 const IntArrayVar2D& minDD = pminDD[patch];
519 const IntArrayVar2D& maxDD = pmaxDD[patch];
522 for (
int d=1; d<
dim; ++d)
527 MFEM_VERIFY(3 == dim,
"Only 3D so far");
530 const auto qd =
Reshape(pa_data.
Read(), Q1D[0]*Q1D[1]*Q1D[2],
531 (symmetric ? 6 : 9));
534 std::vector<Array3D<real_t>> grad(dim);
536 for (
int d=0; d<
dim; ++d)
538 grad[d].SetSize(Q1D[0], Q1D[1], Q1D[2]);
541 Array3D<real_t> gradDXY(D1D[0], D1D[1], dim);
542 Array2D<real_t> gradDX(D1D[0], dim);
547 int *smati =
nullptr;
548 int *smatj =
nullptr;
552 Array<int> maxw(dim);
555 for (
int d=0; d<
dim; ++d)
557 for (
int i=0; i<D1D[d]; ++i)
559 maxw[d] = std::max(maxw[d], maxDD[d][i] - minDD[d][i] + 1);
563 cdofs.SetSize(maxw[0], maxw[1], maxw[2]);
566 smati = Memory<int>(ndof+1);
569 for (
int dof_j=0; dof_j<ndof; ++dof_j)
571 const int jdz = dof_j / (D1D[0] * D1D[1]);
572 const int jdy = (dof_j - (jdz * D1D[0] * D1D[1])) / D1D[0];
573 const int jdx = dof_j - (jdz * D1D[0] * D1D[1]) - (jdy * D1D[0]);
575 MFEM_VERIFY(jdx + (D1D[0] * (jdy + (D1D[1] * jdz))) == dof_j,
"");
577 const int jd[3] = {jdx, jdy, jdz};
579 for (
int i=0; i<
dim; ++i)
581 nd[i] = maxDD[i][jd[i]] - minDD[i][jd[i]] + 1;
585 smati[dof_j + 1] = smati[dof_j] + ndd;
589 smatj = Memory<int>(nnz);
590 smata = Memory<real_t>(nnz);
592 for (
int i=0; i<nnz; ++i)
598 for (
int dof_j=0; dof_j<ndof; ++dof_j)
600 const int jdz = dof_j / (D1D[0] * D1D[1]);
601 const int jdy = (dof_j - (jdz * D1D[0] * D1D[1])) / D1D[0];
602 const int jdx = dof_j - (jdz * D1D[0] * D1D[1]) - (jdy * D1D[0]);
604 const int jd[3] = {jdx, jdy, jdz};
605 for (
int i=0; i<
dim; ++i)
607 nd[i] = maxDD[i][jd[i]] - minDD[i][jd[i]] + 1;
610 for (
int i=0; i<nd[0]; ++i)
611 for (
int j=0; j<nd[1]; ++j)
612 for (
int k=0; k<nd[2]; ++k)
614 cdofs(i,j,k) = minDD[0][jdx] + i + (D1D[0] *
615 (minDD[1][jdy] + j + (D1D[1] * (minDD[2][jdz] + k))));
618 for (
int d=0; d<
dim; ++d)
619 for (
int qz = minD[2][jdz]; qz <= maxD[2][jdz]; ++qz)
621 for (
int qy = minD[1][jdy]; qy <= maxD[1][jdy]; ++qy)
623 for (
int qx = minD[0][jdx]; qx <= maxD[0][jdx]; ++qx)
625 grad[d](qx,qy,qz) = 0.0;
630 for (
int qz = minD[2][jdz]; qz <= maxD[2][jdz]; ++qz)
632 const real_t wz = B[2](qz,jdz);
633 const real_t wDz = G[2](qz,jdz);
635 for (
int qy = minD[1][jdy]; qy <= maxD[1][jdy]; ++qy)
637 const real_t wy = B[1](qy,jdy);
638 const real_t wDy = G[1](qy,jdy);
640 for (
int qx = minD[0][jdx]; qx <= maxD[0][jdx]; ++qx)
642 const int q = qx + ((qy + (qz * Q1D[1])) * Q1D[0]);
643 const real_t O11 = qd(q,0);
644 const real_t O12 = qd(q,1);
645 const real_t O13 = qd(q,2);
646 const real_t O21 = symmetric ? O12 : qd(q,3);
647 const real_t O22 = symmetric ? qd(q,3) : qd(q,4);
648 const real_t O23 = symmetric ? qd(q,4) : qd(q,5);
649 const real_t O31 = symmetric ? O13 : qd(q,6);
650 const real_t O32 = symmetric ? O23 : qd(q,7);
651 const real_t O33 = symmetric ? qd(q,5) : qd(q,8);
653 const real_t wx = B[0](qx,jdx);
654 const real_t wDx = G[0](qx,jdx);
656 const real_t gradX = wDx * wy * wz;
657 const real_t gradY = wx * wDy * wz;
658 const real_t gradZ = wx * wy * wDz;
660 grad[0](qx,qy,qz) = (O11*gradX)+(O12*gradY)+(O13*gradZ);
661 grad[1](qx,qy,qz) = (O21*gradX)+(O22*gradY)+(O23*gradZ);
662 grad[2](qx,qy,qz) = (O31*gradX)+(O32*gradY)+(O33*gradZ);
667 for (
int qz = minD[2][jdz]; qz <= maxD[2][jdz]; ++qz)
669 for (
int dy = minDD[1][jdy]; dy <= maxDD[1][jdy]; ++dy)
671 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
673 for (
int d=0; d<
dim; ++d)
675 gradDXY(dx,dy,d) = 0.0;
679 for (
int qy = minD[1][jdy]; qy <= maxD[1][jdy]; ++qy)
681 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
683 for (
int d=0; d<
dim; ++d)
688 for (
int qx = minD[0][jdx]; qx <= maxD[0][jdx]; ++qx)
690 const real_t gX = grad[0](qx,qy,qz);
691 const real_t gY = grad[1](qx,qy,qz);
692 const real_t gZ = grad[2](qx,qy,qz);
693 for (
int dx = minQ[0][qx]; dx <= maxQ[0][qx]; ++dx)
695 const real_t wx = B[0](qx,dx);
696 const real_t wDx = G[0](qx,dx);
697 gradDX(dx,0) += gX * wDx;
698 gradDX(dx,1) += gY * wx;
699 gradDX(dx,2) += gZ * wx;
702 for (
int dy = minQ[1][qy]; dy <= maxQ[1][qy]; ++dy)
704 const real_t wy = B[1](qy,dy);
705 const real_t wDy = G[1](qy,dy);
706 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
708 gradDXY(dx,dy,0) += gradDX(dx,0) * wy;
709 gradDXY(dx,dy,1) += gradDX(dx,1) * wDy;
710 gradDXY(dx,dy,2) += gradDX(dx,2) * wy;
714 for (
int dz = minQ[2][qz]; dz <= maxQ[2][qz]; ++dz)
716 const real_t wz = B[2](qz,dz);
717 const real_t wDz = G[2](qz,dz);
718 for (
int dy = minDD[1][jdy]; dy <= maxDD[1][jdy]; ++dy)
720 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
722 const real_t v = (gradDXY(dx,dy,0) * wz) +
723 (gradDXY(dx,dy,1) * wz) +
724 (gradDXY(dx,dy,2) * wDz);
726 const int loc = dx - minDD[0][jd[0]] + (nd[0] * (dy - minDD[1][jd[1]] +
727 (nd[1] * (dz - minDD[2][jd[2]]))));
729 const int odof = cdofs(dx - minDD[0][jd[0]],
730 dy - minDD[1][jd[1]],
731 dz - minDD[2][jd[2]]);
733 const int m = smati[dof_j] + loc;
734 MFEM_ASSERT(smatj[m] == odof || smatj[m] == -1,
"");
744 smat =
new SparseMatrix(smati, smatj, smata, ndof, ndof);
747void DiffusionIntegrator::SetupPatchBasisData(Mesh *mesh,
unsigned int patch)
749 MFEM_VERIFY(pB.size() == patch && pG.size() == patch,
"");
750 MFEM_VERIFY(pQ1D.size() == patch && pD1D.size() == patch,
"");
751 MFEM_VERIFY(pminQ.size() == patch && pmaxQ.size() == patch,
"");
752 MFEM_VERIFY(pminD.size() == patch && pmaxD.size() == patch,
"");
753 MFEM_VERIFY(pminDD.size() == patch && pmaxDD.size() == patch,
"");
754 MFEM_VERIFY(pir1d.size() == patch,
"");
757 Array<const KnotVector*> pkv;
758 mesh->NURBSext->GetPatchKnotVectors(patch, pkv);
759 MFEM_VERIFY(pkv.Size() == dim,
"");
762 Array<int> orders(dim);
764 std::vector<Array2D<real_t>> B(dim);
765 std::vector<Array2D<real_t>> G(dim);
766 Array<const IntegrationRule*> ir1d(dim);
768 IntArrayVar2D minD(dim);
769 IntArrayVar2D maxD(dim);
770 IntArrayVar2D minQ(dim);
771 IntArrayVar2D maxQ(dim);
773 IntArrayVar2D minDD(dim);
774 IntArrayVar2D maxDD(dim);
776 for (
int d=0; d<
dim; ++d)
782 orders[d] = pkv[d]->GetOrder();
783 D1D[d] = pkv[d]->GetNCP();
785 Vector shapeKV(orders[d]+1);
786 Vector dshapeKV(orders[d]+1);
788 B[d].SetSize(Q1D[d], D1D[d]);
789 G[d].SetSize(Q1D[d], D1D[d]);
791 minD[d].assign(D1D[d], Q1D[d]);
792 maxD[d].assign(D1D[d], 0);
794 minQ[d].assign(Q1D[d], D1D[d]);
795 maxQ[d].assign(Q1D[d], 0);
801 MFEM_VERIFY(knotSpan1D.Size() == Q1D[d],
"");
803 for (
int i = 0; i < Q1D[d]; i++)
805 const IntegrationPoint &ip = ir1d[d]->IntPoint(i);
806 const int ijk = knotSpan1D[i];
807 const real_t kv0 = (*pkv[d])[orders[d] + ijk];
808 real_t kv1 = (*pkv[d])[0];
809 for (
int j = orders[d] + ijk + 1; j < pkv[d]->Size(); ++j)
811 if ((*pkv[d])[j] > kv0)
818 MFEM_VERIFY(kv1 > kv0,
"");
820 pkv[d]->CalcShape(shapeKV, ijk, (ip.x - kv0) / (kv1 - kv0));
821 pkv[d]->CalcDShape(dshapeKV, ijk, (ip.x - kv0) / (kv1 - kv0));
826 for (
int j=0; j<orders[d]+1; ++j)
828 B[d](i,ijk + j) = shapeKV[j];
829 G[d](i,ijk + j) = dshapeKV[j];
831 minD[d][ijk + j] = std::min(minD[d][ijk + j], i);
832 maxD[d][ijk + j] = std::max(maxD[d][ijk + j], i);
835 minQ[d][i] = std::min(minQ[d][i], ijk);
836 maxQ[d][i] = std::max(maxQ[d][i], ijk + orders[d]);
840 minDD[d].resize(D1D[d]);
841 maxDD[d].resize(D1D[d]);
842 for (
int i=0; i<D1D[d]; ++i)
844 const int qmin = minD[d][i];
845 minDD[d][i] = minQ[d][qmin];
847 const int qmax = maxD[d][i];
848 maxDD[d][i] = maxQ[d][qmax];
859 pminQ.push_back(minQ);
860 pmaxQ.push_back(maxQ);
862 pminD.push_back(minD);
863 pmaxD.push_back(maxD);
865 pminDD.push_back(minDD);
866 pmaxDD.push_back(maxDD);
868 pir1d.push_back(ir1d);
872void DiffusionIntegrator::AssemblePatchMatrix_reducedQuadrature(
873 const int patch,
const FiniteElementSpace &fes, SparseMatrix*& smat)
875 MFEM_VERIFY(
patchRules,
"patchRules must be defined");
877 const int spaceDim =
dim;
879 Mesh *mesh = fes.GetMesh();
884 "Unexpected dimension for VectorCoefficient");
889 "Unexpected width for MatrixCoefficient");
891 "Unexpected height for MatrixCoefficient");
894#ifdef MFEM_THREAD_SAFE
895 DenseMatrix M(
MQ ? spaceDim : 0);
902 SetupPatchBasisData(mesh, patch);
904 MFEM_VERIFY(3 == dim,
"Only 3D so far");
910 SetupPatchPA(patch, mesh,
true);
912 const Array<int>& Q1D = pQ1D[patch];
913 const Array<int>& D1D = pD1D[patch];
914 const std::vector<Array2D<real_t>>& B = pB[patch];
915 const std::vector<Array2D<real_t>>& G = pG[patch];
917 const IntArrayVar2D& minD = pminD[patch];
918 const IntArrayVar2D& maxD = pmaxD[patch];
919 const IntArrayVar2D& minQ = pminQ[patch];
920 const IntArrayVar2D& maxQ = pmaxQ[patch];
922 const IntArrayVar2D& minDD = pminDD[patch];
923 const IntArrayVar2D& maxDD = pmaxDD[patch];
926 for (
int d=1; d<
dim; ++d)
931 auto rw =
Reshape(reducedWeights.data(), numTypes, dim, numPatches);
932 auto rid =
Reshape(reducedIDs.data(), numTypes, dim, numPatches);
934 const auto qd =
Reshape(pa_data.
Read(), Q1D[0]*Q1D[1]*Q1D[2],
935 (symmetric ? 6 : 9));
938 std::vector<Array3D<real_t>> grad(dim);
939 for (
int d=0; d<
dim; ++d)
941 grad[d].SetSize(Q1D[0], Q1D[1], Q1D[2]);
947 Array3D<bool> gradUsed;
948 gradUsed.SetSize(Q1D[0], Q1D[1], Q1D[2]);
950 Array3D<real_t> gradDXY(D1D[0], D1D[1], dim);
951 Array2D<real_t> gradDX(D1D[0], dim);
956 int *smati =
nullptr;
957 int *smatj =
nullptr;
959 bool bugfound =
false;
962 Array<int> maxw(dim);
965 for (
int d=0; d<
dim; ++d)
967 for (
int i=0; i<D1D[d]; ++i)
969 maxw[d] = std::max(maxw[d], maxDD[d][i] - minDD[d][i] + 1);
973 cdofs.SetSize(maxw[0], maxw[1], maxw[2]);
976 smati = Memory<int>(ndof+1);
979 for (
int dof_j=0; dof_j<ndof; ++dof_j)
981 const int jdz = dof_j / (D1D[0] * D1D[1]);
982 const int jdy = (dof_j - (jdz * D1D[0] * D1D[1])) / D1D[0];
983 const int jdx = dof_j - (jdz * D1D[0] * D1D[1]) - (jdy * D1D[0]);
985 MFEM_VERIFY(jdx + (D1D[0] * (jdy + (D1D[1] * jdz))) == dof_j,
"");
987 const int jd[3] = {jdx, jdy, jdz};
989 for (
int i=0; i<
dim; ++i)
991 nd[i] = maxDD[i][jd[i]] - minDD[i][jd[i]] + 1;
995 smati[dof_j + 1] = smati[dof_j] + ndd;
999 smatj = Memory<int>(nnz);
1000 smata = Memory<real_t>(nnz);
1002 for (
int i=0; i<nnz; ++i)
1008 for (
int dof_j=0; dof_j<ndof; ++dof_j)
1010 const int jdz = dof_j / (D1D[0] * D1D[1]);
1011 const int jdy = (dof_j - (jdz * D1D[0] * D1D[1])) / D1D[0];
1012 const int jdx = dof_j - (jdz * D1D[0] * D1D[1]) - (jdy * D1D[0]);
1014 const int jd[3] = {jdx, jdy, jdz};
1015 for (
int i=0; i<
dim; ++i)
1017 nd[i] = maxDD[i][jd[i]] - minDD[i][jd[i]] + 1;
1020 for (
int i=0; i<nd[0]; ++i)
1021 for (
int j=0; j<nd[1]; ++j)
1022 for (
int k=0; k<nd[2]; ++k)
1024 cdofs(i,j,k) = minDD[0][jdx] + i + (D1D[0] *
1025 (minDD[1][jdy] + j + (D1D[1] * (minDD[2][jdz] + k))));
1028 for (
int qz = minD[2][jdz]; qz <= maxD[2][jdz]; ++qz)
1030 for (
int qy = minD[1][jdy]; qy <= maxD[1][jdy]; ++qy)
1032 for (
int qx = minD[0][jdx]; qx <= maxD[0][jdx]; ++qx)
1034 gradUsed(qx,qy,qz) =
false;
1039 for (
int zquad = 0; zquad<2; ++zquad)
1042 const int nwz =
static_cast<int>(rid(zquad,2,patch)[jdz].size());
1043 for (
int irz=0; irz < nwz; ++irz)
1045 const int qz = rid(zquad,2,patch)[jdz][irz] + minD[2][jdz];
1046 const real_t zw = rw(zquad,2,patch)[jdz][irz];
1048 const real_t gwz = B[2](qz,jdz);
1049 const real_t gwDz = G[2](qz,jdz);
1051 for (
int dy = minDD[1][jdy]; dy <= maxDD[1][jdy]; ++dy)
1053 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
1055 for (
int d=0; d<
dim; ++d)
1057 gradDXY(dx,dy,d) = 0.0;
1062 for (
int yquad = 0; yquad<2; ++yquad)
1065 const int nwy =
static_cast<int>(rid(yquad,1,patch)[jdy].size());
1066 for (
int iry=0; iry < nwy; ++iry)
1068 const int qy = rid(yquad,1,patch)[jdy][iry] + minD[1][jdy];
1069 const real_t yw = rw(yquad,1,patch)[jdy][iry];
1071 const real_t gwy = B[1](qy,jdy);
1072 const real_t gwDy = G[1](qy,jdy);
1074 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
1076 for (
int d=0; d<
dim; ++d)
1083 for (
int xquad=0; xquad<2; ++xquad)
1085 const int nwx =
static_cast<int>(rid(xquad,0,patch)[jdx].size());
1086 for (
int irx=0; irx < nwx; ++irx)
1088 const int qx = rid(xquad,0,patch)[jdx][irx] + minD[0][jdx];
1090 if (!gradUsed(qx,qy,qz))
1092 const real_t gwx = B[0](qx,jdx);
1093 const real_t gwDx = G[0](qx,jdx);
1095 const int q = qx + ((qy + (qz * Q1D[1])) * Q1D[0]);
1096 const real_t O11 = qd(q,0);
1097 const real_t O12 = qd(q,1);
1098 const real_t O13 = qd(q,2);
1099 const real_t O21 = symmetric ? O12 : qd(q,3);
1100 const real_t O22 = symmetric ? qd(q,3) : qd(q,4);
1101 const real_t O23 = symmetric ? qd(q,4) : qd(q,5);
1102 const real_t O31 = symmetric ? O13 : qd(q,6);
1103 const real_t O32 = symmetric ? O23 : qd(q,7);
1104 const real_t O33 = symmetric ? qd(q,5) : qd(q,8);
1106 const real_t gradX = gwDx * gwy * gwz;
1107 const real_t gradY = gwx * gwDy * gwz;
1108 const real_t gradZ = gwx * gwy * gwDz;
1110 grad[0](qx,qy,qz) = (O11*gradX)+(O12*gradY)+(O13*gradZ);
1111 grad[1](qx,qy,qz) = (O21*gradX)+(O22*gradY)+(O23*gradZ);
1112 grad[2](qx,qy,qz) = (O31*gradX)+(O32*gradY)+(O33*gradZ);
1114 gradUsed(qx,qy,qz) =
true;
1120 const int nw =
static_cast<int>(rid(0,0,patch)[jdx].size());
1121 for (
int irx=0; irx < nw; ++irx)
1123 const int qx = rid(0,0,patch)[jdx][irx] + minD[0][jdx];
1125 const real_t gY = grad[1](qx,qy,qz);
1126 const real_t gZ = grad[2](qx,qy,qz);
1127 const real_t xw = rw(0,0,patch)[jdx][irx];
1128 for (
int dx = minQ[0][qx]; dx <= maxQ[0][qx]; ++dx)
1130 const real_t wx = B[0](qx,dx);
1133 gradDX(dx,1) += gY * wx * xw;
1137 gradDX(dx,2) += gZ * wx * xw;
1143 const int nw11 =
static_cast<int>(rid(1,0,patch)[jdx].size());
1145 for (
int irx=0; irx < nw11; ++irx)
1147 const int qx = rid(1,0,patch)[jdx][irx] + minD[0][jdx];
1149 const real_t gX = grad[0](qx,qy,qz);
1150 const real_t xw = rw(1,0,patch)[jdx][irx];
1151 for (
int dx = minQ[0][qx]; dx <= maxQ[0][qx]; ++dx)
1153 const real_t wDx = G[0](qx,dx);
1154 gradDX(dx,0) += gX * wDx * xw;
1158 for (
int dy = minQ[1][qy]; dy <= maxQ[1][qy]; ++dy)
1160 const real_t wy = B[1](qy,dy);
1161 const real_t wDy = G[1](qy,dy);
1162 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
1168 gradDXY(dx,dy,2) += gradDX(dx,2) * wy * yw;
1172 gradDXY(dx,dy,0) += gradDX(dx,0) * wy * yw;
1175 else if (zquad == 0)
1177 gradDXY(dx,dy,1) += gradDX(dx,1) * wDy * yw;
1183 for (
int dz = minQ[2][qz]; dz <= maxQ[2][qz]; ++dz)
1185 const real_t wz = B[2](qz,dz);
1186 const real_t wDz = G[2](qz,dz);
1187 for (
int dy = minDD[1][jdy]; dy <= maxDD[1][jdy]; ++dy)
1189 for (
int dx = minDD[0][jdx]; dx <= maxDD[0][jdx]; ++dx)
1191 real_t v = (zquad == 0) ? (gradDXY(dx,dy,0) * wz) +
1192 (gradDXY(dx,dy,1) * wz) : gradDXY(dx,dy,2) * wDz;
1196 const int loc = dx - minDD[0][jd[0]] + (nd[0] * (dy - minDD[1][jd[1]] +
1197 (nd[1] * (dz - minDD[2][jd[2]]))));
1199 const int odof = cdofs(dx - minDD[0][jd[0]],
1200 dy - minDD[1][jd[1]],
1201 dz - minDD[2][jd[2]]);
1203 const int m = smati[dof_j] + loc;
1204 if (!(smatj[m] == odof || smatj[m] == -1))
1218 MFEM_VERIFY(!bugfound,
"");
1220 for (
int i=0; i<nnz; ++i)
1222 if (smata[i] == 0.0)
1231 smat =
new SparseMatrix(smati, smatj, smata, ndof, ndof);
1240 AssemblePatchMatrix_reducedQuadrature(patch, fes, smat);
1244 AssemblePatchMatrix_fullQuadrature(patch, fes, smat);
Dynamic 2D array using row-major layout.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
Data type dense matrix using column-major storage.
void AssemblePatchMatrix(const int patch, const FiniteElementSpace &fes, SparseMatrix *&smat) override
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Class for integration point with weight.
Class for an integration rule - an Array of IntegrationPoint.
int GetNPoints() const
Returns the number of the points in the integration rule.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
NURBSMeshRules * patchRules
virtual void Eval(DenseMatrix &K, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the matrix coefficient in the element described by T at the point ip, storing the result in ...
int GetWidth() const
Get the width of the matrix.
int GetHeight() const
Get the height of the matrix.
void Mult(const Vector &w, Vector &sol) const override
Compute the non-negative least squares solution to the underdetermined system.
void SetOperator(const Operator &op) override
The operator must be a DenseMatrix.
const IntegrationRule * GetPatchRule1D(const int patch, const int dimension) const
For tensor product rules defined on each patch by SetPatchRules1D(), return a pointer to the 1D rule ...
int GetPointElement(int patch, int i, int j, int k) const
For tensor product rules defined on each patch by SetPatchRules1D(), returns the index of the element...
const Array< int > & GetPatchRule1D_KnotSpan(const int patch, const int dimension) const
For tensor product rules defined on each patch by SetPatchRules1D(), returns an array of knot span in...
void GetIntegrationPointFrom1D(const int patch, int i, int j, int k, IntegrationPoint &ip)
For tensor product rules defined on each patch by SetPatchRules1D(), return the integration point wit...
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
int GetVDim()
Returns dimension of the vector.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void GetReducedRule(const int nq, const int nd, Array2D< real_t > const &B, Array2D< real_t > const &G, std::vector< int > minQ, std::vector< int > maxQ, std::vector< int > minD, std::vector< int > maxD, std::vector< int > minDD, std::vector< int > maxDD, const IntegrationRule *ir, const bool zeroOrder, std::vector< Vector > &reducedWeights, std::vector< std::vector< int > > &reducedIDs)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void SetupPatch3D(const int Q1Dx, const int Q1Dy, const int Q1Dz, const int coeffDim, const bool symmetric, const Array< real_t > &w, const Vector &j, const Vector &c, Vector &d)
real_t p(const Vector &x, real_t t)