https://mooseframework.inl.gov
ReporterData.h
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 #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 
49 {
50 public:
51  class WriteKey
52  {
62  WriteKey() {} // private constructor
63  friend class Reporter;
64  friend class Postprocessor;
65  friend class Receiver;
66  friend class ConstantPostprocessor;
67  friend class VectorPostprocessor;
69  };
70 
71  ReporterData(MooseApp & moose_app);
72 
76  template <typename T>
77  bool hasReporterValue(const ReporterName & reporter_name) const;
78 
82  bool hasReporterValue(const ReporterName & reporter_name) const;
83 
88  template <typename T>
89  bool hasReporterState(const ReporterName & reporter_name) const;
90 
94  bool hasReporterState(const ReporterName & reporter_name) const;
95 
99  std::set<ReporterName> getReporterNames() const;
100 
104  std::set<std::string> getPostprocessorNames() const;
105 
110  DenseVector<Real> getAllRealReporterValues() const;
111 
118  std::vector<std::string> getAllRealReporterFullNames() const;
119 
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 
146  template <typename T>
147  const T & getReporterValue(const ReporterName & reporter_name,
148  const std::size_t time_index = 0) const;
149 
165  template <typename T>
166  void setReporterValue(const ReporterName & reporter_name,
167  const T & value,
168  const std::size_t time_index = 0);
169 
177  template <typename T>
178  void needReporterTimeIndex(const ReporterName & reporter_name, const std::size_t time_index);
179 
181 
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 
221  void finalize(const std::string & object_name);
222 
229  void copyValuesBack();
230 
237  void restoreState(bool verbose = false);
238 
242  void check() const;
243 
249  bool hasReporterWithMode(const std::string & obj_name, const ReporterMode & mode) const;
250 
254  const ReporterContextBase & getReporterContextBase(const ReporterName & reporter_name) const;
258 
262  const ReporterStateBase & getReporterStateBase(const ReporterName & reporter_name) const;
264  ReporterStateBase & getReporterStateBase(const ReporterName & reporter_name);
266 
272  const ReporterProducerEnum & getReporterMode(const ReporterName & reporter_name) const;
273 
278  static std::string getReporterInfo(const ReporterStateBase & state,
279  const ReporterContextBase * context);
280 
284  std::string getReporterInfo(const ReporterName & reporter_name) const;
285 
289  std::string getReporterInfo() const;
290 
291 private:
294 
304  template <typename T>
305  ReporterState<T> & getReporterStateHelper(const ReporterName & reporter_name,
306  bool declare,
307  const MooseObject * moose_object = nullptr) const;
308 
312  RestartableDataValue & getRestartableDataHelper(std::unique_ptr<RestartableDataValue> data_ptr,
313  bool declare) const;
314 
320  mutable std::map<ReporterName, ReporterStateBase *> _states;
321 
325  std::map<ReporterName, std::unique_ptr<ReporterContextBase>> _context_ptrs;
326 };
327 
328 template <typename T>
331  bool declare,
332  const MooseObject * moose_object /* = nullptr */) const
333 {
334  if (hasReporterState(reporter_name))
335  {
336  const auto error_helper =
337  [this, &reporter_name, &moose_object, &declare](const std::string & suffix)
338  {
339  std::stringstream oss;
340  oss << "While " << (declare ? "declaring" : "requesting") << " a "
341  << reporter_name.specialTypeToName() << " value with the name \""
342  << reporter_name.getValueName() << "\"";
343  if (!reporter_name.isPostprocessor() && !reporter_name.isVectorPostprocessor())
344  oss << " and type \"" << MooseUtils::prettyCppType<T>() << "\"";
345  oss << ",\na Reporter with the same name " << suffix << ".\n\n";
346  oss << getReporterInfo(reporter_name);
347 
348  if (moose_object)
349  moose_object->mooseError(oss.str());
350  else
351  mooseError(oss.str());
352  };
353 
354  if (declare && hasReporterValue(reporter_name))
355  error_helper("has already been declared");
356  if (!hasReporterState<T>(reporter_name))
357  {
358  std::stringstream oss;
359  oss << "has been " << (declare || !hasReporterValue(reporter_name) ? "requested" : "declared")
360  << " with a different type";
361  error_helper(oss.str());
362  }
363  }
364 
365  // Reporter states are stored as restartable data. The act of registering restartable data
366  // may be done multiple times with the same name, which will happen when more than one
367  // get value is done, or a get value and a declare is done. With this, we create a new
368  // state every time, but said created state may not be the actual state if this state
369  // is already registered as restartable data. Therefore, we create a state, and then
370  // cast the restartable data received back to a state (which may be different than
371  // the one we created, but that's okay)
372  auto state_unique_ptr = std::make_unique<ReporterState<T>>(reporter_name);
373  auto & restartable_value = getRestartableDataHelper(std::move(state_unique_ptr), declare);
374 
375  auto * state = dynamic_cast<ReporterState<T> *>(&restartable_value);
376  mooseAssert(state, "Cast failed. The check above must be broken!");
377 
378  // See declareReporterValue for a comment on what happens if a state for the same
379  // name is requested but with different special types. TLDR: ReporterNames with
380  // different special types are not unique so they'll be the same entry
381  _states.emplace(reporter_name, state);
382 
383  return *state;
384 }
385 
386 template <typename T>
387 const T &
389  const MooseObject & consumer,
390  const ReporterMode & mode,
391  const std::size_t time_index /* = 0 */) const
392 {
393  auto & state = getReporterStateHelper<T>(reporter_name, /* declare = */ false, &consumer);
394  state.addConsumer(mode, consumer);
395  return state.value(time_index);
396 }
397 
398 template <typename T, typename S, typename... Args>
399 T &
401  const ReporterMode & mode,
402  const MooseObject & producer,
403  Args &&... args)
404 {
405  // Get/create the ReporterState
406  auto & state = getReporterStateHelper<T>(reporter_name, /* declare = */ true, &producer);
407 
408  // They key in _states (ReporterName) is not unique by special type. This is done on purpose
409  // because we want to store reporter names a single name regardless of special type.
410  // Because of this, we have the case where someone could request a reporter value
411  // that is later declared as a pp or a vpp value. In this case, when it is first
412  // requested, the _state entry will have a key and name with a special type of ANY.
413  // When it's declared here (later), we will still find the correct entry because
414  // we don't check the special type in the key/name. But... we want the actual
415  // key and name to represent a pp or a vpp. Therefore, we'll set it properly,
416  // remove the entry in the map (which has the ANY key), and re-add it so that it
417  // has the pp/vpp key. This allows us to identify Reporters that really represent
418  // pps/vpps in output and in error reporting.
419  if (reporter_name.isPostprocessor() && !state.getReporterName().isPostprocessor())
420  {
421  state.setIsPostprocessor();
422  _states.erase(reporter_name);
423  _states.emplace(reporter_name, &state);
424  }
425  else if (reporter_name.isVectorPostprocessor() &&
426  !state.getReporterName().isVectorPostprocessor())
427  {
428  state.setIsVectorPostprocessor();
429  _states.erase(reporter_name);
430  _states.emplace(reporter_name, &state);
431  }
432 
433  mooseAssert(!_context_ptrs.count(reporter_name), "Context already exists");
434 
435  // Create the ReporterContext
436  auto context_ptr = std::make_unique<S>(_app, producer, state, args...);
437  context_ptr->init(mode); // initialize the mode, see ContextReporter
438  _context_ptrs.emplace(reporter_name, std::move(context_ptr));
439 
440  return state.value();
441 }
442 
443 template <typename T>
444 bool
445 ReporterData::hasReporterValue(const ReporterName & reporter_name) const
446 {
447  if (!hasReporterValue(reporter_name))
448  return false;
449  return dynamic_cast<const ReporterContext<T> *>(&getReporterContextBase(reporter_name));
450 }
451 
452 template <typename T>
453 bool
454 ReporterData::hasReporterState(const ReporterName & reporter_name) const
455 {
456  if (!hasReporterState(reporter_name))
457  return false;
458  return dynamic_cast<const ReporterState<T> *>(&getReporterStateBase(reporter_name));
459 }
460 
461 template <typename T>
462 const T &
464  const std::size_t time_index) const
465 {
466  if (!hasReporterValue<T>(reporter_name))
467  mooseError("Reporter name \"",
468  reporter_name,
469  "\" with type \"",
470  MooseUtils::prettyCppType<T>(),
471  "\" is not declared.");
472 
473  // Force the const version of value, which does not allow for increasing time index
474  return static_cast<const ReporterState<T> &>(
475  getReporterStateHelper<T>(reporter_name, /* declare = */ false))
476  .value(time_index);
477 }
478 
479 template <typename T>
480 void
482  const T & value,
483  const std::size_t time_index)
484 {
485  // https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func
486  const auto & me = *this;
487  const_cast<T &>(me.getReporterValue<T>(reporter_name, time_index)) = value;
488 }
489 
490 template <typename T>
491 void
493  const std::size_t time_index)
494 {
495  getReporterValue<T>(reporter_name, 0); // for error checking that it is declared
496  getReporterStateHelper<T>(reporter_name, /* declare = */ false).value(time_index);
497 }
498 
499 // This is defined here to avoid cyclic includes, see ReporterContext.h
500 template <typename T>
501 void
503  const ReporterName & r_name,
504  unsigned int time_index) const
505 {
506  r_data.setReporterValue<T>(r_name, _state.value(), time_index);
507 }
508 
509 // This is defined here to avoid cyclic includes, see ReporterContext.h
510 template <typename T>
511 void
513  const ReporterName & r_name,
514  dof_id_type index,
515  unsigned int time_index) const
516 {
517  std::vector<T> & vec =
518  const_cast<std::vector<T> &>(r_data.getReporterValue<std::vector<T>>(r_name, time_index));
519 
520  if (index >= vec.size())
521  mooseError(
522  "Requested index ", index, " is outside the bounds of the vector reporter value ", r_name);
523  vec[index] = _state.value();
524 }
525 
526 // This is defined here to avoid cyclic includes, see ReporterContext.h
527 template <typename T>
528 void
530  const ReporterName & r_name,
531  dof_id_type index,
532  unsigned int time_index) const
533 {
534  if constexpr (is_std_vector<T>::value)
535  {
536  if (index >= _state.value().size())
537  mooseError("Requested index ",
538  index,
539  " is outside the bounds of the vector reporter value ",
540  r_name);
541 
542  using R = typename T::value_type;
543  r_data.setReporterValue<R>(r_name, _state.value()[index], time_index);
544  }
545  else
546  {
547  libmesh_ignore(r_data);
548  libmesh_ignore(r_name);
549  libmesh_ignore(index);
550  libmesh_ignore(time_index);
551  mooseError("transferFromVector can only be used for reporter types that are specializatons of "
552  "std::vector.");
553  }
554 }
555 
556 // This is defined here to avoid cyclic includes, see ReporterContext.h
557 template <typename T>
558 void
560  const ReporterName & r_name,
561  const ReporterMode & mode,
562  const MooseObject & producer) const
563 {
564  r_data.declareReporterValue<T, ReporterGeneralContext<T>>(r_name, mode, producer);
565 }
566 
567 // This is defined here to avoid cyclic includes, see ReporterContext.h
568 template <typename T>
569 void
571  const ReporterName & r_name,
572  const ReporterMode & mode,
573  const MooseObject & producer) const
574 {
575  r_data.declareReporterValue<std::vector<T>, ReporterVectorContext<T>>(r_name, mode, producer);
576 }
577 
578 // This is defined here to avoid cyclic includes, see ReporterContext.h
579 template <typename T>
580 void
582  const ReporterName &,
583  const ReporterMode &,
584  const MooseObject &) const
585 {
586  mooseError("Cannot create clone with ReporterVectorContext.");
587 }
588 
589 // This is defined here to avoid cyclic includes, see ReporterContext.h
590 template <typename T>
591 void
593  const ReporterName &,
594  const ReporterMode &,
595  const MooseObject &) const
596 {
597  mooseError("Cannot create clone with ReporterVectorContext.");
598 }
ReporterData(MooseApp &moose_app)
Definition: ReporterData.C:14
std::map< ReporterName, std::unique_ptr< ReporterContextBase > > _context_ptrs
The ReporterContext objects are created when a value is declared.
Definition: ReporterData.h:325
virtual void declareVectorClone(ReporterData &r_data, const ReporterName &r_name, const ReporterMode &mode, const MooseObject &producer) const final
This simply throws an error to avoid infinite instantiations.
Definition: ReporterData.h:592
A special version of RestartableData to aid in storing Reporter values.
std::map< ReporterName, ReporterStateBase * > _states
Map from ReporterName -> Reporter state.
Definition: ReporterData.h:320
bool isVectorPostprocessor() const
Definition: ReporterName.h:89
virtual void transfer(ReporterData &r_data, const ReporterName &r_name, unsigned int time_index=0) const override
Perform type specific transfer.
Definition: ReporterData.h:502
const ReporterStateBase & getReporterStateBase(const ReporterName &reporter_name) const
The ReporterStateBase associated with the Reporter with name reporter_name.
Definition: ReporterData.C:146
T & declareReporterValue(const ReporterName &reporter_name, const ReporterMode &mode, const MooseObject &producer, Args &&... args)
Method for returning a writable reference to the current Reporter value.
Definition: ReporterData.h:400
This context is specific for vector types of reporters, mainly for declaring a vector of the type fro...
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
MooseEnum designed for the ReporterContext objects to define how a ReporterValue can and is being pro...
Definition: ReporterMode.h:61
WriteKey()
An object that can be passed to FEProblemBase::getReporterData to provide non-const access the Report...
Definition: ReporterData.h:62
void needReporterTimeIndex(const ReporterName &reporter_name, const std::size_t time_index)
Method for setting that a specific time index is requested for a Reporter value.
Definition: ReporterData.h:492
Base class for MOOSE-based applications.
Definition: MooseApp.h:96
virtual void declareVectorClone(ReporterData &r_data, const ReporterName &r_name, const ReporterMode &mode, const MooseObject &producer) const override
Declare a reporter value that is a vector of the same type as this context.
Definition: ReporterData.h:570
Reporter objects allow for the declaration of arbitrary data types that are aggregate values for a si...
Definition: Reporter.h:47
RestartableDataValue & getRestartableDataHelper(std::unique_ptr< RestartableDataValue > data_ptr, bool declare) const
Helper for registering data with the MooseApp to avoid cyclic includes.
Definition: ReporterData.C:174
void libmesh_ignore(const Args &...)
This is a helper class to aid with parallel communication of compute Reporter values as well as provi...
DenseVector< Real > getAllRealReporterValues() const
Get all real reporter values including postprocessor and vector postprocessor values into a dense vec...
Definition: ReporterData.C:81
std::string specialTypeToName() const
Converts the special type to a usable name for error reporting.
Definition: ReporterName.C:83
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
const T & getReporterValue(const ReporterName &reporter_name, const MooseObject &consumer, const ReporterMode &mode, const std::size_t time_index=0) const
Method for returning read only references to Reporter values.
Definition: ReporterData.h:388
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
std::vector< std::string > getAllRealReporterFullNames() const
Get full names of all real reporter values Note: For a postprocessor, the full name is the postproces...
Definition: ReporterData.C:106
bool hasReporterState(const ReporterName &reporter_name) const
Definition: ReporterData.h:454
void finalize(const std::string &object_name)
Helper function for performing post calculation actions via the ReporterContext objects.
Definition: ReporterData.C:48
The base class for storing a Reporter&#39;s state.
Definition: ReporterState.h:32
bool isPostprocessor() const
Definition: ReporterName.h:85
Base class for all Postprocessors.
Definition: Postprocessor.h:23
virtual void transferToVector(ReporterData &r_data, const ReporterName &r_name, dof_id_type index, unsigned int time_index=0) const override
Perform type specific transfer to a vector.
Definition: ReporterData.h:512
void setReporterValue(const ReporterName &reporter_name, const T &value, const std::size_t time_index=0)
Method for setting Reporter values that already exist.
Definition: ReporterData.h:481
std::set< ReporterName > getReporterNames() const
Return a list of all reporter names.
Definition: ReporterData.C:62
virtual void transferFromVector(ReporterData &r_data, const ReporterName &r_name, dof_id_type index, unsigned int time_index=0) const override
Perform type specific transfer from a vector.
Definition: ReporterData.h:529
ReporterState< T > & getReporterStateHelper(const ReporterName &reporter_name, bool declare, const MooseObject *moose_object=nullptr) const
Helper method for creating the necessary RestartableData for Reporter values.
Definition: ReporterData.h:330
virtual void declareClone(ReporterData &r_data, const ReporterName &r_name, const ReporterMode &mode, const MooseObject &producer) const final
This simply throws an error to avoid infinite instantiations.
Definition: ReporterData.h:581
void copyValuesBack()
At the end of a timestep this method is called to copy the values back in time in preparation for the...
Definition: ReporterData.C:17
const ReporterProducerEnum & getReporterMode(const ReporterName &reporter_name) const
Return the ReporterProducerEnum for an existing ReporterValue.
Definition: ReporterData.C:191
MooseApp & _app
For accessing the restart/recover system, which is where Reporter values are stored.
Definition: ReporterData.h:293
virtual void declareClone(ReporterData &r_data, const ReporterName &r_name, const ReporterMode &mode, const MooseObject &producer) const override
Declare a reporter value of same type as this context.
Definition: ReporterData.h:559
std::string getReporterInfo() const
Gets information about all declared/requested Reporters.
Definition: ReporterData.C:247
A class for storing data, it allows the user to change the value of the postprocessor by altering the...
Definition: Receiver.h:18
T & value(const std::size_t time_index=0)
Return a reference to the current value or one of the old values.
bool hasReporterValue(const ReporterName &reporter_name) const
Return True if a Reporter value with the given type and name have been created.
Definition: ReporterData.h:445
General context that is called by all Reporter values to manage the old values.
bool hasReporterWithMode(const std::string &obj_name, const ReporterMode &mode) const
Return true if the supplied mode exists in the produced Reporter values.
Definition: ReporterData.C:181
void check() const
Perform integrity check for get/declare calls.
Definition: ReporterData.C:162
std::set< std::string > getPostprocessorNames() const
Return a list of all postprocessor names.
Definition: ReporterData.C:71
const std::string & getValueName() const
Return the data name for the Reporter value.
Definition: ReporterName.C:41
Base class for Postprocessors that produce a vector of values.
MooseEnumItem that automatically creates the ID and doesn&#39;t allow the ID to be assigned.
Definition: ReporterMode.h:44
Abstract definition of a RestartableData value.
The Reporter system is comprised of objects that can contain any number of data values.
Definition: ReporterName.h:30
A class for storing a constant value.
void restoreState(bool verbose=false)
When a time step fails, this method is called to revert the current reporter values to their old stat...
Definition: ReporterData.C:24
uint8_t dof_id_type
const ReporterContextBase & getReporterContextBase(const ReporterName &reporter_name) const
Definition: ReporterData.C:130
This is a helper class for managing the storage of declared Reporter object values.
Definition: ReporterData.h:48