https://mooseframework.inl.gov
AugmentedLagrangianContactConvergence.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 
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"
32 
35 
36 template <class T>
39 {
42  params.addClassDescription("Convergence for augmented Lagrangian contact");
43  return params;
44 }
45 
46 template <class T>
48  const InputParameters & params)
50 {
51 }
52 
53 template <class T>
56 {
57  // Check convergence of the nonlinear problem
58  auto reason = T::checkConvergence(iter);
59 
60  auto & fe_problem_base = this->getMooseApp().feProblem();
61 
62  auto aug_contact = dynamic_cast<AugmentedLagrangianContactProblemInterface *>(&fe_problem_base);
63  _lagrangian_iteration_number = aug_contact->getLagrangianIterationNumber();
64 
65  bool repeat_augmented_lagrange_step = false;
66 
67  // Nonlinear solve is converged, now check that the constraints are met
69  {
70  if (_lagrangian_iteration_number < _maximum_number_lagrangian_iterations)
71  {
72 
73  auto & nonlinear_sys = fe_problem_base.currentNonlinearSystem();
74  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  const auto displaced_problem = fe_problem_base.getDisplacedProblem();
79  const auto & penetration_locators = (displaced_problem ? displaced_problem->geomSearchData()
80  : 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  for (const auto & pair : penetration_locators)
87  {
88  const auto & boundaries = pair.first;
89 
90  if (!constraints.hasActiveNodeFaceConstraints(boundaries.second, bool(displaced_problem)))
91  continue;
92  const auto & ncs =
93  constraints.getActiveNodeFaceConstraints(boundaries.second, bool(displaced_problem));
94 
95  mccs.emplace_back(nullptr);
96  for (const auto & nc : ncs)
97  if (const auto mcc = std::dynamic_pointer_cast<MechanicalContactConstraint>(nc); !mcc)
98  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  if (mcc->secondaryBoundary() != boundaries.second ||
107  mcc->primaryBoundary() != boundaries.first)
108  continue;
109 
110  // save one constraint pointer for each contact pair
111  if (!mccs.back())
112  mccs.back() = mcc;
113 
114  // check if any of the constraints is not yet converged
115  if (repeat_augmented_lagrange_step || !mcc->AugmentedLagrangianContactConverged())
116  {
117  repeat_augmented_lagrange_step = true;
118  break;
119  }
120  }
121  }
122 
123  // next loop over penalty mortar user objects
124  const auto & pmuos = this->_app.template getInterfaceObjects<AugmentedLagrangeInterface>();
125  for (auto * pmuo : pmuos)
126  {
127  // check if any of the constraints is not yet converged
128  if (!repeat_augmented_lagrange_step && !pmuo->isAugmentedLagrangianConverged())
129  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  this->_communicator.max(repeat_augmented_lagrange_step);
135 
136  // repeat update step if necessary
137  if (repeat_augmented_lagrange_step)
138  {
139  _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  for (const auto & mcc : mccs)
147  mcc->updateAugmentedLagrangianMultiplier(/* beginning_of_step = */ false);
148 
149  // Update all penalty mortar user objects
150  for (const auto & pmuo : pmuos)
151  pmuo->updateAugmentedLagrangianMultipliers();
152 
153  // call AM setup again (e.g. to update active sets)
154  for (const auto & pmuo : pmuos)
155  pmuo->augmentedLagrangianSetup();
156 
157  // force it to keep 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.";
169  }
170  }
171 
172  return reason;
173 }
174 
std::shared_ptr< DisplacedProblem > displaced_problem
void mooseError(Args &&... args)
const std::vector< std::shared_ptr< NodeFaceConstraint > > & getActiveNodeFaceConstraints(BoundaryID boundary_id, bool displaced) const
bool hasActiveNodeFaceConstraints(BoundaryID boundary_id, bool displaced) const
InputParameters validParams()
Class to check convergence for the augmented Lagrangian contact problem.
virtual Convergence::MooseConvergenceStatus checkConvergence(unsigned int iter) override
Class to provide an interface for parameters and routines required to check convergence for the augme...
AugmentedLagrangianContactConvergence(const InputParameters &params)
void addClassDescription(const std::string &doc_string)
registerMooseObject("ContactApp", AugmentedLagrangianContactReferenceConvergence)