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 : #pragma once 11 : 12 : #include "ParallelUniqueId.h" 13 : #include "FEProblemBase.h" 14 : #include "ThreadedElementLoopBase.h" 15 : #include "ConsoleUtils.h" 16 : #include "SwapBackSentinel.h" 17 : 18 : // Forward declarations 19 : class SystemBase; 20 : 21 : /** 22 : * This mutex is used by all derived classes of the ThreadedElementLoop. It 23 : * is necessary to protect the creation of the strings used in the propagation 24 : * of the error messages. It's possible for a thread to have acquired the 25 : * commonly used mutex in the Threads namespace so this one is here to 26 : * avoid any deadlocking. 27 : */ 28 : static Threads::spin_mutex threaded_element_mutex; 29 : 30 : /** 31 : * Base class for assembly-like calculations. 32 : */ 33 : template <typename RangeType> 34 : class ThreadedElementLoop : public ThreadedElementLoopBase<RangeType> 35 : { 36 : public: 37 : ThreadedElementLoop(FEProblemBase & feproblem); 38 : 39 : ThreadedElementLoop(ThreadedElementLoop & x, Threads::split split); 40 : 41 : virtual ~ThreadedElementLoop(); 42 : 43 : virtual void caughtMooseException(MooseException & e) override; 44 : 45 388188137 : virtual bool keepGoing() override { return !_fe_problem.hasException(); } 46 : 47 : virtual void preElement(const Elem * elem) override; 48 : 49 : virtual void preInternalSide(const Elem * elem, unsigned int side) override; 50 : 51 : virtual void preBoundary(const Elem * elem, 52 : unsigned int side, 53 : BoundaryID bnd_id, 54 : const Elem * lower_d_elem = nullptr) override; 55 : 56 : virtual void neighborSubdomainChanged() override; 57 : 58 : protected: 59 : void prepareElement(const Elem * elem); 60 : void clearVarsAndMaterials(); 61 : 62 : FEProblemBase & _fe_problem; 63 : 64 : /** 65 : * Routine to output the ordering of objects within a vector of pointers to these objects. 66 : * These objects must implement the name() routine, and it must return a string or compatible 67 : * type. 68 : * 69 : * @tparam T the object type 70 : * @param objs the vector with all the objects (should be pointers) 71 : * @param objects_type the name of the type of objects. Defaults to the CPP object name 72 : * @param print_header whether to print a header about the timing of execution and the type of 73 : * objects 74 : */ 75 : template <typename T> 76 : void printExecutionOrdering(const std::vector<T *> & objs, 77 : const bool print_header = true, 78 : const std::string & line_prefix = "[DBG]") const; 79 : template <typename T> 80 : void printExecutionOrdering(const std::vector<std::shared_ptr<T>> & objs_ptrs, 81 : const bool print_header = true, 82 : const std::string & line_prefix = "[DBG]") const; 83 : }; 84 : 85 : template <typename RangeType> 86 3918882 : ThreadedElementLoop<RangeType>::ThreadedElementLoop(FEProblemBase & fe_problem) 87 3918882 : : ThreadedElementLoopBase<RangeType>(fe_problem.mesh()), _fe_problem(fe_problem) 88 : { 89 3918882 : } 90 : 91 : template <typename RangeType> 92 342439 : ThreadedElementLoop<RangeType>::ThreadedElementLoop(ThreadedElementLoop & x, 93 : Threads::split /*split*/) 94 342439 : : ThreadedElementLoopBase<RangeType>(x), _fe_problem(x._fe_problem) 95 : { 96 342439 : } 97 : 98 : template <typename RangeType> 99 4261239 : ThreadedElementLoop<RangeType>::~ThreadedElementLoop() 100 : { 101 4261239 : } 102 : 103 : template <typename RangeType> 104 : void 105 165 : ThreadedElementLoop<RangeType>::caughtMooseException(MooseException & e) 106 : { 107 165 : Threads::spin_mutex::scoped_lock lock(threaded_element_mutex); 108 : 109 165 : std::string what(e.what()); 110 165 : _fe_problem.setException(what); 111 165 : } 112 : 113 : template <typename RangeType> 114 : void 115 388188132 : ThreadedElementLoop<RangeType>::preElement(const Elem * el) 116 : { 117 388188132 : _fe_problem.setCurrentSubdomainID(el, ThreadedElementLoopBase<RangeType>::_tid); 118 388188132 : } 119 : 120 : template <typename RangeType> 121 : void 122 1476509705 : ThreadedElementLoop<RangeType>::preInternalSide(const Elem * el, unsigned int side) 123 : { 124 1476509705 : _fe_problem.setNeighborSubdomainID(el, side, ThreadedElementLoopBase<RangeType>::_tid); 125 1476509705 : } 126 : 127 : template <typename RangeType> 128 : void 129 116160485 : ThreadedElementLoop<RangeType>::preBoundary(const Elem * /*elem*/, 130 : unsigned int /*side*/, 131 : BoundaryID bnd_id, 132 : const Elem * /*=nullptr*/) 133 : { 134 116160485 : _fe_problem.setCurrentBoundaryID(bnd_id, ThreadedElementLoopBase<RangeType>::_tid); 135 116160485 : } 136 : 137 : template <typename RangeType> 138 : void 139 12810469 : ThreadedElementLoop<RangeType>::neighborSubdomainChanged() 140 : { 141 12810469 : _fe_problem.neighborSubdomainSetup(ThreadedElementLoopBase<RangeType>::_neighbor_subdomain, 142 : ThreadedElementLoopBase<RangeType>::_tid); 143 12810469 : } 144 : 145 : template <typename RangeType> 146 : template <typename T> 147 : void 148 13276 : ThreadedElementLoop<RangeType>::printExecutionOrdering(const std::vector<T *> & objs, 149 : const bool print_header, 150 : const std::string & line_prefix) const 151 : { 152 13276 : if (!objs.size()) 153 1460 : return; 154 : 155 11816 : auto & console = _fe_problem.console(); 156 11816 : const auto objects_type = MooseUtils::prettyCppType(objs[0]); 157 11816 : std::vector<MooseObject *> moose_objs; 158 34830 : for (auto obj_ptr : objs) 159 23014 : moose_objs.push_back(dynamic_cast<MooseObject *>(obj_ptr)); 160 11816 : const auto names = ConsoleUtils::mooseObjectVectorToString(moose_objs); 161 : 162 : // Print string with a DBG prefix and with sufficient line breaks 163 12806 : std::string message = print_header ? "Executing " + objects_type + " on " + 164 990 : _fe_problem.getCurrentExecuteOnFlag().name() + "\n" 165 : : ""; 166 11816 : message += (print_header ? "Order of execution:\n" : "") + names; 167 11816 : console << ConsoleUtils::formatString(message, line_prefix) << std::endl; 168 11816 : } 169 : 170 : template <typename RangeType> 171 : template <typename T> 172 : void 173 10826 : ThreadedElementLoop<RangeType>::printExecutionOrdering( 174 : const std::vector<std::shared_ptr<T>> & objs_ptrs, 175 : const bool print_header, 176 : const std::string & line_prefix) const 177 : { 178 10826 : std::vector<T *> regular_ptrs; 179 31320 : for (auto shared_ptr : objs_ptrs) 180 20494 : regular_ptrs.push_back(shared_ptr.get()); 181 10826 : printExecutionOrdering<T>(regular_ptrs, print_header, line_prefix); 182 10826 : } 183 : 184 : template <typename RangeType> 185 : void 186 344434215 : ThreadedElementLoop<RangeType>::prepareElement(const Elem * const elem) 187 : { 188 344434215 : _fe_problem.prepare(elem, this->_tid); 189 344434187 : _fe_problem.reinitElem(elem, this->_tid); 190 344434187 : _fe_problem.reinitMaterials(this->_subdomain, this->_tid); 191 344434129 : } 192 : 193 : template <typename RangeType> 194 : void 195 3797293 : ThreadedElementLoop<RangeType>::clearVarsAndMaterials() 196 : { 197 3797293 : _fe_problem.clearActiveElementalMooseVariables(this->_tid); 198 3797293 : _fe_problem.clearActiveMaterialProperties(this->_tid); 199 3797293 : }