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