www.mooseframework.org
EqualValueBoundaryConstraint.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 // MOOSE includes
12 #include "MooseMesh.h"
13 
14 #include "libmesh/mesh_inserter_iterator.h"
15 #include "libmesh/parallel.h"
16 #include "libmesh/parallel_elem.h"
17 #include "libmesh/parallel_node.h"
18 
19 // C++ includes
20 #include <limits.h>
21 
22 namespace // Anonymous namespace for helpers
23 {
34 struct CompareElemsByLevel
35 {
36  bool operator()(const Elem * a, const Elem * b) const
37  {
38  libmesh_assert(a);
39  libmesh_assert(b);
40  const unsigned int al = a->level(), bl = b->level();
41  const dof_id_type aid = a->id(), bid = b->id();
42 
43  return (al == bl) ? aid < bid : al < bl;
44  }
45 };
46 
47 } // anonymous namespace
48 
50 
51 template <>
54 {
56  params.addParam<unsigned int>(
57  "master",
58  std::numeric_limits<unsigned int>::max(),
59  "The ID of the master node. If no ID is provided, first node of slave set is chosen.");
60  params.addParam<std::vector<unsigned int>>("slave_node_ids", "The IDs of the slave node");
61  params.addParam<BoundaryName>("slave", "NaN", "The boundary ID associated with the slave side");
62  params.addRequiredParam<Real>("penalty", "The penalty used for the boundary term");
63  return params;
64 }
65 
67  : NodalConstraint(parameters),
68  _master_node_id(getParam<unsigned int>("master")),
69  _slave_node_ids(getParam<std::vector<unsigned int>>("slave_node_ids")),
70  _slave_node_set_id(getParam<BoundaryName>("slave")),
71  _penalty(getParam<Real>("penalty"))
72 {
74 }
75 
76 void
78 {
80 }
81 
82 void
84 {
85  _master_node_vector.clear();
86  _connected_nodes.clear();
87 
88  if ((_slave_node_ids.size() == 0) && (_slave_node_set_id == "NaN"))
89  mooseError("Please specify slave node ids or boundary id.");
90  else if ((_slave_node_ids.size() == 0) && (_slave_node_set_id != "NaN"))
91  {
92  std::vector<dof_id_type> nodelist = _mesh.getNodeList(_mesh.getBoundaryID(_slave_node_set_id));
93  std::vector<dof_id_type>::iterator in;
94 
95  // Set master node to first node of the slave node set if no master node id is provided
96  //_master_node_vector defines master nodes in the base class
97  if (_master_node_id == std::numeric_limits<unsigned int>::max())
98  {
99  in = std::min_element(nodelist.begin(), nodelist.end());
100  dof_id_type node_id = (in == nodelist.end()) ? DofObject::invalid_id : *in;
101  _communicator.min(node_id);
102  _master_node_vector.push_back(node_id);
103  }
104  else
106 
107  // Fill in _connected_nodes, which defines slave nodes in the base class
108  for (in = nodelist.begin(); in != nodelist.end(); ++in)
109  {
110  if ((*in != _master_node_vector[0]) &&
111  (_mesh.nodeRef(*in).processor_id() == _subproblem.processor_id()))
112  _connected_nodes.push_back(*in);
113  }
114  }
115  else if ((_slave_node_ids.size() != 0) && (_slave_node_set_id == "NaN"))
116  {
117  if (_master_node_id == std::numeric_limits<unsigned int>::max())
118  _master_node_vector.push_back(
119  _slave_node_ids[0]); //_master_node_vector defines master nodes in the base class
120 
121  // Fill in _connected_nodes, which defines slave nodes in the base class
122  for (const auto & dof : _slave_node_ids)
123  {
124  if (_mesh.queryNodePtr(dof) &&
125  (_mesh.nodeRef(dof).processor_id() == _subproblem.processor_id()) &&
126  (dof != _master_node_vector[0]))
127  _connected_nodes.push_back(dof);
128  }
129  }
130 
131  const auto & node_to_elem_map = _mesh.nodeToElemMap();
132  auto node_to_elem_pair = node_to_elem_map.find(_master_node_vector[0]);
133 
134  bool found_elems = (node_to_elem_pair != node_to_elem_map.end());
135 
136  // Add elements connected to master node to Ghosted Elements.
137 
138  // On a distributed mesh, these elements might have already been
139  // remoted, in which case we need to gather them back first.
140  if (!_mesh.getMesh().is_serial())
141  {
142 #ifndef NDEBUG
143  bool someone_found_elems = found_elems;
144  _mesh.getMesh().comm().max(someone_found_elems);
145  mooseAssert(someone_found_elems, "Missing entry in node to elem map");
146 #endif
147 
148  std::set<Elem *, CompareElemsByLevel> master_elems_to_ghost;
149  std::set<Node *> nodes_to_ghost;
150  if (found_elems)
151  {
152  for (dof_id_type id : node_to_elem_pair->second)
153  {
154  Elem * elem = _mesh.queryElemPtr(id);
155  if (elem)
156  {
157  master_elems_to_ghost.insert(elem);
158 
159  const unsigned int n_nodes = elem->n_nodes();
160  for (unsigned int n = 0; n != n_nodes; ++n)
161  nodes_to_ghost.insert(elem->node_ptr(n));
162  }
163  }
164  }
165 
166  // Send nodes first since elements need them
167  _mesh.getMesh().comm().allgather_packed_range(&_mesh.getMesh(),
168  nodes_to_ghost.begin(),
169  nodes_to_ghost.end(),
170  mesh_inserter_iterator<Node>(_mesh.getMesh()));
171 
172  _mesh.getMesh().comm().allgather_packed_range(&_mesh.getMesh(),
173  master_elems_to_ghost.begin(),
174  master_elems_to_ghost.end(),
175  mesh_inserter_iterator<Elem>(_mesh.getMesh()));
176 
177  _mesh.update(); // Rebuild node_to_elem_map
178 
179  // Find elems again now that we know they're there
180  const auto & new_node_to_elem_map = _mesh.nodeToElemMap();
181  node_to_elem_pair = new_node_to_elem_map.find(_master_node_vector[0]);
182  found_elems = (node_to_elem_pair != new_node_to_elem_map.end());
183  }
184 
185  if (!found_elems)
186  mooseError("Couldn't find any elements connected to master node");
187 
188  const std::vector<dof_id_type> & elems = node_to_elem_pair->second;
189 
190  if (elems.size() == 0)
191  mooseError("Couldn't find any elements connected to master node");
192  _subproblem.addGhostedElem(elems[0]);
193 }
194 
195 Real
197 {
198  switch (type)
199  {
200  case Moose::Slave:
201  return (_u_slave[_i] - _u_master[_j]) * _penalty;
202  case Moose::Master:
203  return (_u_master[_j] - _u_slave[_i]) * _penalty;
204  }
205  return 0.;
206 }
207 
208 Real
210 {
211  switch (type)
212  {
213  case Moose::SlaveSlave:
214  return _penalty;
215  case Moose::SlaveMaster:
216  return -_penalty;
217  case Moose::MasterMaster:
218  return _penalty;
219  case Moose::MasterSlave:
220  return -_penalty;
221  default:
222  mooseError("Unsupported type");
223  break;
224  }
225  return 0.;
226 }
SubProblem & _subproblem
SubProblem that contains tag info.
const VariableValue & _u_master
Holds the current solution at the current quadrature point.
void updateConstrainedNodes()
Update the sets of nodes with constrained DOFs.
ConstraintType
Definition: MooseTypes.h:523
InputParameters validParams< EqualValueBoundaryConstraint >()
unsigned int _j
virtual void meshChanged() override
Called on this object when the mesh changes.
virtual const Node * queryNodePtr(const dof_id_type i) const
Definition: MooseMesh.C:472
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void mooseError(Args &&... args) const
Definition: MooseObject.h:147
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:436
unsigned int _i
Counter for master and slave nodes.
const VariableValue & _u_slave
Value of the unknown variable this BC is action on.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
InputParameters validParams< NodalConstraint >()
virtual Elem * queryElemPtr(const dof_id_type i)
Definition: MooseMesh.C:2279
const std::string & type() const
Get the type of this object.
Definition: MooseObject.h:53
std::vector< unsigned int > _slave_node_ids
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
std::vector< dof_id_type > _connected_nodes
node IDs connected to the master node (slave nodes)
MooseMesh & _mesh
Definition: Constraint.h:73
const std::vector< dof_id_type > & getNodeList(boundary_id_type nodeset_id) const
Return a writable reference to a vector of node IDs that belong to nodeset_id.
Definition: MooseMesh.C:2594
void update()
Calls buildNodeListFromSideList(), buildNodeList(), and buildBndElemList().
Definition: MooseMesh.C:403
registerMooseObject("MooseApp", EqualValueBoundaryConstraint)
MatType type
std::vector< dof_id_type > _master_node_vector
node IDs of the master node
PetscInt n
EqualValueBoundaryConstraint(const InputParameters &parameters)
virtual void addGhostedElem(dof_id_type elem_id)=0
Will make sure that all dofs connected to elem_id are ghosted to this processor.
ConstraintJacobianType
Definition: MooseTypes.h:543
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
Computes the jacobian for the constraint.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
virtual Real computeQpResidual(Moose::ConstraintType type) override
Computes the residual for the current slave node.
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition: MooseMesh.C:1007
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...
Definition: MooseMesh.C:690