LCOV - code coverage report
Current view: top level - src/dampers - ContactSlipDamper.C (source / functions) Hit Total Coverage
Test: idaholab/moose contact: 8601ad Lines: 111 124 89.5 %
Date: 2025-07-18 13:27:36 Functions: 5 5 100.0 %
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 "ContactSlipDamper.h"
      11             : #include "FEProblem.h"
      12             : #include "DisplacedProblem.h"
      13             : #include "AuxiliarySystem.h"
      14             : #include "PenetrationLocator.h"
      15             : #include "NearestNodeLocator.h"
      16             : 
      17             : registerMooseObject("ContactApp", ContactSlipDamper);
      18             : 
      19             : InputParameters
      20         234 : ContactSlipDamper::validParams()
      21             : {
      22         234 :   InputParameters params = GeneralDamper::validParams();
      23         468 :   params.addParam<std::vector<BoundaryName>>(
      24             :       "primary", "IDs of the primary surfaces for which slip reversals should be damped");
      25         468 :   params.addParam<std::vector<BoundaryName>>(
      26             :       "secondary", "IDs of the secondary surfaces for which slip reversals should be damped");
      27         468 :   params.addParam<Real>(
      28         468 :       "max_iterative_slip", std::numeric_limits<Real>::max(), "Maximum iterative slip");
      29         702 :   params.addRangeCheckedParam<Real>("min_damping_factor",
      30         468 :                                     0.0,
      31             :                                     "min_damping_factor < 1.0",
      32             :                                     "Minimum permissible value for damping factor");
      33         468 :   params.addParam<Real>("damping_threshold_factor",
      34         468 :                         1.0e3,
      35             :                         "If previous iterations's slip is below the slip tolerance, "
      36             :                         "only damp a slip reversal if the slip magnitude is greater "
      37             :                         "than than this factor times the old slip.");
      38         468 :   params.addParam<bool>("debug_output", false, "Output detailed debugging information");
      39         234 :   params.addClassDescription(
      40             :       "Damp the iterative solution to minimize oscillations in frictional contact "
      41             :       "constriants between nonlinear iterations");
      42         234 :   return params;
      43           0 : }
      44             : 
      45         117 : ContactSlipDamper::ContactSlipDamper(const InputParameters & parameters)
      46             :   : GeneralDamper(parameters),
      47         117 :     _aux_sys(parameters.get<FEProblemBase *>("_fe_problem_base")->getAuxiliarySystem()),
      48         117 :     _displaced_problem(parameters.get<FEProblemBase *>("_fe_problem_base")->getDisplacedProblem()),
      49         117 :     _num_contact_nodes(0),
      50         117 :     _num_sticking(0),
      51         117 :     _num_slipping(0),
      52         117 :     _num_slipping_friction(0),
      53         117 :     _num_stick_locked(0),
      54         117 :     _num_slip_reversed(0),
      55         117 :     _max_iterative_slip(parameters.get<Real>("max_iterative_slip")),
      56         117 :     _min_damping_factor(parameters.get<Real>("min_damping_factor")),
      57         117 :     _damping_threshold_factor(parameters.get<Real>("damping_threshold_factor")),
      58         351 :     _debug_output(parameters.get<bool>("debug_output"))
      59             : {
      60         117 :   if (!_displaced_problem)
      61           0 :     mooseError("Must have displaced problem to use ContactSlipDamper");
      62             : 
      63         234 :   std::vector<BoundaryName> primary = getParam<std::vector<BoundaryName>>("primary");
      64         351 :   std::vector<BoundaryName> secondary = getParam<std::vector<BoundaryName>>("secondary");
      65             : 
      66         117 :   unsigned int num_interactions = primary.size();
      67         117 :   if (num_interactions != secondary.size())
      68           0 :     mooseError(
      69             :         "Sizes of primary surface and secondary surface lists must match in ContactSlipDamper");
      70         117 :   if (num_interactions == 0)
      71           0 :     mooseError("Must define at least one primary/secondary pair in ContactSlipDamper");
      72             : 
      73         234 :   for (unsigned int i = 0; i < primary.size(); ++i)
      74             :   {
      75         117 :     std::pair<int, int> ms_pair(_subproblem.mesh().getBoundaryID(primary[i]),
      76         117 :                                 _subproblem.mesh().getBoundaryID(secondary[i]));
      77         117 :     _interactions.insert(ms_pair);
      78             :   }
      79         117 : }
      80             : 
      81             : void
      82         540 : ContactSlipDamper::timestepSetup()
      83             : {
      84         540 :   GeometricSearchData & displaced_geom_search_data = _displaced_problem->geomSearchData();
      85             :   const auto & penetration_locators = displaced_geom_search_data._penetration_locators;
      86             : 
      87        1080 :   for (const auto & pl : penetration_locators)
      88             :   {
      89         540 :     PenetrationLocator & pen_loc = *pl.second;
      90             : 
      91         540 :     if (operateOnThisInteraction(pen_loc))
      92             :     {
      93        2940 :       for (const auto & secondary_node_num : pen_loc._nearest_node._secondary_nodes)
      94        2400 :         if (pen_loc._penetration_info[secondary_node_num])
      95             :         {
      96        2360 :           PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
      97        2360 :           const Node & node = _displaced_problem->mesh().nodeRef(secondary_node_num);
      98             : 
      99        2360 :           if (node.processor_id() == processor_id())
     100             :             //              && info.isCaptured())                  //TODO maybe just set this
     101             :             //              everywhere?
     102        1660 :             info._slip_reversed = false;
     103             :         }
     104             :     }
     105             :   }
     106         540 : }
     107             : 
     108             : Real
     109        3547 : ContactSlipDamper::computeDamping(const NumericVector<Number> & solution,
     110             :                                   const NumericVector<Number> & /*update*/)
     111             : {
     112             :   std::map<unsigned int, const NumericVector<Number> *> nl_soln;
     113        3547 :   nl_soln.emplace(_sys.number(), &solution);
     114             : 
     115             :   // Do new contact search to update positions of slipped nodes
     116        3547 :   _displaced_problem->updateMesh(nl_soln, *_aux_sys.currentSolution());
     117             : 
     118        3547 :   Real damping = 1.0;
     119             : 
     120        3547 :   _num_contact_nodes = 0;
     121        3547 :   _num_sticking = 0;
     122        3547 :   _num_slipping = 0;
     123        3547 :   _num_slipping_friction = 0;
     124        3547 :   _num_stick_locked = 0;
     125        3547 :   _num_slip_reversed = 0;
     126             : 
     127        3547 :   GeometricSearchData & displaced_geom_search_data = _displaced_problem->geomSearchData();
     128             :   const auto & penetration_locators = displaced_geom_search_data._penetration_locators;
     129             : 
     130        7094 :   for (const auto & pl : penetration_locators)
     131             :   {
     132        3547 :     PenetrationLocator & pen_loc = *pl.second;
     133             : 
     134        3547 :     if (operateOnThisInteraction(pen_loc))
     135             :     {
     136       20162 :       for (const auto & secondary_node_num : pen_loc._nearest_node._secondary_nodes)
     137       16615 :         if (pen_loc._penetration_info[secondary_node_num])
     138             :         {
     139       16395 :           PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
     140       16395 :           const Node & node = _displaced_problem->mesh().nodeRef(secondary_node_num);
     141             : 
     142       16395 :           if (node.processor_id() == processor_id())
     143             :           {
     144       10590 :             if (info.isCaptured())
     145             :             {
     146        6780 :               _num_contact_nodes++;
     147        6780 :               if (info._mech_status == PenetrationInfo::MS_STICKING)
     148         324 :                 _num_sticking++;
     149        6456 :               else if (info._mech_status == PenetrationInfo::MS_SLIPPING)
     150          66 :                 _num_slipping++;
     151        6390 :               else if (info._mech_status == PenetrationInfo::MS_SLIPPING_FRICTION)
     152        6390 :                 _num_slipping_friction++;
     153        6780 :               if (info._stick_locked_this_step >= 2) // TODO get from contact interaction
     154         334 :                 _num_stick_locked++;
     155             : 
     156             :               RealVectorValue tangential_inc_slip_prev_iter =
     157             :                   info._incremental_slip_prev_iter -
     158             :                   (info._incremental_slip_prev_iter * info._normal) * info._normal;
     159             :               RealVectorValue tangential_inc_slip =
     160             :                   info._incremental_slip - (info._incremental_slip * info._normal) * info._normal;
     161             : 
     162             :               RealVectorValue tangential_it_slip =
     163             :                   tangential_inc_slip - tangential_inc_slip_prev_iter;
     164        6780 :               Real node_damping_factor = 1.0;
     165        6780 :               if ((tangential_inc_slip_prev_iter * tangential_inc_slip < 0.0) &&
     166             :                   info._mech_status == PenetrationInfo::MS_SLIPPING_FRICTION)
     167             :               {
     168         132 :                 info._slip_reversed = true;
     169         132 :                 _num_slip_reversed++;
     170         132 :                 Real prev_iter_slip_mag = tangential_inc_slip_prev_iter.norm();
     171             :                 RealVectorValue prev_iter_slip_dir =
     172             :                     tangential_inc_slip_prev_iter / prev_iter_slip_mag;
     173             :                 Real cur_it_slip_in_old_dir = tangential_it_slip * prev_iter_slip_dir;
     174             : 
     175         132 :                 if (prev_iter_slip_mag > info._slip_tol ||
     176          16 :                     cur_it_slip_in_old_dir > -_damping_threshold_factor * prev_iter_slip_mag)
     177         116 :                   node_damping_factor =
     178         116 :                       1.0 - (cur_it_slip_in_old_dir + prev_iter_slip_mag) / cur_it_slip_in_old_dir;
     179             : 
     180         132 :                 if (node_damping_factor < 0.0)
     181           0 :                   mooseError("Damping factor can't be negative");
     182             : 
     183         132 :                 if (node_damping_factor < _min_damping_factor)
     184           0 :                   node_damping_factor = _min_damping_factor;
     185             :               }
     186             : 
     187        6780 :               if (tangential_it_slip.norm() > _max_iterative_slip)
     188           0 :                 node_damping_factor =
     189           0 :                     (tangential_it_slip.norm() - _max_iterative_slip) / tangential_it_slip.norm();
     190             : 
     191        6780 :               if (_debug_output && node_damping_factor < 1.0)
     192           0 :                 _console << "Damping node: " << node.id()
     193           0 :                          << " prev iter slip: " << info._incremental_slip_prev_iter
     194           0 :                          << " curr iter slip: " << info._incremental_slip
     195           0 :                          << " slip_tol: " << info._slip_tol
     196           0 :                          << " damping factor: " << node_damping_factor << std::endl;
     197             : 
     198        6780 :               if (node_damping_factor < damping)
     199         116 :                 damping = node_damping_factor;
     200             :             }
     201             :           }
     202             :         }
     203             :     }
     204             :   }
     205        3547 :   _console << std::flush;
     206        3547 :   _communicator.sum(_num_contact_nodes);
     207        3547 :   _communicator.sum(_num_sticking);
     208        3547 :   _communicator.sum(_num_slipping);
     209        3547 :   _communicator.sum(_num_slipping_friction);
     210        3547 :   _communicator.sum(_num_stick_locked);
     211        3547 :   _communicator.sum(_num_slip_reversed);
     212        3547 :   _communicator.min(damping);
     213             : 
     214             :   _console << "   ContactSlipDamper: Damping     #Cont    #Stick     #Slip #SlipFric #StickLock  "
     215        3547 :               "#SlipRev\n";
     216             : 
     217        3547 :   _console << std::right << std::setw(29) << damping << std::setw(10) << _num_contact_nodes
     218        3547 :            << std::setw(10) << _num_sticking << std::setw(10) << _num_slipping << std::setw(10)
     219        3547 :            << _num_slipping_friction << std::setw(11) << _num_stick_locked << std::setw(10)
     220        3547 :            << _num_slip_reversed << "\n\n";
     221        3547 :   _console << std::flush;
     222             : 
     223        3547 :   return damping;
     224             : }
     225             : 
     226             : bool
     227        4087 : ContactSlipDamper::operateOnThisInteraction(const PenetrationLocator & pen_loc)
     228             : {
     229             :   bool operate_on_this_interaction = false;
     230             :   std::set<std::pair<int, int>>::iterator ipit;
     231             :   std::pair<int, int> ms_pair(pen_loc._primary_boundary, pen_loc._secondary_boundary);
     232             :   ipit = _interactions.find(ms_pair);
     233        4087 :   if (ipit != _interactions.end())
     234             :     operate_on_this_interaction = true;
     235        4087 :   return operate_on_this_interaction;
     236             : }

Generated by: LCOV version 1.14