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>;