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 "FVBoundaryScalarLagrangeMultiplierConstraint.h" 11 : 12 : #include "MooseVariableScalar.h" 13 : #include "MooseVariableFV.h" 14 : #include "Assembly.h" 15 : #include "SystemBase.h" 16 : 17 : InputParameters 18 14290 : FVBoundaryScalarLagrangeMultiplierConstraint::validParams() 19 : { 20 14290 : InputParameters params = FVFluxBC::validParams(); 21 14290 : params.addClassDescription( 22 : "Base class for imposing constraints using scalar Lagrange multipliers"); 23 14290 : params.addParam<PostprocessorName>("phi0", "0", "The value that the constraint will enforce."); 24 14290 : params.addRequiredCoupledVar("lambda", "Lagrange multiplier variable"); 25 14290 : return params; 26 0 : } 27 : 28 13 : FVBoundaryScalarLagrangeMultiplierConstraint::FVBoundaryScalarLagrangeMultiplierConstraint( 29 13 : const InputParameters & parameters) 30 : : FVFluxBC(parameters), 31 13 : _phi0(getPostprocessorValue("phi0")), 32 13 : _lambda_var(*getScalarVar("lambda", 0)), 33 26 : _lambda(adCoupledScalarValue("lambda")) 34 : { 35 13 : } 36 : 37 : void 38 0 : FVBoundaryScalarLagrangeMultiplierConstraint::computeResidual(const FaceInfo & fi) 39 : { 40 0 : _face_info = &fi; 41 0 : _normal = fi.normal(); 42 0 : _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number())); 43 : 44 : // For FV flux kernels, the normal is always oriented outward from the lower-id 45 : // element's perspective. But for BCs, there is only a Jacobian 46 : // contribution to one element (one side of the face). Because of this, we 47 : // make an exception and orient the normal to point outward from whichever 48 : // side of the face the BC's variable is defined on; we flip it if this 49 : // variable is defined on the neighbor side of the face (instead of elem) since 50 : // the FaceInfo normal polarity is always oriented with respect to the lower-id element. 51 0 : if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 52 0 : _normal = -_normal; 53 : 54 : // Primal 55 0 : prepareVectorTag(_assembly, _var.number()); 56 : mooseAssert(_local_re.size() == 1, "We should only have a single dof"); 57 : mooseAssert(_lambda.size() == 1 && _lambda_var.order() == 1, 58 : "The lambda variable should be first order"); 59 0 : _local_re(0) += MetaPhysicL::raw_value(_lambda[0]) * fi.faceArea() * fi.faceCoord(); 60 0 : accumulateTaggedLocalResidual(); 61 : 62 : // LM 63 0 : const auto lm_r = MetaPhysicL::raw_value(computeQpResidual()) * fi.faceArea() * fi.faceCoord(); 64 : mooseAssert(_lambda_var.dofIndices().size() == 1, "We should only have a single dof"); 65 0 : addResiduals(_assembly, 66 0 : std::array<Real, 1>{{lm_r}}, 67 0 : _lambda_var.dofIndices(), 68 0 : _lambda_var.scalingFactor()); 69 0 : } 70 : 71 : void 72 160 : FVBoundaryScalarLagrangeMultiplierConstraint::computeJacobian(const FaceInfo & fi) 73 : { 74 160 : _face_info = &fi; 75 160 : _normal = fi.normal(); 76 160 : _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number())); 77 : 78 : // For FV flux kernels, the normal is always oriented outward from the lower-id 79 : // element's perspective. But for BCs, there is only a Jacobian 80 : // contribution to one element (one side of the face). Because of this, we 81 : // make an exception and orient the normal to point outward from whichever 82 : // side of the face the BC's variable is defined on; we flip it if this 83 : // variable is defined on the neighbor side of the face (instead of elem) since 84 : // the FaceInfo normal polarity is always oriented with respect to the lower-id element. 85 160 : if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 86 0 : _normal = -_normal; 87 : 88 160 : const auto & dof_indices = (_face_type == FaceInfo::VarFaceNeighbors::ELEM) 89 160 : ? _var.dofIndices() 90 0 : : _var.dofIndicesNeighbor(); 91 : 92 : mooseAssert(dof_indices.size() == 1, "We're currently built to use CONSTANT MONOMIALS"); 93 : 94 : // Primal 95 : mooseAssert(_lambda.size() == 1 && _lambda_var.order() == 1, 96 : "The lambda variable should be first order"); 97 160 : const auto primal_r = _lambda[0] * (fi.faceArea() * fi.faceCoord()); 98 320 : addResidualsAndJacobian( 99 320 : _assembly, std::array<ADReal, 1>{{primal_r}}, dof_indices, _var.scalingFactor()); 100 : 101 : // LM 102 160 : const auto lm_r = computeQpResidual() * (fi.faceArea() * fi.faceCoord()); 103 : mooseAssert(_lambda_var.dofIndices().size() == 1, "We should only have one dof"); 104 640 : addResidualsAndJacobian(_assembly, 105 160 : std::array<ADReal, 1>{{lm_r}}, 106 160 : _lambda_var.dofIndices(), 107 160 : _lambda_var.scalingFactor()); 108 480 : }