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 57371 : virtual ~Reporter() = default;
53 : virtual void store(nlohmann::json & json) const;
54 :
55 : /**
56 : * @returns Whether or not this Reporter should store its value at this specific time.
57 : *
58 : * Basic Reporters (those that are not GeneralReporters) will store at all times
59 : * when requested.
60 : */
61 0 : virtual bool shouldStore() const { return true; }
62 :
63 : /**
64 : * Method that can be overriden to declare "late" Reporter values.
65 : *
66 : * Values are considered "late" when they need to be declared after all
67 : * other Reporters have been instantiated. This is called by the
68 : * "declare_late_reporters" task, which should be called right after
69 : * the "add_reporters" task.
70 : */
71 60578 : virtual void declareLateValues() {}
72 :
73 : protected:
74 : ///@{
75 : /**
76 : * Method to define a value that the Reporter object is to produced.
77 : * @tparam T The C++ type of the value to be produced
78 : * @tparam S (optional) Context type for performing special operations. For example
79 : * using the ReporterBroadcastContext will automatically broadcast the produced value
80 : * from the root processor.
81 : * @param name A unique name for the value to be produced.
82 : * @param mode (optional) The mode that indicates how the value produced is represented in
83 : * parallel, there is more information about this below
84 : * @param args (optional) Any number of optional arguments passed into the ReporterContext given
85 : * by the S template parameter. If S = ReporterContext then the first argument
86 : * can be used as the default value (see ReporterContext.h).
87 : *
88 : * The 'mode' indicates how the value that is produced is represented in parallel. It is the
89 : * responsibility of the Reporter object to get it to that state. The ReporterContext objects
90 : * are designed to help with this. The mode can be one of the following:
91 : *
92 : * ReporterMode::ROOT Indicates that the value produced is complete/correct on the
93 : * root processor for the object.
94 : * ReporterMode::REPLICATED Indicates that the value produced is complete/correct on
95 : * all processors AND that the value is the same on all
96 : * processors
97 : * ReporterMode::DISTRIBUTED Indicates that the value produced is complete/correct on
98 : * all processors AND that the value is NOT the same on all
99 : * processors
100 : *
101 : * WARNING! Using the "default value" in ReporterContext:
102 : * The Reporter system, like the systems before it, allow for objects that consume values to be
103 : * constructed prior to the produce objects. When a value is requested either by a producer
104 : * (Reporter) or consumer (ReporterInterface) the data is allocated. As such the assigned default
105 : * value from the producer should not be relied upon on the consumer side during object
106 : * construction.
107 : *
108 : * NOTE:
109 : * The ReporterContext is just a mechanism to allow for handling of values in special ways. In
110 : * practice it might be better to have specific methods for these special cases. For example,
111 : * a declareBroadcastValue, etc. Please refer to the ReporterData object for more information
112 : * on how the data system operates for Reporter values.
113 : */
114 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
115 : T & declareValue(const std::string & param_name, Args &&... args);
116 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
117 : T & declareValue(const std::string & param_name, ReporterMode mode, Args &&... args);
118 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
119 : T & declareValueByName(const ReporterValueName & value_name, Args &&... args);
120 : template <typename T, template <typename> class S = ReporterGeneralContext, typename... Args>
121 : T & declareValueByName(const ReporterValueName & value_name, ReporterMode mode, Args &&... args);
122 :
123 : template <typename T, typename S, typename... Args>
124 : T & declareValue(const std::string & param_name, Args &&... args);
125 : template <typename T, typename S, typename... Args>
126 : T & declareValue(const std::string & param_name, ReporterMode mode, Args &&... args);
127 : template <typename T, typename S, typename... Args>
128 : T & declareValueByName(const ReporterValueName & value_name, Args &&... args);
129 : template <typename T, typename S, typename... Args>
130 : T & declareValueByName(const ReporterValueName & value_name, ReporterMode mode, Args &&... args);
131 : ///@}
132 :
133 : /**
134 : * Declare a unused value with type T.
135 : *
136 : * This is useful when you have a reporter that has optional values. In this case,
137 : * you want to create references to all reporter values. However, because some values
138 : * are optional, you need _something_ to fill into the reference. This helper will
139 : * create a unused value. It also allows for the passing of arguments in the case
140 : * that your value is not trivially default constructable (constructable by default
141 : * without arguments).
142 : */
143 : template <typename T, typename... Args>
144 : T & declareUnusedValue(Args &&... args);
145 :
146 : private:
147 : /**
148 : * Internal base struct for use in storing unused values.
149 : *
150 : * In order to store a vector of arbitrary unused values for declareUnusedValue(),
151 : * we need some base object that is constructable without template arguments.
152 : */
153 : struct UnusedWrapperBase
154 : {
155 : /// Needed for polymorphism
156 5138 : virtual ~UnusedWrapperBase() {}
157 : };
158 :
159 : /**
160 : * Internal struct for storing a unused value. This allows for the storage
161 : * of arbitrarily typed objects in a single vector for use in
162 : * declareUnusedValue().
163 : */
164 : template <typename T>
165 : struct UnusedWrapper : UnusedWrapperBase
166 : {
167 : T value;
168 : };
169 :
170 : /**
171 : * @returns The ReporterValueName associated with the parameter \p param_name.
172 : *
173 : * Performs error checking on if the parameter is valid.
174 : */
175 : const ReporterValueName & getReporterValueName(const std::string & param_name) const;
176 :
177 : /// The MooseObject creating this Reporter
178 : const MooseObject & _reporter_moose_object;
179 :
180 : /// Ref. to MooseObject params
181 : const InputParameters & _reporter_params;
182 :
183 : /// The name of the MooseObject, from "_object_name" param
184 : const std::string & _reporter_name;
185 :
186 : /// Needed for access to FEProblemBase::getReporterData
187 : FEProblemBase & _reporter_fe_problem;
188 :
189 : /// Data storage
190 : ReporterData & _reporter_data;
191 :
192 : /// Storage for unused values declared with declareUnusedValue().
193 : std::vector<std::unique_ptr<UnusedWrapperBase>> _unused_values;
194 : };
195 :
196 : template <typename T, template <typename> class S, typename... Args>
197 : T &
198 103 : Reporter::declareValue(const std::string & param_name, Args &&... args)
199 : {
200 103 : return declareValue<T, S<T>>(param_name, REPORTER_MODE_UNSET, args...);
201 : }
202 :
203 : template <typename T, template <typename> class S, typename... Args>
204 : T &
205 43 : Reporter::declareValue(const std::string & param_name, ReporterMode mode, Args &&... args)
206 : {
207 43 : return declareValue<T, S<T>>(param_name, mode, args...);
208 : }
209 :
210 : template <typename T, typename S, typename... Args>
211 : T &
212 : Reporter::declareValue(const std::string & param_name, Args &&... args)
213 : {
214 : return declareValue<T, S>(param_name, REPORTER_MODE_UNSET, args...);
215 : }
216 :
217 : template <typename T, typename S, typename... Args>
218 : T &
219 146 : Reporter::declareValue(const std::string & param_name, ReporterMode mode, Args &&... args)
220 : {
221 146 : return declareValueByName<T, S>(getReporterValueName(param_name), mode, args...);
222 : }
223 :
224 : template <typename T, template <typename> class S, typename... Args>
225 : T &
226 4085 : Reporter::declareValueByName(const ReporterValueName & value_name, Args &&... args)
227 : {
228 4085 : return declareValueByName<T, S<T>>(value_name, REPORTER_MODE_UNSET, args...);
229 : }
230 :
231 : template <typename T, template <typename> class S, typename... Args>
232 : T &
233 2195 : Reporter::declareValueByName(const ReporterValueName & value_name,
234 : ReporterMode mode,
235 : Args &&... args)
236 : {
237 2195 : return declareValueByName<T, S<T>>(value_name, mode, args...);
238 : }
239 :
240 : template <typename T, typename S, typename... Args>
241 : T &
242 : Reporter::declareValueByName(const ReporterValueName & value_name, Args &&... args)
243 : {
244 : return declareValueByName<T, S>(value_name, REPORTER_MODE_UNSET, args...);
245 : }
246 :
247 : template <typename T, typename S, typename... Args>
248 : T &
249 8030 : Reporter::declareValueByName(const ReporterValueName & value_name,
250 : ReporterMode mode,
251 : Args &&... args)
252 : {
253 8030 : const ReporterName state_name(_reporter_name, value_name);
254 :
255 16060 : buildOutputHideVariableList({state_name.getCombinedName()});
256 :
257 : // Only thread 0 will declare the reporter value. The rest will get a reference
258 : // to an UnusedValue
259 16060 : const THREAD_ID tid = _reporter_moose_object.parameters().isParamValid("_tid")
260 8030 : ? _reporter_moose_object.parameters().get<THREAD_ID>("_tid")
261 : : 0;
262 8030 : if (tid)
263 10 : return declareUnusedValue<T>();
264 8020 : return _reporter_data.declareReporterValue<T, S>(
265 8012 : state_name, mode, _reporter_moose_object, args...);
266 16052 : }
267 :
268 : template <typename T, typename... Args>
269 : T &
270 5138 : Reporter::declareUnusedValue(Args &&... args)
271 : {
272 5138 : _unused_values.emplace_back(std::make_unique<UnusedWrapper<T>>(std::forward(args)...));
273 5138 : UnusedWrapper<T> * wrapper = dynamic_cast<UnusedWrapper<T> *>(_unused_values.back().get());
274 5138 : return wrapper->value;
275 : }
|