https://mooseframework.inl.gov
Loading...
Searching...
No Matches
EqualValueBoundaryConstraint.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
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 "DisplacedProblem.h"
13#include "MooseMesh.h"
14
16
19{
22 "Constraint for enforcing that variables on each side of a boundary are equivalent.");
23 params.addParam<unsigned int>(
24 "primary",
25 "The ID of the primary node. If no ID is provided, first node of secondary set is chosen.");
26 params.addParam<Point>("primary_node_coord", "Coordinates of the primary node to locate.");
27 params.addParam<std::vector<unsigned int>>("secondary_node_ids", "The IDs of the secondary node");
28 params.addParam<BoundaryName>("secondary", "The boundary ID associated with the secondary side");
29 params.addRequiredParam<Real>("penalty", "The penalty used for the boundary term");
30 return params;
31}
32
34 : NodalConstraint(parameters), _penalty(getParam<Real>("penalty"))
35{
37}
38
39void
44
45void
52
53void
55{
56 // user provided nothing
57 if (!isParamValid("secondary_node_ids") && !isParamValid("secondary"))
58 paramError("secondary", "Either secondary or secondary_node_ids must be provided.");
59
60 // user provided conflicting params
61 if (isParamValid("secondary_node_ids") && isParamValid("secondary"))
62 paramError("secondary",
63 "Both 'secondary' and 'secondary_node_ids' parameters are set. They are mutually "
64 "exclusive.");
65
66 // Fill in _connected_nodes, which defines local secondary nodes in the base class
67 //
68 // Note that later on when we pick the primary node from the secondary node set, we
69 // will make sure to remove it from _connected_nodes
70 _connected_nodes.clear();
71
72 // user provided boundary name
73 if (isParamValid("secondary"))
74 {
75 const auto & secondary_bnd = getParam<BoundaryName>("secondary");
76 const auto & secondary_nodes = _mesh.getNodeList(_mesh.getBoundaryID(secondary_bnd));
77
78 for (const auto & nid : secondary_nodes)
79 if (_mesh.nodeRef(nid).processor_id() == _subproblem.processor_id())
80 _connected_nodes.push_back(nid);
81 }
82 // user provided node ids
83 else if (isParamValid("secondary_node_ids"))
84 {
85 const auto & secondary_node_ids = getParam<std::vector<unsigned int>>("secondary_node_ids");
86 for (const auto & nid : secondary_node_ids)
87 if (_mesh.queryNodePtr(nid) &&
88 _mesh.nodeRef(nid).processor_id() == _subproblem.processor_id())
89 _connected_nodes.push_back(nid);
90 }
91}
92
93void
95{
96 // user provided nothing
97 if (isParamValid("primary") && isParamValid("primary_node_coord"))
99 "Both 'primary' and 'primary_node_coord' parameters are set. They are mutually exclusive.");
100
101 dof_id_type primary_node_id = Node::invalid_id;
102
103 // user provided primary node coordinates
104 if (isParamValid("primary_node_coord"))
105 primary_node_id = getPrimaryNodeIDByCoord();
106 // user provided primary node id
107 else if (isParamValid("primary"))
108 primary_node_id = getParam<unsigned int>("primary");
109 // no primary node provided, so we pick one from secondary nodes
110 else
111 {
112 // If the user provided secondary node ids, set primary node to first one
113 if (isParamValid("secondary_node_ids"))
114 {
115 if (_connected_nodes.size())
116 primary_node_id = _connected_nodes[0];
117 }
118 // otherwise, we pick the minimum node id from the secondary node set
119 else
120 {
121 if (_connected_nodes.size())
122 primary_node_id = (*std::min_element(_connected_nodes.begin(), _connected_nodes.end()));
123 _mesh.comm().min(primary_node_id);
124 }
125 }
126
127 mooseAssert(primary_node_id != Node::invalid_id, "We should have found a primary node");
128
129 // Remove primary node from secondary nodes
130 auto it = std::find(_connected_nodes.begin(), _connected_nodes.end(), primary_node_id);
131 if (it != _connected_nodes.end())
132 _connected_nodes.erase(it);
133
134 // Store primary node id
135 _primary_node_vector.resize(1);
136 _primary_node_vector[0] = primary_node_id;
137}
138
139dof_id_type
141{
142 const Real eps = libMesh::TOLERANCE;
143 std::unordered_set<dof_id_type> local_primary_node_ids;
144 const auto & primary_node_coord = getParam<Point>("primary_node_coord");
145
146 // Gather local candidates
147 for (const auto & bnd_node : *_mesh.getBoundaryNodeRange())
148 {
149 if ((*(bnd_node->_node) - primary_node_coord).norm() < eps)
150 {
151 // The primary node we found should belong to the secondary node set
152 //
153 // Note that we do not immediately break once a match is found because in theory, although it
154 // is extremely unlikely, there could be multiple coinciding nodes on the secondary boundary
155 // that match the provided coordinates. In that case, we would like to emit a meaning error
156 // message.
157 if (std::find(_connected_nodes.begin(), _connected_nodes.end(), bnd_node->_node->id()) !=
158 _connected_nodes.end())
159 local_primary_node_ids.insert(bnd_node->_node->id());
160 }
161 }
162
163 // Gather all candidates from all ranks
164 const std::vector<dof_id_type> local_node_vec(local_primary_node_ids.begin(),
165 local_primary_node_ids.end());
166 std::vector<std::vector<dof_id_type>> gathered_node_vecs;
167 _mesh.comm().allgather(local_node_vec, gathered_node_vecs);
168
169 // Deduplicate
170 std::unordered_set<dof_id_type> global_primary_node_ids;
171 for (const auto & vec : gathered_node_vecs)
172 global_primary_node_ids.insert(vec.begin(), vec.end());
173
174 // Make sure we found one and exactly one
175 if (global_primary_node_ids.size() == 0)
176 mooseError("Couldn't find a node ID for the specified primary_node_coord.");
177 else if (global_primary_node_ids.size() > 1)
178 mooseError("Multiple nodes found for the specified primary_node_coord.");
179
180 return *global_primary_node_ids.begin();
181}
182
183void
185{
186 mooseAssert(_primary_node_vector.size() == 1, type() + " should have exactly one primary node");
187
188 const auto primary_node_id = _primary_node_vector.front();
189 const auto connected_elem_ids =
190 gatherAndRetainConnectedElems(_fe_problem.mesh(), {primary_node_id});
191 const auto primary_elem_id = connected_elem_ids.front();
192 _subproblem.addGhostedElem(primary_elem_id);
193
195 {
196 const auto displaced_connected_elem_ids =
197 gatherAndRetainConnectedElems(displaced_problem->mesh(), {primary_node_id});
198 const auto displaced_primary_elem_id = displaced_connected_elem_ids.front();
199 if (displaced_primary_elem_id != primary_elem_id)
200 mooseError("Reference and displaced meshes selected different primary elements");
201 }
202}
203
204Real
206{
207 switch (type)
208 {
209 case Moose::Secondary:
210 return (_u_secondary[_i] - _u_primary[_j]) * _penalty;
211 case Moose::Primary:
212 return (_u_primary[_j] - _u_secondary[_i]) * _penalty;
213 }
214 return 0.;
215}
216
217Real
219{
220 switch (type)
221 {
223 return _penalty;
225 return -_penalty;
227 return _penalty;
229 return -_penalty;
230 default:
231 mooseError("Unsupported type");
232 break;
233 }
234 return 0.;
235}
registerMooseObject("MooseApp", EqualValueBoundaryConstraint)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
std::shared_ptr< DisplacedProblem > displaced_problem
dof_id_type getPrimaryNodeIDByCoord() const
Get the primary node ID by searching for the node with coordinates matching _primary_node_coord on th...
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
Computes the jacobian for the constraint.
void pickPrimaryNode()
Pick the primary node from user input or from the secondary node set.
void populateSecondaryNodes()
Populate the set of secondary nodes from user input.
void ghostPrimary()
Ghost elements and nodes connected to the primary node.
EqualValueBoundaryConstraint(const InputParameters &parameters)
void updateConstrainedNodes()
Update the sets of nodes with constrained DOFs.
Real _penalty
Penalty if constraint is not satisfied.
virtual void meshChanged() override
Called on this object when the mesh changes.
virtual Real computeQpResidual(Moose::ConstraintType type) override
Computes the residual for the current secondary node.
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual MooseMesh & mesh() override
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
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...
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.
const std::string & type() const
Get the type of this class.
Definition MooseBase.h:93
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
virtual const Node & nodeRef(const dof_id_type i) const
Definition MooseMesh.C:844
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition MooseMesh.C:1684
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:3579
libMesh::StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > * getBoundaryNodeRange()
Definition MooseMesh.C:1288
virtual const Node * queryNodePtr(const dof_id_type i) const
Definition MooseMesh.C:870
unsigned int _i
Counter for primary and secondary nodes.
std::vector< dof_id_type > _primary_node_vector
node IDs of the primary node
std::vector< dof_id_type > _connected_nodes
node IDs connected to the primary node (secondary nodes)
std::vector< dof_id_type > gatherAndRetainConnectedElems(MooseMesh &mesh, const std::vector< dof_id_type > &node_ids)
Gather and retain elements connected to the provided nodes on the provided mesh.
static InputParameters validParams()
const VariableValue & _u_secondary
Value of the unknown variable this BC is action on.
const VariableValue & _u_primary
Holds the current solution at the current quadrature point.
MooseMesh & _mesh
Reference to this Kernel's mesh object.
SubProblem & _subproblem
Reference to this kernel's SubProblem.
FEProblemBase & _fe_problem
Reference to this kernel's FEProblemBase.
virtual void addGhostedElem(dof_id_type elem_id)=0
Will make sure that all dofs connected to elem_id are ghosted to this processor.
void min(const T &r, T &o, Request &req) const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
ConstraintType
Definition MooseTypes.h:812
@ Primary
Definition MooseTypes.h:814
@ Secondary
Definition MooseTypes.h:813
ConstraintJacobianType
Definition MooseTypes.h:851
@ SecondarySecondary
Definition MooseTypes.h:852
@ SecondaryPrimary
Definition MooseTypes.h:853
@ PrimarySecondary
Definition MooseTypes.h:854
@ PrimaryPrimary
Definition MooseTypes.h:855
static constexpr Real TOLERANCE