www.mooseframework.org
EqualValueBoundaryConstraint.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* DO NOT MODIFY THIS HEADER */
3 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
4 /* */
5 /* (c) 2010 Battelle Energy Alliance, LLC */
6 /* ALL RIGHTS RESERVED */
7 /* */
8 /* Prepared by Battelle Energy Alliance, LLC */
9 /* Under Contract No. DE-AC07-05ID14517 */
10 /* With the U. S. Department of Energy */
11 /* */
12 /* See COPYRIGHT for full restrictions */
13 /****************************************************************/
14 
15 // MOOSE includes
17 #include "MooseMesh.h"
18 
19 #include "libmesh/mesh_inserter_iterator.h"
20 #include "libmesh/parallel.h"
21 #include "libmesh/parallel_elem.h"
22 #include "libmesh/parallel_node.h"
23 
24 // C++ includes
25 #include <limits.h>
26 
27 namespace // Anonymous namespace for helpers
28 {
39 struct CompareElemsByLevel
40 {
41  bool operator()(const Elem * a, const Elem * b) const
42  {
43  libmesh_assert(a);
44  libmesh_assert(b);
45  const unsigned int al = a->level(), bl = b->level();
46  const dof_id_type aid = a->id(), bid = b->id();
47 
48  return (al == bl) ? aid < bid : al < bl;
49  }
50 };
51 
52 } // anonymous namespace
53 
54 template <>
57 {
59  params.addParam<unsigned int>(
60  "master",
61  std::numeric_limits<unsigned int>::max(),
62  "The ID of the master node. If no ID is provided, first node of slave set is chosen.");
63  params.addParam<std::vector<unsigned int>>("slave_node_ids", "The IDs of the slave node");
64  params.addParam<BoundaryName>("slave", "NaN", "The boundary ID associated with the slave side");
65  params.addRequiredParam<Real>("penalty", "The penalty used for the boundary term");
66  return params;
67 }
68 
70  : NodalConstraint(parameters),
71  _master_node_id(getParam<unsigned int>("master")),
72  _slave_node_ids(getParam<std::vector<unsigned int>>("slave_node_ids")),
73  _slave_node_set_id(getParam<BoundaryName>("slave")),
74  _penalty(getParam<Real>("penalty"))
75 {
77 }
78 
79 void
81 {
83 }
84 
85 void
87 {
88  _master_node_vector.clear();
89  _connected_nodes.clear();
90 
91  if ((_slave_node_ids.size() == 0) && (_slave_node_set_id == "NaN"))
92  mooseError("Please specify slave node ids or boundary id.");
93  else if ((_slave_node_ids.size() == 0) && (_slave_node_set_id != "NaN"))
94  {
95  std::vector<dof_id_type> nodelist = _mesh.getNodeList(_mesh.getBoundaryID(_slave_node_set_id));
96  std::vector<dof_id_type>::iterator in;
97 
98  // Set master node to first node of the slave node set if no master node id is provided
99  //_master_node_vector defines master nodes in the base class
100  if (_master_node_id == std::numeric_limits<unsigned int>::max())
101  {
102  in = std::min_element(nodelist.begin(), nodelist.end());
103  dof_id_type node_id = (in == nodelist.end()) ? DofObject::invalid_id : *in;
104  _communicator.min(node_id);
105  _master_node_vector.push_back(node_id);
106  }
107  else
109 
110  // Fill in _connected_nodes, which defines slave nodes in the base class
111  for (in = nodelist.begin(); in != nodelist.end(); ++in)
112  {
113  if ((*in != _master_node_vector[0]) &&
114  (_mesh.nodeRef(*in).processor_id() == _subproblem.processor_id()))
115  _connected_nodes.push_back(*in);
116  }
117  }
118  else if ((_slave_node_ids.size() != 0) && (_slave_node_set_id == "NaN"))
119  {
120  if (_master_node_id == std::numeric_limits<unsigned int>::max())
121  _master_node_vector.push_back(
122  _slave_node_ids[0]); //_master_node_vector defines master nodes in the base class
123 
124  // Fill in _connected_nodes, which defines slave nodes in the base class
125  for (const auto & dof : _slave_node_ids)
126  {
127  if (_mesh.queryNodePtr(dof) &&
128  (_mesh.nodeRef(dof).processor_id() == _subproblem.processor_id()) &&
129  (dof != _master_node_vector[0]))
130  _connected_nodes.push_back(dof);
131  }
132  }
133 
134  const auto & node_to_elem_map = _mesh.nodeToElemMap();
135  auto node_to_elem_pair = node_to_elem_map.find(_master_node_vector[0]);
136 
137  bool found_elems = (node_to_elem_pair != node_to_elem_map.end());
138 
139  // Add elements connected to master node to Ghosted Elements.
140 
141  // On a distributed mesh, these elements might have already been
142  // remoted, in which case we need to gather them back first.
143  if (!_mesh.getMesh().is_serial())
144  {
145 #ifndef NDEBUG
146  bool someone_found_elems = found_elems;
147  _mesh.getMesh().comm().max(someone_found_elems);
148  mooseAssert(someone_found_elems, "Missing entry in node to elem map");
149 #endif
150 
151  std::set<Elem *, CompareElemsByLevel> master_elems_to_ghost;
152  std::set<Node *> nodes_to_ghost;
153  if (found_elems)
154  {
155  for (dof_id_type id : node_to_elem_pair->second)
156  {
157  Elem * elem = _mesh.queryElemPtr(id);
158  if (elem)
159  {
160  master_elems_to_ghost.insert(elem);
161 
162  const unsigned int n_nodes = elem->n_nodes();
163  for (unsigned int n = 0; n != n_nodes; ++n)
164  nodes_to_ghost.insert(elem->node_ptr(n));
165  }
166  }
167  }
168 
169  // Send nodes first since elements need them
170  _mesh.getMesh().comm().allgather_packed_range(&_mesh.getMesh(),
171  nodes_to_ghost.begin(),
172  nodes_to_ghost.end(),
173  mesh_inserter_iterator<Node>(_mesh.getMesh()));
174 
175  _mesh.getMesh().comm().allgather_packed_range(&_mesh.getMesh(),
176  master_elems_to_ghost.begin(),
177  master_elems_to_ghost.end(),
178  mesh_inserter_iterator<Elem>(_mesh.getMesh()));
179 
180  _mesh.update(); // Rebuild node_to_elem_map
181 
182  // Find elems again now that we know they're there
183  const auto & new_node_to_elem_map = _mesh.nodeToElemMap();
184  node_to_elem_pair = new_node_to_elem_map.find(_master_node_vector[0]);
185  found_elems = (node_to_elem_pair != new_node_to_elem_map.end());
186  }
187 
188  if (!found_elems)
189  mooseError("Couldn't find any elements connected to master node");
190 
191  const std::vector<dof_id_type> & elems = node_to_elem_pair->second;
192 
193  if (elems.size() == 0)
194  mooseError("Couldn't find any elements connected to master node");
195  _subproblem.addGhostedElem(elems[0]);
196 }
197 
198 Real
200 {
201  switch (type)
202  {
203  case Moose::Slave:
204  return (_u_slave[_i] - _u_master[_j]) * _penalty;
205  case Moose::Master:
206  return (_u_master[_j] - _u_slave[_i]) * _penalty;
207  }
208  return 0.;
209 }
210 
211 Real
213 {
214  switch (type)
215  {
216  case Moose::SlaveSlave:
217  return _penalty;
218  case Moose::SlaveMaster:
219  return -_penalty;
220  case Moose::MasterMaster:
221  return _penalty;
222  case Moose::MasterSlave:
223  return -_penalty;
224  }
225  return 0.;
226 }
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:198
InputParameters validParams< EqualValueBoundaryConstraint >()
unsigned int _j
virtual void meshChanged() override
Called on this object when the mesh changes.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
virtual const Node * queryNodePtr(const dof_id_type i) const
Definition: MooseMesh.C:473
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 >()
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition: MooseMesh.C:968
virtual Elem * queryElemPtr(const dof_id_type i)
Definition: MooseMesh.C:2127
std::vector< unsigned int > _slave_node_ids
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2408
std::vector< dof_id_type > _connected_nodes
node IDs connected to the master node (slave nodes)
MooseMesh & _mesh
Definition: Constraint.h:81
void update()
Calls buildNodeListFromSideList(), buildNodeList(), and buildBndElemList().
Definition: MooseMesh.C:406
SubProblem & _subproblem
Definition: Constraint.h:74
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:204
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:437
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...
void mooseError(Args &&...args) const
Definition: MooseObject.h:80
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:2435
virtual Real computeQpResidual(Moose::ConstraintType type) override
Computes the residual for the current slave node.
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:681