18 #include "libmesh/libmesh_common.h" 
   19 #include "libmesh/petsc_macro.h" 
   21 #ifdef LIBMESH_HAVE_PETSC 
   22 #if !PETSC_VERSION_LESS_THAN(3,7,3) 
   23 #if defined(LIBMESH_ENABLE_AMR) && defined(LIBMESH_HAVE_METAPHYSICL) 
   25 #include "libmesh/ignore_warnings.h" 
   27 #if PETSC_VERSION_LESS_THAN(3,12,0) 
   28 #include <petsc/private/dmimpl.h> 
   30 #include <petscdmshell.h> 
   31 #include "libmesh/restore_warnings.h" 
   33 #include "libmesh/petsc_dm_wrapper.h" 
   34 #include "libmesh/libmesh_logging.h" 
   35 #include "libmesh/system.h" 
   36 #include "libmesh/mesh.h" 
   37 #include "libmesh/mesh_base.h" 
   38 #include "libmesh/mesh_refinement.h" 
   39 #include "libmesh/partitioner.h" 
   40 #include "libmesh/dof_map.h" 
   41 #include "libmesh/elem.h" 
   57 #if PETSC_VERSION_LESS_THAN(3,9,0) 
   79           ierr = DMShellCreate(PetscObjectComm((PetscObject) dm), 
subdm);
 
   90 #if PETSC_VERSION_LESS_THAN(3,12,0) 
   93               ierr = DMShellSetCoarsen(*
subdm, dm->ops->coarsen);
 
   97           PetscErrorCode (*coarsen)(DM,MPI_Comm,DM*) = 
nullptr;
 
   98           ierr = DMShellGetCoarsen(dm, &coarsen);
 
  102               ierr = DMShellSetCoarsen(*
subdm, coarsen);
 
  108 #if PETSC_VERSION_LESS_THAN(3,12,0) 
  111               ierr = DMShellSetRefine(*
subdm, dm->ops->refine);
 
  115           PetscErrorCode (*refine)(DM,MPI_Comm,DM*) = 
nullptr;
 
  116           ierr = DMShellGetRefine(dm, &refine);
 
  125 #if PETSC_VERSION_LESS_THAN(3,12,0) 
  126           if (dm->ops->createinterpolation)
 
  128               ierr = DMShellSetCreateInterpolation(*
subdm, dm->ops->createinterpolation);
 
  132           PetscErrorCode (*interp)(DM,DM,Mat*,Vec*) = 
nullptr;
 
  133           ierr = DMShellGetCreateInterpolation(dm, &interp);
 
  137               ierr = DMShellSetCreateInterpolation(*
subdm, interp);
 
  143 #if PETSC_VERSION_LESS_THAN(3,12,0) 
  144           if (dm->ops->createrestriction)
 
  146               ierr = DMShellSetCreateRestriction(*
subdm, dm->ops->createrestriction);
 
  150           PetscErrorCode (*createrestriction)(DM,DM,Mat*) = 
nullptr;
 
  151           ierr = DMShellGetCreateRestriction(dm, &createrestriction);
 
  153           if (createrestriction)
 
  155               ierr = DMShellSetCreateRestriction(*
subdm, createrestriction);
 
  161 #if PETSC_VERSION_LESS_THAN(3,12,0) 
  162           if (dm->ops->createsubdm)
 
  164               ierr = DMShellSetCreateSubDM(*
subdm, dm->ops->createsubdm);
 
  168           PetscErrorCode (*createsubdm)(DM,PetscInt,
const PetscInt[],IS*,DM*) = 
nullptr;
 
  169           ierr = DMShellGetCreateSubDM(dm, &createsubdm);
 
  173               ierr = DMShellSetCreateSubDM(*
subdm, createsubdm);
 
  183 #if PETSC_VERSION_LESS_THAN(3,11,0) 
  205       void * ctx_c = 
nullptr;
 
  227       void * ctx_f = 
nullptr;
 
  245       PetscInt nfieldsf, nfieldsg;
 
  251       ierr = DMCreateFieldIS(dmf, &nfieldsf, &fieldnamesf, 
nullptr);
 
  253       ierr = DMCreateFieldIS(*globaldm, &nfieldsg, &fieldnamesg, 
nullptr);
 
  260       if ( nfieldsf < nfieldsg )
 
  270           for (
int i = 0; i < nfieldsf ; i++)
 
  272               for (
int j = 0; j < nfieldsg ;j++)
 
  273                 if ( strcmp( fieldnamesg[j], fieldnamesf[i] ) == 0 )
 
  284           void * ctx_c = 
nullptr;
 
  308                                          Mat * mat ,Vec * vec)
 
  318       PetscObjectGetComm((PetscObject)dmc, &comm);
 
  321       void * ctx_c = 
