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 : }