LCOV - code coverage report
Current view: top level - src/convergence - AugmentedLagrangianContactConvergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose contact: 8601ad Lines: 45 48 93.8 %
Date: 2025-07-18 13:27:36 Functions: 6 6 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 "AugmentedLagrangianContactConvergence.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "AuxiliarySystem.h"
      14             : #include "DisplacedProblem.h"
      15             : #include "MooseApp.h"
      16             : #include "MooseMesh.h"
      17             : #include "MooseVariable.h"
      18             : #include "NearestNodeLocator.h"
      19             : #include "NonlinearSystem.h"
      20             : #include "PenetrationLocator.h"
      21             : #include "FEProblemBase.h"
      22             : #include "SystemBase.h"
      23             : #include "Assembly.h"
      24             : #include "Executioner.h"
      25             : #include "AddVariableAction.h"
      26             : #include "ConstraintWarehouse.h"
      27             : #include "MortarUserObject.h"
      28             : #include "AugmentedLagrangeInterface.h"
      29             : #include "DefaultNonlinearConvergence.h"
      30             : #include "ReferenceResidualConvergence.h"
      31             : #include "MechanicalContactConstraint.h"
      32             : 
      33             : registerMooseObject("ContactApp", AugmentedLagrangianContactReferenceConvergence);
      34             : registerMooseObject("ContactApp", AugmentedLagrangianContactFEProblemConvergence);
      35             : 
      36             : template <class T>
      37             : InputParameters
      38         537 : AugmentedLagrangianContactConvergence<T>::validParams()
      39             : {
      40         537 :   InputParameters params = T::validParams();
      41         537 :   params += AugmentedLagrangianContactProblemInterface::validParams();
      42         537 :   params.addClassDescription("Convergence for augmented Lagrangian contact");
      43         537 :   return params;
      44           0 : }
      45             : 
      46             : template <class T>
      47         287 : AugmentedLagrangianContactConvergence<T>::AugmentedLagrangianContactConvergence(
      48             :     const InputParameters & params)
      49         287 :   : T(params), AugmentedLagrangianContactProblemInterface(params)
      50             : {
      51         287 : }
      52             : 
      53             : template <class T>
      54             : Convergence::MooseConvergenceStatus
      55        1797 : AugmentedLagrangianContactConvergence<T>::checkConvergence(unsigned int iter)
      56             : {
      57             :   // Check convergence of the nonlinear problem
      58        1797 :   auto reason = T::checkConvergence(iter);
      59             : 
      60        1797 :   auto & fe_problem_base = this->getMooseApp().feProblem();
      61             : 
      62        1797 :   auto aug_contact = dynamic_cast<AugmentedLagrangianContactProblemInterface *>(&fe_problem_base);
      63        1797 :   _lagrangian_iteration_number = aug_contact->getLagrangianIterationNumber();
      64             : 
      65        1797 :   bool repeat_augmented_lagrange_step = false;
      66             : 
      67             :   // Nonlinear solve is converged, now check that the constraints are met
      68        1797 :   if (reason == Convergence::MooseConvergenceStatus::CONVERGED)
      69             :   {
      70         452 :     if (_lagrangian_iteration_number < _maximum_number_lagrangian_iterations)
      71             :     {
      72             : 
      73             :       auto & nonlinear_sys = fe_problem_base.currentNonlinearSystem();
      74         452 :       nonlinear_sys.update();
      75             : 
      76             :       // Get the penetration locator from the displaced mesh if it exist, otherwise get
      77             :       // it from the undisplaced mesh.
      78         452 :       const auto displaced_problem = fe_problem_base.getDisplacedProblem();
      79         452 :       const auto & penetration_locators = (displaced_problem ? displaced_problem->geomSearchData()
      80           0 :                                                              : fe_problem_base.geomSearchData())
      81             :                                               ._penetration_locators;
      82             : 
      83             :       // loop over contact pairs (penetration locators)
      84             :       const ConstraintWarehouse & constraints = nonlinear_sys.getConstraintWarehouse();
      85             :       std::list<std::shared_ptr<MechanicalContactConstraint>> mccs;
      86        1064 :       for (const auto & pair : penetration_locators)
      87             :       {
      88             :         const auto & boundaries = pair.first;
      89             : 
      90         612 :         if (!constraints.hasActiveNodeFaceConstraints(boundaries.second, bool(displaced_problem)))
      91         303 :           continue;
      92             :         const auto & ncs =
      93         309 :             constraints.getActiveNodeFaceConstraints(boundaries.second, bool(displaced_problem));
      94             : 
      95         309 :         mccs.emplace_back(nullptr);
      96         663 :         for (const auto & nc : ncs)
      97         510 :           if (const auto mcc = std::dynamic_pointer_cast<MechanicalContactConstraint>(nc); !mcc)
      98           0 :             mooseError("AugmentedLagrangianContactProblem: dynamic cast of "
      99             :                        "MechanicalContactConstraint object failed.");
     100             :           else
     101             :           {
     102             :             // Return if this constraint does not correspond to the primary-secondary pair
     103             :             // prepared by the outer loops.
     104             :             // This continue statement is required when, e.g. one secondary surface constrains
     105             :             // more than one primary surface.
     106         510 :             if (mcc->secondaryBoundary() != boundaries.second ||
     107         510 :                 mcc->primaryBoundary() != boundaries.first)
     108             :               continue;
     109             : 
     110             :             // save one constraint pointer for each contact pair
     111         510 :             if (!mccs.back())
     112             :               mccs.back() = mcc;
     113             : 
     114             :             // check if any of the constraints is not yet converged
     115         510 :             if (repeat_augmented_lagrange_step || !mcc->AugmentedLagrangianContactConverged())
     116             :             {
     117         156 :               repeat_augmented_lagrange_step = true;
     118             :               break;
     119             :             }
     120             :           }
     121             :       }
     122             : 
     123             :       // next loop over penalty mortar user objects
     124         452 :       const auto & pmuos = this->_app.template getInterfaceObjects<AugmentedLagrangeInterface>();
     125         595 :       for (auto * pmuo : pmuos)
     126             :       {
     127             :         // check if any of the constraints is not yet converged
     128         143 :         if (!repeat_augmented_lagrange_step && !pmuo->isAugmentedLagrangianConverged())
     129         117 :           repeat_augmented_lagrange_step = true;
     130             :       }
     131             : 
     132             :       // Communicate the repeat_augmented_lagrange_step in parallel.
     133             :       // If one proc needs to do another loop, all do.
     134         452 :       this->_communicator.max(repeat_augmented_lagrange_step);
     135             : 
     136             :       // repeat update step if necessary
     137         452 :       if (repeat_augmented_lagrange_step)
     138             :       {
     139         273 :         _lagrangian_iteration_number++;
     140             :         Moose::out << "Augmented Lagrangian contact repeat " << _lagrangian_iteration_number
     141             :                    << '\n';
     142             : 
     143             :         // Each contact pair will have constraints for all displacements, but those share the
     144             :         // Lagrange multipliers, which are stored on the penetration locator. We call update
     145             :         // only for the first constraint for each contact pair.
     146         429 :         for (const auto & mcc : mccs)
     147         156 :           mcc->updateAugmentedLagrangianMultiplier(/* beginning_of_step = */ false);
     148             : 
     149             :         // Update all penalty mortar user objects
     150         390 :         for (const auto & pmuo : pmuos)
     151         117 :           pmuo->updateAugmentedLagrangianMultipliers();
     152             : 
     153             :         // call AM setup again (e.g. to update active sets)
     154         390 :         for (const auto & pmuo : pmuos)
     155         117 :           pmuo->augmentedLagrangianSetup();
     156             : 
     157             :         // force it to keep iterating
     158             :         reason = Convergence::MooseConvergenceStatus::ITERATING;
     159             :         Moose::out << "Augmented Lagrangian Multiplier needs updating.";
     160             :       }
     161             :       else
     162             :         Moose::out << "Augmented Lagrangian contact constraint enforcement is satisfied.";
     163             :     }
     164             :     else
     165             :     {
     166             :       // maxed out
     167             :       Moose::out << "Maximum Augmented Lagrangian contact iterations have been reached.";
     168             :       reason = Convergence::MooseConvergenceStatus::DIVERGED;
     169             :     }
     170             :   }
     171             : 
     172        1797 :   return reason;
     173             : }
     174             : 
     175             : template class AugmentedLagrangianContactConvergence<ReferenceResidualConvergence>;
     176             : template class AugmentedLagrangianContactConvergence<DefaultNonlinearConvergence>;

Generated by: LCOV version 1.14