nullptr;
 
  322       ierr = DMShellGetContext(dmc, &ctx_c);
 
  328       void * ctx_f = 
nullptr;
 
  339       PetscInt nfieldsf, nfieldsg;
 
  344       ierr = DMCreateFieldIS(dmf, &nfieldsf, 
nullptr, 
nullptr);
 
  346       ierr = DMCreateFieldIS(*globaldm, &nfieldsg, 
nullptr, 
nullptr);
 
  352       if ( nfieldsf < nfieldsg)
 
  355           std::vector<std::vector<numeric_index_type>> allrows,allcols;
 
  356           std::vector<numeric_index_type> rows,cols;
 
  363           const int n_subfields = p_ctx_f->
subfields.size();
 
  364           if ( n_subfields >= 1 )
 
  368                   rows.insert(rows.end(), allrows[i].begin(), allrows[i].end());
 
  369                   cols.insert(cols.end(), allcols[i].begin(), allcols[i].end());
 
  371               std::sort(rows.begin(),rows.end());
 
  372               std::sort(cols.begin(),cols.end());
 
  407       PetscObjectGetComm((PetscObject)dmc, &comm);
 
  410       void * ctx_f = 
nullptr;
 
  447     START_LOG (
"init_and_attach_petscdm()", 
"PetscDMWrapper");
 
  455     mesh.allow_renumbering(
false);
 
  456     mesh.allow_remote_element_removal(
false);
 
  457     mesh.partitioner() = 
nullptr;
 
  461     for ( 
auto & elem : 
mesh.active_local_element_ptr_range() )
 
  472     unsigned int usr_requested_mg_lvls = 0;
 
  473     usr_requested_mg_lvls = 
command_line_next(
"-pc_mg_levels", usr_requested_mg_lvls);
 
  476     if ( usr_requested_mg_lvls != 0 )
 
  479         libmesh_assert_less_equal( usr_requested_mg_lvls, 
n_levels );
 
  500     for(
unsigned int level = 
n_levels; level >= 1; level--)
 
  507         DM & dm = this->
get_dm(level-1);
 
  508         PetscSection & section = this->
get_section(level-1);
 
  512         ierr = DMShellCreate(system.
comm().get(), &dm);
 
  513         CHKERRABORT(system.
comm().get(),
ierr);
 
  516         ierr = DMSetCoordinateDim(dm, 
mesh.mesh_dimension());
 
  517         CHKERRABORT(system.
comm().get(),
ierr);
 
  521 #if PETSC_VERSION_LESS_THAN(3,12,0) 
  522         ierr = DMSetDefaultSection(dm, section);
 
  524         ierr = DMSetSection(dm, section);
 
  526         CHKERRABORT(system.
comm().get(),
ierr);
 
  532             this->
build_sf(system, star_forest);
 
  533 #if PETSC_VERSION_LESS_THAN(3,12,0) 
  534             ierr = DMSetDefaultSF(dm, star_forest);
 
  536             ierr = DMSetSectionSF(dm, star_forest);
 
  538             CHKERRABORT(system.
comm().get(),
ierr);
 
  543         CHKERRABORT(system.
comm().get(),
ierr);
 
  546         bool supply_restriction = 
false;
 
  547         if (supply_restriction)
 
  550             CHKERRABORT(system.
comm().get(),
ierr);
 
  554         CHKERRABORT(system.
comm().get(),
ierr);
 
  557         CHKERRABORT(system.
comm().get(),
ierr);
 
  560         CHKERRABORT(system.
comm().get(), 
ierr);
 
  565             START_LOG (
"PDM_coarsen", 
"PetscDMWrapper");
 
  567             STOP_LOG  (
"PDM_coarsen", 
"PetscDMWrapper");
 
  569             START_LOG (
"PDM_dist_dof", 
"PetscDMWrapper");
 
  571             STOP_LOG  (
"PDM_dist_dof", 
"PetscDMWrapper");
 
  576     for( 
unsigned int i=1; i <= 
n_levels; i++ )
 
  593                 (*
_ctx_vec[i-1]).coarser_dm = 
nullptr;
 
  599                 (*
_ctx_vec[i-1]).finer_dm   = 
nullptr;
 
  614         for ( 
unsigned int i = 1; i <= 
n_levels ; ++i)
 
  616             DM & dm = this->
