https://mooseframework.inl.gov
Loading...
Searching...
No Matches
TheWarehouse.C
Go to the documentation of this file.
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"
17#include "BlockRestrictable.h"
18#include "ScalarCoupleable.h"
19#include "ScalarKernelBase.h"
20#include "MooseVariableScalar.h"
21#include "Conversion.h"
22
23#include <algorithm>
24#include <iterator>
25#include <memory>
26
28{
29public:
30 virtual ~WarehouseStorage() = default;
31 virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) = 0;
32 virtual std::vector<std::size_t> query(const std::vector<std::unique_ptr<Attribute>> & conds) = 0;
33 virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) = 0;
34};
35
36bool
37operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs)
38{
39 return (*lhs) == (*rhs);
40}
41
42Attribute::Attribute(TheWarehouse & w, const std::string name) : _id(w.attribID(name)) {}
43
44void
48
49bool
50AttribSorted::isMatch(const Attribute & other) const
51{
52 auto a = dynamic_cast<const AttribSorted *>(&other);
53 return _initd && a && a->_initd && (a->_val == _val);
54}
55
56bool
57AttribSorted::isEqual(const Attribute & other) const
58{
59 return isMatch(other);
60}
61
63{
64public:
65 virtual void add(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
66 {
67 std::lock_guard<std::mutex> l(_mutex);
68 if (obj_id != _data.size())
69 throw std::runtime_error("object with id " + std::to_string(obj_id) + " already added");
70 _data.push_back(std::move(attribs));
71 }
72
73 virtual std::vector<std::size_t>
74 query(const std::vector<std::unique_ptr<Attribute>> & conds) override
75 {
76 std::vector<std::size_t> ids;
77 std::lock_guard<std::mutex> l(_mutex);
78 for (std::size_t i = 0; i < _data.size(); i++)
79 {
80 auto & data = _data[i];
81 bool ismatch = true;
82 for (auto & cond : conds)
83 {
84 if (!data[cond->id()]->isMatch(*cond))
85 {
86 ismatch = false;
87 break;
88 }
89 }
90 if (ismatch)
91 {
92 mooseAssert(std::find(ids.begin(), ids.end(), i) == ids.end(), "Duplicate object");
93 ids.push_back(i);
94 }
95 }
96 return ids;
97 }
98
99 virtual void set(std::size_t obj_id, std::vector<std::unique_ptr<Attribute>> attribs) override
100 {
101 if (obj_id > _data.size())
102 throw std::runtime_error("unknown object id " + std::to_string(obj_id));
103
104 std::lock_guard<std::mutex> l(_mutex);
105
106 auto & dst = _data[obj_id];
107 for (auto & attrib : attribs)
108 dst[attrib->id()] = std::move(attrib);
109 }
110
111private:
112 std::mutex _mutex;
113 std::vector<std::vector<std::unique_ptr<Attribute>>> _data;
114};
115
116TheWarehouse::TheWarehouse() : _store(std::make_unique<VecStore>()) {}
118
119void isValid(MooseObject * obj);
120
121void
122TheWarehouse::add(std::shared_ptr<MooseObject> obj)
123{
124 isValid(obj.get());
125
126 std::size_t obj_id = 0;
127 {
128 std::lock_guard<std::mutex> lock(_obj_mutex);
129
130 mooseAssert(!_obj_ids.count(obj.get()), obj->typeAndName() + " has already been added");
131
132 _objects.push_back(obj);
133 obj_id = _objects.size() - 1;
134 _obj_ids[obj.get()] = obj_id;
135
136 // reset/invalidate the query cache since query results may have been affected by this warehouse
137 // insertion.
138 _obj_cache.clear();
139 _query_cache.clear();
140 }
141
142 std::vector<std::unique_ptr<Attribute>> attribs;
143 readAttribs(obj.get(), attribs);
144 _store->add(obj_id, std::move(attribs));
145}
146
147void
149{
150 std::vector<std::unique_ptr<Attribute>> attribs;
151 attribs.push_back(extra.clone());
152 _store->set(_obj_ids[obj], std::move(attribs));
153 // reset/invalidate the query cache since query results may have been affected by this object
154 // attribute modification.
155 _obj_cache.clear();
156 _query_cache.clear();
157}
158
159void
161{
162 std::vector<std::unique_ptr<Attribute>> attribs;
163 readAttribs(obj, attribs);
164 _store->set(_obj_ids[obj], std::move(attribs));
165 // reset/invalidate the query cache since query results may have been affected by this object
166 // attribute modification.
167 _obj_cache.clear();
168 _query_cache.clear();
169}
170
171int
172TheWarehouse::prepare(std::vector<std::unique_ptr<Attribute>> conds)
173{
174 bool sort = false;
175 std::unique_ptr<Attribute> sorted_attrib;
176 if (!conds.empty() && dynamic_cast<AttribSorted *>(conds.back().get()))
177 {
178 sorted_attrib = std::move(conds.back());
179 static const AttribSorted sorted_attrib_true(*this, true);
180 sort = sorted_attrib->isMatch(sorted_attrib_true);
181 // Remove the sorted condition temporarily
182 conds.pop_back();
183 }
184
185#ifdef DEBUG
186 for (auto & cond : conds)
187 mooseAssert(!dynamic_cast<AttribSorted *>(cond.get()),
188 "There should be no sorted attributes in this container.");
189#endif
190
191 auto obj_ids = _store->query(conds);
192 if (sorted_attrib)
193 conds.push_back(std::move(sorted_attrib));
194
195 std::lock_guard<std::mutex> lock(_obj_cache_mutex);
196 auto & vec = _obj_cache.emplace_back(obj_ids.size());
197 const auto query_id = _obj_cache.size() - 1;
198 {
199 std::lock_guard<std::mutex> lock(_query_cache_mutex);
200 _query_cache[std::move(conds)] = query_id;
201 }
202
203 std::lock_guard<std::mutex> o_lock(_obj_mutex);
204 for (const auto i : index_range(obj_ids))
205 {
206 auto obj = _objects[obj_ids[i]].get();
207 mooseAssert(std::find(vec.begin(), vec.end(), obj) == vec.end(), "Duplicate object");
208 vec[i] = obj;
209 }
210
211 if (sort && !vec.empty() && dynamic_cast<DependencyResolverInterface *>(vec[0]))
212 {
213 std::vector<DependencyResolverInterface *> dependers;
214 for (auto obj : vec)
215 {
216 auto d = dynamic_cast<DependencyResolverInterface *>(obj);
217 if (!d)
218 {
219 dependers.clear();
220 break;
221 }
222 dependers.push_back(d);
223 }
224
225 try
226 {
228 }
230 {
231 DependencyResolverInterface::cyclicDependencyError<MooseObject *>(
232 e,
233 "Cyclic dependency detected in object ordering",
235 {
236 auto * moose_obj = dynamic_cast<MooseObject *>(obj);
237 mooseAssert(moose_obj, "Failed to cast dependency object to MooseObject");
238 return moose_obj->name();
239 });
240 }
241
242 mooseAssert(dependers.size() == vec.size(), "Dependency resolution size mismatch");
243 for (unsigned int i = 0; i < dependers.size(); i++)
244 vec[i] = dynamic_cast<MooseObject *>(dependers[i]);
245 }
246
247 return query_id;
248}
249
250const std::vector<MooseObject *> &
252{
253 if (static_cast<std::size_t>(query_id) >= _obj_cache.size())
254 throw std::runtime_error("unknown query id");
255 return _obj_cache[query_id];
256}
257
258std::size_t
259TheWarehouse::queryID(const std::vector<std::unique_ptr<Attribute>> & conds)
260{
261 {
262 std::lock_guard<std::mutex> lock(_query_cache_mutex);
263 auto it = _query_cache.find(conds);
264 if (it != _query_cache.end())
265 return it->second;
266 }
267
268 std::vector<std::unique_ptr<Attribute>> conds_clone;
269 conds_clone.resize(conds.size());
270 for (std::size_t i = 0; i < conds.size(); i++)
271 conds_clone[i] = conds[i]->clone();
272 return prepare(std::move(conds_clone));
273}
274
275std::size_t
276TheWarehouse::count(const std::vector<std::unique_ptr<Attribute>> & conds)
277{
278 auto query_id = queryID(conds);
279 std::lock_guard<std::mutex> lock(_obj_cache_mutex);
280 auto & objs = query(query_id);
281 std::size_t count = 0;
282 for (auto obj : objs)
283 if (obj->enabled())
284 count++;
285 return count;
286}
287
288void
290 std::vector<std::unique_ptr<Attribute>> & attribs)
291{
292 for (auto & ref : _attrib_list)
293 {
294 attribs.emplace_back(ref->clone());
295 attribs.back()->initFrom(obj);
296 }
297}
298
306void
308{
309 const auto & var = scalar_kernel.variable();
310 const auto & subdomains = var.activeSubdomains();
311
312 // An empty set of active subdomains means the variable lives on the whole mesh
313 if (subdomains.empty())
314 return;
315
316 for (const MooseVariableScalar * const coupled_var : scalar_kernel.getCoupledMooseScalarVars())
317 {
318 const auto & coupled_subdomains = coupled_var->activeSubdomains();
319 if (coupled_subdomains.empty())
320 continue;
321
322 std::set<SubdomainID> shared_subdomains;
323 std::set_intersection(subdomains.begin(),
324 subdomains.end(),
325 coupled_subdomains.begin(),
326 coupled_subdomains.end(),
327 std::inserter(shared_subdomains, shared_subdomains.begin()));
328
329 if (shared_subdomains.empty())
330 mooseError("The 'block' parameter of the scalar variable '",
331 coupled_var->name(),
332 "' coupled into the object '",
333 scalar_kernel.name(),
334 "' must overlap the 'block' parameter of the variable '",
335 var.name(),
336 "' that the object acts on:\n Variable '",
337 var.name(),
338 "': ",
339 Moose::stringify(subdomains, ", "),
340 "\n Variable '",
341 coupled_var->name(),
342 "': ",
343 Moose::stringify(coupled_subdomains, ", "));
344 }
345}
346
347void
349{
350 auto blk = dynamic_cast<BlockRestrictable *>(obj);
351 if (!blk)
352 {
353 // Scalar kernels are not block restrictable, so their coupled scalar variables are checked
354 // against the variable the kernel acts on
355 if (auto scalar_kernel = dynamic_cast<ScalarKernelBase *>(obj))
356 checkCoupledScalarVariableBlocks(*scalar_kernel);
357 return;
358 }
359
360 // Check variables
361 auto c_ptr = dynamic_cast<Coupleable *>(obj);
362 if (c_ptr)
363 for (MooseVariableFEBase * var : c_ptr->getCoupledMooseVars())
364 blk->checkVariable(*var);
365
366 // Check scalar variables
367 auto sc_ptr = dynamic_cast<ScalarCoupleable *>(obj);
368 if (sc_ptr)
369 for (MooseVariableScalar * var : sc_ptr->getCoupledMooseScalarVars())
370 blk->checkVariable(*var);
371
372 const InputParameters & parameters = obj->parameters();
373
374 SubProblem & problem = *parameters.get<SubProblem *>("_subproblem");
375
376 THREAD_ID tid = parameters.get<THREAD_ID>("_tid");
377
378 if (parameters.isParamValid("variable"))
379 {
380 // Try the scalar version first
381 std::string variable_name = parameters.getMooseType("variable");
382 if (variable_name == "")
383 // When using vector variables, we are only going to use the first one in the list at the
384 // interface level...
385 variable_name = parameters.getVecMooseType("variable")[0];
386
387 blk->checkVariable(problem.getVariable(
389 }
390}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int THREAD_ID
Definition MooseTypes.h:237
unsigned int count
Definition MortarUtils.C:53
bool operator==(const std::unique_ptr< Attribute > &lhs, const std::unique_ptr< Attribute > &rhs)
TheWarehouse uses this operator function for indexing and caching queries.
void isValid(MooseObject *obj)
void checkCoupledScalarVariableBlocks(ScalarKernelBase &scalar_kernel)
Check the scalar variables coupled into a scalar kernel.
This attribute describes sorting state.
virtual bool isMatch(const Attribute &other) const override
isMatch returns true if the meta-data stored in this attribute is equivalent to that stored in other.
virtual bool isEqual(const Attribute &other) const override
isEqual returns true if the meta-data stored in this attribute is identical to that stored in other.
virtual void initFrom(const MooseObject *obj) override
initFrom reads and stores the desired meta-data from obj for later matching comparisons.
Attribute is an abstract class that can be implemented in order to track custom metadata about MooseO...
Attribute(TheWarehouse &w, const std::string name)
Constructs/initializes a new attribute with the specified name for use in warehouse w.
virtual std::unique_ptr< Attribute > clone() const =0
clone creates and returns and identical (deep) copy of this attribute - i.e.
An interface that restricts an object to subdomains via the 'blocks' input parameter.
Interface for objects that needs coupling capabilities.
Definition Coupleable.h:53
Interface for sorting dependent vectors of objects.
static void sort(typename std::vector< T > &vector)
Given a vector, sort using the getRequested/SuppliedItems sets.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
std::string getMooseType(const std::string &name) const
Utility functions for retrieving one of the MooseTypes variables into the common "string" base class.
std::vector< std::string > getVecMooseType(const std::string &name) const
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another,...
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
Every object that can be built by the factory should be derived from this class.
Definition MooseObject.h:31
const std::set< SubdomainID > & activeSubdomains() const
The subdomains the variable is active on.
This class provides an interface for common operations on field variables of both FE and FV types wit...
Class for scalar variables (they are different).
Interface for objects that needs scalar coupling capabilities.
const std::vector< MooseVariableScalar * > & getCoupledMooseScalarVars()
Get the list of coupled scalar variables.
Base class shared by AD and non-AD scalar kernels.
virtual const MooseVariableScalar & variable() const override
The variable that this kernel operates on.
Generic class for solving transient nonlinear problems.
Definition SubProblem.h:79
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const =0
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
TheWarehouse is a container for MooseObjects that allows querying/filtering over various customizeabl...
int prepare(std::vector< std::unique_ptr< Attribute > > conds)
prepares a query and returns an associated query_id (i.e. for use with the query function).
std::mutex _query_cache_mutex
std::mutex _obj_mutex
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse.
std::vector< std::shared_ptr< MooseObject > > _objects
void add(std::shared_ptr< MooseObject > obj)
add adds a new object to the warehouse and stores attributes/metadata about it for running queries/fi...
std::size_t count(const std::vector< std::unique_ptr< Attribute > > &conds)
count returns the number of objects that match the provided query conditions.
std::unordered_map< MooseObject *, std::size_t > _obj_ids
void readAttribs(const MooseObject *obj, std::vector< std::unique_ptr< Attribute > > &attribs)
void update(MooseObject *obj)
update updates the metadata/attribute-info stored for the given object obj that must already exists i...
std::vector< std::vector< MooseObject * > > _obj_cache
std::unique_ptr< WarehouseStorage > _store
std::mutex _obj_cache_mutex
std::unordered_map< std::vector< std::unique_ptr< Attribute > >, int > _query_cache
std::size_t queryID(const std::vector< std::unique_ptr< Attribute > > &conds)
std::vector< std::unique_ptr< Attribute > > _attrib_list
virtual void set(std::size_t obj_id, std::vector< std::unique_ptr< Attribute > > attribs) override
virtual void add(std::size_t obj_id, std::vector< std::unique_ptr< Attribute > > attribs) override
virtual std::vector< std::size_t > query(const std::vector< std::unique_ptr< Attribute > > &conds) override
std::vector< std::vector< std::unique_ptr< Attribute > > > _data
std::mutex _mutex
virtual void set(std::size_t obj_id, std::vector< std::unique_ptr< Attribute > > attribs)=0
virtual std::vector< std::size_t > query(const std::vector< std::unique_ptr< Attribute > > &conds)=0
virtual ~WarehouseStorage()=default
virtual void add(std::size_t obj_id, std::vector< std::unique_ptr< Attribute > > attribs)=0
@ VAR_FIELD_ANY
Definition MooseTypes.h:781
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
@ VAR_ANY
Definition MooseTypes.h:772