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 
326  mutable std::map<ReporterName, ReporterStateBase *> _states;
327 
331  std::map<ReporterName, std::unique_ptr<ReporterContextBase>> _context_ptrs;
332 };
333 
334 template <typename T>
337  bool declare,
338  const MooseObject * moose_object /* = nullptr */) const
339 {
340  if (hasReporterState(reporter_name))
341  {
342  const auto error_helper =
343  [this, &reporter_name, &moose_object, &declare](const std::string & suffix)
344  {
345  std::stringstream oss;
346  oss << "While " << (declare ? "declaring" : "requesting") << " a "
347  << reporter_name.specialTypeToName() << " value with the name \""
348  << reporter_name.getValueName() << "\"";
349  if (!reporter_name.isPostprocessor() && !reporter_name.isVectorPostprocessor())
350  oss << " and type \"" << MooseUtils::prettyCppType<T>() << "\"";
351  oss << ",\na Reporter with the same name " << suffix << ".\n\n";
352  oss << getReporterInfo(reporter_name);
353 
354  if (moose_object)
355  moose_object->mooseError(oss.str());
356  else
357  mooseError(oss.str());
358  };
359 
360  if (declare && hasReporterValue(reporter_name))
361  error_helper("has already been declared");
362  if (!hasReporterState<T>(reporter_name))
363  {
364  std::stringstream oss;
365  oss << "has been " << (declare || !hasReporterValue(reporter_name) ? "requested" : "declared")
366  << " with a different type";
367  error_helper(oss.str());
368  }
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  auto state_unique_ptr = std::make_unique<ReporterState<T>>(reporter_name);
379  auto & restartable_value = getRestartableDataHelper(std::move(state_unique_ptr), declare);
380 
381  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  _states.emplace(reporter_name, state);
388 
389  return *state;
390 }
391 
392 template <typename T>
393 const T &
395  const MooseObject & consumer,
396  const ReporterMode & mode,
397  const std::size_t time_index /* = 0 */) const
398 {
399  auto & state = getReporterStateHelper<T>(reporter_name, /* declare = */ false, &consumer);
400  state.addConsumer(mode, consumer);
401  return state.value(time_index);
402 }
403 
404 template <typename T, typename S, typename... Args>
405 T &
407  const ReporterMode & mode,
408  const MooseObject & producer,
409  Args &&... args)
410 {
411  // Get/create the ReporterState
412  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  if (reporter_name.isPostprocessor() && !state.getReporterName().isPostprocessor())
426  {
427  state.setIsPostprocessor();
428  _states.erase(reporter_name);
429  _states.emplace(reporter_name, &state);
430  }
431  else if (reporter_name.isVectorPostprocessor() &&
432  !state.getReporterName().isVectorPostprocessor())
433  {
434  state.setIsVectorPostprocessor();
435  _states.erase(reporter_name);
436  _states.emplace(reporter_name, &state);
437  }
438 
439  mooseAssert(!_context_ptrs.count(reporter_name), "Context already exists");
440 
441  // Create the ReporterContext
442  auto context_ptr = std::make_unique<S>(_app, producer, state, args...);
443  context_ptr->init(mode); // initialize the mode, see ContextReporter
444  _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.
452 
453  return state.value();
454 }
455 
456 template <typename T>
457 bool
458 ReporterData::hasReporterValue(const ReporterName & reporter_name) const
459 {
460  if (!hasReporterValue(reporter_name))
461  return false;
462  return dynamic_cast<const ReporterContext<T> *>(&getReporterContextBase(reporter_name));
463 }
464 
465 template <typename T>
466 bool
467 ReporterData::hasReporterState(const ReporterName & reporter_name) const
468 {
469  if (!hasReporterState(reporter_name))
470  return false;
471  return dynamic_cast<const ReporterState<T> *>(&getReporterStateBase(reporter_name));
472 }
473 
474 template <typename T>
475 const T &
477  const std::size_t time_index) const
478 {
479  if (!hasReporterValue<T>(reporter_name))
480  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  return static_cast<const ReporterState<T> &>(
488  getReporterStateHelper<T>(reporter_name, /* declare = */ false))
489  .value(time_index);
490 }
491 
492 template <typename T>
493 void
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  const auto & me = *this;
500  const_cast<T &>(me.getReporterValue<T>(reporter_name, time_index)) = value;
501 }
502 
503 template <typename T>
504 void
506  const std::size_t time_index)
507 {
508  getReporterValue<T>(reporter_name, 0); // for error checking that it is declared
509  getReporterStateHelper<T>(reporter_name, /* declare = */ false).value(time_index);
510 }
511 
512 // This is defined here to avoid cyclic includes, see ReporterContext.h
513 template <typename T>
514 void
516  const ReporterName & r_name,
517  unsigned int time_index) const
518 {
519  r_data.setReporterValue<T>(r_name, _state.value(), time_index);
520 }
521 
522 // This is defined here to avoid cyclic includes, see ReporterContext.h
523 template <typename T>
524 void
526  const ReporterName & r_name,
527  dof_id_type index,
528  unsigned int time_index) const
529 {
530  std::vector<T> & vec =
531  const_cast<std::vector<T> &>(r_data.getReporterValue<std::vector<T>>(r_name, time_index));
532 
533  if (index >= vec.size())
534  mooseError(
535  "Requested index ", index, " is outside the bounds of the vector reporter value ", r_name);
536  vec[index] = _state.value();
537 }
538 
539 // This is defined here to avoid cyclic includes, see ReporterContext.h
540 template <typename T>
541 void
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  if (index >= _state.value().size())
550  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  r_data.setReporterValue<R>(r_name, _state.value()[index], time_index);
557  }
558  else
559  {
560  libmesh_ignore(r_data);
561  libmesh_ignore(r_name);
562  libmesh_ignore(index);
563  libmesh_ignore(time_index);
564  mooseError("transferFromVector can only be used for reporter types that are specializatons of "
565  "std::vector.");
566  }
567 }
568 
569 // This is defined here to avoid cyclic includes, see ReporterContext.h
570 template <typename T>
571 void
573  const ReporterName & r_name,
574  const ReporterMode & mode,
575  const MooseObject & producer) const
576 {
577  r_data.declareReporterValue<T, ReporterGeneralContext<T>>(r_name, mode, producer);
578 }
579 
580 // This is defined here to avoid cyclic includes, see ReporterContext.h
581 template <typename T>
582 void
584  const ReporterName & r_name,
585  const ReporterMode & mode,
586  const MooseObject & producer) const
587 {
588  r_data.declareReporterValue<std::vector<T>, ReporterVectorContext<T>>(r_name, mode, producer);
589 }
590 
591 // This is defined here to avoid cyclic includes, see ReporterContext.h
592 template <typename T>
593 void
595  const ReporterName &,
596  const ReporterMode &,
597  const MooseObject &) const
598 {
599  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
606  const ReporterName &,
607  const ReporterMode &,
608  const MooseObject &) const
609 {
610  mooseError("Cannot create clone with ReporterVectorContext.");
611 }
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:331
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:605
A special version of RestartableData to aid in storing Reporter values.
std::map< ReporterName, ReporterStateBase * > _states
Map from ReporterName -> Reporter state.
Definition: ReporterData.h:326
bool isVectorPostprocessor() const
Definition: ReporterName.h:98
virtual void transfer(ReporterData &r_data, const ReporterName &r_name, unsigned int time_index=0) const override
Perform type specific transfer.
Definition: ReporterData.h:515
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:406
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:311
MooseEnum designed for the ReporterContext objects to define how a ReporterValue can and is being pro...
Definition: ReporterMode.h:62
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:505
Base class for MOOSE-based applications.
Definition: MooseApp.h:108
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:583
void restoreReporterStateIfAvailable(RestartableDataValue &state) const
Helper for restoring state from the checkpoint reader if available.
Definition: ReporterData.C:181
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:89
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:394
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:467
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:94
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:525
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:494
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:542
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:336
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:594
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:197
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:572
std::string getReporterInfo() const
Gets information about all declared/requested Reporters.
Definition: ReporterData.C:253
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:458
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:187
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:47
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:45
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