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 "MortarNodalAuxKernel.h" 11 : #include "MooseVariableField.h" 12 : #include "MortarUtils.h" 13 : #include "MooseUtils.h" 14 : #include "libmesh/quadrature.h" 15 : 16 : namespace 17 : { 18 : const InputParameters & 19 84 : setBoundaryParam(const InputParameters & params_in) 20 : { 21 84 : InputParameters & ret = const_cast<InputParameters &>(params_in); 22 168 : ret.set<std::vector<BoundaryName>>("boundary") = { 23 252 : params_in.get<BoundaryName>("secondary_boundary")}; 24 84 : return ret; 25 168 : } 26 : } 27 : 28 : template <typename ComputeValueType> 29 : InputParameters 30 14427 : MortarNodalAuxKernelTempl<ComputeValueType>::validParams() 31 : { 32 14427 : InputParameters params = AuxKernelTempl<ComputeValueType>::validParams(); 33 14427 : params += MortarConsumerInterface::validParams(); 34 14427 : params.set<bool>("ghost_point_neighbors") = true; 35 14427 : params.suppressParameter<std::vector<BoundaryName>>("boundary"); 36 14427 : params.suppressParameter<std::vector<SubdomainName>>("block"); 37 43281 : params.addParam<bool>( 38 28854 : "incremental", false, "Whether to accumulate mortar auxiliary kernel value"); 39 : 40 : // We should probably default use_displaced_mesh to true. If no displaced mesh exists 41 : // FEProblemBase::addKernel will automatically correct it to false. However, 42 : // this will still prompt a call from AugmentSparsityOnInterface to get a displaced 43 : // mortar interface since object._use_displaced_mesh = true. 44 : 45 14427 : return params; 46 0 : } 47 : 48 : template <typename ComputeValueType> 49 84 : MortarNodalAuxKernelTempl<ComputeValueType>::MortarNodalAuxKernelTempl( 50 : const InputParameters & parameters) 51 : : AuxKernelTempl<ComputeValueType>(setBoundaryParam(parameters)), 52 : MortarConsumerInterface(this), 53 84 : _displaced(this->template getParam<bool>("use_displaced_mesh")), 54 84 : _fe_problem(*this->template getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")), 55 84 : _msm_volume(0), 56 84 : _incremental(this->template getParam<bool>("incremental")), 57 84 : _u_old(uOld()), 58 84 : _test_lower(_var.phiLower()), 59 168 : _coord_msm(_assembly.mortarCoordTransformation()) 60 : { 61 84 : if (!isNodal()) 62 0 : paramError("variable", 63 : "MortarNodalAuxKernel derived classes populate nodal aux variables only."); 64 84 : } 65 : 66 : template <typename ComputeValueType> 67 : void 68 84 : MortarNodalAuxKernelTempl<ComputeValueType>::initialSetup() 69 : { 70 84 : std::array<const MortarNodalAuxKernelTempl<ComputeValueType> *, 1> consumers = {{this}}; 71 : 72 84 : Moose::Mortar::setupMortarMaterials(consumers, 73 : _fe_problem, 74 : amg(), 75 : _tid, 76 84 : _secondary_ip_sub_to_mats, 77 84 : _primary_ip_sub_to_mats, 78 84 : _secondary_boundary_mats); 79 84 : } 80 : 81 : template <typename ComputeValueType> 82 : void 83 774 : MortarNodalAuxKernelTempl<ComputeValueType>::compute() 84 : { 85 774 : if (!_var.isNodalDefined()) 86 99 : return; 87 : 88 675 : ComputeValueType value(0); 89 675 : Real total_volume = 0; 90 : 91 675 : const auto & its = amg().secondariesToMortarSegments(*_current_node); 92 : 93 4527 : auto act_functor = [&value, &total_volume, this]() 94 : { 95 1284 : _msm_volume = 0; 96 1284 : setNormals(); 97 1284 : value += computeValue(); 98 0 : total_volume += _msm_volume; 99 : }; 100 : 101 675 : std::array<MortarNodalAuxKernelTempl<ComputeValueType> *, 1> consumers = {{this}}; 102 : 103 675 : Moose::Mortar::loopOverMortarSegments(its, 104 : _assembly, 105 : _subproblem, 106 : _fe_problem, 107 : amg(), 108 675 : _displaced, 109 : consumers, 110 : _tid, 111 675 : _secondary_ip_sub_to_mats, 112 675 : _primary_ip_sub_to_mats, 113 675 : _secondary_boundary_mats, 114 : act_functor, 115 : /*reinit_mortar_user_objects=*/false); 116 : 117 : // We have to reinit the node for this variable in order to get the dof index set for the node 118 675 : _var.reinitNode(); 119 : 120 : // If the node doesn't have corresponding mortar segments, force the value assigned in this step 121 : // to be zero. This can be useful when nodes initially do not project but will project at a 122 : // different stage of the simulation 123 : 124 675 : if (MooseUtils::relativeFuzzyEqual(total_volume, 0.0)) 125 0 : value = 0; 126 : else 127 675 : value /= total_volume; 128 : 129 : // Allow mortar auxiliary kernels to compute quantities incrementally 130 675 : if (!_incremental) 131 675 : _var.setNodalValue(value); 132 : else 133 : { 134 : mooseAssert(_u_old.size() == 1, 135 : "Expected 1 value in MortarNodalAuxKernel, but got " << _u_old.size()); 136 0 : _var.setNodalValue(value + _u_old[0]); 137 : } 138 675 : } 139 : 140 : template <typename ComputeValueType> 141 : void 142 0 : MortarNodalAuxKernelTempl<ComputeValueType>::precalculateValue() 143 : { 144 0 : mooseError( 145 : "not clear where this should be implemented in the compute loop. If you want to implement " 146 : "this function, please contact a MOOSE developer and tell them your use case"); 147 : } 148 : 149 : // Explicitly instantiates the two versions of the MortarNodalAuxKernelTempl class 150 : template class MortarNodalAuxKernelTempl<Real>; 151 : template class MortarNodalAuxKernelTempl<RealVectorValue>;