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 "BoundaryLinearFVFluxIntegral.h" 11 : #include "LinearFVBoundaryCondition.h" 12 : #include "LinearFVFluxKernel.h" 13 : #include <set> 14 : 15 : registerMooseObject("MooseApp", BoundaryLinearFVFluxIntegral); 16 : 17 : InputParameters 18 3217 : BoundaryLinearFVFluxIntegral::validParams() 19 : { 20 3217 : InputParameters params = SideIntegralPostprocessor::validParams(); 21 12868 : params.addRequiredParam<std::vector<std::string>>( 22 : "linearfvkernels", "List of LinearFVFluxKernels whose boundary fluxes are integrated."); 23 3217 : params.addClassDescription( 24 : "Computes the side integral of selected LinearFVFluxKernel boundary flux contributions."); 25 3217 : return params; 26 0 : } 27 : 28 78 : BoundaryLinearFVFluxIntegral::BoundaryLinearFVFluxIntegral(const InputParameters & parameters) 29 : : SideIntegralPostprocessor(parameters), 30 78 : _kernel_names(getParam<std::vector<std::string>>("linearfvkernels")), 31 78 : _variable_number(0), 32 156 : _system_number(0) 33 : { 34 78 : _qp_integration = false; 35 : 36 78 : if (_kernel_names.empty()) 37 0 : paramError("linearfvkernels", "At least one kernel must be provided."); 38 78 : } 39 : 40 : void 41 72 : BoundaryLinearFVFluxIntegral::initialSetup() 42 : { 43 72 : SideIntegralPostprocessor::initialSetup(); 44 : 45 : // Kernels are constructed after postprocessors, so we fetch them here. 46 72 : auto base_query = _fe_problem.theWarehouse() 47 144 : .query() 48 72 : .condition<AttribSystem>("LinearFVFluxKernel") 49 72 : .condition<AttribThread>(_tid); 50 : 51 72 : _kernel_objects.clear(); 52 164 : for (const auto & name : _kernel_names) 53 : { 54 94 : std::vector<LinearFVFluxKernel *> kernels; 55 94 : auto query = base_query.clone(); 56 94 : query.condition<AttribName>(name).queryInto(kernels); 57 94 : if (kernels.empty()) 58 4 : paramError("linearfvkernels", 59 : "The given LinearFVFluxKernel with name '", 60 : name, 61 : "' was not found! This can be due to the kernel not existing in the " 62 : "'LinearFVKernels' block or the kernel not inheriting from LinearFVFluxKernel."); 63 : 64 92 : _kernel_objects.push_back(kernels[0]); 65 92 : } 66 : 67 : // Cache shared variable metadata and verify all kernels act on that same variable. 68 70 : const auto & first_variable = _kernel_objects.front()->variable(); 69 70 : _variable_name = first_variable.name(); 70 70 : _variable_number = first_variable.number(); 71 70 : _system_number = first_variable.sys().number(); 72 : 73 162 : for (const auto kernel_ptr : _kernel_objects) 74 92 : if (kernel_ptr->variable().name() != _variable_name) 75 0 : paramError("linearfvkernels", 76 : "All kernels in 'linearfvkernels' must act on the same variable name. The " 77 : "kernel '", 78 0 : kernel_ptr->name(), 79 : "' acts on variable '", 80 0 : kernel_ptr->variable().name(), 81 : "', while the first kernel acts on variable '", 82 0 : _variable_name, 83 : "'."); 84 : 85 : // Postprocessors run initialSetup before variable-side BC caches are guaranteed ready, 86 : // so we resolve BCs directly from the warehouse. 87 70 : auto bc_query = _fe_problem.theWarehouse() 88 140 : .query() 89 70 : .condition<AttribSystem>("LinearFVBoundaryCondition") 90 70 : .condition<AttribThread>(_tid) 91 70 : .condition<AttribVar>(_variable_number) 92 70 : .condition<AttribSysNum>(_system_number); 93 : 94 70 : _boundary_bcs.clear(); 95 140 : for (const auto boundary_id : boundaryIDs()) 96 : { 97 70 : std::vector<LinearFVBoundaryCondition *> bcs; 98 70 : auto bc_query_copy = bc_query; 99 70 : bc_query_copy.condition<AttribBoundaries>(std::set<BoundaryID>({boundary_id})).queryInto(bcs); 100 : 101 70 : if (bcs.empty()) 102 0 : paramError("linearfvkernels", 103 : "Variable '", 104 0 : _variable_name, 105 : "' does not have a LinearFVBoundaryCondition on boundary '", 106 0 : _mesh.getBoundaryName(boundary_id), 107 : "'."); 108 : 109 70 : if (bcs.size() > 1) 110 0 : paramError("linearfvkernels", 111 : "Variable '", 112 0 : _variable_name, 113 : "' has multiple LinearFVBoundaryCondition objects on boundary '", 114 0 : _mesh.getBoundaryName(boundary_id), 115 : "', which is not currently supported."); 116 : 117 70 : _boundary_bcs.emplace(boundary_id, bcs[0]); 118 70 : } 119 70 : } 120 : 121 : Real 122 42 : BoundaryLinearFVFluxIntegral::computeFaceInfoIntegral(const FaceInfo * const fi) 123 : { 124 : mooseAssert(fi, "FaceInfo should not be null."); 125 : mooseAssert(fi->boundaryIDs().size() == 1, "Expected exactly one boundary per face."); 126 : 127 42 : const auto boundary_id = *fi->boundaryIDs().begin(); 128 42 : const auto face_type = fi->faceType(std::make_pair(_variable_number, _system_number)); 129 42 : if (face_type != FaceInfo::VarFaceNeighbors::ELEM && 130 : face_type != FaceInfo::VarFaceNeighbors::NEIGHBOR) 131 0 : mooseError("Cannot compute boundary flux on boundary '", 132 0 : _mesh.getBoundaryName(boundary_id), 133 : "' because the variable face type is not boundary-only."); 134 : 135 42 : auto * const bc = libmesh_map_find(_boundary_bcs, boundary_id); 136 42 : bc->setupFaceData(fi, face_type); 137 : 138 42 : Real flux_value = 0.0; 139 98 : for (const auto kernel_ptr : _kernel_objects) 140 : { 141 56 : kernel_ptr->setupFaceData(fi); 142 : // SideIntegralPostprocessor multiplies by geometric factors, so we just do 1 here. 143 56 : kernel_ptr->setCurrentFaceArea(1.0); 144 56 : flux_value += kernel_ptr->computeBoundaryFlux(*bc); 145 : } 146 : 147 42 : return flux_value; 148 : } 149 : 150 : Real 151 0 : BoundaryLinearFVFluxIntegral::computeQpIntegral() 152 : { 153 0 : mooseError("We should never call this function."); 154 : }