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 62880 : 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 239944552 : operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs) 32 : { 33 239944552 : return (*lhs) == (*rhs); 34 : } 35 : 36 210651482 : Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {} 37 : 38 : void 39 301831 : AttribSorted::initFrom(const MooseObject *) 40 : { 41 301831 : } 42 : 43 : bool 44 53633154 : AttribSorted::isMatch(const Attribute & other) const 45 : { 46 53633154 : auto a = dynamic_cast<const AttribSorted *>(&other); 47 53633154 : return _initd && a && a->_initd && (a->_val == _val); 48 : } 49 : 50 : bool 51 49153422 : AttribSorted::isEqual(const Attribute & other) const 52 : { 53 49153422 : return isMatch(other); 54 : } 55 : 56 : class VecStore : public WarehouseStorage 57 : { 58 : public: 59 301831 : virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override 60 : { 61 301831 : std::lock_guard<std::mutex> l(_mutex); 62 301831 : if (obj_id != _data.size()) 63 0 : throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added"); 64 301831 : _data.push_back(std::move(attribs)); 65 301831 : } 66 : 67 : virtual std::vector<std::size_t> 68 4558399 : query(const std::vector<std::unique_ptr<Attribute>> & conds) override 69 : { 70 4558399 : std::vector<std::size_t> ids; 71 4558399 : std::lock_guard<std::mutex> l(_mutex); 72 30175278 : for (std::size_t i = 0; i < _data.size(); i++) 73 : { 74 25616879 : auto & data = _data[i]; 75 25616879 : bool ismatch = true; 76 40042338 : for (auto & cond : conds) 77 : { 78 39150671 : if (!data[cond->id()]->isMatch(*cond)) 79 : { 80 24725212 : ismatch = false; 81 24725212 : break; 82 : } 83 : } 84 25616879 : if (ismatch) 85 : { 86 : mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object"); 87 891667 : ids.push_back(i); 88 : } 89 : } 90 9116798 : return ids; 91 4558399 : } 92 : 93 75320 : virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override 94 : { 95 75320 : if (obj_id > _data.size()) 96 0 : throw std::runtime_error("unknown object id " + std::to_string(obj_id)); 97 : 98 75320 : std::lock_guard<std::mutex> l(_mutex); 99 : 100 75320 : auto & dst = _data[obj_id]; 101 150640 : for (auto & attrib : attribs) 102 75320 : dst[attrib->id()] = std::move(attrib); 103 75320 : } 104 : 105 : private: 106 : std::mutex _mutex; 107 : std::vector<std::vector<std::unique_ptr<Attribute>>> _data; 108 : }; 109 : 110 66999 : TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {} 111 62880 : TheWarehouse::~TheWarehouse() {} 112 : 113 : void isValid(MooseObject * obj); 114 : 115 : void 116 301837 : TheWarehouse::add(std::shared_ptr<MooseObject> obj) 117 : { 118 301837 : isValid(obj.get()); 119 : 120 301831 : std::size_t obj_id = 0; 121 : { 122 301831 : std::lock_guard<std::mutex> lock(_obj_mutex); 123 : 124 : mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added"); 125 : 126 301831 : _objects.push_back(obj); 127 301831 : obj_id = _objects.size() - 1; 128 301831 : _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 301831 : _obj_cache.clear(); 133 301831 : _query_cache.clear(); 134 301831 : } 135 : 136 301831 : std::vector<std::unique_ptr<Attribute>> attribs; 137 301831 : readAttribs(obj.get(), attribs); 138 301831 : _store->add(obj_id, std::move(attribs)); 139 301831 : } 140 : 141 : void 142 75320 : TheWarehouse::update(MooseObject * obj, const Attribute & extra) 143 : { 144 75320 : std::vector<std::unique_ptr<Attribute>> attribs; 145 75320 : attribs.push_back(extra.clone()); 146 75320 : _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 75320 : _obj_cache.clear(); 150 75320 : _query_cache.clear(); 151 75320 : } 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 4558399 : TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds) 167 : { 168 4558399 : bool sort = false; 169 4558399 : std::unique_ptr<Attribute> sorted_attrib; 170 4558399 : if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get())) 171 : { 172 4479732 : sorted_attrib = std::move(conds.back()); 173 4479732 : static const AttribSorted sorted_attrib_true(*this, true); 174 4479732 : sort = sorted_attrib->isMatch(sorted_attrib_true); 175 : // Remove the sorted condition temporarily 176 4479732 : 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 4558399 : auto obj_ids = _store->query(conds); 186 4558399 : if (sorted_attrib) 187 4479732 : conds.push_back(std::move(sorted_attrib)); 188 : 189 4558399 : std::lock_guard<std::mutex> lock(_obj_cache_mutex); 190 4558399 : auto & vec = _obj_cache.emplace_back(obj_ids.size()); 191 4558399 : const auto query_id = _obj_cache.size() - 1; 192 : { 193 4558399 : std::lock_guard<std::mutex> lock(_query_cache_mutex); 194 4558399 : _query_cache[std::move(conds)] = query_id; 195 4558399 : } 196 : 197 4558399 : std::lock_guard<std::mutex> o_lock(_obj_mutex); 198 5450066 : for (const auto i : index_range(obj_ids)) 199 : { 200 891667 : auto obj = _objects[obj_ids[i]].get(); 201 : mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object"); 202 891667 : vec[i] = obj; 203 : } 204 : 205 4558399 : if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0])) 206 : { 207 241197 : std::vector<DependencyResolverInterface *> dependers; 208 707729 : for (auto obj : vec) 209 : { 210 466532 : auto d = dynamic_cast<DependencyResolverInterface *>(obj); 211 466532 : if (!d) 212 : { 213 0 : dependers.clear(); 214 0 : break; 215 : } 216 466532 : dependers.push_back(d); 217 : } 218 : 219 : try 220 : { 221 241197 : DependencyResolverInterface::sort(dependers); 222 : } 223 0 : catch (CyclicDependencyException<DependencyResolverInterface *> & e) 224 : { 225 0 : DependencyResolverInterface::cyclicDependencyError<MooseObject *>( 226 : e, 227 : "Cyclic dependency detected in object ordering", 228 0 : [](DependencyResolverInterface * obj) 229 : { 230 0 : auto * moose_obj = dynamic_cast<MooseObject *>(obj); 231 : mooseAssert(moose_obj, "Failed to cast dependency object to MooseObject"); 232 0 : return moose_obj->name(); 233 : }); 234 0 : } 235 : 236 : mooseAssert(dependers.size() == vec.size(), "Dependency resolution size mismatch"); 237 707729 : for (unsigned int i = 0; i < dependers.size(); i++) 238 466532 : vec[i] = dynamic_cast<MooseObject *>(dependers[i]); 239 241197 : } 240 : 241 4558399 : return query_id; 242 4558399 : } 243 : 244 : const std::vector<MooseObject *> & 245 116897612 : TheWarehouse::query(int query_id) 246 : { 247 116897612 : if (static_cast<std::size_t>(query_id) >= _obj_cache.size()) 248 0 : throw std::runtime_error("unknown query id"); 249 116897612 : return _obj_cache[query_id]; 250 : } 251 : 252 : std::size_t 253 53961685 : TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds) 254 : { 255 : { 256 53961685 : std::lock_guard<std::mutex> lock(_query_cache_mutex); 257 53961685 : auto it = _query_cache.find(conds); 258 53961685 : if (it != _query_cache.end()) 259 49403286 : return it->second; 260 53961685 : } 261 : 262 4558399 : std::vector<std::unique_ptr<Attribute>> conds_clone; 263 4558399 : conds_clone.resize(conds.size()); 264 24462615 : for (std::size_t i = 0; i < conds.size(); i++) 265 19904216 : conds_clone[i] = conds[i]->clone(); 266 4558399 : return prepare(std::move(conds_clone)); 267 4558399 : } 268 : 269 : std::size_t 270 326978 : TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds) 271 : { 272 326978 : auto query_id = queryID(conds); 273 326978 : std::lock_guard<std::mutex> lock(_obj_cache_mutex); 274 326978 : auto & objs = query(query_id); 275 326978 : std::size_t count = 0; 276 349506 : for (auto obj : objs) 277 22528 : if (obj->enabled()) 278 22528 : count++; 279 326978 : return count; 280 326978 : } 281 : 282 : void 283 301831 : TheWarehouse::readAttribs(const MooseObject * obj, 284 : std::vector<std::unique_ptr<Attribute>> & attribs) 285 : { 286 5734689 : for (auto & ref : _attrib_list) 287 : { 288 5432858 : attribs.emplace_back(ref->clone()); 289 5432858 : attribs.back()->initFrom(obj); 290 : } 291 301831 : } 292 : 293 : void 294 301837 : isValid(MooseObject * obj) 295 : { 296 301837 : auto blk = dynamic_cast<BlockRestrictable *>(obj); 297 301837 : if (!blk) 298 167977 : return; 299 : 300 : // Check variables 301 133860 : auto c_ptr = dynamic_cast<Coupleable *>(obj); 302 133860 : if (c_ptr) 303 175259 : for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars()) 304 43704 : blk->checkVariable(*var); 305 : 306 133854 : const InputParameters & parameters = obj->parameters(); 307 : 308 133854 : SubProblem & problem = *parameters.get<SubProblem *>("_subproblem"); 309 : 310 133854 : THREAD_ID tid = parameters.get<THREAD_ID>("_tid"); 311 : 312 267708 : if (parameters.isParamValid("variable")) 313 : { 314 : // Try the scalar version first 315 125923 : std::string variable_name = parameters.getMooseType("variable"); 316 125923 : if (variable_name == "") 317 : // When using vector variables, we are only going to use the first one in the list at the 318 : // interface level... 319 59414 : variable_name = parameters.getVecMooseType("variable")[0]; 320 : 321 125923 : blk->checkVariable(problem.getVariable( 322 : tid, variable_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY)); 323 125923 : } 324 : }