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 "LinearFVFluxKernel.h" 11 : #include "LinearFVBoundaryCondition.h" 12 : 13 : InputParameters 14 45559 : LinearFVFluxKernel::validParams() 15 : { 16 45559 : InputParameters params = LinearFVKernel::validParams(); 17 136677 : params.addParam<bool>("force_boundary_execution", 18 91118 : false, 19 : "Whether to force execution of this object on all external boundaries."); 20 45559 : params.registerSystemAttributeName("LinearFVFluxKernel"); 21 45559 : return params; 22 0 : } 23 : 24 1382 : LinearFVFluxKernel::LinearFVFluxKernel(const InputParameters & params) 25 : : LinearFVKernel(params), 26 : FaceArgProducerInterface(), 27 1382 : _current_face_info(nullptr), 28 1382 : _current_face_type(FaceInfo::VarFaceNeighbors::NEITHER), 29 1382 : _cached_matrix_contribution(false), 30 1382 : _cached_rhs_contribution(false), 31 1382 : _force_boundary_execution(getParam<bool>("force_boundary_execution")), 32 1382 : _dof_indices(2, 0), 33 1382 : _matrix_contribution(2, 2), 34 2764 : _rhs_contribution(2, 0.0) 35 : { 36 1382 : } 37 : 38 : void 39 2881612 : LinearFVFluxKernel::addMatrixContribution() 40 : { 41 : // If we are on an internal face, we populate the four entries in the system matrix 42 : // which touch the face 43 2881612 : if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH) 44 : { 45 : // The dof ids of the variable corresponding to the element and neighbor 46 2679070 : _dof_indices(0) = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 47 2679070 : _dof_indices(1) = _current_face_info->neighborInfo()->dofIndices()[_sys_num][_var_num]; 48 : 49 : // Compute the entries which will go to the neighbor (offdiagonal) and element 50 : // (diagonal). 51 2679070 : const auto elem_matrix_contribution = computeElemMatrixContribution(); 52 2679070 : const auto neighbor_matrix_contribution = computeNeighborMatrixContribution(); 53 : 54 : // Populate matrix 55 2679070 : if (hasBlocks(_current_face_info->elemInfo()->subdomain_id())) 56 : { 57 2679063 : _matrix_contribution(0, 0) = elem_matrix_contribution; 58 2679063 : _matrix_contribution(0, 1) = neighbor_matrix_contribution; 59 : } 60 : 61 2679070 : if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id())) 62 : { 63 2679047 : _matrix_contribution(1, 0) = -elem_matrix_contribution; 64 2679047 : _matrix_contribution(1, 1) = -neighbor_matrix_contribution; 65 : } 66 : 67 : // We add the contributions to every tagged matrix 68 5358140 : for (auto & matrix : _matrices) 69 2679070 : (*matrix).add_matrix(_matrix_contribution, _dof_indices.get_values()); 70 : } 71 : // We are at a block boundary where the variable is not defined on one of the adjacent cells. 72 : // We check if we have a boundary condition here 73 202542 : else if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM || 74 3906 : _current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 75 : { 76 : mooseAssert( 77 : _current_face_info->boundaryIDs().size() == 1, 78 : "We should only have one boundary on every face. Current face center: " + 79 : Moose::stringify(_current_face_info->faceCentroid()) + 80 : " boundaries specified: " + Moose::stringify(_current_face_info->boundaryIDs())); 81 : 82 : LinearFVBoundaryCondition * bc_pointer = 83 202542 : _var.getBoundaryCondition(*_current_face_info->boundaryIDs().begin()); 84 : 85 202542 : if (bc_pointer || _force_boundary_execution) 86 : { 87 195982 : if (bc_pointer) 88 195982 : bc_pointer->setupFaceData(_current_face_info, _current_face_type); 89 195982 : const auto matrix_contribution = computeBoundaryMatrixContribution(*bc_pointer); 90 : 91 : // We allow internal (for the mesh) boundaries too, so we have to check on which side we 92 : // are on (assuming that this is a boundary for the variable) 93 195982 : if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) 94 : { 95 192076 : const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 96 : 97 : // We add the contributions to every tagged matrix 98 384152 : for (auto & matrix : _matrices) 99 192076 : (*matrix).add(dof_id_elem, dof_id_elem, matrix_contribution); 100 : } 101 3906 : else if (_current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 102 : { 103 : const auto dof_id_neighbor = 104 3906 : _current_face_info->neighborInfo()->dofIndices()[_sys_num][_var_num]; 105 : 106 : // We add the contributions to every tagged matrix 107 7812 : for (auto & matrix : _matrices) 108 3906 : (*matrix).add(dof_id_neighbor, dof_id_neighbor, matrix_contribution); 109 : } 110 : } 111 : } 112 2881612 : } 113 : 114 : void 115 2881612 : LinearFVFluxKernel::addRightHandSideContribution() 116 : { 117 : // If we are on an internal face, we populate the two entries in the right hand side 118 : // which touch the face 119 2881612 : if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH) 120 : { 121 : // The dof ids of the variable corresponding to the element and neighbor 122 2679070 : _dof_indices(0) = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 123 2679070 : _dof_indices(1) = _current_face_info->neighborInfo()->dofIndices()[_sys_num][_var_num]; 124 : 125 : // Compute the entries which will go to the neighbor and element positions. 126 2679070 : const auto elem_rhs_contribution = computeElemRightHandSideContribution(); 127 2679070 : const auto neighbor_rhs_contribution = computeNeighborRightHandSideContribution(); 128 : 129 : // Populate right hand side 130 2679070 : if (hasBlocks(_current_face_info->elemInfo()->subdomain_id())) 131 2679063 : _rhs_contribution(0) = elem_rhs_contribution; 132 2679070 : if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id())) 133 2679047 : _rhs_contribution(1) = neighbor_rhs_contribution; 134 : 135 : // We add the contributions to every tagged vector 136 5358140 : for (auto & vector : _vectors) 137 2679070 : (*vector).add_vector(_rhs_contribution.get_values().data(), _dof_indices.get_values()); 138 : } 139 : // We are at a block boundary where the variable is not defined on one of the adjacent cells. 140 : // We check if we have a boundary condition here 141 202542 : else if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM || 142 3906 : _current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 143 : { 144 : mooseAssert(_current_face_info->boundaryIDs().size() == 1, 145 : "We should only have one boundary on every face."); 146 : LinearFVBoundaryCondition * bc_pointer = 147 202542 : _var.getBoundaryCondition(*_current_face_info->boundaryIDs().begin()); 148 : 149 202542 : if (bc_pointer || _force_boundary_execution) 150 : { 151 195982 : if (bc_pointer) 152 195982 : bc_pointer->setupFaceData(_current_face_info, _current_face_type); 153 : 154 195982 : const auto rhs_contribution = computeBoundaryRHSContribution(*bc_pointer); 155 : 156 : // We allow internal (for the mesh) boundaries too, so we have to check on which side we 157 : // are on (assuming that this is a boundary for the variable) 158 195982 : if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) 159 : { 160 192076 : const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 161 : // We add the contributions to every tagged vector 162 384152 : for (auto & vector : _vectors) 163 192076 : (*vector).add(dof_id_elem, rhs_contribution); 164 : } 165 3906 : else if (_current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) 166 : { 167 : const auto dof_id_neighbor = 168 3906 : _current_face_info->neighborInfo()->dofIndices()[_sys_num][_var_num]; 169 : // We add the contributions to every tagged matrix 170 7812 : for (auto & vector : _vectors) 171 3906 : (*vector).add(dof_id_neighbor, rhs_contribution); 172 : } 173 : } 174 : } 175 2881612 : } 176 : 177 : bool 178 3060200 : LinearFVFluxKernel::hasFaceSide(const FaceInfo & fi, bool fi_elem_side) const 179 : { 180 3060200 : const auto ft = fi.faceType(std::make_pair(_var_num, _sys_num)); 181 3060200 : if (fi_elem_side) 182 1530100 : return ft == FaceInfo::VarFaceNeighbors::ELEM || ft == FaceInfo::VarFaceNeighbors::BOTH; 183 : else 184 1530100 : return ft == FaceInfo::VarFaceNeighbors::NEIGHBOR || ft == FaceInfo::VarFaceNeighbors::BOTH; 185 : } 186 : 187 : Moose::FaceArg 188 141994 : LinearFVFluxKernel::singleSidedFaceArg(const FaceInfo * fi, 189 : const Moose::FV::LimiterType limiter_type, 190 : const bool correct_skewness) const 191 : { 192 : mooseAssert(fi, "FaceInfo should not be null!"); 193 141994 : return makeFace(*fi, limiter_type, true, correct_skewness); 194 : } 195 : 196 : void 197 2881612 : LinearFVFluxKernel::setupFaceData(const FaceInfo * face_info) 198 : { 199 2881612 : _cached_matrix_contribution = false; 200 2881612 : _cached_rhs_contribution = false; 201 2881612 : _current_face_info = face_info; 202 2881612 : _current_face_type = _current_face_info->faceType(std::make_pair(_var_num, _sys_num)); 203 2881612 : _matrix_contribution.zero(); 204 2881612 : _dof_indices.zero(); 205 2881612 : _rhs_contribution.zero(); 206 2881612 : }