get_dm(i-1);
 
  618             ierr = DMShellSetGlobalVector( dm, (*
_ctx_vec[ i-1 ]).current_vec->vec() );
 
  619             CHKERRABORT(system.
comm().get(),
ierr);
 
  622             CHKERRABORT(system.
comm().get(),
ierr);
 
  636         for( 
unsigned int v = 0; v < 
n_vars; v++ )
 
  638             std::vector<numeric_index_type> di;
 
  643         START_LOG (
"PDM_refine", 
"PetscDMWrapper");
 
  645         STOP_LOG  (
"PDM_refine", 
"PetscDMWrapper");
 
  647         START_LOG (
"PDM_dist_dof", 
"PetscDMWrapper");
 
  649         STOP_LOG  (
"PDM_dist_dof", 
"PetscDMWrapper");
 
  651         START_LOG (
"PDM_cnstrnts", 
"PetscDMWrapper");
 
  653         STOP_LOG (
"PDM_cnstrnts", 
"PetscDMWrapper");
 
  657     for ( 
unsigned int i = 1 ; i < 
n_levels ; ++i )
 
  665             for( 
unsigned int v = 0; v < 
n_vars; v++ )
 
  667                 std::vector<numeric_index_type> di;
 
  682             unsigned int ndofs_old_size  = ndofs_old_end - ndofs_old_first;
 
  685             _ctx_vec[i-1]->K_interp_ptr->init(ndofs_f, ndofs_c, ndofs_local, ndofs_old_size, 30 , 20);
 
  688             _ctx_vec[i-1]->K_interp_ptr->set_destroy_mat_on_exit(
false);
 
  689             _ctx_vec[i-1]->K_sub_interp_ptr->set_destroy_mat_on_exit(
false);
 
  695             START_LOG (
"PDM_proj_mat", 
"PetscDMWrapper");
 
  697             STOP_LOG  (
"PDM_proj_mat", 
"PetscDMWrapper");
 
  700             _ctx_vec[i-1]->K_interp_ptr->close();
 
  706             START_LOG (
"PDM_refine", 
"PetscDMWrapper");
 
  708             STOP_LOG  (
"PDM_refine", 
"PetscDMWrapper");
 
  710             START_LOG (
"PDM_dist_dof", 
"PetscDMWrapper");
 
  712             STOP_LOG (
"PDM_dist_dof", 
"PetscDMWrapper");
 
  714             START_LOG (
"PDM_cnstrnts", 
"PetscDMWrapper");
 
  716             STOP_LOG  (
"PDM_cnstrnts", 
"PetscDMWrapper");
 
  722     DM & dm = this->
get_dm(n_levels-1);
 
  723     ierr = SNESSetDM(snes, dm);
 
  724     CHKERRABORT(system.
comm().get(),
ierr);
 
  726     STOP_LOG (
"init_and_attach_petscdm()", 
"PetscDMWrapper");
 
  731     START_LOG (
"build_section()", 
"PetscDMWrapper");
 
  734     ierr = PetscSectionCreate(system.
comm().get(),§ion);
 
  735     CHKERRABORT(system.
comm().get(),
ierr);
 
  738     ierr = PetscSectionSetNumFields(section,system.
n_vars());
 
  739     CHKERRABORT(system.
comm().get(),
ierr);
 
  745         CHKERRABORT(system.
comm().get(),
ierr);
 
  757     std::unordered_map<dof_id_type,dof_id_type> node_map;
 
  758     std::unordered_map<dof_id_type,dof_id_type> elem_map;
 
  759     std::map<dof_id_type,unsigned int> scalar_map;
 
  774       libmesh_error_msg(
"ERROR: Must use --node-major-dofs with PetscSection!");
 
  786     ierr = PetscSectionSetUp(section);
 
  787     CHKERRABORT(system.
comm().get(),
ierr);
 
  792     STOP_LOG (
"build_section()", 
"PetscDMWrapper");
 
  797     START_LOG (
"build_sf()", 
"PetscDMWrapper");
 
  801     const std::vector<dof_id_type> & send_list = dof_map.
get_send_list();
 
  804     const PetscInt n_leaves = cast_int<PetscInt>(send_list.size());
 
  807     const PetscInt n_roots = dof_map.
n_local_dofs() + n_leaves;
 
  812     static_assert(
sizeof(PetscInt) == 
sizeof(
dof_id_type),
"PetscInt is not a dof_id_type!");
 
  813     PetscInt * local_dofs = reinterpret_cast<PetscInt *>(const_cast<dof_id_type *>(send_list.data()));
 
  820     std::vector<PetscSFNode> sf_nodes(send_list.size());
 
  830         PetscInt index = incoming_dof - dof_map.
