LCOV - code coverage report
Current view: top level - src/userobjects - LMWeightedGapUserObject.C (source / functions) Hit Total Coverage
Test: idaholab/moose contact: #33390 (250e9c) with base 846a5c Lines: 39 47 83.0 %
Date: 2026-07-31 18:16:12 Functions: 9 9 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 "LMWeightedGapUserObject.h"
      11             : #include "MooseVariableFE.h"
      12             : #include "SystemBase.h"
      13             : 
      14             : registerMooseObject("ContactApp", LMWeightedGapUserObject);
      15             : 
      16             : InputParameters
      17        1308 : LMWeightedGapUserObject::newParams()
      18             : {
      19        1308 :   auto params = emptyInputParameters();
      20        2616 :   params.addRequiredCoupledVar(
      21             :       "lm_variable", "The Lagrange multiplier variable representing the contact pressure.");
      22        2616 :   params.addParam<bool>(
      23        2616 :       "use_petrov_galerkin", false, "Whether to use the Petrov-Galerkin approach.");
      24        2616 :   params.addCoupledVar("aux_lm",
      25             :                        "Auxiliary Lagrange multiplier variable that is utilized together with the "
      26             :                        "Petrov-Galerkin approach.");
      27        1308 :   return params;
      28           0 : }
      29             : 
      30             : InputParameters
      31         830 : LMWeightedGapUserObject::validParams()
      32             : {
      33         830 :   InputParameters params = WeightedGapUserObject::validParams();
      34         830 :   params.addClassDescription(
      35             :       "Provides the mortar normal Lagrange multiplier for constraint enforcement.");
      36         830 :   params.set<bool>("allow_nodal_normal_derivatives") = true;
      37         830 :   params += LMWeightedGapUserObject::newParams();
      38         830 :   return params;
      39           0 : }
      40             : 
      41         656 : LMWeightedGapUserObject::LMWeightedGapUserObject(const InputParameters & parameters)
      42             :   : WeightedGapUserObject(parameters),
      43         652 :     _lm_var(getVar("lm_variable", 0)),
      44        1304 :     _use_petrov_galerkin(getParam<bool>("use_petrov_galerkin")),
      45        1350 :     _aux_lm_var(isCoupled("aux_lm") ? getVar("aux_lm", 0) : nullptr)
      46             : {
      47         652 :   checkInput(_lm_var, "lm_variable");
      48         652 :   verifyLagrange(*_lm_var, "lm_variable");
      49             : 
      50         736 :   if (_use_petrov_galerkin && ((!isParamValid("aux_lm")) || _aux_lm_var == nullptr))
      51           0 :     paramError("use_petrov_galerkin",
      52             :                "We need to specify an auxiliary variable `aux_lm` while using the Petrov-Galerkin "
      53             :                "approach");
      54             : 
      55         652 :   if (_use_petrov_galerkin && _aux_lm_var->useDual())
      56           0 :     paramError("aux_lm",
      57             :                "Auxiliary LM variable needs to use standard shape function, i.e., set `use_dual = "
      58             :                "false`.");
      59         652 : }
      60             : 
      61             : void
      62         964 : LMWeightedGapUserObject::checkInput(const MooseVariable * const var,
      63             :                                     const std::string & var_param_name) const
      64             : {
      65         964 :   if (isCoupledConstant(var_param_name))
      66           0 :     paramError(var_param_name,
      67             :                "The Lagrange multiplier variable must be an actual variable and not a constant.");
      68         964 :   else if (!var)
      69           0 :     paramError(var_param_name,
      70             :                "The Lagrange multiplier variables must be provided and be actual variables.");
      71         964 : }
      72             : 
      73             : void
      74         964 : LMWeightedGapUserObject::verifyLagrange(const MooseVariable & var,
      75             :                                         const std::string & var_param_name) const
      76             : {
      77         964 :   if (var.feType().family != LAGRANGE)
      78           0 :     paramError(var_param_name, "The Lagrange multiplier variables must be of Lagrange type");
      79         964 : }
      80             : 
      81             : const VariableTestValue &
      82         629 : LMWeightedGapUserObject::test() const
      83             : {
      84         629 :   return _use_petrov_galerkin ? _aux_lm_var->phiLower() : _lm_var->phiLower();
      85             : }
      86             : 
      87             : const ADVariableValue &
      88   203356868 : LMWeightedGapUserObject::contactPressure() const
      89             : {
      90   203356868 :   return _lm_var->adSlnLower();
      91             : }
      92             : 
      93             : Real
      94       11269 : LMWeightedGapUserObject::getNormalContactPressure(const Node * const node) const
      95             : {
      96       11269 :   const auto sys_num = _lm_var->sys().number();
      97       11269 :   const auto var_num = _lm_var->number();
      98       11269 :   if (!node->n_dofs(sys_num, var_num))
      99           0 :     mooseError("No degrees of freedom for the Lagrange multiplier at the node. If this is being "
     100             :                "called from an aux kernel make sure that your aux variable has the same order as "
     101             :                "your Lagrange multiplier");
     102             : 
     103       11269 :   const auto dof_number = node->dof_number(sys_num, var_num, /*component=*/0);
     104       11269 :   return (*_lm_var->sys().currentSolution())(dof_number);
     105             : }

Generated by: LCOV version 1.14