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