LCOV - code coverage report
Current view: top level - src/userobjects - BilinearMixedModeCohesiveZoneModel.C (source / functions) Hit Total Coverage
Test: idaholab/moose contact: 8601ad Lines: 247 259 95.4 %
Date: 2025-07-18 13:27:36 Functions: 28 29 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "BilinearMixedModeCohesiveZoneModel.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"
      18             : #include "FactorizedRankTwoTensor.h"
      19             : 
      20             : #include "ADReal.h"
      21             : #include "CohesiveZoneModelTools.h"
      22             : #include <Eigen/Core>
      23             : 
      24             : registerMooseObject("ContactApp", BilinearMixedModeCohesiveZoneModel);
      25             : 
      26             : InputParameters
      27         144 : BilinearMixedModeCohesiveZoneModel::validParams()
      28             : {
      29         144 :   InputParameters params = PenaltySimpleCohesiveZoneModel::validParams();
      30             : 
      31         144 :   params.addClassDescription("Computes the bilinear mixed mode cohesive zone model.");
      32         288 :   params.addRequiredCoupledVar("displacements",
      33             :                                "The string of displacements suitable for the problem statement");
      34             : 
      35             :   // Input parameters for bilinear mixed mode traction.
      36         288 :   params.addParam<MaterialPropertyName>("GI_c",
      37             :                                         "Critical energy release rate in normal direction.");
      38         288 :   params.addParam<MaterialPropertyName>("GII_c",
      39             :                                         "Critical energy release rate in shear direction.");
      40         288 :   params.addParam<MaterialPropertyName>("normal_strength", "Tensile strength in normal direction.");
      41         288 :   params.addParam<MaterialPropertyName>("shear_strength", "Tensile strength in shear direction.");
      42         288 :   params.addParam<Real>("power_law_parameter", "The power law parameter.");
      43         288 :   MooseEnum criterion("POWER_LAW BK", "BK");
      44         288 :   params.addParam<Real>("viscosity", 0.0, "Viscosity for damage model.");
      45         288 :   params.addParam<MooseEnum>(
      46             :       "mixed_mode_criterion", criterion, "Option for mixed mode propagation criterion.");
      47         288 :   params.addParam<bool>(
      48             :       "lag_displacement_jump",
      49         288 :       false,
      50             :       "Whether to use old displacement jumps to compute the effective displacement jump.");
      51         288 :   params.addParam<Real>(
      52         288 :       "regularization_alpha", 1e-10, "Regularization parameter for the Macaulay bracket.");
      53         288 :   params.addRangeCheckedParam<Real>(
      54             :       "penalty_stiffness", "penalty_stiffness > 0.0", "Penalty stiffness for CZM.");
      55         288 :   params.addParamNamesToGroup(
      56             :       "GI_c GII_c normal_strength shear_strength power_law_parameter viscosity "
      57             :       "mixed_mode_criterion lag_displacement_jump regularization_alpha "
      58             :       "penalty_stiffness",
      59             :       "Bilinear mixed mode traction");
      60             :   // End of input parameters for bilinear mixed mode traction.
      61             : 
      62             :   // Suppress augmented Lagrange parameters. AL implementation for CZM remains to be done.
      63         144 :   params.suppressParameter<Real>("max_penalty_multiplier");
      64         144 :   params.suppressParameter<Real>("penalty_multiplier");
      65         144 :   params.suppressParameter<Real>("penetration_tolerance");
      66         144 :   return params;
      67         144 : }
      68             : 
      69          72 : BilinearMixedModeCohesiveZoneModel::BilinearMixedModeCohesiveZoneModel(
      70          72 :     const InputParameters & parameters)
      71             :   : WeightedGapUserObject(parameters),
      72             :     PenaltyWeightedGapUserObject(parameters),
      73             :     WeightedVelocitiesUserObject(parameters),
      74             :     PenaltySimpleCohesiveZoneModel(parameters),
      75          72 :     _ndisp(coupledComponents("displacements")),
      76         144 :     _normal_strength(getMaterialProperty<Real>("normal_strength")),
      77         144 :     _shear_strength(getMaterialProperty<Real>("shear_strength")),
      78         144 :     _GI_c(getMaterialProperty<Real>("GI_c")),
      79         144 :     _GII_c(getMaterialProperty<Real>("GII_c")),
      80         144 :     _penalty_stiffness_czm(getParam<Real>("penalty_stiffness")),
      81         144 :     _mix_mode_criterion(getParam<MooseEnum>("mixed_mode_criterion").getEnum<MixedModeCriterion>()),
      82         144 :     _power_law_parameter(getParam<Real>("power_law_parameter")),
      83         144 :     _viscosity(getParam<Real>("viscosity")),
      84         288 :     _regularization_alpha(getParam<Real>("regularization_alpha"))
      85             : {
      86          72 :   _czm_interpolated_traction.resize(_ndisp);
      87             : 
      88         216 :   for (unsigned int i = 0; i < _ndisp; ++i)
      89             :   {
      90         144 :     _grad_disp.push_back(&adCoupledGradient("displacements", i));
      91         288 :     _grad_disp_neighbor.push_back(&adCoupledGradient("displacements", i));
      92             :   }
      93             : 
      94             :   // Set non-intervening components to zero
      95         144 :   for (unsigned int i = _ndisp; i < 3; i++)
      96             :   {
      97          72 :     _grad_disp.push_back(&_ad_grad_zero);
      98          72 :     _grad_disp_neighbor.push_back(&_ad_grad_zero);
      99             :   }
     100             : 
     101             :   // Checks for bilinear traction input.
     102         504 :   if (!isParamValid("GI_c") || !isParamValid("GII_c") || !isParamValid("normal_strength") ||
     103         504 :       !isParamValid("shear_strength") || !isParamValid("power_law_parameter") ||
     104         216 :       !isParamValid("penalty_stiffness"))
     105           0 :     paramError("GI_c",
     106             :                "The CZM bilinear mixed mode traction parameters GI_c, GII_c, normal_strength, "
     107             :                "shear_strength, and power_law_parameter are required. Revise your input and add "
     108             :                "those parameters if you want to use the bilinear mixed mode traction model. ");
     109          72 : }
     110             : 
     111             : void
     112       30068 : BilinearMixedModeCohesiveZoneModel::computeQpProperties()
     113             : {
     114       30068 :   WeightedVelocitiesUserObject::computeQpProperties();
     115             : 
     116             :   // Called after computeQpProperties() within the same algorithmic step.
     117             : 
     118             :   // Compute F and R.
     119       30068 :   const auto F = (ADRankTwoTensor::Identity() +
     120       60136 :                   ADRankTwoTensor::initializeFromRows(
     121       60136 :                       (*_grad_disp[0])[_qp], (*_grad_disp[1])[_qp], (*_grad_disp[2])[_qp]));
     122       30068 :   const auto F_neighbor = (ADRankTwoTensor::Identity() +
     123       60136 :                            ADRankTwoTensor::initializeFromRows((*_grad_disp_neighbor[0])[_qp],
     124       30068 :                                                                (*_grad_disp_neighbor[1])[_qp],
     125       60136 :                                                                (*_grad_disp_neighbor[2])[_qp]));
     126             : 
     127             :   // TODO in follow-on PRs: Trim interior node variable derivatives
     128       30068 :   _F_interpolation = F * (_JxW_msm[_qp] * _coord[_qp]);
     129       30068 :   _F_neighbor_interpolation = F_neighbor * (_JxW_msm[_qp] * _coord[_qp]);
     130       30068 :   _normal_strength_interpolation = _normal_strength[_qp] * _JxW_msm[_qp] * _coord[_qp];
     131       30068 :   _shear_strength_interpolation = _shear_strength[_qp] * _JxW_msm[_qp] * _coord[_qp];
     132       30068 :   _GI_c_interpolation = _GI_c[_qp] * _JxW_msm[_qp] * _coord[_qp];
     133       30068 :   _GII_c_interpolation = _GII_c[_qp] * _JxW_msm[_qp] * _coord[_qp];
     134       30068 : }
     135             : 
     136             : void
     137       60136 : BilinearMixedModeCohesiveZoneModel::computeQpIProperties()
     138             : {
     139       60136 :   WeightedVelocitiesUserObject::computeQpIProperties();
     140             : 
     141             :   // Get the _dof_to_weighted_gap map
     142       60136 :   const auto * const dof = static_cast<const DofObject *>(_lower_secondary_elem->node_ptr(_i));
     143             : 
     144             :   // TODO: Probably better to interpolate the deformation gradients.
     145      120272 :   _dof_to_F[dof] += (*_test)[_i][_qp] * _F_interpolation;
     146      120272 :   _dof_to_F_neighbor[dof] += (*_test)[_i][_qp] * _F_neighbor_interpolation;
     147      120272 :   _dof_to_normal_strength[dof] += (*_test)[_i][_qp] * _normal_strength_interpolation;
     148      120272 :   _dof_to_shear_strength[dof] += (*_test)[_i][_qp] * _shear_strength_interpolation;
     149             : 
     150      120272 :   _dof_to_GI_c[dof] += (*_test)[_i][_qp] * _GI_c_interpolation;
     151      120272 :   _dof_to_GII_c[dof] += (*_test)[_i][_qp] * _GII_c_interpolation;
     152       60136 : }
     153             : 
     154             : template <class T>
     155             : T
     156      360816 : BilinearMixedModeCohesiveZoneModel::normalizeQuantity(
     157             :     const std::unordered_map<const DofObject *, T> & map, const Node * const node)
     158             : {
     159      360816 :   return libmesh_map_find(map, node) / _dof_to_weighted_gap[node].second;
     160             : }
     161             : 
     162             : void
     163         585 : BilinearMixedModeCohesiveZoneModel::timestepSetup()
     164             : {
     165             :   // instead we call it explicitly here
     166         585 :   PenaltySimpleCohesiveZoneModel::timestepSetup();
     167             : 
     168             :   // save off tangential traction from the last timestep
     169        1996 :   for (auto & map_pr : _dof_to_damage)
     170             :   {
     171             :     auto & [damage, old_damage] = map_pr.second;
     172        1411 :     old_damage = {MetaPhysicL::raw_value(damage)};
     173        1411 :     damage = {0.0};
     174             :   }
     175             : 
     176         585 :   for (auto & [dof_object, delta_tangential_lm] : _dof_to_frictional_lagrange_multipliers)
     177             :     delta_tangential_lm.setZero();
     178         585 : }
     179             : 
     180             : void
     181        7091 : BilinearMixedModeCohesiveZoneModel::initialize()
     182             : {
     183             :   // instead we call it explicitly here
     184        7091 :   PenaltySimpleCohesiveZoneModel::initialize();
     185             : 
     186             :   // Avoid accumulating interpolation over the time step
     187             :   _dof_to_F.clear();
     188             :   _dof_to_F_neighbor.clear();
     189             :   _dof_to_mode_mixity_ratio.clear();
     190             :   _dof_to_normal_strength.clear();
     191             :   _dof_to_shear_strength.clear();
     192             :   _dof_to_GI_c.clear();
     193             :   _dof_to_GII_c.clear();
     194             :   _dof_to_delta_initial.clear();
     195             :   _dof_to_delta_final.clear();
     196             :   _dof_to_delta_max.clear();
     197             :   _dof_to_czm_traction.clear();
     198             :   _dof_to_interface_displacement_jump.clear();
     199        7091 :   _dof_to_czm_normal_traction.clear();
     200             :   _dof_to_interface_F.clear();
     201             :   _dof_to_interface_R.clear();
     202             : 
     203       21572 :   for (auto & map_pr : _dof_to_rotation_matrix)
     204       14481 :     map_pr.second.setToIdentity();
     205        7091 : }
     206             : 
     207             : void
     208       15034 : BilinearMixedModeCohesiveZoneModel::prepareJumpKinematicQuantities()
     209             : {
     210             :   // Compute rotation matrix from secondary surface
     211             :   // Rotation matrices and local interface displacement jump.
     212       45102 :   for (const auto i : make_range(_test->size()))
     213             :   {
     214       30068 :     const Node * const node = _lower_secondary_elem->node_ptr(i);
     215             : 
     216             :     // First call does not have maps available
     217       30068 :     const bool return_boolean = _dof_to_weighted_gap.find(node) == _dof_to_weighted_gap.end();
     218       30068 :     if (return_boolean)
     219           0 :       return;
     220             : 
     221       60136 :     _dof_to_rotation_matrix[node] = CohesiveZoneModelTools::computeReferenceRotation<true>(
     222       30068 :         _normals[i], _subproblem.mesh().dimension());
     223             : 
     224             :     // Every time we used quantities from a map we "denormalize" it from the mortar integral.
     225             :     // See normalizing member functions.
     226       30068 :     if (_dof_to_weighted_displacements.find(node) != _dof_to_weighted_displacements.end())
     227       60136 :       _dof_to_interface_displacement_jump[node] =
     228       30068 :           (libmesh_map_find(_dof_to_weighted_displacements, node));
     229             :   }
     230             : }
     231             : 
     232             : void
     233       30068 : BilinearMixedModeCohesiveZoneModel::computeFandR(const Node * const node)
     234             : {
     235             :   // First call does not have maps available
     236       30068 :   const bool return_boolean = _dof_to_F.find(node) == _dof_to_F.end();
     237       30068 :   if (return_boolean)
     238           0 :     return;
     239             : 
     240       30068 :   const auto normalized_F = normalizeQuantity(_dof_to_F, node);
     241       30068 :   const auto normalized_F_neighbor = normalizeQuantity(_dof_to_F_neighbor, node);
     242             : 
     243             :   // This 'averaging' assumption below can probably be improved upon.
     244       90204 :   _dof_to_interface_F[node] = 0.5 * (normalized_F + normalized_F_neighbor);
     245             : 
     246      120272 :   for (const auto i : make_range(3))
     247      360816 :     for (const auto j : make_range(3))
     248      270612 :       if (!std::isfinite(MetaPhysicL::raw_value(normalized_F(i, j))))
     249           0 :         throw MooseException(
     250             :             "The deformation gradient on the secondary surface is not finite in "
     251           0 :             "PenaltySimpleCohesiveZoneModel. MOOSE needs to cut the time step size.");
     252             : 
     253       30068 :   const auto dof_to_interface_F_node = libmesh_map_find(_dof_to_interface_F, node);
     254             : 
     255       30068 :   const ADFactorizedRankTwoTensor C = dof_to_interface_F_node.transpose() * dof_to_interface_F_node;
     256       30068 :   const auto Uinv = MathUtils::sqrt(C).inverse().get();
     257       60136 :   _dof_to_interface_R[node] = dof_to_interface_F_node * Uinv;
     258             : 
     259             :   // Transform interface jump according to two rotation matrices
     260       30068 :   const auto global_interface_displacement = _dof_to_interface_displacement_jump[node];
     261       60136 :   _dof_to_interface_displacement_jump[node] =
     262       30068 :       (_dof_to_interface_R[node] * _dof_to_rotation_matrix[node]).transpose() *
     263       30068 :       global_interface_displacement;
     264             : }
     265             : 
     266             : void
     267       30068 : BilinearMixedModeCohesiveZoneModel::computeBilinearMixedModeTraction(const Node * const node)
     268             : {
     269             :   // First call does not have maps available
     270       30068 :   const bool return_boolean = _dof_to_weighted_gap.find(node) == _dof_to_weighted_gap.end();
     271       30068 :   if (return_boolean)
     272           0 :     return;
     273             : 
     274       30068 :   computeModeMixity(node);
     275       30068 :   computeCriticalDisplacementJump(node);
     276       30068 :   computeFinalDisplacementJump(node);
     277       30068 :   computeEffectiveDisplacementJump(node);
     278       30068 :   computeDamage(node);
     279             : 
     280             :   // Split displacement jump into active and inactive parts
     281             :   const auto interface_displacement_jump =
     282       30068 :       normalizeQuantity(_dof_to_interface_displacement_jump, node);
     283             : 
     284       30068 :   const ADRealVectorValue delta_active(std::max(interface_displacement_jump(0), 0.0),
     285             :                                        interface_displacement_jump(1),
     286             :                                        interface_displacement_jump(2));
     287       30068 :   const ADRealVectorValue delta_inactive(std::min(interface_displacement_jump(0), 0.0), 0.0, 0.0);
     288             : 
     289             :   // This traction vector is local at this point.
     290       60136 :   _dof_to_czm_traction[node] =
     291       90204 :       -(1.0 - _dof_to_damage[node].first) * _penalty_stiffness_czm * delta_active -
     292       60136 :       _penalty_stiffness_czm * delta_inactive;
     293             : }
     294             : 
     295             : void
     296       30068 : BilinearMixedModeCohesiveZoneModel::computeGlobalTraction(const Node * const node)
     297             : {
     298             :   // First call does not have maps available
     299       30068 :   const bool return_boolean = _dof_to_czm_traction.find(node) == _dof_to_czm_traction.end();
     300       30068 :   if (return_boolean)
     301           0 :     return;
     302             : 
     303       30068 :   const auto local_traction_vector = libmesh_map_find(_dof_to_czm_traction, node);
     304       30068 :   const auto rotation_matrix = libmesh_map_find(_dof_to_rotation_matrix, node);
     305             : 
     306       60136 :   _dof_to_czm_traction[node] = rotation_matrix * local_traction_vector;
     307             : }
     308             : 
     309             : void
     310       30068 : BilinearMixedModeCohesiveZoneModel::computeModeMixity(const Node * const node)
     311             : {
     312             :   const auto interface_displacement_jump =
     313       30068 :       normalizeQuantity(_dof_to_interface_displacement_jump, node);
     314             : 
     315       30068 :   if (interface_displacement_jump(0) > _epsilon_tolerance)
     316             :   {
     317       26596 :     const auto delta_s = std::sqrt(interface_displacement_jump(1) * interface_displacement_jump(1) +
     318       26596 :                                    interface_displacement_jump(2) * interface_displacement_jump(2) +
     319       26596 :                                    _epsilon_tolerance);
     320             : 
     321       26596 :     _dof_to_mode_mixity_ratio[node] = delta_s / interface_displacement_jump(0);
     322             :   }
     323             :   else
     324        3472 :     _dof_to_mode_mixity_ratio[node] = 0;
     325       30068 : }
     326             : 
     327             : void
     328       30068 : BilinearMixedModeCohesiveZoneModel::computeCriticalDisplacementJump(const Node * const node)
     329             : {
     330             :   const auto interface_displacement_jump =
     331       30068 :       normalizeQuantity(_dof_to_interface_displacement_jump, node);
     332             : 
     333       30068 :   const auto mixity_ratio = libmesh_map_find(_dof_to_mode_mixity_ratio, node);
     334             : 
     335             :   const auto delta_normal_knot =
     336       30068 :       normalizeQuantity(_dof_to_normal_strength, node) / _penalty_stiffness_czm;
     337             :   const auto delta_shear_knot =
     338       30068 :       normalizeQuantity(_dof_to_shear_strength, node) / _penalty_stiffness_czm;
     339             : 
     340       30068 :   _dof_to_delta_initial[node] = delta_shear_knot;
     341             : 
     342       30068 :   if (interface_displacement_jump(0) > _epsilon_tolerance)
     343             :   {
     344       26596 :     const auto delta_mixed = std::sqrt(delta_shear_knot * delta_shear_knot +
     345       26596 :                                        Utility::pow<2>(mixity_ratio * delta_normal_knot));
     346             : 
     347       53192 :     _dof_to_delta_initial[node] = delta_normal_knot * delta_shear_knot *
     348       79788 :                                   std::sqrt(1.0 + mixity_ratio * mixity_ratio) / delta_mixed;
     349             :   }
     350       30068 : }
     351             : 
     352             : void
     353       30068 : BilinearMixedModeCohesiveZoneModel::computeFinalDisplacementJump(const Node * const node)
     354             : {
     355             :   const auto interface_displacement_jump =
     356       30068 :       normalizeQuantity(_dof_to_interface_displacement_jump, node);
     357             : 
     358       30068 :   const auto mixity_ratio = libmesh_map_find(_dof_to_mode_mixity_ratio, node);
     359             : 
     360       30068 :   const auto normalized_GI_c = normalizeQuantity(_dof_to_GI_c, node);
     361       30068 :   const auto normalized_GII_c = normalizeQuantity(_dof_to_GII_c, node);
     362             : 
     363       60136 :   _dof_to_delta_final[node] =
     364       60136 :       std::sqrt(2.0) * 2.0 * normalized_GII_c / normalizeQuantity(_dof_to_shear_strength, node);
     365             : 
     366       30068 :   if (interface_displacement_jump(0) > _epsilon_tolerance)
     367             :   {
     368       26596 :     if (_mix_mode_criterion == MixedModeCriterion::BK)
     369             :     {
     370       18524 :       _dof_to_delta_final[node] =
     371        9262 :           2.0 / _penalty_stiffness_czm / libmesh_map_find(_dof_to_delta_initial, node) *
     372        9262 :           (normalized_GI_c +
     373        9262 :            (normalized_GII_c - normalized_GI_c) *
     374       27786 :                std::pow(mixity_ratio * mixity_ratio / (1 + mixity_ratio * mixity_ratio),
     375       18524 :                         _power_law_parameter));
     376             :     }
     377       17334 :     else if (_mix_mode_criterion == MixedModeCriterion::POWER_LAW)
     378             :     {
     379             :       const auto Gc_mixed =
     380       34668 :           std::pow(1.0 / normalized_GI_c, _power_law_parameter) +
     381       34668 :           std::pow(mixity_ratio * mixity_ratio / normalized_GII_c, _power_law_parameter);
     382       52002 :       _dof_to_delta_final[node] = (2.0 + 2.0 * mixity_ratio * mixity_ratio) /
     383       17334 :                                   _penalty_stiffness_czm /
     384       17334 :                                   libmesh_map_find(_dof_to_delta_initial, node) *
     385       34668 :                                   std::pow(Gc_mixed, -1.0 / _power_law_parameter);
     386             :     }
     387             :   }
     388       30068 : }
     389             : 
     390             : void
     391       30068 : BilinearMixedModeCohesiveZoneModel::computeEffectiveDisplacementJump(const Node * const node)
     392             : {
     393             :   const auto interface_displacement_jump =
     394       30068 :       normalizeQuantity(_dof_to_interface_displacement_jump, node);
     395             : 
     396             :   const auto delta_normal_pos =
     397       30068 :       MathUtils::regularizedHeavyside(interface_displacement_jump(0), _regularization_alpha) *
     398             :       interface_displacement_jump(0);
     399             : 
     400       60136 :   _dof_to_delta_max[node] = std::sqrt(Utility::pow<2>(interface_displacement_jump(1)) +
     401       30068 :                                       Utility::pow<2>(interface_displacement_jump(2)) +
     402       60136 :                                       Utility::pow<2>(delta_normal_pos) + _epsilon_tolerance);
     403       30068 : }
     404             : 
     405             : void
     406       30068 : BilinearMixedModeCohesiveZoneModel::computeDamage(const Node * const node)
     407             : {
     408       30068 :   const auto delta_max = libmesh_map_find(_dof_to_delta_max, node);
     409       30068 :   const auto delta_initial = libmesh_map_find(_dof_to_delta_initial, node);
     410       30068 :   const auto delta_final = libmesh_map_find(_dof_to_delta_final, node);
     411             : 
     412       30068 :   if (delta_max < delta_initial)
     413       30068 :     _dof_to_damage[node].first = 0;
     414           0 :   else if (delta_max > delta_final)
     415           0 :     _dof_to_damage[node].first = 1.0;
     416             :   else
     417           0 :     _dof_to_damage[node].first =
     418           0 :         delta_final * (delta_max - delta_initial) / delta_max / (delta_final - delta_initial);
     419             : 
     420       30068 :   if (_dof_to_damage[node].first < _dof_to_damage[node].second)
     421             :     // Irreversibility
     422           0 :     _dof_to_damage[node].first = _dof_to_damage[node].second;
     423             : 
     424             :   // Viscous regularization
     425       30068 :   _dof_to_damage[node].first =
     426       30068 :       (_dof_to_damage[node].first + _viscosity * _dof_to_damage[node].second / _dt) /
     427       60136 :       (_viscosity / _dt + 1.0);
     428       30068 : }
     429             : 
     430             : void
     431       15034 : BilinearMixedModeCohesiveZoneModel::reinit()
     432             : {
     433             :   // Normal contact pressure with penalty
     434       15034 :   PenaltySimpleCohesiveZoneModel::reinit();
     435             : 
     436       45102 :   for (const auto i : index_range(_czm_interpolated_traction))
     437             :   {
     438       30068 :     _czm_interpolated_traction[i].resize(_qrule_msm->n_points());
     439             : 
     440       90204 :     for (const auto qp : make_range(_qrule_msm->n_points()))
     441       60136 :       _czm_interpolated_traction[i][qp] = 0.0;
     442             :   }
     443             : 
     444             :   // iterate over nodes
     445       45102 :   for (const auto i : make_range(_test->size()))
     446             :   {
     447             :     // current node
     448       30068 :     const Node * const node = _lower_secondary_elem->node_ptr(i);
     449             : 
     450             :     // End of CZM bilinear computations
     451       30068 :     if (_dof_to_czm_traction.find(node) == _dof_to_czm_traction.end())
     452             :       return;
     453             : 
     454       30068 :     const auto & test_i = (*_test)[i];
     455       90204 :     for (const auto qp : make_range(_qrule_msm->n_points()))
     456      180408 :       for (const auto idx : index_range(_czm_interpolated_traction))
     457      240544 :         _czm_interpolated_traction[idx][qp] += test_i[qp] * _dof_to_czm_traction[node](idx);
     458             :   }
     459             : }
     460             : 
     461             : void
     462        7091 : BilinearMixedModeCohesiveZoneModel::finalize()
     463             : {
     464        7091 :   PenaltySimpleCohesiveZoneModel::finalize();
     465             : 
     466        7091 :   const bool send_data_back = !constrainedByOwner();
     467             : 
     468       14182 :   Moose::Mortar::Contact::communicateR2T(
     469        7091 :       _dof_to_F, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     470             : 
     471       14182 :   Moose::Mortar::Contact::communicateR2T(
     472        7091 :       _dof_to_F_neighbor, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     473             : 
     474       14182 :   Moose::Mortar::Contact::communicateRealObject(
     475        7091 :       _dof_to_normal_strength, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     476             : 
     477       14182 :   Moose::Mortar::Contact::communicateRealObject(
     478        7091 :       _dof_to_shear_strength, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     479             : 
     480       14182 :   Moose::Mortar::Contact::communicateRealObject(
     481        7091 :       _dof_to_GI_c, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     482             : 
     483       14182 :   Moose::Mortar::Contact::communicateRealObject(
     484        7091 :       _dof_to_GII_c, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     485             : 
     486       14182 :   Moose::Mortar::Contact::communicateRealObject(
     487        7091 :       _dof_to_weighted_displacements, _subproblem.mesh(), _nodal, _communicator, send_data_back);
     488        7091 : }
     489             : 
     490             : const ADVariableValue &
     491      240544 : BilinearMixedModeCohesiveZoneModel::czmGlobalTraction(const unsigned int i) const
     492             : {
     493             :   mooseAssert(i <= 3,
     494             :               "Internal error in czmGlobalTraction. Index exceeds the traction vector size.");
     495             : 
     496      240544 :   return _czm_interpolated_traction[i];
     497             : }
     498             : 
     499             : Real
     500         960 : BilinearMixedModeCohesiveZoneModel::getModeMixityRatio(const Node * const node) const
     501             : {
     502         960 :   const auto it = _dof_to_mode_mixity_ratio.find(_subproblem.mesh().nodePtr(node->id()));
     503             : 
     504         960 :   if (it != _dof_to_mode_mixity_ratio.end())
     505         960 :     return MetaPhysicL::raw_value(it->second);
     506             :   else
     507             :     return 0.0;
     508             : }
     509             : 
     510             : Real
     511         960 : BilinearMixedModeCohesiveZoneModel::getCohesiveDamage(const Node * const node) const
     512             : {
     513         960 :   const auto it = _dof_to_damage.find(_subproblem.mesh().nodePtr(node->id()));
     514             : 
     515         960 :   if (it != _dof_to_damage.end())
     516         960 :     return MetaPhysicL::raw_value(it->second.first);
     517             :   else
     518             :     return 0.0;
     519             : }
     520             : 
     521             : Real
     522         960 : BilinearMixedModeCohesiveZoneModel::getLocalDisplacementNormal(const Node * const node) const
     523             : {
     524         960 :   const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
     525         960 :   const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
     526             : 
     527         960 :   if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
     528        1920 :     return MetaPhysicL::raw_value(it->second(0) / it2->second.second);
     529             :   else
     530             :     return 0.0;
     531             : }
     532             : 
     533             : Real
     534         960 : BilinearMixedModeCohesiveZoneModel::getLocalDisplacementTangential(const Node * const node) const
     535             : {
     536         960 :   const auto it = _dof_to_interface_displacement_jump.find(_subproblem.mesh().nodePtr(node->id()));
     537         960 :   const auto it2 = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
     538             : 
     539         960 :   if (it != _dof_to_interface_displacement_jump.end() && it2 != _dof_to_weighted_gap.end())
     540        1920 :     return MetaPhysicL::raw_value(it->second(1) / it2->second.second);
     541             :   else
     542             :     return 0.0;
     543             : }

Generated by: LCOV version 1.14