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 : #pragma once
11 :
12 : // MOOSE includes
13 : #include "ThreadedElementLoop.h"
14 : #include "ExecFlagEnum.h"
15 : #include "AuxiliarySystem.h"
16 :
17 : #include "libmesh/elem_range.h"
18 :
19 : #include <map>
20 :
21 : class InternalSideUserObject;
22 : class ElementUserObject;
23 : class ShapeElementUserObject;
24 : class InterfaceUserObject;
25 : class DomainUserObject;
26 :
27 : // libMesh forward declarations
28 : namespace libMesh
29 : {
30 : template <typename T>
31 : class NumericVector;
32 : }
33 :
34 : /**
35 : * Class for threaded computation of UserObjects.
36 : */
37 : class ComputeUserObjectsThread : public ThreadedElementLoop<ConstElemRange>
38 : {
39 : public:
40 : ComputeUserObjectsThread(FEProblemBase & problem, const TheWarehouse::Query & query);
41 : // Splitting Constructor
42 : ComputeUserObjectsThread(ComputeUserObjectsThread & x, Threads::split);
43 :
44 : virtual ~ComputeUserObjectsThread();
45 :
46 : virtual void onElement(const Elem * elem) override;
47 : virtual void onBoundary(const Elem * elem,
48 : unsigned int side,
49 : BoundaryID bnd_id,
50 : const Elem * lower_d_elem = nullptr) override;
51 : virtual void onInternalSide(const Elem * elem, unsigned int side) override;
52 : virtual void onExternalSide(const Elem * elem, unsigned int side) override;
53 : virtual void onInterface(const Elem * elem, unsigned int side, BoundaryID bnd_id) override;
54 : virtual void post() override;
55 : virtual void subdomainChanged() override;
56 :
57 : void join(const ComputeUserObjectsThread & /*y*/);
58 :
59 : protected:
60 : /// Print general information about the loop, like the ordering of class of objects
61 : void printGeneralExecutionInformation() const override;
62 :
63 : /// Print information about the loop, mostly order of execution of particular objects
64 : void printBlockExecutionInformation() const override;
65 :
66 : /// Format output of vector of UOs
67 : template <typename T>
68 : void printVectorOrdering(std::vector<T *> uos, const std::string & name) const;
69 :
70 : private:
71 : template <typename T>
72 1513395 : void querySubdomain(Interfaces iface, std::vector<T> & results)
73 : {
74 1513395 : _query_subdomain.queryInto(results, _tid, _subdomain, iface);
75 1513395 : }
76 : template <typename T>
77 5963286 : void queryBoundary(Interfaces iface, BoundaryID bnd, std::vector<T> & results)
78 : {
79 5963286 : _query_boundary.queryInto(results, _tid, std::make_tuple(bnd, false), iface);
80 5963286 : }
81 :
82 : const TheWarehouse::Query _query;
83 : TheWarehouse::QueryCache<AttribThread, AttribSubdomains, AttribInterfaces> _query_subdomain;
84 : TheWarehouse::QueryCache<AttribThread, AttribBoundaries, AttribInterfaces> _query_boundary;
85 : std::vector<InternalSideUserObject *> _internal_side_objs;
86 : std::vector<InterfaceUserObject *> _interface_user_objects;
87 : std::vector<ElementUserObject *> _element_objs;
88 : std::vector<ShapeElementUserObject *> _shape_element_objs;
89 : std::vector<DomainUserObject *> _domain_objs;
90 : std::vector<DomainUserObject *> _all_domain_objs;
91 :
92 : AuxiliarySystem & _aux_sys;
93 : };
94 :
95 : // determine when we need to run user objects based on whether any initial conditions or aux
96 : // kernels depend on the user objects. If so we need to run them either before ics, before aux
97 : // kernels, or after aux kernels (if nothing depends on them). Mark/store this information as
98 : // attributes in the warehouse for later reference.
99 : template <typename T>
100 : void
101 55548 : groupUserObjects(TheWarehouse & w,
102 : AuxiliarySystem & aux,
103 : const ExecFlagEnum & execute_flags,
104 : const std::vector<T *> & objs,
105 : const std::set<std::string> & ic_deps)
106 : {
107 : // These flags indicate when a user object will be executed for a given exec flag time.
108 : // The attributes are set by this function and their values are queried in
109 : // FEProblemBase::computeUserObjectsInternal(). If a UO is found to be in one of the
110 : // three groups: PRE_IC, PRE_AUX, or POST_AUX, then that UO is executed with that group.
111 : //
112 : // PRE_IC objects are run before initial conditions during the "INITIAL" exec flag time.
113 : // On any other exec flag time, they are run in POST_AUX by default or if there is
114 : // an dependency for some exec flag or if force_preaux is set, they are run in
115 : // PRE_AUX
116 : //
117 : // PRE_AUX objects are run before the dependent AuxKernels exec flag
118 : //
119 : // POST_AUX objects are run after AuxKernels on any given exec flag time, and is the
120 : // default group for UOs. Dependencies that would otherwise move a UO into the
121 : // PRE_AUX group can be overridden by specifying the parameter force_postaux
122 : //
123 : // This function attempts to sort a UO based on any ICs or AuxKernels which depend on
124 : // it. Alternatively, a user may select which group to execute their object with by
125 : // controlling the force_preic, force_preaux and force_postaux input parameters.
126 : //
127 :
128 55548 : std::map<T *, std::set<int>> pre_aux_dependencies;
129 55548 : std::map<T *, std::set<int>> post_aux_dependencies;
130 : // This map is used to indicate, after all dependencies have
131 : // been looked through, whether the UO has been flagged to
132 : // execute on EXEC_INITIAL, either through a dependency or
133 : // because force_preic was indicated. If neither of these
134 : // are true, the UO needs to be run in POST_AUX for EXEC_INITIAL
135 55548 : std::map<T *, bool> is_pre_ic;
136 :
137 126850 : for (const auto obj : objs)
138 71302 : is_pre_ic[obj] = false;
139 :
140 1499785 : for (const ExecFlagType & flag : execute_flags.items())
141 : {
142 1444237 : std::set<std::string> depend_objects_aux = aux.getDependObjects(flag);
143 3298087 : for (const auto obj : objs)
144 : {
145 1853850 : if (depend_objects_aux.count(obj->name()) > 0)
146 : {
147 3620 : pre_aux_dependencies[obj].insert(flag);
148 3620 : if (flag == EXEC_INITIAL)
149 1076 : is_pre_ic.at(obj) = true;
150 : }
151 1850230 : else if (flag != EXEC_INITIAL)
152 : // default is for UO to be post_aux. If EXEC_INITIAL, check first if UO
153 : // will be dependent on IC or have force_preic before deciding to put in
154 : // post_aux
155 1780004 : post_aux_dependencies[obj].insert(flag);
156 : }
157 : }
158 :
159 126850 : for (const auto obj : objs)
160 : {
161 142470 : if (ic_deps.count(obj->name()) > 0 ||
162 142470 : (obj->isParamValid("force_preic") && obj->template getParam<bool>("force_preic")))
163 : {
164 291 : w.update(obj, AttribPreIC(w, true));
165 291 : is_pre_ic.at(obj) = true;
166 : }
167 :
168 71302 : if ((obj->isParamValid("force_preaux") && obj->template getParam<bool>("force_preaux")))
169 : {
170 516 : post_aux_dependencies[obj].clear();
171 13932 : for (const ExecFlagType & flag : execute_flags.items())
172 13416 : pre_aux_dependencies[obj].insert(flag);
173 : }
174 70786 : else if (obj->isParamValid("force_postaux") && obj->template getParam<bool>("force_postaux"))
175 : {
176 39 : pre_aux_dependencies[obj].clear();
177 1053 : for (const ExecFlagType & flag : execute_flags.items())
178 1014 : post_aux_dependencies[obj].insert(flag);
179 : }
180 : else
181 : {
182 : // If at this point, then check if the UO has already been set to execute
183 : // by either the force_preic param, an IC dependency, or a dependency
184 : // already found for exec flage EXEC_INITIAL. If none of these are true,
185 : // then is_pre_ic.at(obj) is false and the UO is added to the default
186 : // post_aux group for the EXEC_INITIAL flag
187 70747 : if (!is_pre_ic.at(obj))
188 69432 : post_aux_dependencies[obj].insert(EXEC_INITIAL);
189 : }
190 : }
191 :
192 58456 : for (auto & item : pre_aux_dependencies)
193 2908 : w.update(item.first, AttribPreAux(w, item.second));
194 :
195 126850 : for (auto & item : post_aux_dependencies)
196 71302 : w.update(item.first, AttribPostAux(w, item.second));
197 55548 : }
|