13 #include <petscerror.h> 14 #include <petsc/private/dmimpl.h> 26 #include "libmesh/nonlinear_implicit_system.h" 27 #include "libmesh/nonlinear_solver.h" 28 #include "libmesh/petsc_macro.h" 29 #include "libmesh/petsc_vector.h" 30 #include "libmesh/petsc_matrix.h" 31 #include "libmesh/dof_map.h" 32 #include "libmesh/preconditioner.h" 33 #include "libmesh/elem_side_builder.h" 37 template <
typename I1,
typename I2>
39 checkSize(
const std::string & split_name,
const I1 split_size,
const I2 size_expected_by_parent)
41 if (libMesh::cast_int<libMesh::numeric_index_type>(split_size) !=
42 libMesh::cast_int<libMesh::numeric_index_type>(size_expected_by_parent))
46 libMesh::cast_int<libMesh::numeric_index_type>(split_size),
47 " but the parent split expected size ",
48 libMesh::cast_int<libMesh::numeric_index_type>(size_expected_by_parent),
49 ". Make sure that you have non-overlapping complete sets for variables and " 50 "blocks as well as consistency in sides/unsides, contacts/uncontacts, etc.");
60 std::map<std::string, unsigned int> *
_var_ids;
79 typedef std::pair<BoundaryID, BoundaryID>
ContactID;
99 std::map<std::string, SplitInfo> *
_splits;
110 void checkChildSize(DM child, PetscInt child_size,
const std::string & child_name);
116 for (
const auto &
split : *_splits)
117 if (
split.second._dm == child)
119 mooseAssert(
split.first == child_name,
"These should match");
120 PetscInt parent_expected_size;
121 auto ierr = ISGetLocalSize(
split.second._rembedding, &parent_expected_size);
124 checkSize(child_name, child_size, parent_expected_size);
137 PetscValidHeaderSpecific(
dm, DM_CLASSID, 1);
140 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
142 "Got DM of type %s, not of type %s",
143 ((PetscObject)
dm)->type_name,
150 std::vector<std::pair<std::string, std::string>> & contact_names,
151 std::vector<PetscBool> & displaced)
158 contact_names.push_back(it.second);
166 std::vector<std::pair<std::string, std::string>> & uncontact_names,
167 std::vector<PetscBool> & displaced)
174 uncontact_names.push_back(it.second);
187 side_names.push_back(it.first);
198 side_names.push_back(it.first);
209 block_names.push_back(it.first);
219 for (
const auto & it : *(dmm->
_var_ids))
220 var_names.push_back(it.first);
230 SETERRQ(((PetscObject)
dm)->comm,
232 "Cannot reset the NonlinearSystem after DM has been set up.");
244 SETERRQ(((PetscObject)
dm)->comm,
246 "Cannot reset the degree of freedom map after DM has been set up.");
258 SETERRQ(((PetscObject)
dm)->comm,
260 "Cannot reset the degree of freedom map after DM has been set up.");
272 SETERRQ(((PetscObject)
dm)->comm,
274 "Cannot reset the MOOSE DM name after DM has been set up.");
276 *dmm->
_name = dm_name;
286 SETERRQ(((PetscObject)
dm)->comm,
288 "Cannot reset the parent DM after the child DM has been set up.");
306 std::set<std::string> processed_vars;
307 for (
const auto & var_name :
vars)
309 const auto *
const var =
315 processed_vars.insert(var->arrayVariableComponent(i));
317 processed_vars.insert(var_name);
320 dmm->
_vars =
new std::set<std::string>(std::move(processed_vars));
365 dmm->
_unsides =
new std::set<std::string>(unsides);
386 const std::vector<std::pair<std::string, std::string>> &
contacts,
387 const std::vector<PetscBool> & displaced)
395 if (
contacts.size() != displaced.size())
396 LIBMESH_SETERRQ2(PETSC_COMM_SELF,
398 "Nonmatching sizes of the contact and displaced arrays: %" LIBMESH_PETSCINT_FMT
399 " != %" LIBMESH_PETSCINT_FMT,
400 static_cast<PetscInt>(
contacts.size()),
401 static_cast<PetscInt>(displaced.size()));
405 dmm->
_contacts =
new std::set<DM_Moose::ContactName>();
406 for (
unsigned int i = 0; i <
contacts.size(); ++i)
416 const std::vector<std::pair<std::string, std::string>> &
uncontacts,
417 const std::vector<PetscBool> & displaced)
429 "Nonmatching sizes of the uncontact and displaced arrays: %" LIBMESH_PETSCINT_FMT
430 " != %" LIBMESH_PETSCINT_FMT,
432 static_cast<PetscInt>(displaced.size()));
436 dmm->
_uncontacts =
new std::set<DM_Moose::ContactName>();
437 for (
unsigned int i = 0; i <
uncontacts.size(); ++i)
464 for (
auto & it : *(dmm->
_splits))
470 dmm->
_splits = LIBMESH_PETSC_NULLPTR;
477 dmm->
_splits =
new std::map<std::string, DM_Moose::SplitInfo>();
478 dmm->
_splitlocs =
new std::multimap<std::string, unsigned int>();
479 for (
unsigned int i = 0; i < split_names.size(); ++i)
482 info.
_dm = LIBMESH_PETSC_NULLPTR;
483 info._rembedding = LIBMESH_PETSC_NULLPTR;
484 std::string
name = split_names[i];
497 if (!
dm->setupcalled)
504 std::string sname = lit.first;
505 unsigned int sloc = lit.second;
506 split_names[sloc] = sname;
511 static PetscErrorCode
549 std::vector<dof_id_type> node_indices;
550 auto process_nodal_dof_indices =
551 [&dofmap, &node_indices](
const Node & node,
552 const unsigned int var_num,
553 std::set<dof_id_type> & local_indices,
554 std::set<dof_id_type> *
const nonlocal_indices =
nullptr)
557 for (
const auto index : node_indices)
559 if (index >= dofmap.first_dof() && index < dofmap.end_dof())
560 local_indices.insert(index);
561 else if (nonlocal_indices)
562 nonlocal_indices->insert(index);
566 auto process_elem_dof_indices =
567 [&dofmap](
const std::vector<dof_id_type> & elem_indices,
568 std::set<dof_id_type> & local_indices,
569 std::set<dof_id_type> *
const nonlocal_indices =
nullptr)
571 for (
const auto index : elem_indices)
573 if (index >= dofmap.first_dof() && index < dofmap.end_dof())
574 local_indices.insert(index);
575 else if (nonlocal_indices)
576 nonlocal_indices->insert(index);
580 std::set<dof_id_type> indices;
581 std::set<dof_id_type> unindices;
582 std::set<dof_id_type> cached_indices;
583 std::set<dof_id_type> cached_unindices;
586 for (
const auto & vit : *(dmm->
_var_ids))
588 unsigned int v = vit.second;
594 for (
const auto & elem :
as_range(lm_mesh.active_local_subdomain_elements_begin(b),
595 lm_mesh.active_local_subdomain_elements_end(b)))
598 std::vector<dof_id_type> evindices;
599 dofmap.dof_indices(elem, evindices, v);
600 process_elem_dof_indices(evindices, indices);
605 bool is_on_current_block =
false;
606 for (
auto & node : lm_mesh.local_node_ptr_range())
608 const unsigned int n_comp = node->n_comp(dmm->
_system->
number(), v);
614 auto node_to_elem_pair = node_to_elem_map.find(node->id());
615 is_on_current_block =
false;
616 for (
const auto & elem_num : node_to_elem_pair->second)
620 const Elem & neighbor_elem = lm_mesh.elem_ref(elem_num);
623 is_on_current_block =
true;
628 if (!is_on_current_block)
631 process_nodal_dof_indices(*node, v, indices);
652 for (
const auto & bnode : bnodes)
658 const Node * node = bnode->_node;
659 process_nodal_dof_indices(*node, v, indices);
667 for (
const auto & bnode : bnodes)
672 const Node * node = bnode->_node;
673 process_nodal_dof_indices(*node, v, unindices);
678 std::set<BoundaryID> eligible_bids;
681 eligible_bids.insert(bid);
684 for (
const auto & bnode : bnodes)
687 if (eligible_bids.count(boundary_id))
689 const Node * node = bnode->_node;
690 process_nodal_dof_indices(*node, v, unindices);
695 auto process_contact_all_nodes =
696 [dmm, process_nodal_dof_indices, v](
const auto & contact_names,
697 auto & indices_to_insert_to)
699 std::set<boundary_id_type> bc_id_set;
701 for (
const auto & [contact_bid_pair, contact_bname_pair] : contact_names)
704 bc_id_set.insert(contact_bid_pair.first);
705 bc_id_set.insert(contact_bid_pair.second);
709 for (
const auto & belem : range)
711 const Elem * elem_bdry = belem->_elem;
712 const auto side = belem->_side;
715 if (bc_id_set.find(boundary_id) == bc_id_set.end())
720 process_nodal_dof_indices(elem_bdry->
node_ref(node_idx), v, indices_to_insert_to);
724 auto process_contact_some_nodes =
725 [dmm, process_nodal_dof_indices, v, &dofmap, &lm_mesh, process_elem_dof_indices](
726 const auto & contact_names,
727 auto & indices_to_insert_to,
728 auto & nonlocal_indices_to_insert_to)
730 std::vector<dof_id_type> evindices;
731 for (
const auto & it : contact_names)
741 std::ostringstream
err;
742 err <<
"Cannot use a displaced uncontact (" << it.second.first <<
"," 743 << it.second.second <<
") with an undisplaced problem";
753 auto lend = locator->_penetration_info.end();
754 for (
auto lit = locator->_penetration_info.begin(); lit != lend; ++lit)
760 const Node & secondary_node = lm_mesh.node_ref(secondary_node_num);
761 process_nodal_dof_indices(
762 secondary_node, v, indices_to_insert_to, &nonlocal_indices_to_insert_to);
766 const Elem * primary_side = pinfo->
_side;
767 dofmap.dof_indices(primary_side, evindices, v);
768 process_elem_dof_indices(
769 evindices, indices_to_insert_to, &nonlocal_indices_to_insert_to);
781 process_contact_some_nodes(*dmm->
_contact_names, indices, cached_indices);
789 process_contact_some_nodes(*dmm->
_uncontact_names, unindices, cached_unindices);
792 std::vector<dof_id_type> local_vec_indices(cached_indices.size());
793 std::copy(cached_indices.begin(), cached_indices.end(), local_vec_indices.begin());
797 for (
const auto & dof : local_vec_indices)
798 if (dof >= dofmap.first_dof() && dof < dofmap.end_dof())
801 local_vec_indices.clear();
802 local_vec_indices.resize(cached_unindices.size());
803 std::copy(cached_unindices.begin(), cached_unindices.end(), local_vec_indices.begin());
807 for (
const auto & dof : local_vec_indices)
808 if (dof >= dofmap.first_dof() && dof < dofmap.end_dof())
809 unindices.insert(dof);
811 std::set<dof_id_type> dindices;
812 std::set_difference(indices.begin(),
816 std::inserter(dindices, dindices.end()));
820 for (
const auto & dof : dindices)
826 ((PetscObject)
dm)->comm, dindices.size(), darray, PETSC_OWN_POINTER, &dmm->
_embedding));
839 ISCreateStride(((PetscObject)
dm)->comm, (high - low), low, 1, &dmm->
_embedding));
848 static PetscErrorCode
850 DM
dm, PetscInt * len,
char *** namelist, IS ** islist, DM ** dmlist)
856 PetscInt split_size_sum = 0;
870 unsigned int d = dit.second;
871 std::string dname = dit.first;
878 PetscObjectSetOptionsPrefix((PetscObject)dinfo.
_dm, ((PetscObject)
dm)->prefix));
879 std::string suffix = std::string(
"fieldsplit_") + dname +
"_";
891 IS dembedding, lembedding;
897 const PetscInt * lindices;
898 PetscInt len, dlen, llen, *rindices, off, i;
903 ((PetscObject)
dm)->comm, PETSC_ERR_PLIB,
"Failed to embed split %u", d);
917 #ifdef PETSC_USE_64BIT_INDICES
923 ((PetscObject)
dm)->comm);
926 for (i = 0; i < llen; ++i)
929 ((PetscObject)
dm)->comm, llen, rindices, PETSC_OWN_POINTER, &(dinfo.
_rembedding)));
940 split_size_sum += is_size;
945 (*dmlist)[d] = dinfo.
_dm;
949 mooseAssert(islist,
"What does it even mean if this is NULL?");
959 static PetscErrorCode
961 DM
dm, PetscInt * len,
char *** namelist, IS ** innerislist, IS ** outerislist, DM ** dmlist)
967 *outerislist = LIBMESH_PETSC_NULLPTR;
972 static PetscErrorCode
988 X_global.
swap(X_sys);
990 X_global.swap(X_sys);
1006 std::ostringstream
err;
1007 err <<
"ERROR: cannot specifiy both a function and object to compute the Residual!" 1013 std::ostringstream
err;
1014 err <<
"ERROR: cannot specifiy both a function and object to compute the combined Residual & " 1029 nl->
nonlinearSolver()->residual_and_jacobian_object->residual_and_jacobian(
1033 std::ostringstream
err;
1034 err <<
"No suitable residual computation routine found";
1041 static PetscErrorCode
1051 static PetscErrorCode
1072 X_global.
swap(X_sys);
1074 X_global.swap(X_sys);
1090 std::ostringstream
err;
1091 err <<
"ERROR: cannot specifiy both a function and object to compute the Jacobian!" 1097 std::ostringstream
err;
1098 err <<
"ERROR: cannot specifiy both a function and object to compute the combined Residual & " 1115 nl->
nonlinearSolver()->residual_and_jacobian_object->residual_and_jacobian(
1122 std::ostringstream
err;
1123 err <<
"No suitable Jacobian routine or object";
1131 static PetscErrorCode
1141 static PetscErrorCode
1160 ((PetscObject)
dm)->comm, PETSC_ERR_ARG_WRONG,
"No bounds calculation in this Moose object");
1164 static PetscErrorCode
1193 #if PETSC_RELEASE_LESS_THAN(3, 13, 0) 1201 static PetscErrorCode
1220 const auto & dof_map = *dmm->
_dof_map;
1221 PetscInt M,
N, m, n;
1223 M = dof_map.n_dofs();
1225 m =
static_cast<PetscInt
>(dof_map.n_local_dofs());
1237 static PetscErrorCode
1241 const char *
name, *prefix;
1245 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1251 PetscViewerASCIIPrintf(viewer,
"DM Moose with name %s and prefix %s\n",
name, prefix));
1253 for (
const auto & vit : *(dmm->
_var_ids))
1255 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"(%s,%u) ", vit.first.c_str(), vit.second));
1261 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", bit.first.c_str(), bit.second));
1268 for (
const auto & sit : *(dmm->
_side_ids))
1271 PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", sit.first.c_str(), sit.second));
1282 PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", sit.first.c_str(), sit.second));
1293 viewer,
"(%s,%s,", cit.second.first.c_str(), cit.second.second.c_str()));
1308 viewer,
"(%s,%s,", cit.second.first.c_str(), cit.second.second.c_str()));
1323 std::string dname = dit.first;
1330 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"Non-ASCII viewers are not supported");
1335 static PetscErrorCode
1348 libmesh_parallel_only(
mesh.
comm());
1349 for (
const auto & elem :
mesh.active_element_ptr_range())
1350 blocks.insert(elem->subdomain_id());
1356 static PetscErrorCode
1367 const auto & dofmap = *dmm->
_dof_map;
1385 dmm->
_sides = LIBMESH_PETSC_NULLPTR;
1402 dmm->
_unsides = LIBMESH_PETSC_NULLPTR;
1413 const auto colon_pos =
name.find(
":");
1414 auto unside_name =
name.substr(0, colon_pos);
1415 auto var_name =
name.substr(colon_pos + 1);
1417 bool var_found =
false;
1418 for (
unsigned int v = 0; v < dofmap.n_variables(); ++v)
1420 const auto & vname = dofmap.variable(v).name();
1421 if (vname == var_name)
1429 mooseError(
"No variable named '", var_name,
"' found");
1440 for (
const auto & cpair : *(dmm->
_contacts))
1446 cpair.first, cpair.second);
1452 std::ostringstream
err;
1453 err <<
"Problem retrieving contact for PenetrationLocator with primary " << cpair.first
1454 <<
" and secondary " << cpair.second;
1474 cpair.first, cpair.second);
1480 std::ostringstream
err;
1481 err <<
"Problem retrieving uncontact for PenetrationLocator with primary " << cpair.first
1482 <<
" and secondary " << cpair.second;
1499 for (
unsigned int v = 0; v < dofmap.n_variables(); ++v)
1501 std::string vname = dofmap.variable(v).name();
1504 dmm->
_var_ids->insert(std::pair<std::string, unsigned int>(vname, v));
1505 dmm->
_var_names->insert(std::pair<unsigned int, std::string>(v, vname));
1507 if (dmm->
_var_ids->size() == dofmap.n_variables())
1514 dmm->
_vars = LIBMESH_PETSC_NULLPTR;
1519 std::set<subdomain_id_type>
blocks;
1522 SETERRQ(((PetscObject)
dm)->comm, PETSC_ERR_PLIB,
"No mesh blocks found.");
1524 for (
const auto & bid :
blocks)
1527 if (!bname.length())
1532 std::ostringstream ss;
1556 && dmm->
_blocks->find(std::to_string(bid)) == dmm->
_blocks->end()))
1559 dmm->
_block_ids->insert(std::make_pair(bname, bid));
1570 dmm->
_blocks = LIBMESH_PETSC_NULLPTR;
1576 name +=
"_" + vit.second;
1581 name +=
"_" + bit.second;
1587 name +=
"_" + sit.second;
1593 name +=
"_" + sit.second;
1597 name +=
"_contacts";
1599 name +=
"_primary_" + cit.second.first +
"_secondary_" + cit.second.second;
1603 name +=
"_uncontacts";
1605 name +=
"_primary_" + cit.second.first +
"_secondary_" + cit.second.second;
1624 for (
auto & it : *(dmm->
_splits))
1631 dm->setupcalled = PETSC_FALSE;
1635 static PetscErrorCode
1646 const char *
name, *prefix;
1652 "DM Moose with name %s and prefix %s\n",
1658 "\thas a trivial embedding\n"));
1663 "\thas embedding defined by IS:\n"));
1682 #if !PETSC_VERSION_LESS_THAN(3, 23, 0) 1685 #elif !PETSC_VERSION_LESS_THAN(3, 18, 0) 1688 #elif !PETSC_VERSION_LESS_THAN(3, 7, 0) 1705 #if !PETSC_VERSION_LESS_THAN(3, 18, 0) 1709 ((PetscObject)
dm)->comm, ((PetscObject)
dm)->prefix,
"DMMoose options",
"DM"));
1717 opt =
"-dm_moose_vars";
1718 help =
"Variables in DMMoose";
1720 opt.c_str(),
help.c_str(),
"DMMooseSetVars",
vars, &
nvars, LIBMESH_PETSC_NULLPTR));
1737 opt =
"-dm_moose_blocks";
1738 help =
"Blocks in DMMoose";
1741 for (PetscInt i = 0; i <
nblocks; ++i)
1756 opt =
"-dm_moose_sides";
1757 help =
"Sides to include in DMMoose";
1759 opt.c_str(),
help.c_str(),
"DMMooseSetSides",
sides, &
nsides, LIBMESH_PETSC_NULLPTR));
1760 for (PetscInt i = 0; i <
nsides; ++i)
1769 opt =
"-dm_moose_unsides";
1770 help =
"Sides to exclude from DMMoose";
1773 opt.c_str(),
help.c_str(),
"DMMooseSetUnSides",
sides, &
nsides, LIBMESH_PETSC_NULLPTR));
1775 for (PetscInt i = 0; i <
nsides; ++i)
1784 opt =
"-dm_moose_unside_by_var";
1785 help =
"Sides to exclude from DMMoose on a by-var basis";
1788 opt.c_str(),
help.c_str(),
"DMMooseSetUnSideByVar",
sides, &
nsides, LIBMESH_PETSC_NULLPTR));
1790 for (PetscInt i = 0; i <
nsides; ++i)
1805 std::vector<DM_Moose::ContactName>
contacts;
1807 PetscInt ncontacts = 0;
1808 opt =
"-dm_moose_ncontacts";
1810 "Number of contacts to include in DMMoose. For each <n> < " 1811 "dm_moose_contacts\n\t-dm_moose_contact_<n> is a comma-separated <primary>,<secondary> pair " 1812 "defining the contact surfaces" 1813 "\t-dm_moose_contact_<n>_displaced <bool> determines whether the contact is defined on " 1814 "the displaced mesh or not";
1817 "DMMooseSetContacts",
1820 LIBMESH_PETSC_NULLPTR));
1822 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
1824 "Number of requested contacts %" LIBMESH_PETSCINT_FMT
1825 " exceeds the maximum number of contacts %" LIBMESH_PETSCINT_FMT,
1828 for (PetscInt i = 0; i < ncontacts; ++i)
1831 char * primary_secondary[2];
1833 std::ostringstream oopt, ohelp;
1834 oopt <<
"-dm_moose_contact_" << i;
1835 ohelp <<
"Primary and secondary for contact " << i;
1837 ohelp.str().c_str(),
1838 "DMMooseSetContacts",
1841 LIBMESH_PETSC_NULLPTR));
1844 ((PetscObject)
dm)->comm,
1846 "Expected 2 sideset IDs (primary & secondary) for contact %" LIBMESH_PETSCINT_FMT
1847 ", got %" LIBMESH_PETSCINT_FMT
" instead",
1851 std::string(primary_secondary[1])));
1856 PetscBool displaced = PETSC_FALSE;
1857 std::ostringstream oopt, ohelp;
1858 oopt <<
"-dm_moose_contact_" << i <<
"_displaced";
1859 ohelp <<
"Whether contact " << i <<
" is determined using displaced mesh or not";
1861 ohelp.str().c_str(),
1862 "DMMooseSetContacts",
1865 LIBMESH_PETSC_NULLPTR));
1872 std::ostringstream oopt, ohelp;
1874 oopt <<
"-dm_moose_includeAllContactNodes";
1875 ohelp <<
"Whether to include all nodes on the contact surfaces into the subsolver";
1877 ohelp.str().c_str(),
1881 LIBMESH_PETSC_NULLPTR));
1887 opt =
"-dm_moose_nuncontacts";
1889 "Number of contacts to exclude from DMMoose. For each <n> < " 1890 "dm_moose_contacts\n\t-dm_moose_contact_<n> is a comma-separated <primary>,<secondary> pair " 1891 "defining the contact surfaces" 1892 "\t-dm_moose_contact_<n>_displaced <bool> determines whether the contact is defined on " 1893 "the displaced mesh or not";
1896 "DMMooseSetUnContacts",
1899 LIBMESH_PETSC_NULLPTR));
1901 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
1903 "Number of requested uncontacts %" LIBMESH_PETSCINT_FMT
1904 " exceeds the maximum number of contacts %" LIBMESH_PETSCINT_FMT,
1910 char * primary_secondary[2];
1912 std::ostringstream oopt, ohelp;
1913 oopt <<
"-dm_moose_uncontact_" << i;
1914 ohelp <<
"Primary and secondary for uncontact " << i;
1916 ohelp.str().c_str(),
1917 "DMMooseSetUnContacts",
1920 LIBMESH_PETSC_NULLPTR));
1923 ((PetscObject)
dm)->comm,
1925 "Expected 2 sideset IDs (primary & secondary) for uncontact %" LIBMESH_PETSCINT_FMT
1926 ", got %" LIBMESH_PETSCINT_FMT
" instead",
1930 std::string(primary_secondary[1])));
1935 PetscBool displaced = PETSC_FALSE;
1936 std::ostringstream oopt, ohelp;
1937 oopt <<
"-dm_moose_uncontact_" << i <<
"_displaced";
1938 ohelp <<
"Whether uncontact " << i <<
" is determined using displaced mesh or not";
1940 ohelp.str().c_str(),
1941 "DMMooseSetUnContact",
1944 LIBMESH_PETSC_NULLPTR));
1954 const char *
fdhelp =
"Number of named fieldsplits defined by the DM.\n\ 1955 \tNames of fieldsplits are defined by -dm_moose_fieldsplit_names <splitname1> <splitname2> ...\n\ 1956 \tEach split can be configured with its own variables, blocks and sides, as any DMMoose";
1962 std::vector<std::string> split_names;
1966 "Names of fieldsplits defined by the DM",
1967 "DMMooseSetSplitNames",
1970 LIBMESH_PETSC_NULLPTR));
1973 for (PetscInt i = 0; i <
nsplits; ++i)
1975 std::ostringstream s;
1977 split_names.push_back(s.str());
1981 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
1983 "Expected %" LIBMESH_PETSCINT_FMT
1984 " fieldsplit names, got %" LIBMESH_PETSCINT_FMT
" instead",
1989 for (PetscInt i = 0; i <
nsplits; ++i)
1991 split_names.push_back(std::string(splitnames[i]));
1999 "Print IS embedding DM's dofs",
2003 LIBMESH_PETSC_NULLPTR));
2010 static PetscErrorCode
2046 for (
auto & sit : *(dmm->
_splits))
2065 const std::string & dm_name,
2085 PetscValidHeaderSpecific(
dm, DM_CLASSID, 1);
2086 #if PETSC_RELEASE_LESS_THAN(3, 18, 0) 2088 #else // PetscNewLog was deprecated 2093 dmm->
_name =
new (std::string);
2094 dmm->
_var_ids =
new (std::map<std::string, unsigned int>);
2095 dmm->
_block_ids =
new (std::map<std::string, subdomain_id_type>);
2096 dmm->
_var_names =
new (std::map<unsigned int, std::string>);
2097 dmm->
_block_names =
new (std::map<unsigned int, std::string>);
2098 dmm->
_side_ids =
new (std::map<std::string, BoundaryID>);
2099 dmm->
_side_names =
new (std::map<BoundaryID, std::string>);
2100 dmm->
_unside_ids =
new (std::map<std::string, BoundaryID>);
2101 dmm->
_unside_names =
new (std::map<BoundaryID, std::string>);
2103 dmm->
_contact_names =
new (std::map<DM_Moose::ContactID, DM_Moose::ContactName>);
2104 dmm->
_uncontact_names =
new (std::map<DM_Moose::ContactID, DM_Moose::ContactName>);
2108 dmm->
_splits =
new (std::map<std::string, DM_Moose::SplitInfo>);
2113 dm->ops->createlocalvector = 0;
2114 dm->ops->getcoloring = 0;
2116 dm->ops->createinterpolation = 0;
2118 dm->ops->refine = 0;
2119 dm->ops->coarsen = 0;
2120 #if PETSC_RELEASE_LESS_THAN(3, 12, 0) 2121 dm->ops->getinjection = 0;
2122 dm->ops->getaggregates = 0;
2124 dm->ops->createinjection = 0;
2139 #define __FUNCT__ "SNESUpdateDMMoose" 2153 const char * prefix;
2182 static PetscBool DMMooseRegisterAllCalled = PETSC_FALSE;
2185 if (!DMMooseRegisterAllCalled)
2188 DMMooseRegisterAllCalled = PETSC_TRUE;
PetscErrorCode DMMooseRegisterAll()
std::string name(const ElemQuality q)
static PetscErrorCode DMSetUp_Moose(DM dm)
std::set< ContactName > * _uncontacts
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
PetscErrorCode DMMooseGetBlocks(DM dm, std::vector< std::string > &block_names)
std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator * > _penetration_locators
PetscErrorCode DMMooseSetContacts(DM dm, const std::vector< std::pair< std::string, std::string >> &contacts, const std::vector< PetscBool > &displaced)
const DofMapBase * _dof_map
std::set< std::pair< BoundaryID, unsigned int > > * _unside_by_var_set
PetscErrorCode DMMooseSetVariables(DM dm, const std::set< std::string > &vars)
std::map< BoundaryID, std::string > * _side_names
std::shared_ptr< DisplacedProblem > displaced_problem
PetscErrorCode DMCreateMoose(MPI_Comm comm, NonlinearSystemBase &nl, const DofMapBase &dof_map, const System &system, const std::string &dm_name, DM *dm)
Create a MOOSE DM.
std::set< std::string > varset
std::set< std::string > sideset
PetscErrorCode DMMooseGetUnSides(DM dm, std::vector< std::string > &side_names)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Data structure used to hold penetration information.
virtual unsigned int n_variables() const=0
std::map< ContactName, PetscBool > * _contact_displaced
std::vector< DM_Moose::ContactName > uncontacts
PetscErrorCode DMMooseGetNonlinearSystem(DM dm, NonlinearSystemBase *&nl)
PetscBool is_include_all_nodes
PetscErrorCode DMMooseSetUnContacts(DM dm, const std::vector< std::pair< std::string, std::string >> &uncontacts, const std::vector< PetscBool > &displaced)
PetscErrorCode DMSetFromOptions_Moose(DM dm, PetscOptionItems) PetscErrorCode DMSetFromOptions_Moose(DM dm
std::map< std::string, BoundaryID > * _side_ids
bool _include_all_contact_nodes
std::string * _name
The name of this DM.
std::set< std::string > blockset
PetscErrorCode SNESUpdateDMMoose(SNES snes, PetscInt iteration)
static PetscErrorCode DMMooseGetMeshBlocks_Private(DM dm, std::set< subdomain_id_type > &blocks)
PetscErrorCode PetscOptionItems *PetscErrorCode DM dm
void checkSize(const std::string &split_name, const I1 split_size, const I2 size_expected_by_parent)
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const=0
std::map< ContactName, PetscBool > * _uncontact_displaced
const Parallel::Communicator & comm() const
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver()=0
std::vector< PetscBool > uncontact_displaced
PetscErrorCode DMMooseReset(DM dm)
PetscErrorCode DMMooseGetUnContacts(DM dm, std::vector< std::pair< std::string, std::string >> &uncontact_names, std::vector< PetscBool > &displaced)
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
PetscErrorCode DMMooseSetNonlinearSystem(DM dm, NonlinearSystemBase &nl)
const BoundaryInfo & get_boundary_info() const
const MeshBase & get_mesh() const
static PetscErrorCode DMSetUp_Moose_Pre(DM dm)
std::set< std::string > * _sides
virtual GeometricSearchData & geomSearchData() override
static PetscErrorCode DMVariableBounds_Moose(DM dm, Vec xl, Vec xu)
std::map< std::string, unsigned int > * _var_ids
virtual void swap(NumericVector< T > &v) override
std::map< unsigned int, std::string > * _var_names
EXTERN_C_BEGIN PetscErrorCode DMCreate_Moose(DM dm)
Nonlinear system to be solved.
static PetscErrorCode DMMooseJacobian(DM dm, Vec x, Mat jac, Mat pc)
PetscErrorCode DMMooseGetContacts(DM dm, std::vector< std::pair< std::string, std::string >> &contact_names, std::vector< PetscBool > &displaced)
void libmesh_ignore(const Args &...)
FEProblemBase & feProblem()
static PetscErrorCode SNESJacobian_DMMoose(SNES, Vec x, Mat jac, Mat pc, void *ctx)
unsigned int number() const
const Node & node_ref(const unsigned int i) const
static PetscErrorCode DMView_Moose(DM dm, PetscViewer viewer)
std::map< ContactID, ContactName > * _uncontact_names
boundary_id_type BoundaryID
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::set< ContactName > * _contacts
std::unique_ptr< NumericVector< Number > > solution
PetscErrorCode DMMooseGetSplitNames(DM dm, std::vector< std::string > &split_names)
PetscErrorCode DMMooseSetParentDM(DM dm, DM_Moose *parent)
std::set< std::string > * _unside_by_var
std::string & subdomain_name(subdomain_id_type id)
OStreamProxy err(std::cerr)
std::map< std::string, SplitInfo > * _splits
static PetscErrorCode DMCreateFieldDecomposition_Moose(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
virtual bool hasVariable(const std::string &var_name) const
Query a system for a variable.
std::pair< BoundaryID, BoundaryID > ContactID
std::set< std::string > * _unsides
std::set< std::string > * _vars
virtual MooseVariableScalar & getScalarVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a scalar variable with specified number.
static PetscErrorCode DMMooseGetEmbedding_Private(DM dm, IS *embedding)
LibmeshPetscCallQ(DMShellGetContext(dm, &ctx))
std::map< std::string, BoundaryID > * _unside_ids
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
PetscErrorCode DMMooseGetSides(DM dm, std::vector< std::string > &side_names)
PetscBool _print_embedding
subdomain_id_type subdomain_id() const
NonlinearSystemBase * _nl
PetscErrorCode DMMooseSetName(DM dm, const std::string &dm_name)
static PetscErrorCode SNESFunction_DMMoose(SNES, Vec x, Vec r, void *ctx)
PetscErrorCode DMMooseValidityCheck(DM dm)
const std::set< boundary_id_type > & get_global_boundary_ids() const
PetscErrorCode DMMooseSetSides(DM dm, const std::set< std::string > &sides)
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
dof_id_type n_local_dofs() const
std::unique_ptr< NumericVector< Number > > current_local_solution
std::map< std::string, subdomain_id_type > * _block_ids
IntRange< unsigned short > node_index_range() const
void checkChildSize(DM child, PetscInt child_size, const std::string &child_name)
Check whether the size of the child matches the size we expect.
PetscErrorCode DMMooseSetDofMap(DM dm, const DofMapBase &dof_map)
PetscErrorCode DMMooseSetUnSideByVar(DM dm, const std::set< std::string > &unside_by_var)
static PetscErrorCode DMMooseFunction(DM dm, Vec x, Vec r)
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
std::set< subdomain_id_type > meshblocks
const std::string & name() const
std::set< std::string > * _blocks
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
static PetscErrorCode DMCreateGlobalVector_Moose(DM dm, Vec *x)
PetscErrorCode DMMooseSetBlocks(DM dm, const std::set< std::string > &blocks)
std::map< ContactID, ContactName > * _contact_names
PetscErrorCode DMMooseSetSystem(DM dm, const System &system)
std::multimap< std::string, unsigned int > * _splitlocs
std::pair< std::string, std::string > ContactName
const DofMap & get_dof_map() const
static PetscErrorCode DMDestroy_Moose(DM dm)
static PetscErrorCode DMCreateDomainDecomposition_Moose(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
PetscErrorCode DMMooseSetSplitNames(DM dm, const std::vector< std::string > &split_names)
static PetscErrorCode DMCreateMatrix_Moose(DM dm, Mat *A)
for(PetscInt i=0;i< nvars;++i)
libMesh::StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > * getBoundaryNodeRange()
PetscOptionsBegin(((PetscObject) dm) ->comm,((PetscObject) dm) ->prefix, "DMMoose options", "DM")
PetscErrorCode DMMooseSetUnSides(DM dm, const std::set< std::string > &unsides)
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
PetscErrorCode DMMooseGetVariables(DM dm, std::vector< std::string > &var_names)
std::map< BoundaryID, std::string > * _unside_names
PenetrationLocator & getPenetrationLocator(const BoundaryName &primary, const BoundaryName &secondary, libMesh::Order order=libMesh::FIRST)
const std::map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
If not already created, creates a map from every node to all elements to which they are connected...
virtual void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn, int p_level=-12345) const=0
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
void set_union(T &data, const unsigned int root_id) const
std::map< unsigned int, std::string > * _block_names
virtual libMesh::System & system() override
Get the reference to the libMesh system.