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)