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 "MortarFrictionalPressureVectorAux.h" 11 : #include "SystemBase.h" 12 : 13 : registerMooseObject("ContactApp", MortarFrictionalPressureVectorAux); 14 : 15 : InputParameters 16 589 : MortarFrictionalPressureVectorAux::validParams() 17 : { 18 589 : InputParameters params = AuxKernel::validParams(); 19 589 : params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END; 20 : 21 589 : params.addClassDescription("This class creates an auxiliary vector for outputting the mortar " 22 : "frictional pressure vector."); 23 1178 : params.addRequiredCoupledVar( 24 : "tangent_one", 25 : "First tangent vector Lagrange's multiplier for computing the mortar " 26 : "frictional pressure vector."); 27 1178 : params.addRequiredCoupledVar( 28 : "tangent_two", 29 : "Second tangent vector Lagrange's multiplier for computing the mortar " 30 : "frictional pressure vector."); 31 1178 : params.addRequiredParam<unsigned int>("component", 32 : "Cartesian component of frictional tangent vector"); 33 : 34 1178 : params.addRequiredParam<BoundaryName>("primary_boundary", 35 : "The name of the primary boundary sideset."); 36 1178 : params.addRequiredParam<BoundaryName>("secondary_boundary", 37 : "The name of the secondary boundary sideset."); 38 1178 : params.addParam<bool>( 39 1178 : "use_displaced_mesh", true, "Whether to use the displaced mesh to get the mortar interface."); 40 589 : return params; 41 0 : } 42 : 43 360 : MortarFrictionalPressureVectorAux::MortarFrictionalPressureVectorAux(const InputParameters & params) 44 : : AuxKernel(params), 45 360 : _tangent_one(&coupledValueLower("tangent_one")), 46 360 : _tangent_two(&coupledValueLower("tangent_two")), 47 360 : _fe_problem(*params.get<FEProblemBase *>("_fe_problem_base")), 48 720 : _primary_id(_fe_problem.mesh().getBoundaryID(getParam<BoundaryName>("primary_boundary"))), 49 720 : _secondary_id(_fe_problem.mesh().getBoundaryID(getParam<BoundaryName>("secondary_boundary"))), 50 720 : _component(getParam<unsigned int>("component")), 51 1080 : _use_displaced_mesh(getParam<bool>("use_displaced_mesh")) 52 : { 53 : // Only consider nodal quantities 54 360 : if (!isNodal()) 55 0 : mooseError( 56 : "MortarFrictionalPressureVector auxiliary kernel can only be used with nodal kernels."); 57 : 58 360 : if (!_use_displaced_mesh) 59 0 : paramError("use_displaced_mesh", 60 : "This auxiliary kernel requires the use of displaced meshes to compute the " 61 : "frictional pressure vector."); 62 : 63 : // Kernel need to be boundary restricted 64 360 : if (!this->_bnd) 65 0 : paramError("boundary", 66 : "MortarFrictionalPressureVector auxiliary kernel must be restricted to a boundary."); 67 : 68 : // Get mortar interfaces 69 : const auto & displaced_mortar_interfaces = 70 360 : _fe_problem.getMortarInterfaces(/*displaced=*/_use_displaced_mesh); 71 : 72 360 : if (displaced_mortar_interfaces.size() == 0) 73 0 : paramError("tangent_one", 74 : "No mortar interface could be identified in this problem. Make sure mortar contact " 75 : "is enabled."); 76 : 77 360 : const auto mortar_dimension = _fe_problem.mesh().dimension() - 1; 78 360 : if (mortar_dimension == 1) 79 0 : paramError("tangent_two", 80 : "MortarFrictionalPressureVector auxiliary kernel can only be used in " 81 : "three-dimensional problems"); 82 : 83 : // Get automatic generation object for the boundary pair this auxiliary acts on. 84 360 : if (displaced_mortar_interfaces.count(std::make_pair(_primary_id, _secondary_id)) != 1) 85 0 : mooseError("primary_boundary", 86 : "The boundary pairs do not correspond to a single mortar contact boundary pair. " 87 : "Please revise your input file for proper mortar contact constraints and mortar " 88 : "frictional pressure vector auxiliary variable definition."); 89 : 90 360 : _mortar_generation_object = 91 360 : &libmesh_map_find(displaced_mortar_interfaces, std::make_pair(_primary_id, _secondary_id)); 92 360 : } 93 : 94 : Real 95 11295 : MortarFrictionalPressureVectorAux::computeValue() 96 : { 97 : 98 : // A node id may correspond to more than one lower-d elements on the secondary surface. 99 : // However, we are looping over nodes below, so we will locate the correct geometry 100 : const Elem * lower_dimensional_element = 101 11295 : libmesh_map_find(_mortar_generation_object->nodesToSecondaryElem(), _current_node->id())[0]; 102 : 103 : // Get nodal tangents for this element 104 : const auto & nodal_tangents = 105 11295 : _mortar_generation_object->getNodalTangents(*lower_dimensional_element); 106 : 107 : Real tangent_one_component = 0; 108 : Real tangent_two_component = 0; 109 : 110 32295 : for (const auto lowerd_node : make_range(lower_dimensional_element->n_nodes())) 111 : { 112 32295 : if (_current_node->id() == lower_dimensional_element->node_id(lowerd_node)) 113 : { 114 11295 : tangent_one_component = nodal_tangents[0][lowerd_node](_component); 115 11295 : tangent_two_component = nodal_tangents[1][lowerd_node](_component); 116 11295 : break; 117 : } 118 : } 119 : 120 : // Compute nodal tangent vector component 121 : const Real tangent_vector_component = 122 11295 : tangent_one_component * (*_tangent_one)[_qp] + tangent_two_component * (*_tangent_two)[_qp]; 123 : 124 11295 : return tangent_vector_component; 125 : }