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 "LinearFVGradientInterface.h" 11 : 12 : #include "ComputeLinearFVGreenGaussGradientFaceThread.h" 13 : #include "ComputeLinearFVGreenGaussGradientVolumeThread.h" 14 : #include "ComputeLinearFVLimitedGradientThread.h" 15 : #include "FEProblemBase.h" 16 : #include "PerfGraphInterface.h" 17 : #include "PerfGuard.h" 18 : #include "SystemBase.h" 19 : #include "MooseVariableFieldBase.h" 20 : #include "MooseError.h" 21 : 22 : #include "libmesh/numeric_vector.h" 23 : 24 : using namespace libMesh; 25 : 26 : void 27 52237 : LinearFVGradientInterface::computeGradients() 28 : { 29 : // No gradients have been requested, by now we should have set up the 30 : // containers to receive the gradients. Time to early return. 31 52237 : if (_raw_grad_container.empty()) 32 8660 : return; 33 : 34 43577 : auto & temporary_gradient = temporaryLinearFVGradientContainer(); 35 : mooseAssert(temporary_gradient.size() == _raw_grad_container.size(), 36 : "Temporary and raw gradient containers must have the same size."); 37 121291 : for (auto & vec : temporary_gradient) 38 77714 : vec->zero(); 39 : 40 43577 : auto & fe_problem = _sys.feProblem(); 41 43577 : auto * const perf_graph_interface = dynamic_cast<PerfGraphInterface *>(&_sys); 42 : mooseAssert(perf_graph_interface, 43 : "LinearFVGradientInterface requires its owning system to implement " 44 : "PerfGraphInterface."); 45 87154 : const auto perf_id = perf_graph_interface->registerTimedSection("LinearVariableFV_Gradients", 3); 46 : mooseAssert(!Threads::in_threads, "PerfGraph timing cannot be used within threaded sections"); 47 43577 : PerfGuard time_guard(perf_graph_interface->perfGraph(), perf_id); 48 : 49 : PARALLEL_TRY 50 : { 51 : using FaceInfoRange = StoredRange<MooseMesh::const_face_info_iterator, const FaceInfo *>; 52 87154 : FaceInfoRange face_info_range(fe_problem.mesh().ownedFaceInfoBegin(), 53 130731 : fe_problem.mesh().ownedFaceInfoEnd()); 54 : 55 : ComputeLinearFVGreenGaussGradientFaceThread gradient_face_thread( 56 43577 : fe_problem, _sys, temporary_gradient); 57 43577 : Threads::parallel_reduce(face_info_range, gradient_face_thread); 58 43577 : } 59 43577 : fe_problem.checkExceptionAndStopSolve(); 60 : 61 121291 : for (auto & vec : temporary_gradient) 62 77714 : vec->close(); 63 : 64 : PARALLEL_TRY 65 : { 66 : using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>; 67 87154 : ElemInfoRange elem_info_range(fe_problem.mesh().ownedElemInfoBegin(), 68 130731 : fe_problem.mesh().ownedElemInfoEnd()); 69 : 70 : ComputeLinearFVGreenGaussGradientVolumeThread gradient_volume_thread( 71 43577 : fe_problem, _sys, temporary_gradient); 72 43577 : Threads::parallel_reduce(elem_info_range, gradient_volume_thread); 73 43577 : } 74 43577 : fe_problem.checkExceptionAndStopSolve(); 75 : 76 121291 : for (const auto i : index_range(_raw_grad_container)) 77 77714 : temporary_gradient[i]->close(); 78 : 79 43577 : _raw_grad_container.swap(temporary_gradient); 80 : 81 43577 : if (!requestedLinearFVLimitedGradientTypes().empty()) 82 : { 83 : using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>; 84 23740 : ElemInfoRange elem_info_range(fe_problem.mesh().ownedElemInfoBegin(), 85 35610 : fe_problem.mesh().ownedElemInfoEnd()); 86 : 87 23740 : for (const auto limiter_type : requestedLinearFVLimitedGradientTypes()) 88 : { 89 11870 : if (limiter_type == Moose::FV::GradientLimiterType::None) 90 0 : continue; 91 : 92 11870 : auto & raw_container = rawLinearFVLimitedGradientContainer(limiter_type); 93 11870 : auto & temporary_container = temporaryLinearFVLimitedGradientContainer(limiter_type); 94 : mooseAssert(temporary_container.size() == raw_container.size(), 95 : "Temporary and raw limited gradient containers must have the same size."); 96 32580 : for (auto & vec : temporary_container) 97 20710 : vec->zero(); 98 : 99 : PARALLEL_TRY 100 : { 101 : ComputeLinearFVLimitedGradientThread limited_gradient_thread( 102 : fe_problem, 103 : _sys, 104 11870 : _raw_grad_container, 105 : temporary_container, 106 : limiter_type, 107 11870 : requestedLinearFVLimitedGradientVariables(limiter_type)); 108 11870 : Threads::parallel_reduce(elem_info_range, limited_gradient_thread); 109 : } 110 11870 : fe_problem.checkExceptionAndStopSolve(); 111 : 112 32580 : for (auto & vec : temporary_container) 113 20710 : vec->close(); 114 : 115 11870 : raw_container.swap(temporary_container); 116 : } 117 11870 : } 118 43577 : } 119 : 120 : bool 121 63722 : LinearFVGradientInterface::needsLinearFVGradientStorage() const 122 : { 123 159472 : for (const auto * const field_var : _sys.variableWarehouse().fieldVariables()) 124 96574 : if (field_var->needsGradientVectorStorage()) 125 824 : return true; 126 : 127 62898 : return false; 128 : } 129 : 130 : void 131 1774 : LinearFVGradientInterface::initializeContainer( 132 : std::vector<std::unique_ptr<NumericVector<Number>>> & container) const 133 : { 134 1774 : container.clear(); 135 : mooseAssert(_sys.currentSolution(), 136 : "Current solution must exist before building FV gradient storage."); 137 4702 : for (unsigned int i = 0; i < _sys.mesh().dimension(); ++i) 138 2928 : container.push_back(_sys.currentSolution()->zero_clone()); 139 1774 : } 140 : 141 : void 142 63722 : LinearFVGradientInterface::rebuildLinearFVGradientStorage() 143 : { 144 63722 : _raw_grad_container.clear(); 145 63722 : _temporary_gradient.clear(); 146 63722 : _raw_limited_grad_containers.clear(); 147 63722 : _temporary_limited_gradient.clear(); 148 : 149 63722 : if (!needsLinearFVGradientStorage()) 150 62898 : return; 151 : 152 824 : initializeContainer(_raw_grad_container); 153 824 : initializeContainer(_temporary_gradient); 154 : 155 887 : for (const auto limiter_type : _requested_limited_gradient_types) 156 : { 157 63 : if (limiter_type == Moose::FV::GradientLimiterType::None) 158 0 : continue; 159 : 160 63 : initializeContainer(_raw_limited_grad_containers[limiter_type]); 161 63 : initializeContainer(_temporary_limited_gradient[limiter_type]); 162 : } 163 : } 164 : 165 : void 166 63 : LinearFVGradientInterface::requestLinearFVLimitedGradients( 167 : const Moose::FV::GradientLimiterType limiter_type, const unsigned int variable_number) 168 : { 169 63 : if (limiter_type == Moose::FV::GradientLimiterType::None) 170 0 : return; 171 : 172 : auto * const variable = 173 63 : dynamic_cast<MooseVariableFieldBase *>(_sys.variableWarehouse().getVariable(variable_number)); 174 63 : if (!variable) 175 0 : mooseError("Limited gradients were requested for variable number ", 176 : variable_number, 177 : " on system '", 178 0 : _sys.name(), 179 : "', but no field variable with that number exists on the system."); 180 : 181 63 : if (!variable->needsGradientVectorStorage()) 182 0 : mooseError("Limited gradients were requested for variable '", 183 0 : variable->name(), 184 : "' on system '", 185 0 : _sys.name(), 186 : "', but regular gradients were not requested for that variable."); 187 : 188 63 : _requested_limited_gradient_variables[limiter_type].insert(variable_number); 189 : 190 63 : if (_requested_limited_gradient_types.insert(limiter_type).second && !_raw_grad_container.empty()) 191 : { 192 0 : initializeContainer(_raw_limited_grad_containers[limiter_type]); 193 0 : initializeContainer(_temporary_limited_gradient[limiter_type]); 194 : } 195 : } 196 : 197 : const std::vector<std::unique_ptr<NumericVector<Number>>> & 198 28016490 : LinearFVGradientInterface::linearFVLimitedGradientContainer( 199 : const Moose::FV::GradientLimiterType limiter_type) const 200 : { 201 28016490 : if (limiter_type == Moose::FV::GradientLimiterType::None) 202 0 : return _raw_grad_container; 203 : 204 28016490 : const auto it = _raw_limited_grad_containers.find(limiter_type); 205 28016490 : if (it == _raw_limited_grad_containers.end()) 206 0 : mooseError("Limited gradient container was requested but not initialized on system '", 207 0 : _sys.name(), 208 : "'."); 209 : 210 28016490 : return it->second; 211 : }