Exemple #1
0
SparseMatrix* FiniteElementSpace::NC_GlobalRestrictionMatrix
(FiniteElementSpace* cfes, NCMesh* ncmesh)
{
   Array<int> rows, cols, rs, cs;
   LinearFECollection linfec;

   NCMesh::FineTransform* transforms = ncmesh->GetFineTransforms();

   SparseMatrix* R = new SparseMatrix(cfes->GetVSize(), this->GetVSize());

   // we mark each fine DOF the first time its column is set so that slave node
   // values don't get represented twice in R
   Array<int> mark(this->GetNDofs());
   mark = 0;

   // loop over the fine elements, get interpolations of the coarse elements
   for (int k = 0; k < mesh->GetNE(); k++)
   {
      mesh->SetState(Mesh::TWO_LEVEL_COARSE);
      cfes->GetElementDofs(transforms[k].coarse_index, rows);

      mesh->SetState(Mesh::TWO_LEVEL_FINE);
      this->GetElementDofs(k, cols);

      if (!transforms[k].IsIdentity())
      {
         int geom = mesh->GetElementBaseGeometry(k);
         const FiniteElement *fe = fec->FiniteElementForGeometry(geom);

         IsoparametricTransformation trans;
         trans.SetFE(linfec.FiniteElementForGeometry(geom));
         trans.GetPointMat() = transforms[k].point_matrix;

         DenseMatrix I(fe->GetDof());
         fe->GetLocalInterpolation(trans, I);
         // TODO: use std::unordered_map to cache I matrices (point_matrix as key)

         // make sure we don't set any column of R more than once
         for (int i = 0; i < I.Height(); i++)
         {
            int col = cols[i];
            if (col < 0)
               col = -1 - col;
            if (mark[col]++)
               I.SetRow(i, 0); // zero the i-th row of I
         }

         cfes->DofsToVDofs(rows);
         this->DofsToVDofs(cols);
         SetVDofSubMatrixTranspose(*R, rows, cols, I, vdim);
      }
      else // optimization: insert identity for elements that were not refined
      {
         MFEM_ASSERT(rows.Size() == cols.Size(), "");
         for (int i = 0; i < rows.Size(); i++)
         {
            int col = cols[i];
            if (col < 0)
               col = -1 - col;
            if (!mark[col]++)
               for (int vd = 0; vd < vdim; vd++)
                  R->Set(cfes->DofToVDof(rows[i], vd),
                         this->DofToVDof(cols[i], vd), 1.0);
         }
      }
   }

   delete [] transforms;
   return R;
}