Beispiel #1
0
    //! Help PETSc identify the coarser DM dmc given the fine DM dmf
    PetscErrorCode libmesh_petsc_DMCoarsen(DM dmf, MPI_Comm /*comm*/, DM * dmc)
    {
      libmesh_assert(dmc);
      libmesh_assert(dmf);

      PetscErrorCode ierr;

      // Extract our context from the incoming dmf
      void * ctx_f = nullptr;
      ierr = DMShellGetContext(dmf, &ctx_f);LIBMESH_CHKERR(ierr);
      libmesh_assert(ctx_f);
      PetscDMContext * p_ctx = static_cast<PetscDMContext*>(ctx_f);

      // First, ensure that there exists a coarse DM that we want to
      // set. There ought to be as we created it while walking the
      // hierarchy.
      libmesh_assert(p_ctx->coarser_dm);
      libmesh_assert(*(p_ctx->coarser_dm));

      // In situations using fieldsplit we need to (potentially)
      // provide a coarser DM which only has the relevant subfields in
      // it. Since we create global DMs for each mesh level, we need
      // to extract the section from the DM, and check the number of
      // fields. When less than all the fields are used, we need to
      // create the proper subsections.

      // Get the number of fields and their names from the incomming
      // fine DM and the global reference DM
      PetscInt nfieldsf, nfieldsg;
      char ** fieldnamesf;
      char ** fieldnamesg;

      libmesh_assert(p_ctx->global_dm);
      DM * globaldm = p_ctx->global_dm;
      ierr = DMCreateFieldIS(dmf, &nfieldsf, &fieldnamesf, nullptr);
      LIBMESH_CHKERR(ierr);
      ierr = DMCreateFieldIS(*globaldm, &nfieldsg, &fieldnamesg, nullptr);
      LIBMESH_CHKERR(ierr);

      // If the probed number of fields is less than the number of
      // global fields, this amounts to PETSc 'indicating' to us we
      // are doing FS. So, we must create subsections for the coarser
      // DMs.
      if ( nfieldsf < nfieldsg )
        {
          PetscSection section;
          PetscSection subsection;
          std::vector<PetscInt> subfields(nfieldsf); // extracted fields

          // First, get the section from the coarse DM
#if PETSC_VERSION_LESS_THAN(3,10,0)
          ierr = DMGetDefaultSection(*(p_ctx->coarser_dm), &section);
#else
          ierr = DMGetSection(*(p_ctx->coarser_dm), &section);
#endif
          LIBMESH_CHKERR(ierr);

          // Now, match fine grid DM field names to their global DM
          //  counterparts. Since PETSc can internally reassign field
          //  numbering under a fieldsplit, we must extract
          //  subsections via the field names. This is admittedly
          //  gross, but c'est la vie.
          for (int i = 0; i < nfieldsf ; i++)
            {
              for (int j = 0; j < nfieldsg ;j++)
                if ( strcmp( fieldnamesg[j], fieldnamesf[i] ) == 0 )
                  subfields[i] = j;
            }

          // Next, for the found fields we now make a subsection and set it for the coarser DM
          ierr = PetscSectionCreateSubsection(section, nfieldsf, subfields.data(), &subsection);
          LIBMESH_CHKERR(ierr);
#if PETSC_VERSION_LESS_THAN(3,10,0)
          ierr = DMSetDefaultSection(*(p_ctx->coarser_dm) , subsection);
#else
          ierr = DMSetSection(*(p_ctx->coarser_dm) , subsection);
#endif
          LIBMESH_CHKERR(ierr);
          ierr = PetscSectionDestroy(&subsection);
          LIBMESH_CHKERR(ierr);
        }

      // Finally, set the coarser DM
      *(dmc) = *(p_ctx->coarser_dm);

      return 0;
    }
Beispiel #2
0
GEN
subfields0(GEN nf,GEN d)
{
  return d? subfields(nf,d): subfieldsall(nf);
}