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 "FVFluxBC.h" 11 : #include "MooseVariableFV.h" 12 : #include "SystemBase.h" 13 : #include "Assembly.h" 14 : #include "ADUtils.h" 15 : 16 : InputParameters 17 27334 : FVFluxBC::validParams() 18 : { 19 27334 : InputParameters params = FVBoundaryCondition::validParams(); 20 27334 : params += TwoMaterialPropertyInterface::validParams(); 21 54668 : params.registerSystemAttributeName("FVFluxBC"); 22 : 23 : // FVFluxBCs always rely on Boundary MaterialData 24 54668 : params.set<Moose::MaterialDataType>("_material_data_type") = Moose::BOUNDARY_MATERIAL_DATA; 25 27334 : params.set<bool>("_residual_object") = true; 26 : 27 27334 : return params; 28 0 : } 29 : 30 1347 : FVFluxBC::FVFluxBC(const InputParameters & parameters) 31 : : FVBoundaryCondition(parameters), 32 : NeighborCoupleableMooseVariableDependencyIntermediateInterface( 33 : this, /*nodal=*/false, /*neighbor_nodal=*/false, /*is_fv=*/true), 34 1347 : TwoMaterialPropertyInterface(this, Moose::EMPTY_BLOCK_IDS, boundaryIDs()) 35 : { 36 1347 : if (_var.kind() == Moose::VarKindType::VAR_AUXILIARY) 37 0 : paramError("variable", 38 : "There should not be a need to specify a flux " 39 : "boundary condition for an auxiliary variable."); 40 1347 : } 41 : 42 : void 43 334559 : FVFluxBC::updateCurrentFace(const FaceInfo & fi) 44 : { 45 334559 : _face_info = &fi; 46 334559 : _normal = fi.normal(); 47 334559 : _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number())); 48 : 49 : // For FV flux kernels, the normal is always oriented outward from the lower-id 50 : // element's perspective. But for BCs, there is only a residual 51 : // contribution to one element (one side of the face). Because of this, we 52 : // make an exception and orient the normal to point outward from whichever 53 : // side of the face the BC's variable is defined on; we flip it if this 54 : // variable is defined on the neighbor side of the face (instead of elem) since 55 : // the FaceInfo normal polarity is always oriented with respect to the lower-id element. 56 334559 : if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 57 0 : _normal = -_normal; 58 334559 : } 59 : 60 : void 61 334535 : FVFluxBC::computeResidual(const FaceInfo & fi) 62 : { 63 334535 : updateCurrentFace(fi); 64 : 65 334535 : if (_face_type == FaceInfo::VarFaceNeighbors::BOTH) 66 3 : mooseError("A FVFluxBC is being triggered on an internal face with centroid: ", 67 : fi.faceCentroid()); 68 334532 : else if (_face_type == FaceInfo::VarFaceNeighbors::NEITHER) 69 3 : mooseError("A FVFluxBC is being triggered on a face which does not connect to a block ", 70 : "with the relevant finite volume variable. Its centroid: ", 71 : fi.faceCentroid()); 72 : 73 334529 : auto r = MetaPhysicL::raw_value(fi.faceArea() * fi.faceCoord() * computeQpResidual()); 74 : 75 : // This could be an "internal" boundary - one created by variable block 76 : // restriction where the var is only defined on one side of the face. We 77 : // need to make sure that we add the residual contribution to the correct 78 : // side - the one where the variable is defined. 79 334529 : if (_face_type == FaceInfo::VarFaceNeighbors::ELEM) 80 334529 : prepareVectorTag(_assembly, _var.number()); 81 0 : else if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 82 0 : prepareVectorTagNeighbor(_assembly, _var.number()); 83 : 84 334529 : _local_re(0) = r; 85 334529 : accumulateTaggedLocalResidual(); 86 334529 : } 87 : 88 : void 89 416 : FVFluxBC::computeResidualAndJacobian(const FaceInfo & fi) 90 : { 91 416 : computeJacobian(fi); 92 416 : } 93 : 94 : void 95 188068 : FVFluxBC::computeJacobian(const FaceInfo & fi) 96 : { 97 188068 : _face_info = &fi; 98 188068 : _normal = fi.normal(); 99 188068 : _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number())); 100 : 101 : // For FV flux kernels, the normal is always oriented outward from the lower-id 102 : // element's perspective. But for BCs, there is only a Jacobian 103 : // contribution to one element (one side of the face). Because of this, we 104 : // make an exception and orient the normal to point outward from whichever 105 : // side of the face the BC's variable is defined on; we flip it if this 106 : // variable is defined on the neighbor side of the face (instead of elem) since 107 : // the FaceInfo normal polarity is always oriented with respect to the lower-id element. 108 188068 : if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 109 0 : _normal = -_normal; 110 : 111 188068 : ADReal r = fi.faceArea() * fi.faceCoord() * computeQpResidual(); 112 : 113 188068 : const auto & dof_indices = (_face_type == FaceInfo::VarFaceNeighbors::ELEM) 114 188068 : ? _var.dofIndices() 115 0 : : _var.dofIndicesNeighbor(); 116 : 117 : mooseAssert(dof_indices.size() == 1, "We're currently built to use CONSTANT MONOMIALS"); 118 : 119 188068 : addResidualsAndJacobian(_assembly, std::array<ADReal, 1>{{r}}, dof_indices, _var.scalingFactor()); 120 188068 : } 121 : 122 : Moose::ElemArg 123 0 : FVFluxBC::elemArg(const bool correct_skewness) const 124 : { 125 0 : return {&_face_info->elem(), correct_skewness}; 126 : } 127 : 128 : Moose::ElemArg 129 0 : FVFluxBC::neighborArg(const bool correct_skewness) const 130 : { 131 0 : return {_face_info->neighborPtr(), correct_skewness}; 132 : }