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 : #include "RestartableData.h"
13 : #include "JsonIO.h"
14 : #include "MooseUtils.h"
15 : #include "ReporterState.h"
16 : #include "ReporterContext.h"
17 : #include "libmesh/parallel_object.h"
18 : #include "libmesh/dense_vector.h"
19 : #include <memory>
20 :
21 : class MooseApp;
22 : class Receiver;
23 :
24 : /**
25 : * This is a helper class for managing the storage of declared Reporter object values. This design
26 : * of the system is a generalization of the VectorPostprocessor system that the Reporter objects
27 : * replaced.
28 : *
29 : * Foremost, this object doesn't store the data. It simply acts as helper for using the restart
30 : * system of the MooseApp. This object automatically handles the old, older, ... data. All
31 : * declarations create std::pair<T, std::vector<T>> restartable data on the MooseApp, where the
32 : * first value is the current value and the data in the vector are the older data.
33 : *
34 : * The ReporterState object is a RestartableData object that serves as a helper for managing the
35 : * time history. A "context" object also exists that uses the ReporterState for performing special
36 : * operations. Refer to ReporterState.h/C for more information.
37 : *
38 : * It is important to note that the Reporter values are not threaded. However, the Reporter
39 : * objects are UserObject based, so the calculation of the values can be threaded.
40 : *
41 : * This object also relies on ReporterName objects, which are simply a combination of the
42 : * Reporter object name and the data name. If you recall the VectorPostprocessor system on which
43 : * this is based required an object name and a vector name. The ReporterName class simply provides
44 : * a convenient way to provide that information in a single object. Special Parser syntax
45 : * was also defined so that application developers do not have to have input parameters for
46 : * both the object and data names (see Parser.C/h).
47 : */
48 : class ReporterData
49 : {
50 : public:
51 : class WriteKey
52 : {
53 : /**
54 : * An object that can be passed to FEProblemBase::getReporterData to provide non-const access
55 : * the ReporterData object that is used to store reporter values.
56 : *
57 : * An attempt was made to limit access to the ReporterData as much as possible to encourage
58 : * developers to use the Reporter and ReporterInterface. This key also prevents the need for
59 : * FEProblemBase to give friend access to these classes, which gives complete access.
60 : * Thanks for the idea @loganharbour
61 : */
62 146772 : WriteKey() {} // private constructor
63 : friend class Reporter;
64 : friend class Postprocessor;
65 : friend class Receiver;
66 : friend class ConstantPostprocessor;
67 : friend class VectorPostprocessor;
68 : friend class ReporterTransferInterface;
69 : };
70 :
71 : ReporterData(MooseApp & moose_app);
72 :
73 : /**
74 : * Return True if a Reporter value with the given type and name have been created.
75 : */
76 : template <typename T>
77 : bool hasReporterValue(const ReporterName & reporter_name) const;
78 :
79 : /**
80 : * Return True if a Reporter value with any type exists with the given name.
81 : */
82 : bool hasReporterValue(const ReporterName & reporter_name) const;
83 :
84 : /**
85 : * @returns True if a ReporterState is defined for the Reporter with name \p reporter_name
86 : * and the given type.
87 : */
88 : template <typename T>
89 : bool hasReporterState(const ReporterName & reporter_name) const;
90 :
91 : /**
92 : * @returns True if a ReporterState is defined for the Reporter with name \p reporter_name.
93 : */
94 : bool hasReporterState(const ReporterName & reporter_name) const;
95 :
96 : /**
97 : * Return a list of all reporter names
98 : */
99 : std::set<ReporterName> getReporterNames() const;
100 :
101 : /**
102 : * Return a list of all postprocessor names
103 : */
104 : std::set<std::string> getPostprocessorNames() const;
105 :
106 : /**
107 : * Get all real reporter values including postprocessor and vector postprocessor values into a
108 : * dense vector
109 : */
110 : DenseVector<Real> getAllRealReporterValues() const;
111 :
112 : /**
113 : * Get full names of all real reporter values
114 : * Note: For a postprocessor, the full name is the postprocessor name plus '/value'.
115 : * For a vector postprocessor, the full name is the vector postprocessor name
116 : * plus the vector name followed by '/#' where '#' is the index of the vector.
117 : */
118 : std::vector<std::string> getAllRealReporterFullNames() const;
119 :
120 : /**
121 : * Method for returning read only references to Reporter values.
122 : * @tparam T The Reporter value C++ type.
123 : * @param reporter_name The name of the reporter value, which includes the object name and the
124 : * data name.
125 : * @param consumer The MooseObject consuming the Reporter value (for error reporting)
126 : * @param mode The mode that the value will be consumed by the by the ReporterInterface object
127 : * @param time_index (optional) When not provided or zero is provided the current value is
128 : * returned. If an index greater than zero is provided then the corresponding
129 : * old data is returned (1 = old, 2 = older, etc.).
130 : */
131 : template <typename T>
132 : const T & getReporterValue(const ReporterName & reporter_name,
133 : const MooseObject & consumer,
134 : const ReporterMode & mode,
135 : const std::size_t time_index = 0) const;
136 :
137 : /**
138 : * Method for returning a read-only reference to Reporter values that already exist.
139 : * @tparam T The Reporter value C++ type.
140 : * @param reporter_name The name of the reporter value, which includes the object name and the
141 : * data name.
142 : * @param time_index (optional) When not provided or zero is provided the current value is
143 : * returned. If an index greater than zero is provided then the corresponding
144 : * old data is returned (1 = old, 2 = older, etc.).
145 : */
146 : template <typename T>
147 : const T & getReporterValue(const ReporterName & reporter_name,
148 : const std::size_t time_index = 0) const;
149 :
150 : /**
151 : * Method for setting Reporter values that already exist.
152 : * @tparam T The Reporter value C++ type.
153 : * @param reporter_name The name of the reporter value, which includes the object name and the
154 : * data name.
155 : * @param value The value to which the Reporter will be changed to.
156 : * @param time_index (optional) When not provided or zero is provided the current value is
157 : * returned. If an index greater than zero is provided then the corresponding
158 : * old data is returned (1 = old, 2 = older, etc.).
159 : * WARNING!
160 : * This method is designed for setting values outside of the traditional interfaces such as is
161 : * necessary for Transfers. This is an advanced capability that should be used with caution.
162 : *
163 : * @see FEProblemBase::setPostprocessorValueByName
164 : */
165 : template <typename T>
166 : void setReporterValue(const ReporterName & reporter_name,
167 : const T & value,
168 : const std::size_t time_index = 0);
169 :
170 : /**
171 : * Method for setting that a specific time index is requested for a Reporter value.
172 : * @tparam T The Reporter value C++ type.
173 : * @param reporter_name The name of the reporter value, which includes the object name and the
174 : * data name.
175 : * @param time_index The time index that is needed
176 : */
177 : template <typename T>
178 : void needReporterTimeIndex(const ReporterName & reporter_name, const std::size_t time_index);
179 :
180 : ///@{
181 : /**
182 : * Method for returning a writable reference to the current Reporter value. This method is
183 : * used by the Reporter class to produce values.
184 : * @tparam T The Reporter value C++ type.
185 : * @tparam S (optional) The ReporterContext for performing specialized actions after the
186 : * values have been computed. For example, ReporterBroadcastContext automatically broadcasts
187 : * the computed value. See ReporterState.C/h for more information.
188 : * @param reporter_name The name of the reporter value, which includes the object name and the
189 : * data name.
190 : * @param mode The mode that the produced value will be computed by the Reporter object
191 : * @param producer The MooseObject that produces this value
192 : * @param args (optional) Any number of optional arguments passed into the Context type given
193 : * by the S template parameter. If S = ReporterContext then the first argument
194 : * can be used as the default value (see ReporterContext.h).
195 : *
196 : * The ReporterContext objects allow for custom handling of data (e.g., broadcasting the
197 : * value). The get/declare methods can be called in any order thus an the underlying
198 : * RestartableData object is often created by the get method before it is declared. Therefore
199 : * the custom functionality cannot be handled by specializing the
200 : * RestartableData/ReporterState object directly because the state is often created prior to
201 : * the declaration that dictates how the produced value shall be computed. Thus, the reason
202 : * for the separate ReporterContext objects.
203 : */
204 : template <typename T, typename S, typename... Args>
205 : T & declareReporterValue(const ReporterName & reporter_name,
206 : const ReporterMode & mode,
207 : const MooseObject & producer,
208 : Args &&... args);
209 :
210 : /**
211 : * Helper function for performing post calculation actions via the ReporterContext objects.
212 : *
213 : * If you recall, the original VectorPostprocessor system included the ability to perform some
214 : * scatter and broadcast actions via the special call on the storage helper object. This
215 : * is a replacement for that method that leverages the ReporterContext objects to perform
216 : * value specific actions, including some automatic operations depending how the data is
217 : * produced and consumed.
218 : *
219 : * See FEProblemBase::joinAndFinalize
220 : */
221 : void finalize(const std::string & object_name);
222 :
223 : /**
224 : * At the end of a timestep this method is called to copy the values back in time in preparation
225 : * for the next timestep.
226 : *
227 : * See FEProblemBase::advanceState
228 : */
229 : void copyValuesBack();
230 :
231 : /**
232 : * When a time step fails, this method is called to revert the current reporter values to their
233 : * old state. @see FEProblemBase::restoreSolutions
234 : *
235 : * @param verbose Set true to print whether the reporters were restored or not.
236 : */
237 : void restoreState(bool verbose = false);
238 :
239 : /**
240 : * Perform integrity check for get/declare calls
241 : */
242 : void check() const;
243 :
244 : /**
245 : * Return true if the supplied mode exists in the produced Reporter values
246 : *
247 : * @see CSV.C/h
248 : */
249 : bool hasReporterWithMode(const std::string & obj_name, const ReporterMode & mode) const;
250 :
251 : /**
252 : * @returns The ReporterContextBase associated with the Reporter with name \p reporter_name.
253 : */
254 : ///@{
255 : const ReporterContextBase & getReporterContextBase(const ReporterName & reporter_name) const;
256 : ReporterContextBase & getReporterContextBase(const ReporterName & reporter_name);
257 : ///@}
258 :
259 : /**
260 : * @Returns The ReporterStateBase associated with the Reporter with name \p reporter_name.
261 : */
262 : ///@{
263 : const ReporterStateBase & getReporterStateBase(const ReporterName & reporter_name) const;
264 : ReporterStateBase & getReporterStateBase(const ReporterName & reporter_name);
265 : ///@}
266 :
267 : /**
268 : * Return the ReporterProducerEnum for an existing ReporterValue
269 : * @param reporter_name The name of the reporter value, which includes the object name and the
270 : * data name.
271 : */
272 : const ReporterProducerEnum & getReporterMode(const ReporterName & reporter_name) const;
273 :
274 : /**
275 : * Gets information pertaining to the Reporter with state \p state and possibly
276 : * context \p context.
277 : */
278 : static std::string getReporterInfo(const ReporterStateBase & state,
279 : const ReporterContextBase * context);
280 :
281 : /**
282 : * Gets information pertaining to the Reporter with name \p reporter_name.
283 : */
284 : std::string getReporterInfo(const ReporterName & reporter_name) const;
285 :
286 : /**
287 : * Gets information about all declared/requested Reporters.
288 : */
289 : std::string getReporterInfo() const;
290 :
291 : private:
292 : /// For accessing the restart/recover system, which is where Reporter values are stored
293 : MooseApp & _app;
294 :
295 : /**
296 : * Helper method for creating the necessary RestartableData for Reporter values.
297 : * @tparam T The desired C++ type for the Reporter value
298 : * @param reporter_name Object/data name for the Reporter value
299 : * @param declare Flag indicating if the ReporterValue is being declared or read. This flag
300 : * is passed to the existing MooseApp restart/recover system that errors if a
301 : * value is declared multiple times.
302 : * @param moose_object The object requesting/declaring the state, used in error handling.
303 : */
304 : template <typename T>
305 : ReporterState<T> & getReporterStateHelper(const ReporterName & reporter_name,
306 : bool declare,
307 : const MooseObject * moose_object = nullptr) const;
308 :
309 : /**
310 : * Helper for registering data with the MooseApp to avoid cyclic includes
311 : */
312 : RestartableDataValue & getRestartableDataHelper(std::unique_ptr<RestartableDataValue> data_ptr,
313 : bool declare) const;
314 :
315 : /**
316 : * Helper for restoring \p state from the checkpoint reader if available.
317 : * Defined in the .C to avoid requiring a complete MooseApp type in the template header.
318 : */
319 : void restoreReporterStateIfAvailable(RestartableDataValue & state) const;
320 :
321 : /// Map from ReporterName -> Reporter state. We need to keep track of all of the states that are
322 : /// created so that we can check them after Reporter declaration to make sure all states have
323 : /// a producer (are delcared). We cannot check _context_ptrs, because a context is only
324 : /// defined for Reporters that have been declared. This is mutable so that it can be inserted
325 : /// into when requesting Reporter values.
326 : mutable std::map<ReporterName, ReporterStateBase *> _states;
327 :
328 : /// The ReporterContext objects are created when a value is declared. The context objects
329 : /// include a reference to the associated ReporterState values. This container stores the
330 : /// context object for each Reporter value.
331 : std::map<ReporterName, std::unique_ptr<ReporterContextBase>> _context_ptrs;
332 : };
333 :
334 : template <typename T>
335 : ReporterState<T> &
336 1695572 : ReporterData::getReporterStateHelper(const ReporterName & reporter_name,
337 : bool declare,
338 : const MooseObject * moose_object /* = nullptr */) const
339 : {
340 1695572 : if (hasReporterState(reporter_name))
341 : {
342 1612802 : const auto error_helper =
343 9 : [this, &reporter_name, &moose_object, &declare](const std::string & suffix)
344 : {
345 9 : std::stringstream oss;
346 0 : oss << "While " << (declare ? "declaring" : "requesting") << " a "
347 : << reporter_name.specialTypeToName() << " value with the name \""
348 9 : << reporter_name.getValueName() << "\"";
349 9 : if (!reporter_name.isPostprocessor() && !reporter_name.isVectorPostprocessor())
350 9 : oss << " and type \"" << MooseUtils::prettyCppType<T>() << "\"";
351 9 : oss << ",\na Reporter with the same name " << suffix << ".\n\n";
352 9 : oss << getReporterInfo(reporter_name);
353 :
354 9 : if (moose_object)
355 9 : moose_object->mooseError(oss.str());
356 : else
357 0 : mooseError(oss.str());
358 0 : };
359 :
360 1612802 : if (declare && hasReporterValue(reporter_name))
361 3 : error_helper("has already been declared");
362 1612799 : if (!hasReporterState<T>(reporter_name))
363 : {
364 6 : std::stringstream oss;
365 3 : oss << "has been " << (declare || !hasReporterValue(reporter_name) ? "requested" : "declared")
366 9 : << " with a different type";
367 6 : error_helper(oss.str());
368 0 : }
369 : }
370 :
371 : // Reporter states are stored as restartable data. The act of registering restartable data
372 : // may be done multiple times with the same name, which will happen when more than one
373 : // get value is done, or a get value and a declare is done. With this, we create a new
374 : // state every time, but said created state may not be the actual state if this state
375 : // is already registered as restartable data. Therefore, we create a state, and then
376 : // cast the restartable data received back to a state (which may be different than
377 : // the one we created, but that's okay)
378 1695563 : auto state_unique_ptr = std::make_unique<ReporterState<T>>(reporter_name);
379 1695563 : auto & restartable_value = getRestartableDataHelper(std::move(state_unique_ptr), declare);
380 :
381 1695563 : auto * state = dynamic_cast<ReporterState<T> *>(&restartable_value);
382 : mooseAssert(state, "Cast failed. The check above must be broken!");
383 :
384 : // See declareReporterValue for a comment on what happens if a state for the same
385 : // name is requested but with different special types. TLDR: ReporterNames with
386 : // different special types are not unique so they'll be the same entry
387 1695563 : _states.emplace(reporter_name, state);
388 :
389 1695563 : return *state;
390 1695563 : }
391 :
392 : template <typename T>
393 : const T &
394 59366 : ReporterData::getReporterValue(const ReporterName & reporter_name,
395 : const MooseObject & consumer,
396 : const ReporterMode & mode,
397 : const std::size_t time_index /* = 0 */) const
398 : {
399 59366 : auto & state = getReporterStateHelper<T>(reporter_name, /* declare = */ false, &consumer);
400 59363 : state.addConsumer(mode, consumer);
401 59363 : return state.value(time_index);
402 : }
403 :
404 : template <typename T, typename S, typename... Args>
405 : T &
406 82770 : ReporterData::declareReporterValue(const ReporterName & reporter_name,
407 : const ReporterMode & mode,
408 : const MooseObject & producer,
409 : Args &&... args)
410 : {
411 : // Get/create the ReporterState
412 82770 : auto & state = getReporterStateHelper<T>(reporter_name, /* declare = */ true, &producer);
413 :
414 : // They key in _states (ReporterName) is not unique by special type. This is done on purpose
415 : // because we want to store reporter names a single name regardless of special type.
416 : // Because of this, we have the case where someone could request a reporter value
417 : // that is later declared as a pp or a vpp value. In this case, when it is first
418 : // requested, the _state entry will have a key and name with a special type of ANY.
419 : // When it's declared here (later), we will still find the correct entry because
420 : // we don't check the special type in the key/name. But... we want the actual
421 : // key and name to represent a pp or a vpp. Therefore, we'll set it properly,
422 : // remove the entry in the map (which has the ANY key), and re-add it so that it
423 : // has the pp/vpp key. This allows us to identify Reporters that really represent
424 : // pps/vpps in output and in error reporting.
425 82764 : if (reporter_name.isPostprocessor() && !state.getReporterName().isPostprocessor())
426 : {
427 12 : state.setIsPostprocessor();
428 12 : _states.erase(reporter_name);
429 12 : _states.emplace(reporter_name, &state);
430 : }
431 104239 : else if (reporter_name.isVectorPostprocessor() &&
432 21487 : !state.getReporterName().isVectorPostprocessor())
433 : {
434 12 : state.setIsVectorPostprocessor();
435 12 : _states.erase(reporter_name);
436 12 : _states.emplace(reporter_name, &state);
437 : }
438 :
439 : mooseAssert(!_context_ptrs.count(reporter_name), "Context already exists");
440 :
441 : // Create the ReporterContext
442 82764 : auto context_ptr = std::make_unique<S>(_app, producer, state, args...);
443 82764 : context_ptr->init(mode); // initialize the mode, see ContextReporter
444 82764 : _context_ptrs.emplace(reporter_name, std::move(context_ptr));
445 :
446 : // On recover, values declared after the bulk restore pass are skipped by it.
447 : // Restore this value in place from the still-open checkpoint reader (no-op on
448 : // normal runs and for values declared before the bulk restore runs, which are
449 : // handled by the bulk pass). This is done after context construction so that
450 : // context-driven resizes do not clobber the restore.
451 82764 : restoreReporterStateIfAvailable(state);
452 :
453 165528 : return state.value();
454 82764 : }
455 :
456 : template <typename T>
457 : bool
458 2306216 : ReporterData::hasReporterValue(const ReporterName & reporter_name) const
459 : {
460 2306216 : if (!hasReporterValue(reporter_name))
461 39633 : return false;
462 2266583 : return dynamic_cast<const ReporterContext<T> *>(&getReporterContextBase(reporter_name));
463 : }
464 :
465 : template <typename T>
466 : bool
467 1612799 : ReporterData::hasReporterState(const ReporterName & reporter_name) const
468 : {
469 1612799 : if (!hasReporterState(reporter_name))
470 0 : return false;
471 1612799 : return dynamic_cast<const ReporterState<T> *>(&getReporterStateBase(reporter_name));
472 : }
473 :
474 : template <typename T>
475 : const T &
476 1549486 : ReporterData::getReporterValue(const ReporterName & reporter_name,
477 : const std::size_t time_index) const
478 : {
479 1549486 : if (!hasReporterValue<T>(reporter_name))
480 0 : mooseError("Reporter name \"",
481 : reporter_name,
482 : "\" with type \"",
483 : MooseUtils::prettyCppType<T>(),
484 : "\" is not declared.");
485 :
486 : // Force the const version of value, which does not allow for increasing time index
487 27694 : return static_cast<const ReporterState<T> &>(
488 1521792 : getReporterStateHelper<T>(reporter_name, /* declare = */ false))
489 1521792 : .value(time_index);
490 : }
491 :
492 : template <typename T>
493 : void
494 589241 : ReporterData::setReporterValue(const ReporterName & reporter_name,
495 : const T & value,
496 : const std::size_t time_index)
497 : {
498 : // https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func
499 589241 : const auto & me = *this;
500 589241 : const_cast<T &>(me.getReporterValue<T>(reporter_name, time_index)) = value;
501 589241 : }
502 :
503 : template <typename T>
504 : void
505 3950 : ReporterData::needReporterTimeIndex(const ReporterName & reporter_name,
506 : const std::size_t time_index)
507 : {
508 3950 : getReporterValue<T>(reporter_name, 0); // for error checking that it is declared
509 3950 : getReporterStateHelper<T>(reporter_name, /* declare = */ false).value(time_index);
510 3950 : }
511 :
512 : // This is defined here to avoid cyclic includes, see ReporterContext.h
513 : template <typename T>
514 : void
515 354 : ReporterContext<T>::transfer(ReporterData & r_data,
516 : const ReporterName & r_name,
517 : unsigned int time_index) const
518 : {
519 354 : r_data.setReporterValue<T>(r_name, _state.value(), time_index);
520 354 : }
521 :
522 : // This is defined here to avoid cyclic includes, see ReporterContext.h
523 : template <typename T>
524 : void
525 568 : ReporterContext<T>::transferToVector(ReporterData & r_data,
526 : const ReporterName & r_name,
527 : dof_id_type index,
528 : unsigned int time_index) const
529 : {
530 0 : std::vector<T> & vec =
531 568 : const_cast<std::vector<T> &>(r_data.getReporterValue<std::vector<T>>(r_name, time_index));
532 :
533 568 : if (index >= vec.size())
534 0 : mooseError(
535 : "Requested index ", index, " is outside the bounds of the vector reporter value ", r_name);
536 568 : vec[index] = _state.value();
537 568 : }
538 :
539 : // This is defined here to avoid cyclic includes, see ReporterContext.h
540 : template <typename T>
541 : void
542 192 : ReporterContext<T>::transferFromVector(ReporterData & r_data,
543 : const ReporterName & r_name,
544 : dof_id_type index,
545 : unsigned int time_index) const
546 : {
547 : if constexpr (is_std_vector<T>::value)
548 : {
549 192 : if (index >= _state.value().size())
550 0 : mooseError("Requested index ",
551 : index,
552 : " is outside the bounds of the vector reporter value ",
553 : r_name);
554 :
555 : using R = typename T::value_type;
556 192 : r_data.setReporterValue<R>(r_name, _state.value()[index], time_index);
557 : }
558 : else
559 : {
560 0 : libmesh_ignore(r_data);
561 0 : libmesh_ignore(r_name);
562 0 : libmesh_ignore(index);
563 0 : libmesh_ignore(time_index);
564 0 : mooseError("transferFromVector can only be used for reporter types that are specializatons of "
565 : "std::vector.");
566 : }
567 192 : }
568 :
569 : // This is defined here to avoid cyclic includes, see ReporterContext.h
570 : template <typename T>
571 : void
572 183 : ReporterGeneralContext<T>::declareClone(ReporterData & r_data,
573 : const ReporterName & r_name,
574 : const ReporterMode & mode,
575 : const MooseObject & producer) const
576 : {
577 183 : r_data.declareReporterValue<T, ReporterGeneralContext<T>>(r_name, mode, producer);
578 183 : }
579 :
580 : // This is defined here to avoid cyclic includes, see ReporterContext.h
581 : template <typename T>
582 : void
583 413 : ReporterGeneralContext<T>::declareVectorClone(ReporterData & r_data,
584 : const ReporterName & r_name,
585 : const ReporterMode & mode,
586 : const MooseObject & producer) const
587 : {
588 413 : r_data.declareReporterValue<std::vector<T>, ReporterVectorContext<T>>(r_name, mode, producer);
589 413 : }
590 :
591 : // This is defined here to avoid cyclic includes, see ReporterContext.h
592 : template <typename T>
593 : void
594 0 : ReporterVectorContext<T>::declareClone(ReporterData &,
595 : const ReporterName &,
596 : const ReporterMode &,
597 : const MooseObject &) const
598 : {
599 0 : mooseError("Cannot create clone with ReporterVectorContext.");
600 : }
601 :
602 : // This is defined here to avoid cyclic includes, see ReporterContext.h
603 : template <typename T>
604 : void
605 0 : ReporterVectorContext<T>::declareVectorClone(ReporterData &,
606 : const ReporterName &,
607 : const ReporterMode &,
608 : const MooseObject &) const
609 : {
610 0 : mooseError("Cannot create clone with ReporterVectorContext.");
611 : }
|