19#include "libmesh/compare_elems_by_level.h"
20#include "libmesh/distributed_mesh.h"
21#include "libmesh/null_output_iterator.h"
22#include "libmesh/parallel_elem.h"
23#include "libmesh/parallel_node.h"
24#include "libmesh/sparse_matrix.h"
32 MooseEnum formulationtype(
"penalty kinematic",
"penalty");
35 "Formulation used to calculate constraint - penalty or kinematic.");
36 params.
addParam<NonlinearVariableName>(
"variable_secondary",
37 "The name of the variable for the secondary nodes, if it "
38 "is different from the primary nodes' variable");
46 this, true,
Moose::VarKindType::VAR_SOLVER,
Moose::VarFieldType::VAR_FIELD_STANDARD),
47 _var(_sys.getFieldVariable<Real>(_tid, parameters.get<NonlinearVariableName>(
"variable"))),
48 _var_secondary(_sys.getFieldVariable<Real>(
50 isParamValid(
"variable_secondary")
51 ? parameters.get<NonlinearVariableName>(
"variable_secondary")
52 : parameters.get<NonlinearVariableName>(
"variable"))),
53 _u_secondary(_var_secondary.dofValuesNeighbor()),
54 _u_primary(_var.dofValues())
59 MooseEnum temp_formulation = getParam<MooseEnum>(
"formulation");
60 if (temp_formulation ==
"penalty")
62 else if (temp_formulation ==
"kinematic")
65 mooseError(
"Formulation must be either Penalty or Kinematic");
68std::vector<dof_id_type>
70 const std::vector<dof_id_type> & node_ids)
72 const auto & node_to_elem_map =
mesh.nodeToElemMap();
87 retained_elems.clear();
89 std::set<Elem *, libMesh::CompareElemIdsByLevel> elems_to_ghost;
90 std::set<Node *> nodes_to_ghost;
93 for (
const auto node_id : node_ids)
95 const auto node_to_elem_pair = node_to_elem_map.find(node_id);
98 bool someone_found_elem =
false;
101 if (node_to_elem_pair != node_to_elem_map.end())
102 for (
const auto elem_id : node_to_elem_pair->second)
103 if (
auto *
const elem =
mesh.queryElemPtr(elem_id))
105 elems_to_ghost.insert(elem);
106 for (
const auto n : make_range(elem->n_nodes()))
107 nodes_to_ghost.insert(elem->node_ptr(n));
109 someone_found_elem =
true;
116 mesh.getMesh().comm().max(someone_found_elem);
117 mooseAssert(someone_found_elem || node_ids.empty(),
"Missing entry in node to elem map");
122 mesh.getMesh().comm().allgather_packed_range(&
mesh.getMesh(),
123 nodes_to_ghost.begin(),
124 nodes_to_ghost.end(),
126 mesh.getMesh().comm().allgather_packed_range(&
mesh.getMesh(),
127 elems_to_ghost.begin(),
128 elems_to_ghost.end(),
136 std::vector<dof_id_type> elem_ids;
137 for (
const auto node_id : node_ids)
140 const auto node_to_elem_pair = node_to_elem_map.find(node_id);
141 if (node_to_elem_pair == node_to_elem_map.end() || node_to_elem_pair->second.empty())
142 mooseError(
"Couldn't find any elements connected to primary node");
145 node_to_elem_pair->second.front();
147 elem_ids.push_back(elem_id);
150 if (distributed_mesh)
152 auto *
const elem =
mesh.elemPtr(elem_id);
153 distributed_mesh->add_extra_ghost_elem(elem);
154 retained_elems.insert(elem);
159 mooseAssert(node_ids.size() == elem_ids.size(),
160 "Mismatch between number of primary nodes and connected elements");
183 DenseVector<Number> re(primarydof.size());
184 DenseVector<Number> neighbor_re(secondarydof.size());
189 for (
_i = 0;
_i < secondarydof.size(); ++
_i)
191 for (
_j = 0;
_j < primarydof.size(); ++
_j)
201 Real res = residual(secondarydof[
_i]);
210 if (!primarydof.empty())
212 if (!secondarydof.empty())
226 DenseMatrix<Number> Kee(primarydof.size(), primarydof.size());
227 DenseMatrix<Number> Ken(primarydof.size(), secondarydof.size());
228 DenseMatrix<Number> Kne(secondarydof.size(), primarydof.size());
234 for (
_i = 0;
_i < secondarydof.size(); ++
_i)
236 for (
_j = 0;
_j < primarydof.size(); ++
_j)
248 Kne(
_i,
_j) += -jacobian(secondarydof[
_i], primarydof[
_j]) / primarydof.size() +
259 for (
_i = 0;
_i < secondarydof.size(); ++
_i)
268 value = -jacobian(secondarydof[
_i], secondarydof[
_i]) / primarydof.size() +
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Base class for all Constraint types.
static InputParameters validParams()
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
void scalingFactor(const std::vector< Real > &factor)
Set the scaling factor for this variable.
void addMooseVariableDependency(MooseVariableFieldBase *var)
Call this function to add the passed in MooseVariableFieldBase as a variable that this object depends...
const std::vector< dof_id_type > & dofIndicesNeighbor() const final
Get neighbor DOF indices for currently selected element.
const std::vector< dof_id_type > & dofIndices() const final
Get local DoF indices.
virtual const OutputTools< T >::VariableValue & value()
The value of the variable this object is operating on.
Enhances MooseVariableInterface interface provide values from neighbor elements.
virtual void computeResidual() override final
Computes the nodal residual.
Moose::ConstraintFormulationType _formulation
Specifies formulation type used to apply constraints.
unsigned int _i
Counter for primary and secondary nodes.
virtual Real computeQpResidual(Moose::ConstraintType type)=0
This is the virtual that derived classes should override for computing the residual on neighboring el...
std::vector< dof_id_type > _primary_node_vector
node IDs of the primary node
NodalConstraint(const InputParameters ¶meters)
std::vector< dof_id_type > _connected_nodes
node IDs connected to the primary node (secondary nodes)
std::vector< Real > _weights
When the secondary node is constrained to move as a linear combination of the primary 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.
std::map< MooseMesh *, std::set< Elem * > > _retained_elems
Elements this constraint retained on each distributed mesh during the previous mesh update.
static InputParameters validParams()
virtual void updateConnectivity()
Built the connectivity for this constraint.
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type)=0
This is the virtual that derived classes should override for computing the Jacobian on neighboring el...
virtual void computeJacobian() override final
Computes the jacobian for the current element.
MooseVariable & _var_secondary
void reinitConstraintNodes()
Reinitialize the primary and secondary nodes on the SubProblem that owns this constraint's variables.
THREAD_ID _tid
The thread ID for this kernel.
Assembly & _assembly
Reference to this Kernel's assembly object.
SubProblem & _subproblem
Reference to this kernel's SubProblem.
void reinitNodesNeighbor(const std::vector< dof_id_type > &nodes, const THREAD_ID tid)
void reinitNodes(const std::vector< dof_id_type > &nodes, const THREAD_ID tid)
void addJacobianElement(Assembly &assembly, Real value, dof_id_type row_index, dof_id_type column_index, Real scaling_factor)
Add into a single Jacobian element.
void addJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
Add the provided residual derivatives into the Jacobian for the provided dof indices.
void addResiduals(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
Add the provided incoming residuals corresponding to the provided dof indices.
virtual void clear_extra_ghost_elems()
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...