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 "TheWarehouse.h" 11 : 12 : #include "Attributes.h" 13 : #include "MooseObject.h" 14 : #include "SubProblem.h" 15 : #include "GeneralUserObject.h" 16 : #include "DependencyResolverInterface.h" 17 : #include "BlockRestrictable.h" 18 : 19 : #include <memory> 20 : 21 : class WarehouseStorage 22 : { 23 : public: 24 62076 : virtual ~WarehouseStorage() = default; 25 : virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) = 0; 26 : virtual std::vector<std::size_t> query(const std::vector<std::unique_ptr<Attribute>> & conds) = 0; 27 : virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) = 0; 28 : }; 29 : 30 : bool 31 229496500 : operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs) 32 : { 33 229496500 : return (*lhs) == (*rhs); 34 : } 35 : 36 194891421 : Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {} 37 : 38 : void 39 310942 : AttribSorted::initFrom(const MooseObject *) 40 : { 41 310942 : } 42 : 43 : bool 44 47734313 : AttribSorted::isMatch(const Attribute & other) const 45 : { 46 47734313 : auto a = dynamic_cast<const AttribSorted *>(&other); 47 47734313 : return _initd && a && a->_initd && (a->_val == _val); 48 : } 49 : 50 : bool 51 44263233 : AttribSorted::isEqual(const Attribute & other) const 52 : { 53 44263233 : return isMatch(other); 54 : } 55 : 56 : class VecStore : public WarehouseStorage 57 : { 58 : public: 59 310942 : virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override 60 : { 61 310942 : std::lock_guard<std::mutex> l(_mutex); 62 310942 : if (obj_id != _data.size()) 63 0 : throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added"); 64 310942 : _data.push_back(std::move(attribs)); 65 310942 : } 66 : 67 : virtual std::vector<std::size_t> 68 3546973 : query(const std::vector<std::unique_ptr<Attribute>> & conds) override 69 : { 70 3546973 : std::vector<std::size_t> ids; 71 3546973 : std::lock_guard<std::mutex> l(_mutex); 72 24278251 : for (std::size_t i = 0; i < _data.size(); i++) 73 : { 74 20731278 : auto & data = _data[i]; 75 20731278 : bool ismatch = true; 76 36334547 : for (auto & cond : conds) 77 : { 78 35342230 : if (!data[cond->id()]->isMatch(*cond)) 79 : { 80 19738961 : ismatch = false; 81 19738961 : break; 82 : } 83 : } 84 20731278 : if (ismatch) 85 : { 86 : mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object"); 87 992317 : ids.push_back(i); 88 : } 89 : } 90 7093946 : return ids; 91 3546973 : } 92 : 93 81142 : virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override 94 : { 95 81142 : if (obj_id > _data.size()) 96 0 : throw std::runtime_error("unknown object id " + std::to_string(obj_id)); 97 : 98 81142 : std::lock_guard<std::mutex> l(_mutex); 99 : 100 81142 : auto & dst = _data[obj_id]; 101 162284 : for (auto & attrib : attribs) 102 81142 : dst[attrib->id()] = std::move(attrib); 103 81142 : } 104 : 105 : private: 106 : std::mutex _mutex; 107 : std::vector<std::vector<std::unique_ptr<Attribute>>> _data; 108 : }; 109 : 110 67612 : TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {} 111 62076 : TheWarehouse::~TheWarehouse() {} 112 : 113 : void isValid(MooseObject * obj); 114 : 115 : void 116 310942 : TheWarehouse::add(std::shared_ptr<MooseObject> obj) 117 : { 118 310942 : isValid(obj.get()); 119 : 120 310942 : std::size_t obj_id = 0; 121 : { 122 310942 : std::lock_guard<std::mutex> lock(_obj_mutex); 123 : 124 : mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added"); 125 : 126 310942 : _objects.push_back(obj); 127 310942 : obj_id = _objects.size() - 1; 128 310942 : _obj_ids[obj.get()] = obj_id; 129 : 130 : // reset/invalidate the query cache since query results may have been affected by this warehouse 131 : // insertion. 132 310942 : _obj_cache.clear(); 133 310942 : _query_cache.clear(); 134 310942 : } 135 : 136 310942 : std::vector<std::unique_ptr<Attribute>> attribs; 137 310942 : readAttribs(obj.get(), attribs); 138 310942 : _store->add(obj_id, std::move(attribs)); 139 310942 : } 140 : 141 : void 142 81142 : TheWarehouse::update(MooseObject * obj, const Attribute & extra) 143 : { 144 81142 : std::vector<std::unique_ptr<Attribute>> attribs; 145 81142 : attribs.push_back(extra.clone()); 146 81142 : _store->set(_obj_ids[obj], std::move(attribs)); 147 : // reset/invalidate the query cache since query results may have been affected by this object 148 : // attribute modification. 149 81142 : _obj_cache.clear(); 150 81142 : _query_cache.clear(); 151 81142 : } 152 : 153 : void 154 0 : TheWarehouse::update(MooseObject * obj) 155 : { 156 0 : std::vector<std::unique_ptr<Attribute>> attribs; 157 0 : readAttribs(obj, attribs); 158 0 : _store->set(_obj_ids[obj], std::move(attribs)); 159 : // reset/invalidate the query cache since query results may have been affected by this object 160 : // attribute modification. 161 0 : _obj_cache.clear(); 162 0 : _query_cache.clear(); 163 0 : } 164 : 165 : int 166 3546973 : TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds) 167 : { 168 3546973 : bool sort = false; 169 3546973 : std::unique_ptr<Attribute> sorted_attrib; 170 3546973 : if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get())) 171 : { 172 3471080 : sorted_attrib = std::move(conds.back()); 173 3471080 : static const AttribSorted sorted_attrib_true(*this, true); 174 3471080 : sort = sorted_attrib->isMatch(sorted_attrib_true); 175 : // Remove the sorted condition temporarily 176 3471080 : conds.pop_back(); 177 : } 178 : 179 : #ifdef DEBUG 180 : for (auto & cond : conds) 181 : mooseAssert(!dynamic_cast<AttribSorted *>(cond.get()), 182 : "There should be no sorted attributes in this container."); 183 : #endif 184 : 185 3546973 : auto obj_ids = _store->query(conds); 186 3546973 : if (sorted_attrib) 187 3471080 : conds.push_back(std::move(sorted_attrib)); 188 : 189 3546973 : std::lock_guard<std::mutex> lock(_obj_cache_mutex); 190 3546973 : auto & vec = _obj_cache.emplace_back(obj_ids.size()); 191 3546973 : const auto query_id = _obj_cache.size() - 1; 192 : { 193 3546973 : std::lock_guard<std::mutex> lock(_query_cache_mutex); 194 3546973 : _query_cache[std::move(conds)] = query_id; 195 3546973 : } 196 : 197 3546973 : std::lock_guard<std::mutex> o_lock(_obj_mutex); 198 4539290 : for (const auto i : index_range(obj_ids)) 199 : { 200 992317 : auto obj = _objects[obj_ids[i]].get(); 201 : mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object"); 202 992317 : vec[i] = obj; 203 : } 204 : 205 3546973 : if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0])) 206 : { 207 253376 : std::vector<DependencyResolverInterface *> dependers; 208 753098 : for (auto obj : vec) 209 : { 210 499722 : auto d = dynamic_cast<DependencyResolverInterface *>(obj); 211 499722 : if (!d) 212 : { 213 0 : dependers.clear(); 214 0 : break; 215 : } 216 499722 : dependers.push_back(d); 217 : } 218 : 219 : try 220 : { 221 253376 : DependencyResolverInterface::sort(dependers); 222 : } 223 0 : catch (CyclicDependencyException<DependencyResolverInterface *> & e) 224 : { 225 0 : DependencyResolverInterface::cyclicDependencyError<UserObject *>( 226 : e, "Cyclic dependency detected in object ordering"); 227 0 : } 228 : 229 : mooseAssert(dependers.size() == vec.size(), "Dependency resolution size mismatch"); 230 753098 : for (unsigned int i = 0; i < dependers.size(); i++) 231 499722 : vec[i] = dynamic_cast<MooseObject *>(dependers[i]); 232 253376 : } 233 : 234 3546973 : return query_id; 235 3546973 : } 236 : 237 : const std::vector<MooseObject *> & 238 149988082 : TheWarehouse::query(int query_id) 239 : { 240 149988082 : if (static_cast<std::size_t>(query_id) >= _obj_cache.size()) 241 0 : throw std::runtime_error("unknown query id"); 242 149988082 : return _obj_cache[query_id]; 243 : } 244 : 245 : std::size_t 246 48074751 : TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds) 247 : { 248 : { 249 48074751 : std::lock_guard<std::mutex> lock(_query_cache_mutex); 250 48074751 : auto it = _query_cache.find(conds); 251 48074751 : if (it != _query_cache.end()) 252 44527778 : return it->second; 253 48074751 : } 254 : 255 3546973 : std::vector<std::unique_ptr<Attribute>> conds_clone; 256 3546973 : conds_clone.resize(conds.size()); 257 19931507 : for (std::size_t i = 0; i < conds.size(); i++) 258 16384534 : conds_clone[i] = conds[i]->clone(); 259 3546973 : return prepare(std::move(conds_clone)); 260 3546973 : } 261 : 262 : std::size_t 263 338900 : TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds) 264 : { 265 338900 : auto query_id = queryID(conds); 266 338900 : std::lock_guard<std::mutex> lock(_obj_cache_mutex); 267 338900 : auto & objs = query(query_id); 268 338900 : std::size_t count = 0; 269 361698 : for (auto obj : objs) 270 22798 : if (obj->enabled()) 271 22798 : count++; 272 338900 : return count; 273 338900 : } 274 : 275 : void 276 310942 : TheWarehouse::readAttribs(const MooseObject * obj, 277 : std::vector<std::unique_ptr<Attribute>> & attribs) 278 : { 279 5907850 : for (auto & ref : _attrib_list) 280 : { 281 5596908 : attribs.emplace_back(ref->clone()); 282 5596908 : attribs.back()->initFrom(obj); 283 : } 284 310942 : } 285 : 286 : void 287 310942 : isValid(MooseObject * obj) 288 : { 289 310942 : auto blk = dynamic_cast<BlockRestrictable *>(obj); 290 310942 : if (!blk) 291 165583 : return; 292 : 293 : // Check variables 294 145359 : auto c_ptr = dynamic_cast<Coupleable *>(obj); 295 145359 : if (c_ptr) 296 185961 : for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars()) 297 43973 : blk->checkVariable(*var); 298 : 299 145359 : const InputParameters & parameters = obj->parameters(); 300 : 301 145359 : SubProblem & problem = *parameters.get<SubProblem *>("_subproblem"); 302 : 303 145359 : THREAD_ID tid = parameters.get<THREAD_ID>("_tid"); 304 : 305 145359 : if (parameters.isParamValid("variable")) 306 : { 307 : // Try the scalar version first 308 135686 : std::string variable_name = parameters.getMooseType("variable"); 309 135686 : if (variable_name == "") 310 : // When using vector variables, we are only going to use the first one in the list at the 311 : // interface level... 312 29724 : variable_name = parameters.getVecMooseType("variable")[0]; 313 : 314 135686 : blk->checkVariable(problem.getVariable( 315 : tid, variable_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY)); 316 135686 : } 317 : }