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.addDeprecatedParam<bool>(
47 "lag_displacement_jump",
48 false,
49 "Whether to use old displacement jumps to compute the effective displacement jump.",
50 "This parameter has no effect in the mortar cohesive zone model and will be removed. Use "
51 "'viscosity' to regularize the damage evolution.");
52 params.addParam<bool>("set_compressive_traction_to_zero",
53 false,
54 "Zero compressive traction (set to true, allowing the use of standard "
55 "zero-penetration mortar contact constraints in "
56 "the normal direction).");
57 params.addParam<Real>(
58 "regularization_alpha", 1e-10, "Regularization parameter for the Macaulay bracket.");
59 params.addRangeCheckedParam<Real>(
60 "penalty_stiffness", "penalty_stiffness > 0.0", "Penalty stiffness for CZM.");
62 "GI_c GII_c normal_strength shear_strength power_law_parameter viscosity "
63 "mixed_mode_criterion regularization_alpha "
64 "penalty_stiffness",
65 "Bilinear mixed mode traction");
66 // End of input parameters for bilinear mixed mode traction.
67
68 return params;
69}
70
72 const InputParameters & parameters)
73 : WeightedGapUserObject(parameters),
76 CohesiveZoneModelBase(parameters),
77 _set_compressive_traction_to_zero(getParam<bool>("set_compressive_traction_to_zero")),
78 _normal_strength(getMaterialProperty<Real>("normal_strength")),
79 _shear_strength(getMaterialProperty<Real>("shear_strength")),
80 _GI_c(getMaterialProperty<Real>("GI_c")),
81 _GII_c(getMaterialProperty<Real>("GII_c")),
82 _penalty_stiffness_czm(getParam<Real>("penalty_stiffness")),
83 _mix_mode_criterion(getParam<MooseEnum>("mixed_mode_criterion").getEnum<MixedModeCriterion>()),
84 _power_law_parameter(getParam<Real>("power_law_parameter")),
85 _viscosity(getParam<Real>("viscosity")),
86 _regularization_alpha(getParam<Real>("regularization_alpha"))
87{
88
89 // Checks for bilinear traction input.
90 if (!isParamValid("GI_c") || !isParamValid("GII_c") || !isParamValid("normal_strength") ||
91 !isParamValid("shear_strength") || !isParamValid("power_law_parameter") ||
92 !isParamValid("penalty_stiffness"))
93 paramError("GI_c",
94 "The CZM bilinear mixed mode traction parameters GI_c, GII_c, normal_strength, "
95 "shear_strength, and power_law_parameter are required. Revise your input and add "
96 "those parameters if you want to use the bilinear mixed mode traction model. ");
97}
98
99void
109
110void
112{
114
115 // Get the _dof_to_weighted_gap map
116 const auto * const dof = cast_ptr<const DofObject *>(_lower_secondary_elem->node_ptr(_i));
117
118 // TODO: Probably better to interpolate the deformation gradients.
121
122 _dof_to_GI_c[dof] += (*_test)[_i][_qp] * _GI_c_interpolation;
123 _dof_to_GII_c[dof] += (*_test)[_i][_qp] * _GII_c_interpolation;
124}
125
126void
128{
129 // instead we call it explicitly here
131
132 // Avoid accumulating interpolation over the time step
137 _dof_to_GI_c.clear();
138 _dof_to_GII_c.clear();
139 _dof_to_delta_initial.clear();
140 _dof_to_delta_final.clear();
141 _dof_to_delta_max.clear();
142}
143
144void
146{
147 using std::max, std::min;
148
149 // First call does not have maps available
150 const bool return_boolean = _dof_to_weighted_gap.find(node) == _dof_to_weighted_gap.end();
151 if (return_boolean)
152 return;
153
154 computeModeMixity(node);
158 computeDamage(node);
159
160 // Split displacement jump into active and inactive parts
161 const auto interface_displacement_jump =
163
164 const ADRealVectorValue delta_active(max(interface_displacement_jump(0), 0.0),
165 interface_displacement_jump(1),
166 interface_displacement_jump(2));
167 const ADRealVectorValue delta_inactive(min(interface_displacement_jump(0), 0.0), 0.0, 0.0);
168
169 // This traction vector is local at this point.
171 -(1.0 - libmesh_map_find(_dof_to_damage, node->id()).first) * _penalty_stiffness_czm *
172 delta_active -
174
175 // Save local-frame traction before the base class overwrites this map with global traction.
176 // Raw values only: this map feeds auxiliary output, so derivatives are not needed.
178}
179
180void
182{
183 using std::sqrt;
184
185 const auto interface_displacement_jump =
187
188 if (interface_displacement_jump(0) > _epsilon_tolerance)
189 {
190 const auto delta_s =
191 sqrt(interface_displacement_jump(1) * interface_displacement_jump(1) +
192 interface_displacement_jump(2) * interface_displacement_jump(2) + _epsilon_tolerance);
193
194 _dof_to_mode_mixity_ratio[node] = delta_s / interface_displacement_jump(0);
195 }
196 else
198}
199
200void
202{
203 using std::sqrt;
204
205 const auto interface_displacement_jump =
207
208 const auto mixity_ratio = libmesh_map_find(_dof_to_mode_mixity_ratio, node);
209
210 const auto delta_normal_knot =
212 const auto delta_shear_knot =
214
215 _dof_to_delta_initial[node] = delta_shear_knot;
216
217 if (interface_displacement_jump(0) > _epsilon_tolerance)
218 {
219 const auto delta_mixed = sqrt(delta_shear_knot * delta_shear_knot +
220 Utility::pow<2>(mixity_ratio * delta_normal_knot));
221
222 _dof_to_delta_initial[node] = delta_normal_knot * delta_shear_knot *
223 sqrt(1.0 + mixity_ratio * mixity_ratio) / delta_mixed;
224 }
225}
226
227void
229{
230 using std::sqrt, std::pow;
231
232 const auto interface_displacement_jump =
234
235 const auto mixity_ratio = libmesh_map_find(_dof_to_mode_mixity_ratio, node);
236
237 const auto normalized_GI_c = normalizeQuantity(_dof_to_GI_c, node);
238 const auto normalized_GII_c = normalizeQuantity(_dof_to_GII_c, node);
239
240 _dof_to_delta_final[node] =
241 2.0 * normalized_GII_c / normalizeQuantity(_dof_to_shear_strength, node);
242
243 if (interface_displacement_jump(0) > _epsilon_tolerance)
244 {
246 {
247 _dof_to_delta_final[node] =
248 2.0 / _penalty_stiffness_czm / libmesh_map_find(_dof_to_delta_initial, node) *
249 (normalized_GI_c +
250 (normalized_GII_c - normalized_GI_c) *
251 pow(mixity_ratio * mixity_ratio / (1 + mixity_ratio * mixity_ratio),
253 }
255 {
256 const auto Gc_mixed =
257 pow(1.0 / normalized_GI_c, _power_law_parameter) +
258 pow(mixity_ratio * mixity_ratio / normalized_GII_c, _power_law_parameter);
259 _dof_to_delta_final[node] = (2.0 + 2.0 * mixity_ratio * mixity_ratio) /
261 libmesh_map_find(_dof_to_delta_initial, node) *
262 pow(Gc_mixed, -1.0 / _power_law_parameter);
263 }
264 }
265}
266
267void
269{
270 using std::sqrt;
271
272 const auto interface_displacement_jump =
274
275 const auto delta_normal_pos =
276 MathUtils::regularizedHeavyside(interface_displacement_jump(0), _regularization_alpha) *
277 interface_displacement_jump(0);
278
279 _dof_to_delta_max[node] = sqrt(Utility::pow<2>(interface_displacement_jump(1)) +
280 Utility::pow<2>(interface_displacement_jump(2)) +
281 Utility::pow<2>(delta_normal_pos) + _epsilon_tolerance);
282}
283
284void
286{
287 const auto delta_max = libmesh_map_find(_dof_to_delta_max, node);
288 const auto delta_initial = libmesh_map_find(_dof_to_delta_initial, node);
289 const auto delta_final = libmesh_map_find(_dof_to_delta_final, node);
290
291 auto & [damage, damage_old] = _dof_to_damage[node->id()];
292 if (delta_max < delta_initial)
293 damage = 0;
294 else if (delta_max > delta_final)
295 damage = 1.0;
296 else
297 damage = delta_final * (delta_max - delta_initial) / delta_max / (delta_final - delta_initial);
298
299 if (damage < damage_old)
300 // Irreversibility
301 damage = damage_old;
302
303 // Viscous regularization
304 damage = (damage + _viscosity * damage_old / _dt) / (_viscosity / _dt + 1.0);
305}
306
307void
326
327Real
329{
330 const auto it = _dof_to_mode_mixity_ratio.find(_subproblem.mesh().nodePtr(node->id()));
331
332 if (it != _dof_to_mode_mixity_ratio.end())
333 return MetaPhysicL::raw_value(it->second);
334 else
335 return 0.0;
336}
337
338Real
340{
341 const auto it = _dof_to_damage.find(node->id());
342
343 if (it != _dof_to_damage.end())
344 return MetaPhysicL::raw_value(it->second.first);
345 else
346 return 0.0;
347}
348
349Real
351{
352 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
353 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
354
355 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
356 return MetaPhysicL::raw_value(it->second(0) / it2->second.second);
357 else
358 return 0.0;
359}
360
361Real
366
367Real
369{
370 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
371 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
372
373 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
374 return MetaPhysicL::raw_value(it->second(1) / it2->second.second);
375 else
376 return 0.0;
377}
378
379Real
381{
382 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
383 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
384
385 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
386 return MetaPhysicL::raw_value(it->second(2) / it2->second.second);
387 else
388 return 0.0;
389}
390
391Real
393 const Node * const node) const
394{
395 using std::sqrt;
396
397 const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
398 const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
399
400 if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
401 {
402 // Take raw values before the sqrt: the AD derivative of sqrt divides by zero
403 // when the tangential jump is exactly zero (e.g. pure mode I or post-debond).
404 const auto tangential_one = MetaPhysicL::raw_value(it->second(1) / it2->second.second);
405 const auto tangential_two = MetaPhysicL::raw_value(it->second(2) / it2->second.second);
406 return sqrt(tangential_one * tangential_one + tangential_two * tangential_two);
407 }
408 else
409 return 0.0;
410}
411
412Real
414{
415 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
416
417 if (it != _dof_to_local_czm_traction.end())
418 return it->second(0);
419 else
420 return 0.0;
421}
422
423Real
425 const Node * const node) const
426{
427 using std::sqrt;
428
429 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
430
431 if (it != _dof_to_local_czm_traction.end())
432 return sqrt(it->second(1) * it->second(1) + it->second(2) * it->second(2));
433 else
434 return 0.0;
435}
436
437Real
439{
440 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
441
442 if (it != _dof_to_local_czm_traction.end())
443 return it->second(1);
444 else
445 return 0.0;
446}
447
448Real
450{
451 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
452
453 if (it != _dof_to_local_czm_traction.end())
454 return it->second(2);
455 else
456 return 0.0;
457}
458
459Real
461{
462 const auto it = _dof_to_local_czm_traction.find(_subproblem.mesh().nodePtr(node->id()));
463
464 if (it != _dof_to_local_czm_traction.end())
465 return it->second.norm();
466 else
467 return 0.0;
468}
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 addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
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)