https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
21class MooseApp;
22class Receiver;
23
49{
50public:
52 {
62 WriteKey() {} // private constructor
63 friend class Reporter;
64 friend class Postprocessor;
65 friend class Receiver;
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
255 const ReporterContextBase & getReporterContextBase(const ReporterName & reporter_name) const;
258
263 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
291private:
294
304 template <typename T>
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
334template <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
392template <typename T>
393const 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
404template <typename T, typename S, typename... Args>
405T &
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
456template <typename T>
457bool
459{
460 if (!hasReporterValue(reporter_name))
461 return false;
462 return dynamic_cast<const ReporterContext<T> *>(&getReporterContextBase(reporter_name));
463}
464
465template <typename T>
466bool
468{
469 if (!hasReporterState(reporter_name))
470 return false;
471 return dynamic_cast<const ReporterState<T> *>(&getReporterStateBase(reporter_name));
472}
473
474template <typename T>
475const 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
492template <typename T>
493void
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
503template <typename T>
504void
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
513template <typename T>
514void
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
523template <typename T>
524void
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())
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
540template <typename T>
541void
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
570template <typename T>
571void
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
581template <typename T>
582void
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
592template <typename T>
593void
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
603template <typename T>
604void
606 const ReporterName &,
607 const ReporterMode &,
608 const MooseObject &) const
609{
610 mooseError("Cannot create clone with ReporterVectorContext.");
611}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
A class for storing a constant value.
Base class for MOOSE-based applications.
Definition MooseApp.h:110
Every object that can be built by the factory should be derived from this class.
Definition MooseObject.h:31
Base class for all Postprocessors.
A class for storing data, it allows the user to change the value of the postprocessor by altering the...
Definition Receiver.h:19
This is a helper class to aid with parallel communication of compute Reporter values as well as provi...
General context that is called by all Reporter values to manage the old values.
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.
virtual void transfer(ReporterData &r_data, const ReporterName &r_name, unsigned int time_index=0) const override
Perform type specific transfer.
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.
WriteKey()
An object that can be passed to FEProblemBase::getReporterData to provide non-const access the Report...
This is a helper class for managing the storage of declared Reporter object values.
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.
std::set< ReporterName > getReporterNames() const
Return a list of all reporter names.
bool hasReporterState(const ReporterName &reporter_name) const
std::vector< std::string > getAllRealReporterFullNames() const
Get full names of all real reporter values Note: For a postprocessor, the full name is the postproces...
const ReporterStateBase & getReporterStateBase(const ReporterName &reporter_name) const
@Returns The ReporterStateBase associated with the Reporter with name reporter_name.
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.
MooseApp & _app
For accessing the restart/recover system, which is where Reporter values are stored.
DenseVector< Real > getAllRealReporterValues() const
Get all real reporter values including postprocessor and vector postprocessor values into a dense vec...
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.
void check() const
Perform integrity check for get/declare calls.
void copyValuesBack()
At the end of a timestep this method is called to copy the values back in time in preparation for the...
const ReporterContextBase & getReporterContextBase(const ReporterName &reporter_name) const
bool hasReporterValue(const ReporterName &reporter_name) const
Return True if a Reporter value with the given type and name have been created.
void setReporterValue(const ReporterName &reporter_name, const T &value, const std::size_t time_index=0)
Method for setting Reporter values that already exist.
std::map< ReporterName, std::unique_ptr< ReporterContextBase > > _context_ptrs
The ReporterContext objects are created when a value is declared.
void restoreState(bool verbose=false)
When a time step fails, this method is called to revert the current reporter values to their old stat...
std::map< ReporterName, ReporterStateBase * > _states
Map from ReporterName -> Reporter state.
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.
std::string getReporterInfo() const
Gets information about all declared/requested Reporters.
void restoreReporterStateIfAvailable(RestartableDataValue &state) const
Helper for restoring state from the checkpoint reader if available.
RestartableDataValue & getRestartableDataHelper(std::unique_ptr< RestartableDataValue > data_ptr, bool declare) const
Helper for registering data with the MooseApp to avoid cyclic includes.
bool hasReporterWithMode(const std::string &obj_name, const ReporterMode &mode) const
Return true if the supplied mode exists in the produced Reporter values.
std::set< std::string > getPostprocessorNames() const
Return a list of all postprocessor names.
const ReporterProducerEnum & getReporterMode(const ReporterName &reporter_name) const
Return the ReporterProducerEnum for an existing ReporterValue.
void finalize(const std::string &object_name)
Helper function for performing post calculation actions via the ReporterContext objects.
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.
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.
MooseEnumItem that automatically creates the ID and doesn't allow the ID to be assigned.
The Reporter system is comprised of objects that can contain any number of data values.
std::string specialTypeToName() const
Converts the special type to a usable name for error reporting.
bool isPostprocessor() const
bool isVectorPostprocessor() const
const std::string & getValueName() const
Return the data name for the Reporter value.
MooseEnum designed for the ReporterContext objects to define how a ReporterValue can and is being pro...
The base class for storing a Reporter's state.
A special version of RestartableData to aid in storing Reporter values.
This context is specific for vector types of reporters, mainly for declaring a vector of the type fro...
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.
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.
Reporter objects allow for the declaration of arbitrary data types that are aggregate values for a si...
Definition Reporter.h:48
Abstract definition of a RestartableData value.
Base class for Postprocessors that produce a vector of values.