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 45945 : LinearFVFluxKernel::validParams() 15 : { 16 45945 : InputParameters params = LinearFVKernel::validParams(); 17 137835 : params.addParam<bool>("force_boundary_execution", 18 91890 : false, 19 : "Whether to force execution of this object on all external boundaries."); 20 45945 : params.registerSystemAttributeName("LinearFVFluxKernel"); 21 45945 : return params; 22 0 : } 23 : 24 1575 : LinearFVFluxKernel::LinearFVFluxKernel(const InputParameters & params) 25 : : LinearFVKernel(params), 26 : FaceArgProducerInterface(), 27 1575 : _current_face_info(nullptr), 28 1575 : _current_face_type(FaceInfo::VarFaceNeighbors::NEITHER), 29 1575 : _cached_matrix_contribution(false), 30 1575 : _cached_rhs_contribution(false), 31 1575 : _force_boundary_execution(getParam<bool>("force_boundary_execution")), 32 1575 : _dof_indices(2, 0), 33 1575 : _matrix_contribution(2, 2), 34 3150 : _rhs_contribution(2, 0.0) 35 : { 36 1575 : } 37 : 38 : void 39 2949816 : 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 2949816 : if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH) 44 : { 45 : // The dof ids of the variable corresponding to the element and neighbor 46 2735784 : _dof_indices(0) = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 47 2735784 : _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 2735784 : const auto elem_matrix_contribution = computeElemMatrixContribution(); 52 2735784 : const auto neighbor_matrix_contribution = computeNeighborMatrixContribution(); 53 : 54 : // Populate matrix 55 2735784 : if (hasBlocks(_current_face_info->elemInfo()->subdomain_id())) 56 : { 57 2735777 : _matrix_contribution(0, 0) = elem_matrix_contribution; 58 2735777 : _matrix_contribution(0, 1) = neighbor_matrix_contribution; 59 : } 60 : 61 2735784 : if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id())) 62 : { 63 2735759 : _matrix_contribution(1, 0) = -elem_matrix_contribution; 64 2735759 : _matrix_contribution(1, 1) = -neighbor_matrix_contribution; 65 : } 66 : 67 : // We add the contributions to every tagged matrix 68 5471568 : for (auto & matrix : _matrices) 69 2735784 : (*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 214032 : 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 214032 : _var.getBoundaryCondition(*_current_face_info->boundaryIDs().begin()); 84 : 85 214032 : if (bc_pointer || _force_boundary_execution) 86 : { 87 206552 : if (bc_pointer) 88 206552 : bc_pointer->setupFaceData(_current_face_info, _current_face_type); 89 206552 : 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 206552 : if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) 94 : { 95 202646 : 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 405292 : for (auto & matrix : _matrices) 99 202646 : (*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 2949816 : } 113 : 114 : void 115 2949816 : 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 2949816 : if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH) 120 : { 121 : // The dof ids of the variable corresponding to the element and neighbor 122 2735784 : _dof_indices(0) = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 123 2735784 : _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 2735784 : const auto elem_rhs_contribution = computeElemRightHandSideContribution(); 127 2735784 : const auto neighbor_rhs_contribution = computeNeighborRightHandSideContribution(); 128 : 129 : // Populate right hand side 130 2735784 : if (hasBlocks(_current_face_info->elemInfo()->subdomain_id())) 131 2735777 : _rhs_contribution(0) = elem_rhs_contribution; 132 2735784 : if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id())) 133 2735759 : _rhs_contribution(1) = neighbor_rhs_contribution; 134 : 135 : // We add the contributions to every tagged vector 136 5471568 : for (auto & vector : _vectors) 137 2735784 : (*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 214032 : 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 214032 : _var.getBoundaryCondition(*_current_face_info->boundaryIDs().begin()); 148 : 149 214032 : if (bc_pointer || _force_boundary_execution) 150 : { 151 206552 : if (bc_pointer) 152 206552 : bc_pointer->setupFaceData(_current_face_info, _current_face_type); 153 : 154 206552 : 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 206552 : if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) 159 : { 160 202646 : const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num]; 161 : // We add the contributions to every tagged vector 162 405292 : for (auto & vector : _vectors) 163 202646 : (*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 2949816 : } 176 : 177 : bool 178 3286500 : LinearFVFluxKernel::hasFaceSide(const FaceInfo & fi, bool fi_elem_side) const 179 : { 180 3286500 : const auto ft = fi.faceType(std::make_pair(_var_num, _sys_num)); 181 3286500 : if (fi_elem_side) 182 1643250 : return ft == FaceInfo::VarFaceNeighbors::ELEM || ft == FaceInfo::VarFaceNeighbors::BOTH; 183 : else 184 1643250 : return ft == FaceInfo::VarFaceNeighbors::NEIGHBOR || ft == FaceInfo::VarFaceNeighbors::BOTH; 185 : } 186 : 187 : Moose::FaceArg 188 159662 : 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 159662 : return makeFace(*fi, limiter_type, true, correct_skewness); 194 : } 195 : 196 : void 197 2949816 : LinearFVFluxKernel::setupFaceData(const FaceInfo * face_info) 198 : { 199 2949816 : _cached_matrix_contribution = false; 200 2949816 : _cached_rhs_contribution = false; 201 2949816 : _current_face_info = face_info; 202 2949816 : _current_face_type = _current_face_info->faceType(std::make_pair(_var_num, _sys_num)); 203 2949816 : _matrix_contribution.zero(); 204 2949816 : _dof_indices.zero(); 205 2949816 : _rhs_contribution.zero(); 206 2949816 : }