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