first_dof(rank);
 
  832         sf_nodes[i].rank  = rank; 
 
  833         sf_nodes[i].index = index;
 
  836     PetscSFNode * remote_dofs = sf_nodes.data();
 
  839     ierr = PetscSFCreate(system.
comm().get(), &star_forest);
 
  840     CHKERRABORT(system.
comm().get(),
ierr);
 
  845     ierr = PetscSFSetGraph(star_forest,
 
  852     CHKERRABORT(system.
comm().get(),
ierr);
 
  854     STOP_LOG (
"build_sf()", 
"PetscDMWrapper");
 
  858                                                    PetscSection & section,
 
  859                                                    std::unordered_map<dof_id_type,dof_id_type> & node_map,
 
  860                                                    std::unordered_map<dof_id_type,dof_id_type> & elem_map,
 
  861                                                    std::map<dof_id_type,unsigned int> & scalar_map)
 
  899         node_map.reserve(
mesh.n_local_nodes());
 
  900         elem_map.reserve(
mesh.n_active_local_elem());
 
  906         for (
const auto & elem : 
mesh.active_local_element_ptr_range())
 
  908             for (
const Node & node : elem->node_ref_range())
 
  916                 std::vector<dof_id_type> node_dof_indices;
 
  918                 if( !node_dof_indices.empty() && dof_map.
local_index(node_dof_indices[0]) )
 
  923                     for( 
auto dof : node_dof_indices )
 
  929                     if( node_map.count(node_id) == 0 )
 
  931                         node_map.insert(std::make_pair(node_id,pend));
 
  942             if( elem->n_dofs(system.
number()) > 0 )
 
  945                 elem_map.insert(std::make_pair(elem_id,pend));
 
  960                     scalar_map.insert(std::make_pair(pend,v));
 
  968     PetscErrorCode 
ierr = PetscSectionSetChart(section, pstart, pend);
 
  969     CHKERRABORT(system.
comm().get(),
ierr);
 
  973                                             PetscSection & section,
 
  974                                             const std::unordered_map<dof_id_type,dof_id_type> & node_map,
 
  975                                             const std::unordered_map<dof_id_type,dof_id_type> & elem_map,
 
  976                                             const std::map<dof_id_type,unsigned int> & scalar_map)
 
  988     for (
const auto & nmap : node_map )
 
  995         const Node & node = 
mesh.node_ref(global_node_id);
 
 1003     for (
const auto & emap : elem_map )
 
 1010         const Elem & elem = 
mesh.elem_ref(global_elem_id);
 
 1019         for (
const auto & smap : scalar_map )
 
 1022             const unsigned int scalar_var = smap.second;
 
 1027             ierr = PetscSectionSetFieldDof( section, local_id, scalar_var, n_dofs );
 
 1028             CHKERRABORT(system.
comm().get(),
ierr);
 
 1032             ierr = PetscSectionSetDof( section, local_id, n_dofs );
 
 1033             CHKERRABORT(system.
comm().get(),
ierr);
 
 1042                                         PetscSection & section)
 
 1044     unsigned int total_n_dofs_at_dofobject = 0;
 
 1049         unsigned int n_dofs_at_dofobject = dof_object.
n_dofs(system.
number(), v);
 
 1051         if( n_dofs_at_dofobject > 0 )
 
 1053             PetscErrorCode 
ierr = PetscSectionSetFieldDof( section,
 
 1056                                                            n_dofs_at_dofobject );
 
 1058             CHKERRABORT(system.
comm().get(),
ierr);
 
 1060             total_n_dofs_at_dofobject += n_dofs_at_dofobject;
 
 1064     libmesh_assert_equal_to(total_n_dofs_at_dofobject, dof_object.
n_dofs(system.
number()));
 
 1066     PetscErrorCode 
ierr =
 
 1067       PetscSectionSetDof( section, local_id, total_n_dofs_at_dofobject );
 
 1068     CHKERRABORT(system.
comm().get(),
ierr);
 
 1074     PetscInt n_local_dofs = 0;
 
 1077     PetscInt pstart, pend;
 
 1078     PetscErrorCode 
ierr = PetscSectionGetChart(section, &pstart, &pend);
 
 1083     for( PetscInt p = pstart; p < pend; p++ )
 
 1086         ierr = PetscSectionGetDof(section,p,&n_dofs);
 
 1089         n_local_dofs += n_dofs;
 
 1092     static_assert(
sizeof(PetscInt) == 
sizeof(
dof_id_type),
"PetscInt is not a dof_id_type!");
 
 1093     return n_local_dofs;
 
 1108     for( 
unsigned int i = 0; i < 
n_levels; i++ )
 
 1110         _dms[i] = libmesh_make_unique<DM>();
 
 1111         _sections[i] = libmesh_make_unique<PetscSection>();
 
 1113         _ctx_vec[i] = libmesh_make_unique<PetscDMContext>();
 
 1114         _pmtx_vec[i]= libmesh_make_unique<PetscMatrix<Number>>(comm);
 
 1115         _subpmtx_vec[i]= libmesh_make_unique<PetscMatrix<Number>>(comm);
 
 1116         _vec_vec[i] = libmesh_make_unique<PetscVector<Number>>(comm);
 
 1122 #endif // #if LIBMESH_ENABLE_AMR && LIBMESH_HAVE_METAPHYSICL 
 1123 #endif // PETSC_VERSION 
 1124 #endif // LIBMESH_HAVE_PETSC