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