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 64447 : 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 234702441 : operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs) 32 : { 33 234702441 : return (*lhs) == (*rhs); 34 : } 35 : 36 199165274 : Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {} 37 : 38 : void 39 321246 : AttribSorted::initFrom(const MooseObject *) 40 : { 41 321246 : } 42 : 43 : bool 44 48874845 : AttribSorted::isMatch(const Attribute & other) const 45 : { 46 48874845 : auto a = dynamic_cast<const AttribSorted *>(&other); 47 48874845 : return _initd && a && a->_initd && (a->_val == _val); 48 : } 49 : 50 : bool 51 45269109 : AttribSorted::isEqual(const Attribute & other) const 52 : { 53 45269109 : return isMatch(other); 54 : } 55 : 56 : class VecStore : public WarehouseStorage 57 : { 58 : public: 59 321246 : virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override 60 : { 61 321246 : std::lock_guard<std::mutex> l(_mutex); 62 321246 : if (obj_id != _data.size()) 63 0 : throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added"); 64 321246 : _data.push_back(std::move(attribs)); 65 321246 : } 66 : 67 : virtual std::vector<std::size_t> 68 3691067 : query(const std::vector<std::unique_ptr<Attribute>> & conds) override 69 : { 70 3691067 : std::vector<std::size_t> ids; 71 3691067 : std::lock_guard<std::mutex> l(_mutex); 72 25291482 : for (std::size_t i = 0; i < _data.size(); i++) 73 : { 74 21600415 : auto & data = _data[i]; 75 21600415 : bool ismatch = true; 76 38118081 : for (auto & cond : conds) 77 : { 78 37069756 : if (!data[cond->id()]->isMatch(*cond)) 79 : { 80 20552090 : ismatch = false; 81 20552090 : break; 82 : } 83 : } 84 21600415 : if (ismatch) 85 : { 86 : mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object"); 87 1048325 : ids.push_back(i); 88 : } 89 : } 90 7382134 : return ids; 91 3691067 : } 92 : 93 85530 : virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override 94 : { 95 85530 : if (obj_id > _data.size()) 96 0 : throw std::runtime_error("unknown object id " + std::to_string(obj_id)); 97 : 98 85530 : std::lock_guard<std::mutex> l(_mutex); 99 : 100 85530 : auto & dst = _data[obj_id]; 101 171060 : for (auto & attrib : attribs) 102 85530 : dst[attrib->id()] = std::move(attrib); 103 85530 : } 104 : 105 : private: 106 : std::mutex _mutex; 107 : std::vector<std::vector<std::unique_ptr<Attribute>>> _data; 108 : }; 109 : 110 70213 : TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {} 111 64447 : TheWarehouse::~TheWarehouse() {} 112 : 113 : void isValid(MooseObject * obj); 114 : 115 : void 116 321246 : TheWarehouse::add(std::shared_ptr<MooseObject> obj) 117 : { 118 321246 : isValid(obj.get()); 119 : 120 321246 : std::size_t obj_id = 0; 121 : { 122 321246 : std::lock_guard<std::mutex> lock(_obj_mutex); 123 : 124 : mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added"); 125 : 126 321246 : _objects.push_back(obj); 127 321246 : obj_id = _objects.size() - 1; 128 321246 : _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 321246 : _obj_cache.clear(); 133 321246 : _query_cache.clear(); 134 321246 : } 135 : 136 321246 : std::vector<std::unique_ptr<Attribute>> attribs; 137 321246 : readAttribs(obj.get(), attribs); 138 321246 : _store->add(obj_id, std::move(attribs)); 139 321246 : } 140 : 141 : void 142 85530 : TheWarehouse::update(MooseObject * obj, const Attribute & extra) 143 : { 144 85530 : std::vector<std::unique_ptr<Attribute>> attribs; 145 85530 : attribs.push_back(extra.clone()); 146 85530 : _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 85530 : _obj_cache.clear(); 150 85530 : _query_cache.clear(); 151 85530 : } 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 3691067 : TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds) 167 : { 168 3691067 : bool sort = false; 169 3691067 : std::unique_ptr<Attribute> sorted_attrib; 170 3691067 : if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get())) 171 : { 172 3605736 : sorted_attrib = std::move(conds.back()); 173 3605736 : static const AttribSorted sorted_attrib_true(*this, true); 174 3605736 : sort = sorted_attrib->isMatch(sorted_attrib_true); 175 : // Remove the sorted condition temporarily 176 3605736 : 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 3691067 : auto obj_ids = _store->query(conds); 186 3691067 : if (sorted_attrib) 187 3605736 : conds.push_back(std::move(sorted_attrib)); 188 : 189 3691067 : std::lock_guard<std::mutex> lock(_obj_cache_mutex); 190 3691067 : auto & vec = _obj_cache.emplace_back(obj_ids.size()); 191 3691067 : const auto query_id = _obj_cache.size() - 1; 192 : { 193 3691067 : std::lock_guard<std::mutex> lock(_query_cache_mutex); 194 3691067 : _query_cache[std::move(conds)] = query_id; 195 3691067 : } 196 : 197 3691067 : std::lock_guard<std::mutex> o_lock(_obj_mutex); 198 4739392 : for (const auto i : index_range(obj_ids)) 199 : { 200 1048325 : auto obj = _objects[obj_ids[i]].get(); 201 : mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object"); 202 1048325 : vec[i] = obj; 203 : } 204 : 205 3691067 : if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0])) 206 : { 207 267192 : std::vector<DependencyResolverInterface *> dependers; 208 796525 : for (auto obj : vec) 209 : { 210 529333 : auto d = dynamic_cast<DependencyResolverInterface *>(obj); 211 529333 : if (!d) 212 : { 213 0 : dependers.clear(); 214 0 : break; 215 : } 216 529333 : dependers.push_back(d); 217 : } 218 : 219 : try 220 : { 221 267192 : 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 796525 : for (unsigned int i = 0; i < dependers.size(); i++) 231 529333 : vec[i] = dynamic_cast<MooseObject *>(dependers[i]); 232 267192 : } 233 : 234 3691067 : return query_id; 235 3691067 : } 236 : 237 : const std::vector<MooseObject *> & 238 151385445 : TheWarehouse::query(int query_id) 239 : { 240 151385445 : if (static_cast<std::size_t>(query_id) >= _obj_cache.size()) 241 0 : throw std::runtime_error("unknown query id"); 242 151385445 : return _obj_cache[query_id]; 243 : } 244 : 245 : std::size_t 246 49229730 : TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds) 247 : { 248 : { 249 49229730 : std::lock_guard<std::mutex> lock(_query_cache_mutex); 250 49229730 : auto it = _query_cache.find(conds); 251 49229730 : if (it != _query_cache.end()) 252 45538663 : return it->second; 253 49229730 : } 254 : 255 3691067 : std::vector<std::unique_ptr<Attribute>> conds_clone; 256 3691067 : conds_clone.resize(conds.size()); 257 20749124 : for (std::size_t i = 0; i < conds.size(); i++) 258 17058057 : conds_clone[i] = conds[i]->clone(); 259 3691067 : return prepare(std::move(conds_clone)); 260 3691067 : } 261 : 262 : std::size_t 263 353249 : TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds) 264 : { 265 353249 : auto query_id = queryID(conds); 266 353249 : std::lock_guard<std::mutex> lock(_obj_cache_mutex); 267 353249 : auto & objs = query(query_id); 268 353249 : std::size_t count = 0; 269 378145 : for (auto obj : objs) 270 24896 : if (obj->enabled()) 271 24896 : count++; 272 353249 : return count; 273 353249 : } 274 : 275 : void 276 321246 : TheWarehouse::readAttribs(const MooseObject * obj, 277 : std::vector<std::unique_ptr<Attribute>> & attribs) 278 : { 279 6103574 : for (auto & ref : _attrib_list) 280 : { 281 5782328 : attribs.emplace_back(ref->clone()); 282 5782328 : attribs.back()->initFrom(obj); 283 : } 284 321246 : } 285 : 286 : void 287 321246 : isValid(MooseObject * obj) 288 : { 289 321246 : auto blk = dynamic_cast<BlockRestrictable *>(obj); 290 321246 : if (!blk) 291 172313 : return; 292 : 293 : // Check variables 294 148933 : auto c_ptr = dynamic_cast<Coupleable *>(obj); 295 148933 : if (c_ptr) 296 190869 : for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars()) 297 45385 : blk->checkVariable(*var); 298 : 299 148933 : const InputParameters & parameters = obj->parameters(); 300 : 301 148933 : SubProblem & problem = *parameters.get<SubProblem *>("_subproblem"); 302 : 303 148933 : THREAD_ID tid = parameters.get<THREAD_ID>("_tid"); 304 : 305 297866 : if (parameters.isParamValid("variable")) 306 : { 307 : // Try the scalar version first 308 138696 : std::string variable_name = parameters.getMooseType("variable"); 309 138696 : 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 61178 : variable_name = parameters.getVecMooseType("variable")[0]; 313 : 314 138696 : blk->checkVariable(problem.getVariable( 315 : tid, variable_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY)); 316 138696 : } 317 : }