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"
35template <
typename I1,
typename I2>
37checkSize(
const std::string & split_name,
const I1 split_size,
const I2 size_expected_by_parent)
39 if (libMesh::cast_int<libMesh::numeric_index_type>(split_size) !=
40 libMesh::cast_int<libMesh::numeric_index_type>(size_expected_by_parent))
44 libMesh::cast_int<libMesh::numeric_index_type>(split_size),
45 " but the parent split expected size ",
46 libMesh::cast_int<libMesh::numeric_index_type>(size_expected_by_parent),
47 ". Make sure that you have non-overlapping complete sets for variables and "
48 "blocks as well as consistency in sides/unsides, contacts/uncontacts, etc.");
58 std::map<std::string, unsigned int> *
_var_ids;
77 typedef std::pair<BoundaryID, BoundaryID>
ContactID;
97 std::map<std::string, SplitInfo> *
_splits;
108 void checkChildSize(DM child, PetscInt child_size,
const std::string & child_name);
114 for (
const auto & split : *
_splits)
115 if (split.second._dm == child)
117 mooseAssert(split.first == child_name,
"These should match");
118 PetscInt parent_expected_size;
119 auto ierr = ISGetLocalSize(split.second._rembedding, &parent_expected_size);
122 checkSize(child_name, child_size, parent_expected_size);
135 PetscValidHeaderSpecific(
dm, DM_CLASSID, 1);
138 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
140 "Got DM of type %s, not of type %s",
141 ((PetscObject)
dm)->type_name,
148 std::vector<std::pair<std::string, std::string>> & contact_names,
149 std::vector<PetscBool> & displaced)
156 contact_names.push_back(it.second);
164 std::vector<std::pair<std::string, std::string>> & uncontact_names,
165 std::vector<PetscBool> & displaced)
172 uncontact_names.push_back(it.second);
184 for (
const auto & it : *(dmm->
_side_ids))
185 side_names.push_back(it.first);
196 side_names.push_back(it.first);
207 block_names.push_back(it.first);
217 for (
const auto & it : *(dmm->
_var_ids))
218 var_names.push_back(it.first);
228 SETERRQ(((PetscObject)
dm)->comm,
230 "Cannot reset the NonlinearSystem after DM has been set up.");
242 SETERRQ(((PetscObject)
dm)->comm,
244 "Cannot reset the degree of freedom map after DM has been set up.");
256 SETERRQ(((PetscObject)
dm)->comm,
258 "Cannot reset the degree of freedom map after DM has been set up.");
270 SETERRQ(((PetscObject)
dm)->comm,
272 "Cannot reset the MOOSE DM name after DM has been set up.");
274 *dmm->
_name = dm_name;
284 SETERRQ(((PetscObject)
dm)->comm,
286 "Cannot reset the parent DM after the child DM has been set up.");
304 std::set<std::string> processed_vars;
305 for (
const auto & var_name :
vars)
307 const auto *
const var =
309 ? cast_ptr<MooseVariableBase *>(&dmm->
_nl->
getVariable(0, var_name))
312 for (
const auto i : make_range(var->count()))
313 processed_vars.insert(var->arrayVariableComponent(i));
315 processed_vars.insert(var_name);
318 dmm->
_vars =
new std::set<std::string>(std::move(processed_vars));
363 dmm->
_unsides =
new std::set<std::string>(unsides);
384 const std::vector<std::pair<std::string, std::string>> &
contacts,
385 const std::vector<PetscBool> & displaced)
393 if (
contacts.size() != displaced.size())
394 LIBMESH_SETERRQ2(PETSC_COMM_SELF,
396 "Nonmatching sizes of the contact and displaced arrays: %" LIBMESH_PETSCINT_FMT
397 " != %" LIBMESH_PETSCINT_FMT,
398 static_cast<PetscInt
>(
contacts.size()),
399 static_cast<PetscInt
>(displaced.size()));
403 dmm->
_contacts =
new std::set<DM_Moose::ContactName>();
404 for (
unsigned int i = 0; i <
contacts.size(); ++i)
414 const std::vector<std::pair<std::string, std::string>> &
uncontacts,
415 const std::vector<PetscBool> & displaced)
427 "Nonmatching sizes of the uncontact and displaced arrays: %" LIBMESH_PETSCINT_FMT
428 " != %" LIBMESH_PETSCINT_FMT,
430 static_cast<PetscInt
>(displaced.size()));
434 dmm->
_uncontacts =
new std::set<DM_Moose::ContactName>();
435 for (
unsigned int i = 0; i <
uncontacts.size(); ++i)
462 for (
auto & it : *(dmm->
_splits))
468 dmm->
_splits = LIBMESH_PETSC_NULLPTR;
475 dmm->
_splits =
new std::map<std::string, DM_Moose::SplitInfo>();
476 dmm->
_splitlocs =
new std::multimap<std::string, unsigned int>();
477 for (
unsigned int i = 0; i < split_names.size(); ++i)
480 info._dm = LIBMESH_PETSC_NULLPTR;
481 info._rembedding = LIBMESH_PETSC_NULLPTR;
482 std::string name = split_names[i];
484 dmm->
_splitlocs->insert(std::make_pair(name, i));
495 if (!
dm->setupcalled)
502 std::string sname = lit.first;
503 unsigned int sloc = lit.second;
504 split_names[sloc] = sname;
547 std::vector<dof_id_type> node_indices;
548 auto process_nodal_dof_indices =
549 [&dofmap, &node_indices](
const Node & node,
550 const unsigned int var_num,
551 std::set<dof_id_type> & local_indices,
552 std::set<dof_id_type> *
const nonlocal_indices =
nullptr)
555 for (
const auto index : node_indices)
557 if (index >= dofmap.first_dof() && index < dofmap.end_dof())
558 local_indices.insert(index);
559 else if (nonlocal_indices)
560 nonlocal_indices->insert(index);
564 auto process_elem_dof_indices =
565 [&dofmap](
const std::vector<dof_id_type> & elem_indices,
566 std::set<dof_id_type> & local_indices,
567 std::set<dof_id_type> *
const nonlocal_indices =
nullptr)
569 for (
const auto index : elem_indices)
571 if (index >= dofmap.first_dof() && index < dofmap.end_dof())
572 local_indices.insert(index);
573 else if (nonlocal_indices)
574 nonlocal_indices->insert(index);
578 std::set<dof_id_type> indices;
579 std::set<dof_id_type> unindices;
580 std::set<dof_id_type> cached_indices;
581 std::set<dof_id_type> cached_unindices;
582 auto & lm_mesh = dmm->
_system->get_mesh();
584 for (
const auto & vit : *(dmm->
_var_ids))
586 unsigned int v = vit.second;
591 subdomain_id_type b = bit.second;
592 for (
const auto & elem : as_range(lm_mesh.active_local_subdomain_elements_begin(b),
593 lm_mesh.active_local_subdomain_elements_end(b)))
596 std::vector<dof_id_type> evindices;
597 dofmap.dof_indices(elem, evindices, v);
598 process_elem_dof_indices(evindices, indices);
603 bool is_on_current_block =
false;
604 for (
auto & node : lm_mesh.local_node_ptr_range())
606 const unsigned int n_comp = node->n_comp(dmm->
_system->number(), v);
612 auto node_to_elem_pair = node_to_elem_map.find(node->id());
613 is_on_current_block =
false;
614 for (
const auto & elem_num : node_to_elem_pair->second)
618 const Elem & neighbor_elem = lm_mesh.elem_ref(elem_num);
619 if (neighbor_elem.subdomain_id() == b)
621 is_on_current_block =
true;
626 if (!is_on_current_block)
629 process_nodal_dof_indices(*node, v, indices);
650 for (
const auto & bnode : bnodes)
656 const Node * node = bnode->_node;
657 process_nodal_dof_indices(*node, v, indices);
665 for (
const auto & bnode : bnodes)
670 const Node * node = bnode->_node;
671 process_nodal_dof_indices(*node, v, unindices);
676 std::set<BoundaryID> eligible_bids;
679 eligible_bids.insert(bid);
682 for (
const auto & bnode : bnodes)
685 if (eligible_bids.count(boundary_id))
687 const Node * node = bnode->_node;
688 process_nodal_dof_indices(*node, v, unindices);
693 auto process_contact_all_nodes =
694 [dmm, process_nodal_dof_indices, v](
const auto & contact_names,
695 auto & indices_to_insert_to)
697 std::set<boundary_id_type> bc_id_set;
699 for (
const auto & [contact_bid_pair, contact_bname_pair] : contact_names)
701 libmesh_ignore(contact_bname_pair);
702 bc_id_set.insert(contact_bid_pair.first);
703 bc_id_set.insert(contact_bid_pair.second);
707 for (
const auto & belem : range)
709 const Elem * elem_bdry = belem->_elem;
710 const auto side = belem->_side;
713 if (bc_id_set.find(boundary_id) == bc_id_set.end())
716 for (
const auto node_idx : elem_bdry->node_index_range())
717 if (elem_bdry->is_node_on_side(node_idx, side))
718 process_nodal_dof_indices(elem_bdry->node_ref(node_idx), v, indices_to_insert_to);
722 auto process_contact_some_nodes =
723 [dmm, process_nodal_dof_indices, v, &dofmap, &lm_mesh, process_elem_dof_indices](
724 const auto & contact_names,
725 auto & indices_to_insert_to,
726 auto & nonlocal_indices_to_insert_to)
728 std::vector<dof_id_type> evindices;
729 for (
const auto & it : contact_names)
739 std::ostringstream err;
740 err <<
"Cannot use a displaced uncontact (" << it.second.first <<
","
741 << it.second.second <<
") with an undisplaced problem";
754 const dof_id_type secondary_node_num = lit->first;
758 const Node & secondary_node = lm_mesh.node_ref(secondary_node_num);
759 process_nodal_dof_indices(
760 secondary_node, v, indices_to_insert_to, &nonlocal_indices_to_insert_to);
764 const Elem * primary_side = pinfo->
_side;
765 dofmap.dof_indices(primary_side, evindices, v);
766 process_elem_dof_indices(
767 evindices, indices_to_insert_to, &nonlocal_indices_to_insert_to);
779 process_contact_some_nodes(*dmm->
_contact_names, indices, cached_indices);
787 process_contact_some_nodes(*dmm->
_uncontact_names, unindices, cached_unindices);
790 std::vector<dof_id_type> local_vec_indices(cached_indices.size());
791 std::copy(cached_indices.begin(), cached_indices.end(), local_vec_indices.begin());
795 for (
const auto & dof : local_vec_indices)
796 if (dof >= dofmap.first_dof() && dof < dofmap.end_dof())
799 local_vec_indices.clear();
800 local_vec_indices.resize(cached_unindices.size());
801 std::copy(cached_unindices.begin(), cached_unindices.end(), local_vec_indices.begin());
805 for (
const auto & dof : local_vec_indices)
806 if (dof >= dofmap.first_dof() && dof < dofmap.end_dof())
807 unindices.insert(dof);
809 std::set<dof_id_type> dindices;
810 std::set_difference(indices.begin(),
814 std::inserter(dindices, dindices.end()));
818 for (
const auto & dof : dindices)
824 ((PetscObject)
dm)->comm, dindices.size(), darray, PETSC_OWN_POINTER, &dmm->
_embedding));
837 ISCreateStride(((PetscObject)
dm)->comm, (high - low), low, 1, &dmm->
_embedding));
848 DM
dm, PetscInt * len,
char *** namelist, IS ** islist, DM ** dmlist)
854 PetscInt split_size_sum = 0;
868 unsigned int d = dit.second;
869 std::string dname = dit.first;
876 PetscObjectSetOptionsPrefix((PetscObject)dinfo.
_dm, ((PetscObject)
dm)->prefix));
877 std::string suffix = std::string(
"fieldsplit_") + dname +
"_";
889 IS dembedding, lembedding;
895 const PetscInt * lindices;
896 PetscInt len, dlen, llen, *rindices, off, i;
901 ((PetscObject)
dm)->comm, PETSC_ERR_PLIB,
"Failed to embed split %u", d);
915#ifdef PETSC_USE_64BIT_INDICES
921 ((PetscObject)
dm)->comm);
924 for (i = 0; i < llen; ++i)
927 ((PetscObject)
dm)->comm, llen, rindices, PETSC_OWN_POINTER, &(dinfo.
_rembedding)));
938 split_size_sum += is_size;
943 (*dmlist)[d] = dinfo.
_dm;
947 mooseAssert(islist,
"What does it even mean if this is NULL?");
959 DM
dm, PetscInt * len,
char *** namelist, IS ** innerislist, IS ** outerislist, DM ** dmlist)
965 *outerislist = LIBMESH_PETSC_NULLPTR;
979 PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(nl->
system().
solution.get());
980 PetscVector<Number> X_global(x, nl->
comm()), R(r, nl->
comm());
986 X_global.swap(X_sys);
988 X_global.swap(X_sys);
1004 std::ostringstream err;
1005 err <<
"ERROR: cannot specifiy both a function and object to compute the Residual!"
1011 std::ostringstream err;
1012 err <<
"ERROR: cannot specifiy both a function and object to compute the combined Residual & "
1027 nl->
nonlinearSolver()->residual_and_jacobian_object->residual_and_jacobian(
1031 std::ostringstream err;
1032 err <<
"No suitable residual computation routine found";
1039static PetscErrorCode
1049static PetscErrorCode
1057 PetscMatrix<Number> the_pc(pc, nl->
comm());
1058 PetscMatrix<Number> Jac(jac, nl->
comm());
1059 PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(nl->
system().
solution.get());
1060 PetscVector<Number> X_global(x, nl->
comm());
1070 X_global.swap(X_sys);
1072 X_global.swap(X_sys);
1088 std::ostringstream err;
1089 err <<
"ERROR: cannot specifiy both a function and object to compute the Jacobian!"
1095 std::ostringstream err;
1096 err <<
"ERROR: cannot specifiy both a function and object to compute the combined Residual & "
1113 nl->
nonlinearSolver()->residual_and_jacobian_object->residual_and_jacobian(
1120 std::ostringstream err;
1121 err <<
"No suitable Jacobian routine or object";
1129static PetscErrorCode
1139static PetscErrorCode
1147 PetscVector<Number> XL(xl, nl->
comm());
1148 PetscVector<Number> XU(xu, nl->
comm());
1158 ((PetscObject)
dm)->comm, PETSC_ERR_ARG_WRONG,
"No bounds calculation in this Moose object");
1162static PetscErrorCode
1172 NumericVector<Number> * nv = (dmm->
_system->solution).get();
1173 PetscVector<Number> * pv =
dynamic_cast<PetscVector<Number> *
>(nv);
1191#if PETSC_RELEASE_LESS_THAN(3, 13, 0)
1199static PetscErrorCode
1218 const auto & dof_map = *dmm->
_dof_map;
1219 PetscInt M, N, m, n;
1221 M = dof_map.n_dofs();
1223 m =
static_cast<PetscInt
>(dof_map.n_local_dofs());
1235static PetscErrorCode
1239 const char *name, *prefix;
1243 LibmeshPetscCallQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1249 PetscViewerASCIIPrintf(viewer,
"DM Moose with name %s and prefix %s\n", name, prefix));
1251 for (
const auto & vit : *(dmm->
_var_ids))
1253 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"(%s,%u) ", vit.first.c_str(), vit.second));
1259 LibmeshPetscCallQ(PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", bit.first.c_str(), bit.second));
1266 for (
const auto & sit : *(dmm->
_side_ids))
1269 PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", sit.first.c_str(), sit.second));
1280 PetscViewerASCIIPrintf(viewer,
"(%s,%d) ", sit.first.c_str(), sit.second));
1291 viewer,
"(%s,%s,", cit.second.first.c_str(), cit.second.second.c_str()));
1306 viewer,
"(%s,%s,", cit.second.first.c_str(), cit.second.second.c_str()));
1321 std::string dname = dit.first;
1328 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"Non-ASCII viewers are not supported");
1333static PetscErrorCode
1346 libmesh_parallel_only(
mesh.comm());
1347 for (
const auto & elem :
mesh.active_element_ptr_range())
1348 blocks.insert(elem->subdomain_id());
1354static PetscErrorCode
1365 const auto & dofmap = *dmm->
_dof_map;
1376 for (
const auto & name : *(dmm->
_sides))
1379 dmm->
_side_names->insert(std::make_pair(
id, name));
1380 dmm->
_side_ids->insert(std::make_pair(name,
id));
1383 dmm->
_sides = LIBMESH_PETSC_NULLPTR;
1393 for (
const auto & name : *(dmm->
_unsides))
1397 dmm->
_unside_ids->insert(std::make_pair(name,
id));
1400 dmm->
_unsides = LIBMESH_PETSC_NULLPTR;
1411 const auto colon_pos = name.find(
":");
1412 auto unside_name = name.substr(0, colon_pos);
1413 auto var_name = name.substr(colon_pos + 1);
1415 bool var_found =
false;
1416 for (
unsigned int v = 0; v < dofmap.n_variables(); ++v)
1418 const auto & vname = dofmap.variable(v).name();
1419 if (vname == var_name)
1427 mooseError(
"No variable named '", var_name,
"' found");
1438 for (
const auto & cpair : *(dmm->
_contacts))
1444 cpair.first, cpair.second);
1450 std::ostringstream err;
1451 err <<
"Problem retrieving contact for PenetrationLocator with primary " << cpair.first
1452 <<
" and secondary " << cpair.second;
1472 cpair.first, cpair.second);
1478 std::ostringstream err;
1479 err <<
"Problem retrieving uncontact for PenetrationLocator with primary " << cpair.first
1480 <<
" and secondary " << cpair.second;
1497 for (
unsigned int v = 0; v < dofmap.n_variables(); ++v)
1499 std::string vname = dofmap.variable(v).name();
1502 dmm->
_var_ids->insert(std::pair<std::string, unsigned int>(vname, v));
1503 dmm->
_var_names->insert(std::pair<unsigned int, std::string>(v, vname));
1505 if (dmm->
_var_ids->size() == dofmap.n_variables())
1512 dmm->
_vars = LIBMESH_PETSC_NULLPTR;
1517 std::set<subdomain_id_type>
blocks;
1520 SETERRQ(((PetscObject)
dm)->comm, PETSC_ERR_PLIB,
"No mesh blocks found.");
1522 for (
const auto & bid :
blocks)
1524 std::string bname =
mesh.subdomain_name(bid);
1525 if (!bname.length())
1530 std::ostringstream ss;
1554 && dmm->
_blocks->find(std::to_string(bid)) == dmm->
_blocks->end()))
1557 dmm->
_block_ids->insert(std::make_pair(bname, bid));
1568 dmm->
_blocks = LIBMESH_PETSC_NULLPTR;
1571 std::string name = dmm->
_system->name();
1574 name +=
"_" + vit.second;
1579 name +=
"_" + bit.second;
1585 name +=
"_" + sit.second;
1591 name +=
"_" + sit.second;
1595 name +=
"_contacts";
1597 name +=
"_primary_" + cit.second.first +
"_secondary_" + cit.second.second;
1601 name +=
"_uncontacts";
1603 name +=
"_primary_" + cit.second.first +
"_secondary_" + cit.second.second;
1622 for (
auto & it : *(dmm->
_splits))
1629 dm->setupcalled = PETSC_FALSE;
1633static PetscErrorCode
1644 const char *name, *prefix;
1650 "DM Moose with name %s and prefix %s\n",
1656 "\thas a trivial embedding\n"));
1661 "\thas embedding defined by IS:\n"));
1680#if !PETSC_VERSION_LESS_THAN(3, 23, 0)
1683#elif !PETSC_VERSION_LESS_THAN(3, 18, 0)
1686#elif !PETSC_VERSION_LESS_THAN(3, 7, 0)
1703#if !PETSC_VERSION_LESS_THAN(3, 18, 0)
1707 ((PetscObject)
dm)->comm, ((PetscObject)
dm)->prefix,
"DMMoose options",
"DM"));
1715 opt =
"-dm_moose_vars";
1716 help =
"Variables in DMMoose";
1718 opt.c_str(),
help.c_str(),
"DMMooseSetVars",
vars, &
nvars, LIBMESH_PETSC_NULLPTR));
1735 opt =
"-dm_moose_blocks";
1736 help =
"Blocks in DMMoose";
1739 for (PetscInt i = 0; i <
nblocks; ++i)
1747 PetscInt
maxsides = dmm->
_system->get_mesh().get_boundary_info().get_global_boundary_ids().size();
1754 opt =
"-dm_moose_sides";
1755 help =
"Sides to include in DMMoose";
1757 opt.c_str(),
help.c_str(),
"DMMooseSetSides",
sides, &
nsides, LIBMESH_PETSC_NULLPTR));
1758 for (PetscInt i = 0; i <
nsides; ++i)
1767 opt =
"-dm_moose_unsides";
1768 help =
"Sides to exclude from DMMoose";
1771 opt.c_str(),
help.c_str(),
"DMMooseSetUnSides",
sides, &
nsides, LIBMESH_PETSC_NULLPTR));
1773 for (PetscInt i = 0; i <
nsides; ++i)
1782 opt =
"-dm_moose_unside_by_var";
1783 help =
"Sides to exclude from DMMoose on a by-var basis";
1786 opt.c_str(),
help.c_str(),
"DMMooseSetUnSideByVar",
sides, &
nsides, LIBMESH_PETSC_NULLPTR));
1788 for (PetscInt i = 0; i <
nsides; ++i)
1803 std::vector<DM_Moose::ContactName>
contacts;
1805 PetscInt ncontacts = 0;
1806 opt =
"-dm_moose_ncontacts";
1808 "Number of contacts to include in DMMoose. For each <n> < "
1809 "dm_moose_contacts\n\t-dm_moose_contact_<n> is a comma-separated <primary>,<secondary> pair "
1810 "defining the contact surfaces"
1811 "\t-dm_moose_contact_<n>_displaced <bool> determines whether the contact is defined on "
1812 "the displaced mesh or not";
1815 "DMMooseSetContacts",
1818 LIBMESH_PETSC_NULLPTR));
1820 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
1822 "Number of requested contacts %" LIBMESH_PETSCINT_FMT
1823 " exceeds the maximum number of contacts %" LIBMESH_PETSCINT_FMT,
1826 for (PetscInt i = 0; i < ncontacts; ++i)
1829 char * primary_secondary[2];
1831 std::ostringstream oopt, ohelp;
1832 oopt <<
"-dm_moose_contact_" << i;
1833 ohelp <<
"Primary and secondary for contact " << i;
1835 ohelp.str().c_str(),
1836 "DMMooseSetContacts",
1839 LIBMESH_PETSC_NULLPTR));
1842 ((PetscObject)
dm)->comm,
1844 "Expected 2 sideset IDs (primary & secondary) for contact %" LIBMESH_PETSCINT_FMT
1845 ", got %" LIBMESH_PETSCINT_FMT
" instead",
1849 std::string(primary_secondary[1])));
1854 PetscBool displaced = PETSC_FALSE;
1855 std::ostringstream oopt, ohelp;
1856 oopt <<
"-dm_moose_contact_" << i <<
"_displaced";
1857 ohelp <<
"Whether contact " << i <<
" is determined using displaced mesh or not";
1859 ohelp.str().c_str(),
1860 "DMMooseSetContacts",
1863 LIBMESH_PETSC_NULLPTR));
1870 std::ostringstream oopt, ohelp;
1872 oopt <<
"-dm_moose_includeAllContactNodes";
1873 ohelp <<
"Whether to include all nodes on the contact surfaces into the subsolver";
1875 ohelp.str().c_str(),
1879 LIBMESH_PETSC_NULLPTR));
1885 opt =
"-dm_moose_nuncontacts";
1887 "Number of contacts to exclude from DMMoose. For each <n> < "
1888 "dm_moose_contacts\n\t-dm_moose_contact_<n> is a comma-separated <primary>,<secondary> pair "
1889 "defining the contact surfaces"
1890 "\t-dm_moose_contact_<n>_displaced <bool> determines whether the contact is defined on "
1891 "the displaced mesh or not";
1894 "DMMooseSetUnContacts",
1897 LIBMESH_PETSC_NULLPTR));
1899 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
1901 "Number of requested uncontacts %" LIBMESH_PETSCINT_FMT
1902 " exceeds the maximum number of contacts %" LIBMESH_PETSCINT_FMT,
1908 char * primary_secondary[2];
1910 std::ostringstream oopt, ohelp;
1911 oopt <<
"-dm_moose_uncontact_" << i;
1912 ohelp <<
"Primary and secondary for uncontact " << i;
1914 ohelp.str().c_str(),
1915 "DMMooseSetUnContacts",
1918 LIBMESH_PETSC_NULLPTR));
1921 ((PetscObject)
dm)->comm,
1923 "Expected 2 sideset IDs (primary & secondary) for uncontact %" LIBMESH_PETSCINT_FMT
1924 ", got %" LIBMESH_PETSCINT_FMT
" instead",
1928 std::string(primary_secondary[1])));
1933 PetscBool displaced = PETSC_FALSE;
1934 std::ostringstream oopt, ohelp;
1935 oopt <<
"-dm_moose_uncontact_" << i <<
"_displaced";
1936 ohelp <<
"Whether uncontact " << i <<
" is determined using displaced mesh or not";
1938 ohelp.str().c_str(),
1939 "DMMooseSetUnContact",
1942 LIBMESH_PETSC_NULLPTR));
1952 const char *
fdhelp =
"Number of named fieldsplits defined by the DM.\n\
1953 \tNames of fieldsplits are defined by -dm_moose_fieldsplit_names <splitname1> <splitname2> ...\n\
1954 \tEach split can be configured with its own variables, blocks and sides, as any DMMoose";
1960 std::vector<std::string> split_names;
1964 "Names of fieldsplits defined by the DM",
1965 "DMMooseSetSplitNames",
1968 LIBMESH_PETSC_NULLPTR));
1971 for (PetscInt i = 0; i <
nsplits; ++i)
1973 std::ostringstream s;
1975 split_names.push_back(s.str());
1979 LIBMESH_SETERRQ2(((PetscObject)
dm)->comm,
1981 "Expected %" LIBMESH_PETSCINT_FMT
1982 " fieldsplit names, got %" LIBMESH_PETSCINT_FMT
" instead",
1987 for (PetscInt i = 0; i <
nsplits; ++i)
1989 split_names.push_back(std::string(splitnames[i]));
1997 "Print IS embedding DM's dofs",
2001 LIBMESH_PETSC_NULLPTR));
2008static PetscErrorCode
2044 for (
auto & sit : *(dmm->
_splits))
2062 const System & system,
2063 const std::string & dm_name,
2083 PetscValidHeaderSpecific(
dm, DM_CLASSID, 1);
2084#if PETSC_RELEASE_LESS_THAN(3, 18, 0)
2091 dmm->
_name =
new (std::string);
2092 dmm->
_var_ids =
new (std::map<std::string, unsigned int>);
2093 dmm->
_block_ids =
new (std::map<std::string, subdomain_id_type>);
2094 dmm->
_var_names =
new (std::map<unsigned int, std::string>);
2095 dmm->
_block_names =
new (std::map<unsigned int, std::string>);
2096 dmm->
_side_ids =
new (std::map<std::string, BoundaryID>);
2097 dmm->
_side_names =
new (std::map<BoundaryID, std::string>);
2098 dmm->
_unside_ids =
new (std::map<std::string, BoundaryID>);
2099 dmm->
_unside_names =
new (std::map<BoundaryID, std::string>);
2101 dmm->
_contact_names =
new (std::map<DM_Moose::ContactID, DM_Moose::ContactName>);
2102 dmm->
_uncontact_names =
new (std::map<DM_Moose::ContactID, DM_Moose::ContactName>);
2106 dmm->
_splits =
new (std::map<std::string, DM_Moose::SplitInfo>);
2111 dm->ops->createlocalvector = 0;
2112 dm->ops->getcoloring = 0;
2114 dm->ops->createinterpolation = 0;
2116 dm->ops->refine = 0;
2117 dm->ops->coarsen = 0;
2118#if PETSC_RELEASE_LESS_THAN(3, 12, 0)
2119 dm->ops->getinjection = 0;
2120 dm->ops->getaggregates = 0;
2122 dm->ops->createinjection = 0;
2137#define __FUNCT__ "SNESUpdateDMMoose"
2151 const char * prefix;
2180 static PetscBool DMMooseRegisterAllCalled = PETSC_FALSE;
2183 if (!DMMooseRegisterAllCalled)
2186 DMMooseRegisterAllCalled = PETSC_TRUE;
boundary_id_type BoundaryID
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
PetscErrorCode PetscOptionItems *PetscErrorCode DM dm
PetscErrorCode DMMooseSetSystem(DM dm, const System &system)
static PetscErrorCode DMCreateGlobalVector_Moose(DM dm, Vec *x)
std::set< std::string > blockset
PetscErrorCode DMMooseSetParentDM(DM dm, DM_Moose *parent)
PetscErrorCode DMMooseGetBlocks(DM dm, std::vector< std::string > &block_names)
void checkSize(const std::string &split_name, const I1 split_size, const I2 size_expected_by_parent)
PetscOptionsBegin(((PetscObject) dm) ->comm,((PetscObject) dm) ->prefix, "DMMoose options", "DM")
std::shared_ptr< DisplacedProblem > displaced_problem
PetscBool is_include_all_nodes
static PetscErrorCode DMMooseFunction(DM dm, Vec x, Vec r)
static PetscErrorCode DMCreateDomainDecomposition_Moose(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
std::vector< PetscBool > uncontact_displaced
PetscErrorCode SNESUpdateDMMoose(SNES snes, PetscInt iteration)
static PetscErrorCode DMView_Moose(DM dm, PetscViewer viewer)
static PetscErrorCode DMVariableBounds_Moose(DM dm, Vec xl, Vec xu)
static PetscErrorCode SNESJacobian_DMMoose(SNES, Vec x, Mat jac, Mat pc, void *ctx)
LibmeshPetscCallQ(DMMooseValidityCheck(dm))
static PetscErrorCode DMMooseGetEmbedding_Private(DM dm, IS *embedding)
PetscErrorCode DMMooseSetUnContacts(DM dm, const std::vector< std::pair< std::string, std::string > > &uncontacts, const std::vector< PetscBool > &displaced)
std::vector< DM_Moose::ContactName > uncontacts
static PetscErrorCode DMSetUp_Moose_Pre(DM dm)
PetscErrorCode DMMooseRegisterAll()
static PetscErrorCode SNESFunction_DMMoose(SNES, Vec x, Vec r, void *ctx)
PetscFunctionReturn(PETSC_SUCCESS)
static PetscErrorCode DMDestroy_Moose(DM dm)
std::set< std::string > varset
PetscErrorCode DMMooseSetSplitNames(DM dm, const std::vector< std::string > &split_names)
PetscErrorCode DMMooseGetUnSides(DM dm, std::vector< std::string > &side_names)
PetscErrorCode DMMooseSetDofMap(DM dm, const libMesh::DofMapBase &dof_map)
PetscErrorCode DMMooseSetBlocks(DM dm, const std::set< std::string > &blocks)
PetscErrorCode DMCreateMoose(MPI_Comm comm, NonlinearSystemBase &nl, const libMesh::DofMapBase &dof_map, const System &system, const std::string &dm_name, DM *dm)
PetscErrorCode DMMooseReset(DM dm)
static PetscErrorCode DMSetUp_Moose(DM dm)
std::set< subdomain_id_type > meshblocks
std::set< std::string > sideset
PetscErrorCode DMMooseSetUnSides(DM dm, const std::set< std::string > &unsides)
static PetscErrorCode DMCreateMatrix_Moose(DM dm, Mat *A)
PetscErrorCode DMMooseGetSplitNames(DM dm, std::vector< std::string > &split_names)
PetscErrorCode DMMooseSetSides(DM dm, const std::set< std::string > &sides)
PetscErrorCode DMMooseGetVariables(DM dm, std::vector< std::string > &var_names)
PetscErrorCode DMMooseSetName(DM dm, const std::string &dm_name)
static PetscErrorCode DMCreateFieldDecomposition_Moose(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
PetscErrorCode DMMooseSetContacts(DM dm, const std::vector< std::pair< std::string, std::string > > &contacts, const std::vector< PetscBool > &displaced)
PetscErrorCode DMMooseGetSides(DM dm, std::vector< std::string > &side_names)
static PetscErrorCode DMMooseGetMeshBlocks_Private(DM dm, std::set< subdomain_id_type > &blocks)
static PetscErrorCode DMMooseJacobian(DM dm, Vec x, Mat jac, Mat pc)
PetscErrorCode DMSetFromOptions_Moose(DM dm, PetscOptionItems) PetscErrorCode DMSetFromOptions_Moose(DM dm
PetscErrorCode DMMooseGetUnContacts(DM dm, std::vector< std::pair< std::string, std::string > > &uncontact_names, std::vector< PetscBool > &displaced)
PetscErrorCode DMMooseValidityCheck(DM dm)
PetscErrorCode DMMooseSetVariables(DM dm, const std::set< std::string > &vars)
PetscErrorCode DMMooseGetNonlinearSystem(DM dm, NonlinearSystemBase *&nl)
EXTERN_C_BEGIN PetscErrorCode DMCreate_Moose(DM dm)
PetscErrorCode DMMooseGetContacts(DM dm, std::vector< std::pair< std::string, std::string > > &contact_names, std::vector< PetscBool > &displaced)
PetscErrorCode DMMooseSetNonlinearSystem(DM dm, NonlinearSystemBase &nl)
PetscErrorCode DMMooseSetUnSideByVar(DM dm, const std::set< std::string > &unside_by_var)
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual GeometricSearchData & geomSearchData() override
virtual MooseMesh & mesh() override
std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator * > _penetration_locators
PenetrationLocator & getPenetrationLocator(const BoundaryName &primary, const BoundaryName &secondary, libMesh::Order order=libMesh::FIRST)
const std::unordered_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.
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
libMesh::StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > * getBoundaryNodeRange()
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
Nonlinear system to be solved.
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver()=0
virtual libMesh::System & system() override
Get the reference to the libMesh system.
Data structure used to hold penetration information.
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
Data structure of nodes and their associated penetration information.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
virtual MooseVariableScalar & getScalarVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a scalar variable with specified number.
virtual bool hasVariable(const std::string &var_name) const
Query a system for a variable.
FEProblemBase & feProblem()
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
virtual void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn, int p_level=-12345) const=0
virtual unsigned int n_variables() const=0
dof_id_type n_local_dofs() const
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
const Parallel::Communicator & comm() const
std::unique_ptr< NumericVector< Number > > current_local_solution
std::unique_ptr< NumericVector< Number > > solution
const DofMap & get_dof_map() const
const libMesh::DofMapBase * _dof_map
std::string * _name
The name of this DM.
std::set< ContactName > * _contacts
std::multimap< std::string, unsigned int > * _splitlocs
std::set< std::string > * _sides
std::map< BoundaryID, std::string > * _side_names
std::map< std::string, BoundaryID > * _side_ids
std::map< std::string, BoundaryID > * _unside_ids
std::map< unsigned int, std::string > * _var_names
std::set< std::string > * _unsides
std::map< BoundaryID, std::string > * _unside_names
PetscBool _print_embedding
std::map< ContactID, ContactName > * _uncontact_names
bool _include_all_contact_nodes
std::set< std::pair< BoundaryID, unsigned int > > * _unside_by_var_set
std::map< std::string, SplitInfo > * _splits
NonlinearSystemBase * _nl
void checkChildSize(DM child, PetscInt child_size, const std::string &child_name)
Check whether the size of the child matches the size we expect.
std::set< std::string > * _blocks
std::set< ContactName > * _uncontacts
std::pair< BoundaryID, BoundaryID > ContactID
std::map< std::string, subdomain_id_type > * _block_ids
std::map< unsigned int, std::string > * _block_names
std::set< std::string > * _vars
std::pair< std::string, std::string > ContactName
std::set< std::string > * _unside_by_var
std::map< ContactName, PetscBool > * _uncontact_displaced
std::map< std::string, unsigned int > * _var_ids
std::map< ContactName, PetscBool > * _contact_displaced
std::map< ContactID, ContactName > * _contact_names