LCOV - code coverage report
Current view: top level - src/auxkernels - MortarPressureComponentAux.C (source / functions) Hit Total Coverage
Test: idaholab/moose contact: #31730 (e8b711) with base e0c998 Lines: 49 55 89.1 %
Date: 2025-10-29 16:50:33 Functions: 3 3 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 "MortarPressureComponentAux.h"
      11             : #include "SystemBase.h"
      12             : #include "AutomaticMortarGeneration.h"
      13             : 
      14             : registerMooseObject("ContactApp", MortarPressureComponentAux);
      15             : 
      16             : InputParameters
      17         184 : MortarPressureComponentAux::validParams()
      18             : {
      19         184 :   InputParameters params = AuxKernel::validParams();
      20         184 :   params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
      21             : 
      22         184 :   params.addClassDescription(
      23             :       "This class transforms the Cartesian Lagrange multiplier vector to local coordinates and "
      24             :       "outputs each individual component along the normal or tangential direction.");
      25         368 :   params.addRequiredCoupledVar("lm_var_x", "Lagrange multiplier variable along the x direction.");
      26         368 :   params.addRequiredCoupledVar("lm_var_y", "Lagrange multiplier variable along the y direction.");
      27         368 :   params.addCoupledVar(
      28             :       "lm_var_z",
      29             :       "Lagrange multiplier variable along the z direction (only exist for 3D problems).");
      30         368 :   params.addRequiredParam<MooseEnum>("component",
      31         552 :                                      MooseEnum("normal tangent1 tangent2"),
      32             :                                      "The component of the Lagrange multiplier to compute.");
      33         368 :   params.addRequiredParam<BoundaryName>("primary_boundary",
      34             :                                         "The name of the primary boundary sideset.");
      35         368 :   params.addRequiredParam<BoundaryName>("secondary_boundary",
      36             :                                         "The name of the secondary boundary sideset.");
      37         368 :   params.addParam<bool>(
      38         368 :       "use_displaced_mesh", true, "Whether to use the displaced mesh to get the mortar interface.");
      39         184 :   return params;
      40           0 : }
      41             : 
      42          98 : MortarPressureComponentAux::MortarPressureComponentAux(const InputParameters & params)
      43             :   : AuxKernel(params),
      44          98 :     _lm_var_x(&coupledValueLower("lm_var_x")),
      45          98 :     _lm_var_y(&coupledValueLower("lm_var_y")),
      46         110 :     _lm_var_z(params.isParamValid("lm_var_z") ? &coupledValueLower("lm_var_z") : nullptr),
      47          98 :     _fe_problem(*params.get<FEProblemBase *>("_fe_problem_base")),
      48         196 :     _primary_id(_fe_problem.mesh().getBoundaryID(getParam<BoundaryName>("primary_boundary"))),
      49         196 :     _secondary_id(_fe_problem.mesh().getBoundaryID(getParam<BoundaryName>("secondary_boundary"))),
      50         196 :     _component(getParam<MooseEnum>("component").getEnum<ComponentType>()),
      51         294 :     _use_displaced_mesh(getParam<bool>("use_displaced_mesh"))
      52             : {
      53             :   // Only consider nodal quantities
      54          98 :   if (!isNodal())
      55           0 :     mooseError("MortarPressureComponent auxiliary kernel can only be used with nodal kernels.");
      56             : 
      57          98 :   if (!_use_displaced_mesh)
      58           0 :     paramError("use_displaced_mesh",
      59             :                "This auxiliary kernel requires the use of displaced meshes to compute the "
      60             :                "frictional pressure vector.");
      61             : 
      62             :   // Kernel need to be boundary restricted
      63          98 :   if (!this->_bnd)
      64           0 :     paramError("boundary",
      65             :                "MortarPressureComponent auxiliary kernel must be restricted to a boundary.");
      66             : 
      67             :   // Get mortar interfaces
      68             :   const auto & displaced_mortar_interfaces =
      69          98 :       _fe_problem.getMortarInterfaces(/*displaced=*/_use_displaced_mesh);
      70             : 
      71          98 :   if (displaced_mortar_interfaces.size() == 0)
      72           0 :     paramError("lm_var_x",
      73             :                "No mortar interface could be identified in this problem. Make sure mortar contact "
      74             :                "is enabled.");
      75             : 
      76             :   // Get automatic generation object for the boundary pair this auxiliary acts on.
      77         196 :   if (displaced_mortar_interfaces.count(std::make_pair(_primary_id, _secondary_id)) != 1)
      78           0 :     mooseError("primary_boundary",
      79             :                "The boundary pairs do not correspond to a single mortar contact boundary pair. "
      80             :                "Please revise your input file for proper mortar contact constraints and mortar "
      81             :                "frictional pressure vector auxiliary variable definition.");
      82             : 
      83          98 :   _mortar_generation_object =
      84          98 :       libmesh_map_find(displaced_mortar_interfaces, std::make_pair(_primary_id, _secondary_id))
      85             :           .get();
      86          98 : }
      87             : 
      88             : Real
      89        8742 : MortarPressureComponentAux::computeValue()
      90             : {
      91             :   // A node id may correspond to more than one lower-d elements on the secondary surface.
      92             :   // However, we are looping over nodes below, so we will locate the correct geometry
      93             :   const Elem * lower_dimensional_element =
      94        8742 :       libmesh_map_find(_mortar_generation_object->nodesToSecondaryElem(), _current_node->id())[0];
      95             : 
      96             :   // Get the nodal normals for this element
      97             :   const auto & nodal_normals =
      98        8742 :       _mortar_generation_object->getNodalNormals(*lower_dimensional_element);
      99             : 
     100             :   // Get nodal tangents for this element
     101             :   const auto & nodal_tangents =
     102        8742 :       _mortar_generation_object->getNodalTangents(*lower_dimensional_element);
     103             : 
     104             :   Point normal_vector, tangent1, tangent2;
     105             : 
     106       25992 :   for (const auto lowerd_node : make_range(lower_dimensional_element->n_nodes()))
     107       17250 :     if (_current_node->id() == lower_dimensional_element->node_id(lowerd_node))
     108             :     {
     109        8742 :       normal_vector = nodal_normals[lowerd_node];
     110        8742 :       tangent1 = nodal_tangents[0][lowerd_node];
     111        8742 :       tangent2 = nodal_tangents[1][lowerd_node];
     112        8742 :       break;
     113             :     }
     114             : 
     115             :   Point lm_vector_value(
     116        8742 :       (*_lm_var_x)[_qp], (*_lm_var_y)[_qp], _lm_var_z == nullptr ? 0.0 : (*_lm_var_z)[_qp]);
     117             : 
     118             :   Real pressure_component_value = 0.0;
     119             : 
     120        8742 :   switch (_component)
     121             :   {
     122             :     case ComponentType::NORMAL:
     123             :       pressure_component_value = lm_vector_value * normal_vector;
     124        4371 :       break;
     125             : 
     126             :     case ComponentType::TANGENT1:
     127             :       pressure_component_value = lm_vector_value * tangent1;
     128        4227 :       break;
     129             : 
     130             :     case ComponentType::TANGENT2:
     131             :       pressure_component_value = lm_vector_value * tangent2;
     132         144 :       break;
     133             :   }
     134             : 
     135        8742 :   return pressure_component_value;
     136        8742 : }

Generated by: LCOV version 1.14