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 "MooseTypes.h"
14 : #include "OutputInterface.h"
15 : #include "ReporterData.h"
16 : #include "InputParameters.h"
17 :
18 : // System includes
19 : #include <type_traits>
20 :
21 : // Forward declarations
22 : class FEProblemBase;
23 :
24 : /**
25 : * Reporter objects allow for the declaration of arbitrary data types that are aggregate values
26 : * for a simulation. These aggregate values are then available to other objects for use. They
27 : * operate with the typical producer/consumer relationship. The Reporter object produces values
28 : * that other objects consume.
29 : *
30 : * Originally, MOOSE included a Postprocessor system that allowed for an object to produce a
31 : * single scalar value for consumption by other objects. Then a companion system was created,
32 : * the VectorPostprocessor system, that allowed for an object to produce many std::vector<Real>
33 : * values. The Reporter system is the generalization of these two ideas and follows closely the
34 : * original design of the VectorPostprocessor system.
35 : *
36 : * In practice, the Reporter system provided the following features over the two previous systems.
37 : *
38 : * 1. It can create arbitrary data types rather than only Real and std::vector<Real>
39 : * 2. It can create many values per object. This was possible for VectorPostprocessor objects but
40 : * not for Postprocessors. Therefore, this allows a single Reporter to provide multiple values
41 : * and consolidate similar items. For example, a "counter" object replaced several individual
42 : * Postprocessor objects.
43 : * 3. The ReporterContext system allows for each data value to have special operation within a
44 : * single object. Previously the VectorPostprocessor system had capability to perform
45 : * broadcasting, but it was applied to all vectors in the object.
46 : */
47 : class Reporter : public OutputInterface
48 : {
49 : public:
50 : static InputParameters validParams();
51 : Reporter(const MooseObject * moose_object);
52 62688 : virtual ~Reporter() = default;
53 :
54 : #ifdef MOOSE_KOKKOS_ENABLED
55 : /**
56 : * Special constructor used for Kokkos functor copy during parallel dispatch
57 : */
58 : Reporter(const Reporter & object, const Moose::Kokkos::FunctorCopy & key);
59 : #endif
60 :
61 : virtual void store(nlohmann::json & json) const;
62 :
63 : /**
64 : * @returns Whether or not this Reporter should store its value at this specific time.
65 : *
66 : * Basic Reporters (those that are not GeneralReporters) will store at all times
67 : * when requested.
68 : */
69 22 : virtual bool shouldStore() const { return true; }
70 :
71 : /**
72 : * Method that can be overriden to declare "late" Reporter values.
73 : *
74 : * Values are considered "late" when they need to be declared after all
75 : * other Reporters have been instantiated. This is called by the
76 : * "declare_late_reporters" task, which should be called right after
77 : * the "add_reporters" task.
78 : */
79 64881 : virtual void declareLateValues() {}
80 :
81 : protected:
82 : ///@{
83 : /**
84 : * Method to define a value that the Reporter object is to produced.
85 : * @tparam T The C++ type of the value to be produced
86 : * @tparam S (optional) Context type for performing special operations. For example
87 : * using the ReporterBroadcastContext will automatically broadcast the produced value
88 : * from the root processor.
89 : * @param name A unique name for the value to be produced.
90 : * @param mode (optional) The mode that indicates how the value produced is represented in
91 : * parallel, there is more information about this below
92 : * @param args (optional) Any number of optional arguments passed into the ReporterContext given
93 : * by the S template parameter. If S = ReporterContext then the first argument
94 : * can be used as the default value (see ReporterContext.h).
95 : *
96 : * The 'mode' indicates how the value that is produced is represented in parallel. It is the
97 : * responsibility of the Reporter object to get it to that state. The ReporterContext objects
98 : * are designed to help with this. The mode can be one of the following:
99 : *
100 : * ReporterMode::ROOT Indicates that the value produced is complete/correct on the
101 : * root processor for the object.
102 : * ReporterMode::REPLICATED Indicates that the value produced is complete/correct on
103 : * all processors AND that the value is the same on all
104 : * processors
105 : * ReporterMode::DISTRIBUTED Indicates that the value produced is complete/correct on
106 : * all processors AND that the value is NOT the same on all
107 : * processors
108 : *
109 : * WARNING! Using the "default value" in ReporterContext:
110 : * The Reporter system, like the systems before it, allow for objects that consume values to be
111 : * constructed prior to the produce objects. When a value is requested either by a producer
112 : * (Reporter) or consumer (ReporterInterface) the data is allocated. As such the assigned default
113 : * value from the producer should not be relied upon on the consumer side during object
114 : * construction.
115 : *
116 : * NOTE:
117 : * The ReporterContext is just a mechanism to allow for handling of values in special ways. In
118 : * practice it might be better to have specific methods for these special cases. For example,
119 : * a declareBroadcastValue, etc. Please refer to the ReporterData object for more information
120 : * on how the data system operates for Reporter values.
121 : */
122 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
123 : T & declareValue(const std::string & param_name, Args &&... args);
124 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
125 : T & declareValue(const std::string & param_name, ReporterMode mode, Args &&... args);
126 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
127 : T & declareValueByName(const ReporterValueName & value_name, Args &&... args);
128 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
129 : T & declareValueByName(const ReporterValueName & value_name, ReporterMode mode, Args &&... args);
130 :
131 : template <typename T, typename S, typename... Args>
132 : T & declareValue(const std::string & param_name, Args &&... args);
133 : template <typename T, typename S, typename... Args>
134 : T & declareValue(const std::string & param_name, ReporterMode mode, Args &&... args);
135 : template <typename T, typename S, typename... Args>
136 : T & declareValueByName(const ReporterValueName & value_name, Args &&... args);
137 : template <typename T, typename S, typename... Args>
138 : T & declareValueByName(const ReporterValueName & value_name, ReporterMode mode, Args &&... args);
139 : ///@}
140 :
141 : /**
142 : * Declare a unused value with type T.
143 : *
144 : * This is useful when you have a reporter that has optional values. In this case,
145 : * you want to create references to all reporter values. However, because some values
146 : * are optional, you need _something_ to fill into the reference. This helper will
147 : * create a unused value. It also allows for the passing of arguments in the case
148 : * that your value is not trivially default constructable (constructable by default
149 : * without arguments).
150 : */
151 : template <typename T, typename... Args>
152 : T & declareUnusedValue(Args &&... args);
153 :
154 : private:
155 : /**
156 : * Internal base struct for use in storing unused values.
157 : *
158 : * In order to store a vector of arbitrary unused values for declareUnusedValue(),
159 : * we need some base object that is constructable without template arguments.
160 : */
161 : struct UnusedWrapperBase
162 : {
163 : /// Needed for polymorphism
164 5154 : virtual ~UnusedWrapperBase() {}
165 : };
166 :
167 : /**
168 : * Internal struct for storing a unused value. This allows for the storage
169 : * of arbitrarily typed objects in a single vector for use in
170 : * declareUnusedValue().
171 : */
172 : template <typename T>
173 : struct UnusedWrapper : UnusedWrapperBase
174 : {
175 : T value;
176 : };
177 :
178 : /**
179 : * @returns The ReporterValueName associated with the parameter \p param_name.
180 : *
181 : * Performs error checking on if the parameter is valid.
182 : */
183 : const ReporterValueName & getReporterValueName(const std::string & param_name) const;
184 :
185 : /// The MooseObject creating this Reporter
186 : const MooseObject & _reporter_moose_object;
187 :
188 : /// Ref. to MooseObject params
189 : const InputParameters & _reporter_params;
190 :
191 : /// The name of the MooseObject, from "_object_name" param
192 : const std::string & _reporter_name;
193 :
194 : /// Needed for access to FEProblemBase::getReporterData
195 : FEProblemBase & _reporter_fe_problem;
196 :
197 : /// Data storage
198 : ReporterData & _reporter_data;
199 :
200 : /// Storage for unused values declared with declareUnusedValue().
201 : std::vector<std::unique_ptr<UnusedWrapperBase>> _unused_values;
202 : };
203 :
204 : template <typename T, template <typename> class S, typename... Args>
205 : T &
206 130 : Reporter::declareValue(const std::string & param_name, Args &&... args)
207 : {
208 130 : return declareValue<T, S<T>>(param_name, REPORTER_MODE_UNSET, args...);
209 : }
210 :
211 : template <typename T, template <typename> class S, typename... Args>
212 : T &
213 39 : Reporter::declareValue(const std::string & param_name, ReporterMode mode, Args &&... args)
214 : {
215 39 : return declareValue<T, S<T>>(param_name, mode, args...);
216 : }
217 :
218 : template <typename T, typename S, typename... Args>
219 : T &
220 : Reporter::declareValue(const std::string & param_name, Args &&... args)
221 : {
222 : return declareValue<T, S>(param_name, REPORTER_MODE_UNSET, args...);
223 : }
224 :
225 : template <typename T, typename S, typename... Args>
226 : T &
227 169 : Reporter::declareValue(const std::string & param_name, ReporterMode mode, Args &&... args)
228 : {
229 169 : return declareValueByName<T, S>(getReporterValueName(param_name), mode, args...);
230 : }
231 :
232 : template <typename T, template <typename> class S, typename... Args>
233 : T &
234 4945 : Reporter::declareValueByName(const ReporterValueName & value_name, Args &&... args)
235 : {
236 4945 : return declareValueByName<T, S<T>>(value_name, REPORTER_MODE_UNSET, args...);
237 : }
238 :
239 : template <typename T, template <typename> class S, typename... Args>
240 : T &
241 2649 : Reporter::declareValueByName(const ReporterValueName & value_name,
242 : ReporterMode mode,
243 : Args &&... args)
244 : {
245 2649 : return declareValueByName<T, S<T>>(value_name, mode, args...);
246 : }
247 :
248 : template <typename T, typename S, typename... Args>
249 : T &
250 : Reporter::declareValueByName(const ReporterValueName & value_name, Args &&... args)
251 : {
252 : return declareValueByName<T, S>(value_name, REPORTER_MODE_UNSET, args...);
253 : }
254 :
255 : template <typename T, typename S, typename... Args>
256 : T &
257 9642 : Reporter::declareValueByName(const ReporterValueName & value_name,
258 : ReporterMode mode,
259 : Args &&... args)
260 : {
261 9642 : const ReporterName state_name(_reporter_name, value_name);
262 :
263 28926 : buildOutputHideVariableList({state_name.getCombinedName()});
264 :
265 : // Only thread 0 will declare the reporter value. The rest will get a reference
266 : // to an UnusedValue
267 19284 : const THREAD_ID tid = _reporter_moose_object.parameters().isParamValid("_tid")
268 9570 : ? _reporter_moose_object.parameters().get<THREAD_ID>("_tid")
269 : : 0;
270 9642 : if (tid)
271 26 : return declareUnusedValue<T>();
272 9616 : return _reporter_data.declareReporterValue<T, S>(
273 9538 : state_name, mode, _reporter_moose_object, args...);
274 19278 : }
275 :
276 : template <typename T, typename... Args>
277 : T &
278 5154 : Reporter::declareUnusedValue(Args &&... args)
279 : {
280 5154 : _unused_values.emplace_back(std::make_unique<UnusedWrapper<T>>(std::forward(args)...));
281 5154 : UnusedWrapper<T> * wrapper = dynamic_cast<UnusedWrapper<T> *>(_unused_values.back().get());
282 5154 : return wrapper->value;
283 : }
|