https://mooseframework.inl.gov
Loading...
Searching...
No Matches
BilinearMixedModeCohesiveZoneModel.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
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"
22#include <Eigen/Core>
23#include <cmath>
24
26
29{
31
32 params.addClassDescription("Computes the bilinear mixed mode cohesive zone model.");
33
34 // Input parameters for bilinear mixed mode traction.
35 params.addParam<MaterialPropertyName>("GI_c",
36 "Critical energy release rate in normal direction.");
37 params.addParam<MaterialPropertyName>("GII_c",
38 "Critical energy release rate in shear direction.");
39 params.addParam<MaterialPropertyName>("normal_strength", "Tensile strength in normal direction.");
40 params.addParam<MaterialPropertyName>("shear_strength", "Tensile strength in shear direction.");
41 params.addParam<Real>("power_law_parameter", "The power law parameter.");
42 MooseEnum criterion("POWER_LAW BK", "BK");
43 params.addParam<Real>("viscosity", 0.0, "Viscosity for damage model.");
44 params.addParam<MooseEnum>(
45 "mixed_mode_criterion", criterion, "Option for mixed mode propagation criterion.");
46 params.addParam<bool>(
47 "lag_displacement_jump",
48 false,
49 "Whether to use old displacement jumps to compute the effective displacement jump.");
50 params.addParam<bool>("set_compressive_traction_to_zero",
51 false,
52 "Zero compressive traction (set to true, allowing the use of standard "
53 "zero-penetration mortar contact constraints in "
54 "the normal direction).");
55 params.addParam<Real>(
56 "regularization_alpha", 1e-10, "Regularization parameter for the Macaulay bracket.");
57 params.addRangeCheckedParam<Real>(
58 "penalty_stiffness", "penalty_stiffness > 0.0", "Penalty stiffness for CZM.");
60 "GI_c GII_c normal_strength shear_strength power_law_parameter viscosity "
61 "mixed_mode_criterion lag_displacement_jump regularization_alpha "
62 "penalty_stiffness",
63 "Bilinear mixed mode traction");
64 // End of input parameters for bilinear mixed mode traction.
65
66 return params;
67}
68
70 const InputParameters & parameters)
71 : WeightedGapUserObject(parameters),
74 CohesiveZoneModelBase(parameters),
75 _set_compressive_traction_to_zero(getParam<bool>("set_compressive_traction_to_zero")),
76 _normal_strength(getMaterialProperty<Real>("normal_strength")),
77 _shear_strength(getMaterialProperty<Real>("shear_strength")),
78 _GI_c(getMaterialProperty<Real>("GI_c")),
79 _GII_c(getMaterialProperty<Real>("GII_c")),
80 _penalty_stiffness_czm(getParam<Real>("penalty_stiffness")),
81 _mix_mode_criterion(getParam<MooseEnum>("mixed_mode_criterion").getEnum<MixedModeCriterion>()),
82 _power_law_parameter(getParam<Real>("power_law_parameter")),
83 _viscosity(getParam<Real>("viscosity")),
84 _regularization_alpha(getParam<Real>("regularization_alpha"))
85{
86
87 // Checks for bilinear traction input.
88 if (!isParamValid("GI_c") || !isParamValid("GII_c") || !isParamValid("normal_strength") ||
89 !isParamValid("shear_strength") || !isParamValid("power_law_parameter") ||
90 !isParamValid("penalty_stiffness"))
91 paramError("GI_c",
92 "The CZM bilinear mixed mode traction parameters GI_c, GII_c, normal_strength, "
93 "shear_strength, and power_law_parameter are required. Revise your input and add "
94 "those parameters if you want to use the bilinear mixed mode traction model. ");
95}
96
97void
107
108void
110{
112
113 // Get the _dof_to_weighted_gap map
114 const auto * const dof = static_cast<const DofObject *>(_lower_secondary_elem->node_ptr(_i));
115
116 // TODO: Probably better to interpolate the deformation gradients.
119
120 _dof_to_GI_c[dof] += (*_test)[_i][_qp] * _GI_c_interpolation;
121 _dof_to_GII_c[dof] += (*_test)[_i][_qp] * _GII_c_interpolation;
122}
123
124void
126{
127 // instead we call it explicitly here
129
130 // Avoid accumulating interpolation over the time step
135 _dof_to_GI_c.clear();
136 _dof_to_GII_c.clear();
137 _dof_to_delta_initial.clear();
138 _dof_to_delta_final.clear();
139 _dof_to_delta_max.clear();
140}
141
142void
144{
145 using std::max, std::min;
146
147 // First call does not have maps available
148 const bool return_boolean = _dof_to_weighted_gap.find(node) == _dof_to_weighted_gap.end();
149 if (return_boolean)
150 return;
151
152 computeModeMixity(node);
156 computeDamage(node);
157
158 // Split displacement jump into active and inactive parts
159 const auto interface_displacement_jump =
161
162 const ADRealVectorValue delta_active(max(interface_displacement_jump(0), 0.0),
163 interface_displacement_jump(1),
164 interface_displacement_jump(2));
165 const ADRealVectorValue delta_inactive(min(interface_displacement_jump(0), 0.0), 0.0, 0.0);
166
167 // This traction vector is local at this point.
169 -(1.0 - libmesh_map_find(_dof_to_damage, node->id()).first) * _penalty_stiffness_czm *
170 delta_active -
172
173 // Save local-frame traction before the base class overwrites this map with global traction.
174 // Raw values only: this map feeds auxiliary output, so derivatives are not needed.
176}
177
178void
180{
181 using std::sqrt;
182
183 const auto interface_displacement_jump =
185
186 if (interface_displacement_jump(0) > _epsilon_tolerance)
187 {
188 const auto delta_s =
189 sqrt(interface_displacement_jump(1) * interface_displacement_jump(1) +
190 interface_displacement_jump(2) * interface_displacement_jump(2) + _epsilon_tolerance);
191
192 _dof_to_mode_mixity_ratio[node] = delta_s / interface_displacement_jump(0);
193 }
194 else
196}
197
198void
200{
201 using std::sqrt;
202
203 const auto interface_displacement_jump =
205
206 const auto mixity_ratio = libmesh_map_find(_dof_to_mode_mixity_ratio, node);
207
208 const auto delta_normal_knot =
210 const auto delta_shear_knot =
212
213 _dof_to_delta_initial[node] = delta_shear_knot;
214
215 if (interface_displacement_jump(0) > _epsilon_tolerance)
216 {
217 const auto delta_mixed = sqrt(delta_shear_knot * delta_shear_knot +
218 Utility::pow<2>(mixity_ratio * delta_normal_knot));
219
220 _dof_to_delta_initial[node] = delta_normal_knot * delta_shear_knot *
221 sqrt(1.0 + mixity_ratio * mixity_ratio) / delta_mixed;
222 }
223}
224
225void
227{
228 using std::sqrt, std::pow;
229
230 const auto interface_displacement_jump =
232
233 const auto mixity_ratio = libmesh_map_find(_dof_to_mode_mixity_ratio, node);
234
235 const auto normalized_GI_c = normalizeQuantity(_dof_to_GI_c, node);
236 const auto normalized_GII_c = normalizeQuantity(_dof_to_GII_c, node);
237
238 _dof_to_delta_final[node] =
239 sqrt(2.0) * 2.0 * normalized_GII_c / normalizeQuantity(_dof_to_shear_strength, node);
240
241 if (interface_displacement_jump(0) > _epsilon_tolerance)
242 {
244 {
245 _dof_to_delta_final[node] =
246 2.0 / _penalty_stiffness_czm / libmesh_map_find(_dof_to_delta_initial, node) *
247 (normalized_GI_c +
248 (normalized_GII_c - normalized_GI_c) *
249 pow(mixity_ratio * mixity_ratio / (1 + mixity_ratio * mixity_ratio),
251 }
253 {
254 const auto Gc_mixed =
255 pow(1.0 / normalized_GI_c, _power_law_parameter) +
256 pow(mixity_ratio * mixity_ratio / normalized_GII_c, _power_law_parameter);
257 _dof_to_delta_final[node] = (2.0 + 2.0 * mixity_ratio * mixity_ratio) /
259 libmesh_map_find(_dof_to_delta_initial, node) *
260 pow(Gc_mixed, -1.0 / _power_law_parameter);
261 }
262 }
263}
264
265void
267{
268 using std::sqrt;
269
270 const auto interface_displacement_jump =
272
273 const auto delta_normal_pos =
274 MathUtils::regularizedHeavyside(interface_displacement_jump(0), _regularization_alpha) *
275 interface_displacement_jump(0);
276
277 _dof_to_delta_max[node] = sqrt(Utility::pow<2>(interface_displacement_jump(1)) +
278 Utility::pow<2>(interface_displacement_jump(2)) +
279 Utility::pow<2>(delta_normal_pos) + _epsilon_tolerance);
280}
281
282void
284{
285 const auto delta_max = libmesh_map_find(_dof_to_delta_max, node);
286 const auto delta_initial = libmesh_map_find(_dof_to_delta_initial, node);
287 const auto delta_final = libmesh_map_find(_dof_to_delta_final, node);
288
289 auto & [damage, damage_old] = _dof_to_damage[node->id()];
290 if (delta_max < delta_initial)
291 damage = 0;
292 else if (delta_max > delta_final)
293 damage = 1.0;
294 else
295 damage = delta_final * (delta_max - delta_initial) / delta_max / (delta_final - delta_initial);
296
297 if (damage < damage_old)
298 // Irreversibility
299 damage = damage_old;
300
301 // Viscous regularization
302 damage = (damage + _viscosity * damage_old / _dt) / (_viscosity / _dt + 1.0);
303}
304
305void
324
325Real
327{
328 const auto it = _dof_to_mode_mixity_ratio.find(_subproblem.mesh().nodePtr(node->id()));
329
330 if (it != _dof_to_mode_mixity_ratio.end())
331 return MetaPhysicL::raw_value(it->second);
332 else
333 return 0.0;
334}
335
336Real
338{
339 const auto it = _dof_to_damage.find(node->id());
340
341 if (it != _dof_to_damage.end())
342 return MetaPhysicL::raw_value(it->second.first);
343 else
344 return 0.0;
345}
346
347Real
349{
350 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
351 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
352
353 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
354 return MetaPhysicL::raw_value(it->second(0) / it2->second.second);
355 else
356 return 0.0;
357}
358
359Real
364
365Real
367{
368 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
369 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
370
371 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
372 return MetaPhysicL::raw_value(it->second(1) / it2->second.second);
373 else
374 return 0.0;
375}
376
377Real
379{
380 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
381 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
382
383 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
384 return MetaPhysicL::raw_value(it->second(2) / it2->second.second);
385 else
386 return 0.0;
387}
388
389Real
391 const Node * const node) const
392{
393 using std::sqrt;
394
395 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
396 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
397
398 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
399 {
400 // Take raw values before the sqrt: the AD derivative of sqrt divides by zero
401 // when the tangential jump is exactly zero (e.g. pure mode I or post-debond).
402 const auto tangential_one = MetaPhysicL::raw_value(it->second(1) / it2->second.second);
403 const auto tangential_two = MetaPhysicL::raw_value(it->second(2) / it2->second.second);
404 return sqrt(tangential_one * tangential_one + tangential_two * tangential_two);
405 }
406 else
407 return 0.0;
408}
409
410Real
412{
413 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
414
415 if (it != _dof_to_local_czm_traction.end())
416 return it->second(0);
417 else
418 return 0.0;
419}
420
421Real
423 const Node * const node) const
424{
425 using std::sqrt;
426
427 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
428
429 if (it != _dof_to_local_czm_traction.end())
430 return sqrt(it->second(1) * it->second(1) + it->second(2) * it->second(2));
431 else
432 return 0.0;
433}
434
435Real
437{
438 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
439
440 if (it != _dof_to_local_czm_traction.end())
441 return it->second(1);
442 else
443 return 0.0;
444}
445
446Real
448{
449 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
450
451 if (it != _dof_to_local_czm_traction.end())
452 return it->second(2);
453 else
454 return 0.0;
455}
456
457Real
459{
460 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
461
462 if (it != _dof_to_local_czm_traction.end())
463 return it->second.norm();
464 else
465 return 0.0;
466}
registerMooseObject("ContactApp", BilinearMixedModeCohesiveZoneModel)
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
User object that computes bilinear mixed mode traction separation law.
const bool _set_compressive_traction_to_zero
Zero compressive traction.
std::unordered_map< const DofObject *, ADReal > _dof_to_delta_final
Real getLocalDisplacementTangentialOne(const Node *const node) const
Real getCohesiveDamage(const Node *const node) const
const MaterialProperty< Real > & _normal_strength
The normal strength material property.
MixedModeCriterion
Mixed-mode propagation criterion.
const Real _power_law_parameter
Power law parameter for bilinear traction model.
std::unordered_map< const DofObject *, ADReal > _dof_to_shear_strength
const Real _regularization_alpha
Parameter for the regularization of the Macaulay bracket.
virtual void computeDamage(const Node *const node) override
std::unordered_map< const DofObject *, ADReal > _dof_to_delta_max
Real getLocalDisplacementTangential(const Node *const node) const
Real getCohesiveTractionTangentialMagnitude(const Node *const node) const
virtual void computeQpProperties() override
Computes properties that are functions only of the current quadrature point (_qp),...
Real getLocalDisplacementTangentialEffective(const Node *const node) const
Real getCohesiveTractionTangentialTwo(const Node *const node) const
std::unordered_map< const DofObject *, ADReal > _dof_to_normal_strength
const MaterialProperty< Real > & _GI_c
Fracture parameter mode I.
const MaterialProperty< Real > & _GII_c
Fracture parameter mode II.
std::unordered_map< const DofObject *, ADReal > _dof_to_mode_mixity_ratio
Map from degree of freedom to mode mixity ratio (AD needed?)
Real getCohesiveTractionNormal(const Node *const node) const
virtual void computeQpIProperties() override
Computes properties that are functions both of _qp and _i, for example the weighted gap.
ADReal _GI_c_interpolation
Interpolated value of fracture paramter mode I.
virtual void computeFinalDisplacementJump(const Node *const node)
ADReal _shear_strength_interpolation
Interpolated value of shear_strength.
virtual void computeEffectiveDisplacementJump(const Node *const node)
enum BilinearMixedModeCohesiveZoneModel::MixedModeCriterion _mix_mode_criterion
const Real _viscosity
Viscosity for damage model.
std::unordered_map< const DofObject *, RealVectorValue > _dof_to_local_czm_traction
Map from degree of freedom to the local-frame cohesive traction.
const MaterialProperty< Real > & _shear_strength
The shear strength material property.
Real getModeMixityRatio(const Node *const node) const
Real getLocalDisplacementNormal(const Node *const node) const
virtual void computeModeMixity(const Node *const node)
Real getCohesiveTractionTangentialOne(const Node *const node) const
std::unordered_map< const DofObject *, ADReal > _dof_to_GI_c
std::unordered_map< const DofObject *, ADReal > _dof_to_GII_c
virtual void computeCriticalDisplacementJump(const Node *const node)
virtual void computeCZMTraction(const Node *const node) override
Encapsulate the CZM constitutive behavior.
Real getCohesiveTractionEffective(const Node *const node) const
Real getLocalDisplacementTangentialTwo(const Node *const node) const
ADReal _GII_c_interpolation
Interpolated value of fracture paramter mode II.
ADReal _normal_strength_interpolation
Interpolated value of normal_strength.
std::unordered_map< const DofObject *, ADReal > _dof_to_delta_initial
BilinearMixedModeCohesiveZoneModel(const InputParameters &parameters)
Base class for mortar-based cohesive zone model.
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_interface_displacement_jump
Map from degree of freedom to local displacement jump.
virtual void computeQpProperties() override
Computes properties that are functions only of the current quadrature point (_qp),...
virtual void computeQpIProperties() override
Computes properties that are functions both of _qp and _i, for example the weighted gap.
const Real _epsilon_tolerance
Tolerance to avoid NaN/Inf in automatic differentiation operations.
static InputParameters validParams()
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_czm_traction
Total Lagrangian stress to be applied on CZM interface.
virtual void finalize() override
std::unordered_map< dof_id_type, std::pair< ADReal, Real > > & _dof_to_damage
Damage values (pair of current and old) on CZM interface.
T normalizeQuantity(const std::unordered_map< const DofObject *, T > &map, const Node *const node)
Normalize mortar quantities (remove mortar integral scaling)
virtual void initialize() override
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
bool isParamValid(const std::string &name) const
virtual const Node * nodePtr(const dof_id_type i) const
Elem const *const & _lower_secondary_elem
const std::vector< Real > & _JxW_msm
User object for computing weighted gaps and contact pressure for penalty based mortar constraints.
const Real & _dt
Current delta t... or timestep size.
virtual MooseMesh & mesh()=0
SubProblem & _subproblem
Creates dof object to weighted gap map.
unsigned int _i
Test function index.
unsigned int _qp
Quadrature point index for the mortar segments.
const MooseArray< Real > & _coord
Member for handling change of coordinate systems (xyz, rz, spherical)
std::unordered_map< const DofObject *, std::pair< ADReal, Real > > _dof_to_weighted_gap
A map from node to weighted gap and normalization (if requested)
const bool _nodal
Whether the dof objects are nodal; if they're not, then they're elemental.
Creates dof object to weighted tangential velocities map.
const Parallel::Communicator & _communicator
T regularizedHeavyside(const T &x, Real smoothing_length)
auto raw_value(const Eigen::Map< T > &in)
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)