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/null_output_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 
53 {
55  params.addClassDescription(
56  "Constraint for enforcing that variables on each side of a boundary are equivalent.");
57  params.addParam<unsigned int>(
58  "primary",
60  "The ID of the primary node. If no ID is provided, first node of secondary set is chosen.");
61  params.addParam<std::vector<unsigned int>>(
62  "secondary_node_ids", {}, "The IDs of the secondary node");
63  params.addParam<BoundaryName>(
64  "secondary", "NaN", "The boundary ID associated with the secondary side");
65  params.addRequiredParam<Real>("penalty", "The penalty used for the boundary term");
66  return params;
67 }
68 
70  : NodalConstraint(parameters),
71  _primary_node_id(getParam<unsigned int>("primary")),
72  _secondary_node_ids(getParam<std::vector<unsigned int>>("secondary_node_ids")),
73  _secondary_node_set_id(getParam<BoundaryName>("secondary")),
74  _penalty(getParam<Real>("penalty"))
75 {
77 }
78 
79 void
81 {
83 }
84 
85 void
87 {
88  _primary_node_vector.clear();
89  _connected_nodes.clear();
90 
91  if ((_secondary_node_ids.size() == 0) && (_secondary_node_set_id == "NaN"))
92  mooseError("Please specify secondary node ids or boundary id.");
93  else if ((_secondary_node_ids.size() == 0) && (_secondary_node_set_id != "NaN"))
94  {
95  std::vector<dof_id_type> nodelist =
97  std::vector<dof_id_type>::iterator in;
98 
99  // Set primary node to first node of the secondary node set if no primary node id is provided
100  //_primary_node_vector defines primary nodes in the base class
102  {
103  in = std::min_element(nodelist.begin(), nodelist.end());
104  dof_id_type node_id = (in == nodelist.end()) ? DofObject::invalid_id : *in;
105  _communicator.min(node_id);
106  _primary_node_vector.push_back(node_id);
107  }
108  else
110 
111  // Fill in _connected_nodes, which defines secondary nodes in the base class
112  for (in = nodelist.begin(); in != nodelist.end(); ++in)
113  {
114  if ((*in != _primary_node_vector[0]) &&
115  (_mesh.nodeRef(*in).processor_id() == _subproblem.processor_id()))
116  _connected_nodes.push_back(*in);
117  }
118  }
119  else if ((_secondary_node_ids.size() != 0) && (_secondary_node_set_id == "NaN"))
120  {
122  _primary_node_vector.push_back(
123  _secondary_node_ids[0]); //_primary_node_vector defines primary nodes in the base class
124 
125  // Fill in _connected_nodes, which defines secondary nodes in the base class
126  for (const auto & dof : _secondary_node_ids)
127  {
128  if (_mesh.queryNodePtr(dof) &&
129  (_mesh.nodeRef(dof).processor_id() == _subproblem.processor_id()) &&
130  (dof != _primary_node_vector[0]))
131  _connected_nodes.push_back(dof);
132  }
133  }
134 
135  const auto & node_to_elem_map = _mesh.nodeToElemMap();
136  auto node_to_elem_pair = node_to_elem_map.find(_primary_node_vector[0]);
137 
138  bool found_elems = (node_to_elem_pair != node_to_elem_map.end());
139 
140  // Add elements connected to primary node to Ghosted Elements.
141 
142  // On a distributed mesh, these elements might have already been
143  // remoted, in which case we need to gather them back first.
144  if (!_mesh.getMesh().is_serial())
145  {
146 #ifndef NDEBUG
147  bool someone_found_elems = found_elems;
148  _mesh.getMesh().comm().max(someone_found_elems);
149  mooseAssert(someone_found_elems, "Missing entry in node to elem map");
150 #endif
151 
152  std::set<Elem *, CompareElemsByLevel> primary_elems_to_ghost;
153  std::set<Node *> nodes_to_ghost;
154  if (found_elems)
155  {
156  for (dof_id_type id : node_to_elem_pair->second)
157  {
158  Elem * elem = _mesh.queryElemPtr(id);
159  if (elem)
160  {
161  primary_elems_to_ghost.insert(elem);
162 
163  const unsigned int n_nodes = elem->n_nodes();
164  for (unsigned int n = 0; n != n_nodes; ++n)
165  nodes_to_ghost.insert(elem->node_ptr(n));
166  }
167  }
168  }
169 
170  // Send nodes first since elements need them
171  _mesh.getMesh().comm().allgather_packed_range(&_mesh.getMesh(),
172  nodes_to_ghost.begin(),
173  nodes_to_ghost.end(),
175 
176  _mesh.getMesh().comm().allgather_packed_range(&_mesh.getMesh(),
177  primary_elems_to_ghost.begin(),
178  primary_elems_to_ghost.end(),
180 
181  _mesh.update(); // Rebuild node_to_elem_map
182 
183  // Find elems again now that we know they're there
184  const auto & new_node_to_elem_map = _mesh.nodeToElemMap();
185  node_to_elem_pair = new_node_to_elem_map.find(_primary_node_vector[0]);
186  found_elems = (node_to_elem_pair != new_node_to_elem_map.end());
187  }
188 
189  if (!found_elems)
190  mooseError("Couldn't find any elements connected to primary node");
191 
192  const std::vector<dof_id_type> & elems = node_to_elem_pair->second;
193 
194  if (elems.size() == 0)
195  mooseError("Couldn't find any elements connected to primary node");
196  _subproblem.addGhostedElem(elems[0]);
197 }
198 
199 Real
201 {
202  switch (type)
203  {
204  case Moose::Secondary:
205  return (_u_secondary[_i] - _u_primary[_j]) * _penalty;
206  case Moose::Primary:
207  return (_u_primary[_j] - _u_secondary[_i]) * _penalty;
208  }
209  return 0.;
210 }
211 
212 Real
214 {
215  switch (type)
216  {
218  return _penalty;
220  return -_penalty;
222  return _penalty;
224  return -_penalty;
225  default:
226  mooseError("Unsupported type");
227  break;
228  }
229  return 0.;
230 }
MooseMesh & _mesh
Reference to this Kernel&#39;s mesh object.
void updateConstrainedNodes()
Update the sets of nodes with constrained DOFs.
ConstraintType
Definition: MooseTypes.h:670
const VariableValue & _u_primary
Holds the current solution at the current quadrature point.
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:662
const VariableValue & _u_secondary
Value of the unknown variable this BC is action on.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::vector< unsigned int > _secondary_node_ids
const Parallel::Communicator & _communicator
static InputParameters validParams()
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:636
unsigned int _i
Counter for primary and secondary nodes.
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...
auto max(const L &left, const R &right)
virtual Elem * queryElemPtr(const dof_id_type i)
Definition: MooseMesh.C:2875
std::vector< dof_id_type > _primary_node_vector
node IDs of the primary node
const dof_id_type n_nodes
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3198
void min(const T &r, T &o, Request &req) const
std::vector< dof_id_type > _connected_nodes
node IDs connected to the primary node (secondary nodes)
SubProblem & _subproblem
Reference to this kernel&#39;s SubProblem.
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:3220
libmesh_assert(ctx)
void update()
Calls buildNodeListFromSideList(), buildNodeList(), and buildBndElemList().
Definition: MooseMesh.C:483
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:50
registerMooseObject("MooseApp", EqualValueBoundaryConstraint)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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:709
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
Computes the jacobian for the constraint.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
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 secondary node.
processor_id_type processor_id() const
void ErrorVector unsigned int
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition: MooseMesh.C:1474
uint8_t dof_id_type
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:980