https://mooseframework.inl.gov
CohesiveZoneModelBase.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 #include "CohesiveZoneModelBase.h"
11 #include "MooseVariableFE.h"
12 #include "SystemBase.h"
13 #include "MortarUtils.h"
14 #include "MooseUtils.h"
15 #include "MathUtils.h"
16 
17 #include "MortarContactUtils.h"
19 
20 #include "ADReal.h"
21 
22 #include "CohesiveZoneModelTools.h"
23 
24 #include <Eigen/Core>
25 
28 {
31  params.addRequiredCoupledVar("displacements",
32  "The string of displacements suitable for the problem statement");
33  params.addClassDescription(
34  "Base class for mortar-based cohesive zone model. To handle frictional cohesive interfaces, "
35  "it computes the mortar frictional contact forces using a penalty approach.");
36  params.addParam<Real>(
37  "penalty_friction",
38  "The penalty factor for frictional interaction. If not provided, the normal "
39  "penalty factor is also used for the frictional problem.");
40  params.addParam<Real>(
41  "friction_coefficient", 0.0, "The friction coefficient ruling Coulomb friction equations.");
42  // Suppress augmented Lagrange parameters. AL implementation for CZM remains to be done.
43  params.suppressParameter<Real>("max_penalty_multiplier");
44  params.suppressParameter<Real>("penalty_multiplier");
45  params.suppressParameter<Real>("penetration_tolerance");
46  params.setParameters("penalty", 0.0);
47  return params;
48 }
49 
51  /*
52  * We are using virtual inheritance to avoid the "Diamond inheritance" problem. This means that
53  * we have to construct WeightedGapUserObject explicitly as it will _not_ be constructed in
54  * the intermediate base classes PenaltyWeightedGapUserObject and WeightedVelocitiesUserObject.
55  * Virtual inheritance ensures that only one instance of WeightedGapUserObject is included in this
56  * class. The inheritance diagram is as follows:
57  *
58  * WeightedGapUserObject <----- PenaltyWeightedGapUserObject
59  * ^ ^
60  * | |
61  * WeightedVelocitiesUserObject <----- CohesiveZoneModelBase
62  *
63  */
64  : WeightedGapUserObject(parameters),
65  PenaltyWeightedGapUserObject(parameters),
66  WeightedVelocitiesUserObject(parameters),
67  _ndisp(coupledComponents("displacements")),
68  _penalty_friction(isParamValid("penalty_friction") ? getParam<Real>("penalty_friction")
69  : getParam<Real>("penalty")),
70  _friction_coefficient(getParam<Real>("friction_coefficient")),
71  _dof_to_accumulated_slip(
72  declareRestartableData<std::unordered_map<dof_id_type, std::pair<ADTwoVector, TwoVector>>>(
73  "dof_to_accumulated_slip",
74  std::unordered_map<dof_id_type, std::pair<ADTwoVector, TwoVector>>{})),
75  _dof_to_tangential_traction(
76  declareRestartableData<std::unordered_map<dof_id_type, std::pair<ADTwoVector, TwoVector>>>(
77  "dof_to_tangential_traction",
78  std::unordered_map<dof_id_type, std::pair<ADTwoVector, TwoVector>>{})),
79  _epsilon_tolerance(1.0e-40),
80  _dof_to_damage(declareRestartableData<std::unordered_map<dof_id_type, std::pair<ADReal, Real>>>(
81  "dof_do_damage", std::unordered_map<dof_id_type, std::pair<ADReal, Real>>{}))
82 {
83  _czm_interpolated_traction.resize(_ndisp);
84 
85  for (unsigned int i = 0; i < _ndisp; ++i)
86  {
87  _grad_disp.push_back(&adCoupledGradient("displacements", i));
88  _grad_disp_neighbor.push_back(&adCoupledGradient("displacements", i));
89  }
90 
91  // Set non-intervening components to zero
92  for ([[maybe_unused]] const auto i : make_range(_ndisp))
93  {
94  _grad_disp.push_back(&_ad_grad_zero);
95  _grad_disp_neighbor.push_back(&_ad_grad_zero);
96  }
97 
98  if (_augmented_lagrange_problem)
99  mooseError("CohesiveZoneModelBase constraints cannot be enforced with an augmented "
100  "Lagrange approach.");
101 }
102 
103 const VariableTestValue &
105 {
107 }
108 
109 void
111 {
113 
114  // Compute F and R.
115  const auto F = (ADRankTwoTensor::Identity() +
117  (*_grad_disp[0])[_qp], (*_grad_disp[1])[_qp], (*_grad_disp[2])[_qp]));
118  const auto F_neighbor = (ADRankTwoTensor::Identity() +
120  (*_grad_disp_neighbor[1])[_qp],
121  (*_grad_disp_neighbor[2])[_qp]));
122 
123  // TODO in follow-on PRs: Trim interior node variable derivatives
125  _F_neighbor_interpolation = F_neighbor * (_JxW_msm[_qp] * _coord[_qp]);
126 }
127 
128 void
130 {
132  // Get the _dof_to_weighted_gap map
133  const auto * const dof = static_cast<const DofObject *>(_lower_secondary_elem->node_ptr(_i));
134 
135  // TODO: Probably better to interpolate the deformation gradients.
136  _dof_to_F[dof] += (*_test)[_i][_qp] * _F_interpolation;
137  _dof_to_F_neighbor[dof] += (*_test)[_i][_qp] * _F_neighbor_interpolation;
138 }
139 
140 void
141 CohesiveZoneModelBase::computeFandR(const Node * const node)
142 {
143  // First call does not have maps available
144  const bool return_boolean = _dof_to_F.find(node) == _dof_to_F.end();
145  if (return_boolean)
146  return;
147 
148  const auto normalized_F = normalizeQuantity(_dof_to_F, node);
149  const auto normalized_F_neighbor = normalizeQuantity(_dof_to_F_neighbor, node);
150 
151  // This 'averaging' assumption below can probably be improved upon.
152  _dof_to_interface_F[node] = 0.5 * (normalized_F + normalized_F_neighbor);
153 
154  for (const auto i : make_range(Moose::dim))
155  for (const auto j : make_range(Moose::dim))
156  if (!std::isfinite(MetaPhysicL::raw_value(normalized_F(i, j))))
157  throw MooseException("The deformation gradient on the secondary surface is not finite in "
158  "CohesiveZoneModelBase. MOOSE needs to cut the time step size.");
159 
160  const auto dof_to_interface_F_node = libmesh_map_find(_dof_to_interface_F, node);
161 
162  const ADFactorizedRankTwoTensor C = dof_to_interface_F_node.transpose() * dof_to_interface_F_node;
163  const auto Uinv = MathUtils::sqrt(C).inverse().get();
164  _dof_to_interface_R[node] = dof_to_interface_F_node * Uinv;
165 
166  // Transform interface jump according to two rotation matrices
167  const auto global_interface_displacement = _dof_to_interface_displacement_jump[node];
169  (_dof_to_interface_R[node] * _dof_to_rotation_matrix[node]).transpose() *
170  global_interface_displacement;
171 }
172 
173 void
175 {
176  // these functions do not call WeightedGapUserObject::timestepSetup to avoid double initialization
179 
180  // instead we call it explicitly here
182 
183  // Clear step slip (values used in between AL iterations for penalty adaptivity)
184  for (auto & map_pr : _dof_to_step_slip)
185  {
186  auto & [step_slip, old_step_slip] = map_pr.second;
187  old_step_slip = {0.0, 0.0};
188  step_slip = {0.0, 0.0};
189  }
190 
191  // save off accumulated slip from the last timestep
192  for (auto & map_pr : _dof_to_accumulated_slip)
193  {
194  auto & [accumulated_slip, old_accumulated_slip] = map_pr.second;
195  old_accumulated_slip = MetaPhysicL::raw_value(accumulated_slip);
196  }
197 
198  for (auto & dof_lp : _dof_to_local_penalty_friction)
199  dof_lp.second = _penalty_friction;
200 
201  // save off tangential traction from the last timestep
202  for (auto & map_pr : _dof_to_tangential_traction)
203  {
204  auto & [tangential_traction, old_tangential_traction] = map_pr.second;
205  old_tangential_traction = {MetaPhysicL::raw_value(tangential_traction(0)),
206  MetaPhysicL::raw_value(tangential_traction(1))};
207  tangential_traction = {0.0, 0.0};
208  }
209 
210  for (auto & [dof_object, delta_tangential_lm] : _dof_to_frictional_lagrange_multipliers)
211  delta_tangential_lm.setZero();
212 
213  // save off damage from the last timestep
214  for (auto & map_pr : _dof_to_damage)
215  {
216  auto & [damage, old_damage] = map_pr.second;
217  old_damage = {MetaPhysicL::raw_value(damage)};
218  damage = {0.0};
219  }
220 }
221 
222 void
224 {
225  // these functions do not call WeightedGapUserObject::initialize to avoid double initialization
228 
229  // instead we call it explicitly here
231  _dof_to_F.clear();
232  _dof_to_F_neighbor.clear();
234  _dof_to_interface_F.clear();
235  _dof_to_interface_R.clear();
236  _dof_to_czm_traction.clear();
237  for (auto & map_pr : _dof_to_rotation_matrix)
238  map_pr.second.setToIdentity();
239 }
240 
241 void
243 {
244  // Normal contact pressure with penalty
246 
247  // Compute all rotations that were created as material properties in CZMComputeDisplacementJump
249 
250  // Reset frictional pressure
253 
254  for (const auto qp : make_range(_qrule_msm->n_points()))
255  {
258  }
259 
260  // zero vector
261  const static TwoVector zero{0.0, 0.0};
262 
263  // iterate over nodes
264  for (const auto i : make_range(_test->size()))
265  {
266  // current node
267  const Node * const node = _lower_secondary_elem->node_ptr(i);
268 
269  // Compute the weighted nodal deformation gradient and rotation tensors.
270  computeFandR(node);
271 
272  // The call below is a 'macro' call. Create a utility function or user object for it.
273  computeCZMTraction(node);
274 
275  // Build final traction vector
276  computeGlobalTraction(node);
277 
278  // Compute mechanical contact until end of method.
279  const auto penalty_friction = findValue(
280  _dof_to_local_penalty_friction, static_cast<const DofObject *>(node), _penalty_friction);
281 
282  // utilized quantities
283  const auto & normal_pressure = _dof_to_normal_pressure[node];
284 
285  // map the tangential traction and accumulated slip
286  auto & [tangential_traction, old_tangential_traction] = _dof_to_tangential_traction[node->id()];
287  auto & [accumulated_slip, old_accumulated_slip] = _dof_to_accumulated_slip[node->id()];
288 
289  Real normal_lm = -1;
290  if (auto it = _dof_to_lagrange_multiplier.find(node); it != _dof_to_lagrange_multiplier.end())
291  normal_lm = it->second;
292 
293  // Keep active set fixed from second Uzawa loop
294  if (normal_lm < -TOLERANCE && normal_pressure > TOLERANCE)
295  {
296  using std::abs;
297 
298  const auto & damage = _dof_to_damage[node->id()].first;
299 
300  const auto & real_tangential_velocity =
301  libmesh_map_find(_dof_to_real_tangential_velocity, node);
302  const ADTwoVector slip_distance = {real_tangential_velocity[0] * _dt,
303  real_tangential_velocity[1] * _dt};
304 
305  // frictional lagrange multiplier (delta lambda^(k)_T)
306  const auto & tangential_lm =
308 
309  // tangential trial traction (Simo 3.12)
310  // Modified for implementation in MOOSE: Avoid pingponging on frictional sign (max. 0.4
311  // capacity)
312  ADTwoVector inner_iteration_penalty_friction = penalty_friction * slip_distance;
313 
314  const auto slip_metric = std::abs(MetaPhysicL::raw_value(slip_distance).cwiseAbs()(0)) +
315  std::abs(MetaPhysicL::raw_value(slip_distance).cwiseAbs()(1));
316 
317  const auto slip_norm = (MetaPhysicL::raw_value(slip_distance)).norm();
318  const auto friction_limit = 0.4 * _friction_coefficient * damage * abs(normal_pressure);
319 
320  if (slip_metric > _epsilon_tolerance && penalty_friction * slip_norm > friction_limit)
321  {
322  inner_iteration_penalty_friction =
323  MetaPhysicL::raw_value(friction_limit / (penalty_friction * slip_norm)) *
324  penalty_friction * slip_distance;
325  }
326 
327  ADTwoVector tangential_trial_traction =
328  old_tangential_traction + tangential_lm + inner_iteration_penalty_friction;
329 
330  // Nonlinearity below
331  ADReal tangential_trial_traction_norm =
332  (MetaPhysicL::raw_value(tangential_trial_traction)).norm();
333  ADReal phi_trial = tangential_trial_traction_norm - _friction_coefficient * normal_pressure;
334  tangential_traction = tangential_trial_traction;
335 
336  // Simo considers this a 'return mapping'; we are just capping friction to the Coulomb limit.
337  if (phi_trial > 0.0)
338  // Simo 3.13/3.14 (the penalty formulation has an error in the paper)
339  tangential_traction -=
340  phi_trial * tangential_trial_traction / tangential_trial_traction_norm;
341 
342  // track accumulated slip for output purposes
343  accumulated_slip = old_accumulated_slip + slip_distance.cwiseAbs();
344  }
345  else
346  {
347  // reset slip and clear traction
348  accumulated_slip.setZero();
349  tangential_traction.setZero();
350  }
351 
352  // Now that we have consistent nodal frictional values, create an interpolated frictional
353  // pressure variable.
354  const auto test_i = (*_test)[i];
355  for (const auto qp : make_range(_qrule_msm->n_points()))
356  {
357  _frictional_contact_traction_one[qp] += test_i[qp] * tangential_traction(0);
358  _frictional_contact_traction_two[qp] += test_i[qp] * tangential_traction(1);
359  }
360  }
361 
362  for (const auto i : index_range(_czm_interpolated_traction))
363  {
365 
366  for (const auto qp : make_range(_qrule_msm->n_points()))
367  _czm_interpolated_traction[i][qp] = 0.0;
368  }
369 
370  // iterate over nodes
371  for (const auto i : make_range(_test->size()))
372  {
373  // current node
374  const Node * const node = _lower_secondary_elem->node_ptr(i);
375 
376  // End of CZM bilinear computations
377  auto it = _dof_to_czm_traction.find(node);
378  if (it == _dof_to_czm_traction.end())
379  return;
380 
381  const auto & test_i = (*_test)[i];
382  for (const auto qp : make_range(_qrule_msm->n_points()))
383  for (const auto idx : index_range(_czm_interpolated_traction))
384  _czm_interpolated_traction[idx][qp] += test_i[qp] * (it->second)(idx);
385  }
386 }
387 
388 void
390 {
391  // Compute rotation matrix from secondary surface
392  // Rotation matrices and local interface displacement jump.
393  for (const auto i : make_range(_test->size()))
394  {
395  const Node * const node = _lower_secondary_elem->node_ptr(i);
396 
397  // First call does not have maps available
398  const bool return_boolean = _dof_to_weighted_gap.find(node) == _dof_to_weighted_gap.end();
399  if (return_boolean)
400  return;
401 
402  _dof_to_rotation_matrix[node] = CohesiveZoneModelTools::computeReferenceRotation<true>(
404 
405  // Every time we used quantities from a map we "denormalize" it from the mortar integral.
406  // See normalizing member functions.
407  if (auto it = _dof_to_weighted_displacements.find(node);
408  it != _dof_to_weighted_displacements.end())
409  _dof_to_interface_displacement_jump[node] = it->second;
410  }
411 }
412 
413 void
415 {
418 
419  const bool send_data_back = !constrainedByOwner();
420 
422  _dof_to_F, _subproblem.mesh(), _nodal, _communicator, send_data_back);
423 
426 
429 }
430 
431 const ADVariableValue &
433 {
435 }
436 
437 const ADVariableValue &
439 {
441 }
442 
443 void
445 {
446  // First call does not have maps available
447  const auto it = _dof_to_czm_traction.find(node);
448  if (it == _dof_to_czm_traction.end())
449  return;
450 
451  const auto local_traction_vector = it->second;
452  const auto rotation_matrix = libmesh_map_find(_dof_to_rotation_matrix, node);
453 
454  _dof_to_czm_traction[node] = rotation_matrix * local_traction_vector;
455 }
456 
457 const ADVariableValue &
458 CohesiveZoneModelBase::czmGlobalTraction(const unsigned int i) const
459 {
460  mooseAssert(i <= 3,
461  "Internal error in czmGlobalTraction. Index exceeds the traction vector size.");
462 
463  return _czm_interpolated_traction[i];
464 }
virtual MooseMesh & mesh()=0
std::unordered_map< const DofObject *, std::pair< ADTwoVector, TwoVector > > _dof_to_step_slip
Map from degree of freedom to current and old AD iteration step slip.
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
std::unordered_map< const DofObject *, ADRankTwoTensor > _dof_to_interface_R
Map from degree of freedom to interface rotation tensor.
std::unordered_map< dof_id_type, std::pair< ADTwoVector, TwoVector > > & _dof_to_accumulated_slip
Map from degree of freedom to current and old accumulated slip.
unsigned int _qp
Quadrature point index for the mortar segments.
std::unordered_map< const DofObject *, ADReal > _dof_to_normal_pressure
Map from degree of freedom to normal pressure for reporting.
std::unordered_map< const DofObject *, ADRankTwoTensor > _dof_to_F_neighbor
Map from degree of freedom to neighbor, interpolated deformation gradient tensor. ...
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
V findValue(const std::unordered_map< K, V > &map, const K &key, const V &default_value=0) const
Find a value in a map or return a default if the key doesn&#39;t exist.
void mooseError(Args &&... args)
std::unordered_map< const DofObject *, ADRankTwoTensor > _dof_to_rotation_matrix
*** Kinematics/displacement jump quantities *** Map from degree of freedom to rotation matrix ...
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_czm_traction
Total Lagrangian stress to be applied on CZM interface.
AugmentedLagrangianContactProblemInterface *const _augmented_lagrange_problem
augmented Lagrange problem and iteration number
static InputParameters validParams()
std::unordered_map< const DofObject *, std::array< ADReal, 2 > > _dof_to_real_tangential_velocity
A map from node to two interpolated, physical tangential velocities.
ADRankTwoTensor _F_interpolation
Deformation gradient for interpolation.
T normalizeQuantity(const std::unordered_map< const DofObject *, T > &map, const Node *const node)
Normalize mortar quantities (remove mortar integral scaling)
std::unordered_map< const DofObject *, TwoVector > _dof_to_frictional_lagrange_multipliers
Map from degree of freedom to augmented lagrange multiplier.
const Real & _dt
Current delta t... or timestep size.
virtual const ADVariableValue & contactTangentialPressureDirOne() const override
void communicateRealObject(std::unordered_map< const DofObject *, T > &dof_to_adreal, const MooseMesh &mesh, const bool nodal, const Parallel::Communicator &communicator, const bool send_data_back)
virtual void initialize() override
std::vector< ADVariableValue > _czm_interpolated_traction
The global traction.
if(subdm)
auto raw_value(const Eigen::Map< T > &in)
virtual void computeQpProperties() override
Computes properties that are functions only of the current quadrature point (_qp), e.g.
const Real _friction_coefficient
The friction coefficient.
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_interface_displacement_jump
Map from degree of freedom to local displacement jump.
static constexpr std::size_t dim
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_weighted_displacements
A map from node to weighted displacements.
User object for computing weighted gaps and contact pressure for penalty based mortar constraints...
const bool _nodal
Whether the dof objects are nodal; if they&#39;re not, then they&#39;re elemental.
const std::vector< Real > & _JxW_msm
std::unordered_map< const DofObject *, ADRankTwoTensor > _dof_to_interface_F
Map from degree of freedom to interface deformation gradient tensor.
const Parallel::Communicator & _communicator
Creates dof object to weighted tangential velocities map.
const Real _epsilon_tolerance
Tolerance to avoid NaN/Inf in automatic differentiation operations.
const Number zero
ADVariableValue _frictional_contact_traction_one
The first frictional contact pressure on the mortar segment quadrature points.
static RankTwoTensorTempl Identity()
DualNumber< Real, DNDerivativeType, false > ADReal
const libMesh::QBase *const & _qrule_msm
static const std::string F
Definition: NS.h:169
std::vector< const GenericVariableGradient< true > * > _grad_disp
Coupled displacement gradients.
void suppressParameter(const std::string &name)
virtual void reinit() override
static RankTwoTensorTempl initializeFromRows(const libMesh::TypeVector< ADReal > &row0, const libMesh::TypeVector< ADReal > &row1, const libMesh::TypeVector< ADReal > &row2)
Elem const *const & _lower_secondary_elem
ADVariableValue _frictional_contact_traction_two
The second frictional contact pressure on the mortar segment quadrature points.
virtual void timestepSetup()
virtual unsigned int dimension() const
OutputTools< Real >::VariableTestValue VariableTestValue
std::vector< Point > _normals
const VariableTestValue * _test
A pointer to the test function associated with the weighted gap.
ADRankTwoTensor _F_neighbor_interpolation
Deformation gradient for interpolation of the neighbor projection.
virtual void timestepSetup() override
VariableValueTempl< true > ADVariableValue
unsigned int n_points() const
virtual void computeQpProperties() override
Computes properties that are functions only of the current quadrature point (_qp), e.g.
const Real _penalty_friction
The penalty factor for the frictional constraints.
SubProblem & _subproblem
virtual const ADVariableValue & contactTangentialPressureDirTwo() const override
std::unordered_map< dof_id_type, std::pair< ADTwoVector, TwoVector > > & _dof_to_tangential_traction
virtual void prepareJumpKinematicQuantities()
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
const MooseArray< Real > & _coord
Member for handling change of coordinate systems (xyz, rz, spherical)
virtual bool constrainedByOwner() const override
virtual void computeQpIProperties() override
Computes properties that are functions both of _qp and _i, for example the weighted gap...
Creates dof object to weighted gap map.
const MooseVariable *const _aux_lm_var
The auxiliary Lagrange multiplier variable (used together whith the Petrov-Galerkin approach) ...
virtual void computeFandR(const Node *const node)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm(const T &a)
void communicateR2T(std::unordered_map< const DofObject *, ADRankTwoTensor > &dof_map_adr2t, const MooseMesh &mesh, const bool nodal, const Parallel::Communicator &communicator, const bool send_data_back)
This function is used to communicate velocities across processes.
virtual const VariableTestValue & test() const override
std::unordered_map< const DofObject *, Real > _dof_to_local_penalty_friction
Map from degree of freedom to local friction penalty value.
virtual void computeCZMTraction(const Node *const)=0
Encapsulate the CZM constitutive behavior.
virtual const FieldVariablePhiValue & phiLower() const override
std::unordered_map< const DofObject *, Real > _dof_to_lagrange_multiplier
Map from degree of freedom to augmented lagrange multiplier.
IntRange< T > make_range(T beg, T end)
unsigned int _i
Test function index.
void addClassDescription(const std::string &doc_string)
std::vector< const GenericVariableGradient< true > * > _grad_disp_neighbor
Coupled displacement and neighbor displacement gradient.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual void initialize() override
CohesiveZoneModelBase(const InputParameters &parameters)
const MooseVariable *const _disp_x_var
The x displacement variable.
virtual void computeQpIProperties() override
Computes properties that are functions both of _qp and _i, for example the weighted gap...
std::unordered_map< const DofObject *, std::pair< ADReal, Real > > _dof_to_weighted_gap
A map from node to weighted gap and normalization (if requested)
virtual const ADVariableValue & czmGlobalTraction(unsigned int i) const
std::unordered_map< dof_id_type, std::pair< ADReal, Real > > & _dof_to_damage
Damage values (pair of current and old) on CZM interface.
auto index_range(const T &sizable)
std::unordered_map< const DofObject *, ADRankTwoTensor > _dof_to_F
Map from degree of freedom to secondary, interpolated deformation gradient tensor.
void setParameters(const std::string &name, const T &value, Ts... extra_input_parameters)
static const std::string C
Definition: NS.h:172
virtual void finalize() override
virtual void computeGlobalTraction(const Node *const node)
Compute global traction for mortar application.
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
uint8_t dof_id_type