https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NodalFrictionalConstraint.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#include "Assembly.h"
15#include "SystemBase.h"
16
17// C++ includes
18#include <limits.h>
19
21
24{
26 params.addClassDescription("Frictional nodal constraint for contact");
27 params.addRequiredParam<BoundaryName>("boundary", "The primary boundary");
28 params.addRequiredParam<BoundaryName>("secondary", "The secondary boundary");
29 params.addRequiredParam<Real>("friction_coefficient",
30 "Friction coefficient for slippage in the normal direction");
31 params.addRequiredParam<Real>("normal_force",
32 "Normal force used together with friction_coefficient to compute "
33 "the normal frictional capacity.");
34 params.addRequiredParam<Real>("tangential_penalty",
35 "Stiffness of the spring in the tangential direction.");
36 return params;
37}
38
40 : NodalConstraint(parameters),
41 _primary_boundary_id(getParam<BoundaryName>("boundary")),
42 _secondary_boundary_id(getParam<BoundaryName>("secondary")),
43 _normal_force(getParam<Real>("normal_force")),
44 _tangential_penalty(getParam<Real>("tangential_penalty")),
45 _friction_coefficient(getParam<Real>("friction_coefficient")),
46 _u_secondary_old(_var.dofValuesOldNeighbor()),
47 _u_primary_old(_var.dofValuesOld())
48{
50 paramError("variable_secondary",
51 "Primary variable must be identical to secondary "
52 "variable. Different variables are currently not supported.");
53
55
56 MooseEnum temp_formulation = getParam<MooseEnum>("formulation");
57 if (temp_formulation == "penalty")
59 else if (temp_formulation == "kinematic")
60 mooseError("NodalFrictionalConstraint: Kinematic formulation is currently not supported for "
61 "this constraint.");
62 else
63 mooseError("Formulation must be set to Penalty.");
64}
65
66void
71
72void
74{
76 _connected_nodes.clear();
77 _primary_conn.clear();
78
79 std::vector<dof_id_type> secondary_nodelist =
81 std::vector<dof_id_type> primary_nodelist =
83
84 // Fill in _connected_nodes, which defines secondary nodes in the base class
85 for (auto in : secondary_nodelist)
86 {
87 if (_mesh.nodeRef(in).processor_id() == _subproblem.processor_id())
88 _connected_nodes.push_back(in);
89 }
90
91 // Fill in _primary_node_vector, which defines secondary nodes in the base class
92 for (auto in : primary_nodelist)
93 _primary_node_vector.push_back(in);
94
96 for (const auto elem_id : elem_ids)
98
100 {
101 const auto displaced_elem_ids =
103 if (displaced_elem_ids != elem_ids)
104 mooseError("Reference and displaced meshes selected different primary elements");
105 }
106
107 // Cache map between secondary node and primary node
108 _connected_nodes.clear();
109 _primary_conn.clear();
110 for (unsigned int j = 0; j < secondary_nodelist.size(); ++j)
111 {
112 if (_mesh.nodeRef(secondary_nodelist[j]).processor_id() == _subproblem.processor_id())
113 {
114 Node & secondary_node = _mesh.nodeRef(secondary_nodelist[j]);
115 for (unsigned int i = 0; i < _primary_node_vector.size(); ++i)
116 {
117 Node & primary_node = _mesh.nodeRef(_primary_node_vector[i]);
118 Real d = (secondary_node - primary_node).norm();
119 if (MooseUtils::absoluteFuzzyEqual(d, 0.0))
120 {
121 _primary_conn.push_back(i);
122 _connected_nodes.push_back(secondary_nodelist[j]);
123 break;
124 }
125 }
126 }
127 }
128
129 _console << "total secondary nodes, primary nodes: " << _primary_conn.size() << ", "
130 << _primary_node_vector.size() << '\n';
131}
132
133void
135 /*residual*/)
136{
137 const auto & primarydof = _var.dofIndices();
138 const auto & secondarydof = _var.dofIndicesNeighbor();
139 std::vector<Number> re(primarydof.size());
140 std::vector<Number> neighbor_re(secondarydof.size());
141
142 for (_i = 0; _i < secondarydof.size(); ++_i)
143 {
146 neighbor_re[_i] += computeQpResidual(Moose::Secondary);
147 break;
148 }
149 addResiduals(_assembly, re, primarydof, _var.scalingFactor());
150 addResiduals(_assembly, neighbor_re, secondarydof, _var.scalingFactor());
151}
152
153Real
155{
156 // check whether the tangential spring is already in the yielded state
158 if (MooseUtils::absoluteFuzzyGreaterThan(std::abs(old_force),
160 old_force = _friction_coefficient * _normal_force * old_force / std::abs(old_force);
161
162 Real current_force =
165 old_force;
166 if (MooseUtils::absoluteFuzzyGreaterThan(std::abs(current_force),
168 current_force = _friction_coefficient * _normal_force * current_force / std::abs(current_force);
169
170 switch (type)
171 {
172 case Moose::Secondary:
173 return current_force;
174 case Moose::Primary:
175 return -current_force;
176 }
177 return 0;
178}
179
180void
181NodalFrictionalConstraint::computeJacobian(const SparseMatrix<Number> & /*jacobian*/)
182{
183 // Calculate Jacobian entries and cache those entries along with the row and column indices
184 std::vector<dof_id_type> secondarydof = _var.dofIndicesNeighbor();
185 std::vector<dof_id_type> primarydof = _var.dofIndices();
186
187 DenseMatrix<Number> Kee(primarydof.size(), primarydof.size());
188 DenseMatrix<Number> Ken(primarydof.size(), secondarydof.size());
189 DenseMatrix<Number> Kne(secondarydof.size(), primarydof.size());
190 DenseMatrix<Number> Knn(secondarydof.size(), secondarydof.size());
191
192 Kee.zero();
193 Ken.zero();
194 Kne.zero();
195 Knn.zero();
196
197 for (_i = 0; _i < secondarydof.size(); ++_i)
198 {
204 }
205 addJacobian(_assembly, Kee, primarydof, primarydof, _var.scalingFactor());
206 addJacobian(_assembly, Ken, primarydof, secondarydof, _var.scalingFactor());
207 addJacobian(_assembly, Kne, secondarydof, primarydof, _var.scalingFactor());
208 addJacobian(_assembly, Knn, secondarydof, secondarydof, _var.scalingFactor());
209}
210
211Real
213{
214 Real jac = _tangential_penalty;
215
216 // set jacobian to zero if spring has yielded
218 if (MooseUtils::absoluteFuzzyGreaterThan(std::abs(old_force),
220 old_force = _friction_coefficient * _normal_force * old_force / std::abs(old_force);
221
222 Real current_force =
225 old_force;
226 if (MooseUtils::absoluteFuzzyGreaterThan(std::abs(current_force),
228 jac = 0.0;
229
230 switch (type)
231 {
233 return jac;
235 return -jac;
237 return jac;
239 return -jac;
240 default:
241 mooseError("Invalid type");
242 }
243 return 0.;
244}
registerMooseObject("SolidMechanicsApp", NodalFrictionalConstraint)
std::shared_ptr< DisplacedProblem > displaced_problem
const ConsoleStream _console
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual MooseMesh & mesh() override
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const std::string & type() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
virtual const Node & nodeRef(const dof_id_type i) const
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
const std::vector< dof_id_type > & getNodeList(boundary_id_type nodeset_id) const
void scalingFactor(const std::vector< Real > &factor)
unsigned int number() const
const std::vector< dof_id_type > & dofIndicesNeighbor() const final
const std::vector< dof_id_type > & dofIndices() const final
Moose::ConstraintFormulationType _formulation
unsigned int _i
unsigned int _j
std::vector< dof_id_type > _primary_node_vector
std::vector< dof_id_type > _connected_nodes
std::vector< dof_id_type > gatherAndRetainConnectedElems(MooseMesh &mesh, const std::vector< dof_id_type > &node_ids)
static InputParameters validParams()
MooseVariable & _var
MooseVariable & _var_secondary
const VariableValue & _u_secondary
const VariableValue & _u_primary
const Real & _normal_force
Normal stiffness of spring.
virtual void computeResidual() override final
void updateConstrainedNodes()
Update the sets of nodes with constrained DOFs.
virtual void meshChanged() override
const Real & _tangential_penalty
Tangential stiffness of spring.
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
static InputParameters validParams()
const Real & _friction_coefficient
Coefficient of friction.
const VariableValue & _u_primary_old
Old value of the constrainted variable on the primary nodes.
BoundaryName _primary_boundary_id
Holds the secondary node set or side set.
virtual Real computeQpResidual(Moose::ConstraintType type) override
virtual void computeJacobian() override final
std::vector< dof_id_type > _primary_conn
primary node id connected to each secondary node in _connected_nodes
BoundaryName _secondary_boundary_id
Holds the secondary node set or side set.
NodalFrictionalConstraint(const InputParameters &parameters)
const VariableValue & _u_secondary_old
Old value of the constrainted variable on the secondary nodes.
MooseMesh & _mesh
Assembly & _assembly
SubProblem & _subproblem
FEProblemBase & _fe_problem
virtual void addGhostedElem(dof_id_type elem_id)=0
void addJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
void addResiduals(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
processor_id_type processor_id() const
ConstraintType
ConstraintJacobianType
SecondarySecondary
SecondaryPrimary
PrimarySecondary
PrimaryPrimary