LCOV - code coverage report
Current view: top level - include/reporters - ReporterContext.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 104 132 78.8 %
Date: 2026-05-29 20:35:17 Functions: 286 697 41.0 %
Legend: Lines: hit not hit

          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             : #pragma once
      10             : 
      11             : #include <iostream>
      12             : #include <typeinfo>
      13             : 
      14             : #include "MooseError.h"
      15             : #include "libmesh/id_types.h"
      16             : #include "libmesh/parallel.h"
      17             : #include "libmesh/parallel_object.h"
      18             : 
      19             : #include "ReporterName.h"
      20             : #include "ReporterMode.h"
      21             : #include "ReporterState.h"
      22             : #include "JsonIO.h"
      23             : #include "JsonSyntaxTree.h"
      24             : #include "MooseObject.h"
      25             : #include <type_traits>
      26             : 
      27             : class ReporterData;
      28             : 
      29             : /**
      30             :  * This is a helper class to aid with parallel communication of compute Reporter values as well
      31             :  * as provides a link to the stored Reporter value state object.
      32             :  *
      33             :  * @see Reporter, ReporterData, ReporterState
      34             :  *
      35             :  * This file contains several reporter context types with specific polymorphism:
      36             :  *
      37             :  * ReporterContextBase--->ReporterContext<T>
      38             :  *                        |        |
      39             :  *                        |        ReporterGeneralContext<T>
      40             :  *                        |        |        |      |
      41             :  *                        |        |        |      ReporterGatherContext<T>
      42             :  *                        |        |        ReporterScatterContext<T>
      43             :  *                        |        ReporterBroadcastContext<T>
      44             :  *                        |
      45             :  *                        ReporterVectorContext<std::vector<T>>
      46             :  *
      47             :  * When creating a new context, it is generally advisable to derive from ReporterGeneralContext
      48             :  * (@see VectorPostprocessorContext). The reason for the split between ReporterGeneralContext
      49             :  * and ReporterVectorContext is due to the declareVectorClone and resize functionality. If we
      50             :  * were to declare a vector clone in ReporterContext there would be a infinite instantiation of
      51             :  * of vector contexts, which is why this declare is defined in ReporterGeneralContext and an
      52             :  * error is thrown in ReporterVectorContext. There is also no easy way to partially instantiate
      53             :  * a member function (you have to due it for the entire class), which is why the resize is
      54             :  * defined in ReporterVectorContext. That being said, we are always open for improvements,
      55             :  * especially for simplifying the polymorphism of these contexts.
      56             :  */
      57             : class ReporterContextBase : public libMesh::ParallelObject
      58             : {
      59             : public:
      60             :   ReporterContextBase(const libMesh::ParallelObject & other, const MooseObject & producer);
      61       79476 :   virtual ~ReporterContextBase() = default;
      62             : 
      63             :   /// Return the ReporterName that the context is associated
      64             :   virtual const ReporterName & name() const = 0;
      65             : 
      66             :   /// Return the type of the data stored
      67             :   // This is a helper for ReporterContext::storeInfo
      68             :   virtual std::string type() const = 0;
      69             : 
      70             :   /**
      71             :    * @returns The derived context type for this context.
      72             :    *
      73             :    * This must be overridden in every class.
      74             :    */
      75             :   virtual std::string contextType() const = 0;
      76             : 
      77             :   /// Called by FEProblemBase::advanceState via ReporterData
      78             :   virtual void copyValuesBack() = 0;
      79             : 
      80             :   /// Called by FEProblemBase::restoreSolutions via ReporterData
      81             :   virtual bool restoreState() = 0;
      82             : 
      83             :   /// Called by JSONOutput::outputReporters to output meta data independent of calculated
      84             :   /// values
      85             :   virtual void storeInfo(nlohmann::json & json) const = 0;
      86             : 
      87             :   /// Called by JSONOutput::outputReporters to invoke storage of values for output
      88             :   ///
      89             :   /// This method exists and is distinct from the RestartableData::store method for JSON output
      90             :   /// via the JSONOutput object. The RestartableData::store/load methods are designed for restart
      91             :   /// and include all the data including the old values.
      92             :   ///
      93             :   /// This method only outputs the current value within the JSONOutput object.
      94             :   /// NOTE: nlohmann qualification is needed for argument json because the std::vector overload is
      95             :   ///       not in the std namespace, it's in the nlohmann namespace, and will come up in argument
      96             :   ///       dependent lookup (ADL) only because of this qualification.
      97             :   ///
      98             :   /// @see JsonIO.h
      99             :   /// @see JSONOutput.h
     100             :   virtual void store(nlohmann::json & json) const = 0;
     101             : 
     102             :   /// Called by FEProblemBase::joinAndFinalize via ReporterData
     103             :   virtual void finalize() = 0; // new ReporterContext objects should override
     104             : 
     105             :   /**
     106             :    * Initialize the producer mode.
     107             :    *
     108             :    * This done after construction to allow the constructor to define the available values in the
     109             :    * ReporterProducerEnum.
     110             :    *
     111             :    * @see ReporterData::declareReporterValue
     112             :    */
     113             :   void init(const ReporterMode & mode);
     114             : 
     115             :   /**
     116             :    * Return the MooseObject that produces this Reporter.
     117             :    */
     118         132 :   const MooseObject & getProducer() const { return _producer; }
     119             : 
     120             :   /**
     121             :    * Return the Reporter value produced mode
     122             :    */
     123             :   const ReporterProducerEnum & getProducerModeEnum() const;
     124             : 
     125             :   /**
     126             :    * Helper for enabling generic transfer of Reporter values
     127             :    * @param r_data The ReporterData on the app that this data is being transferred to
     128             :    * @param r_name The name of the Report being transferred to
     129             :    *
     130             :    * @see MultiAppReporterTransfer
     131             :    */
     132             :   virtual void transfer(ReporterData & r_data,
     133             :                         const ReporterName & r_name,
     134             :                         unsigned int time_index = 0) const = 0;
     135             : 
     136             :   /**
     137             :    * Helper for enabling generic transfer of Reporter values to a vector
     138             :    * @param r_data The ReporterData on the app that this data is being transferred to
     139             :    * @param r_name The name of the Report being transfered to
     140             :    *
     141             :    * @see ReporterTransferInterface
     142             :    */
     143             :   virtual void transferToVector(ReporterData & r_data,
     144             :                                 const ReporterName & r_name,
     145             :                                 dof_id_type index,
     146             :                                 unsigned int time_index = 0) const = 0;
     147             : 
     148             :   /**
     149             :    * Helper for enabling generic transfer of a vector Reporter of values to a
     150             :    * single value
     151             :    * @param r_data The ReporterData on the app that this data is being transferred to
     152             :    * @param r_name The name of the Reporter being transferred to
     153             :    *
     154             :    * @see ReporterTransferInterface
     155             :    */
     156             :   virtual void transferFromVector(ReporterData & r_data,
     157             :                                   const ReporterName & r_name,
     158             :                                   dof_id_type index,
     159             :                                   unsigned int time_index = 0) const = 0;
     160             : 
     161             :   /**
     162             :    * Helper for declaring new reporter values based on this context
     163             :    *
     164             :    * @param r_data The ReporterData on the app that this value is being declared
     165             :    * @param r_name The name of the Reporter value being declared
     166             :    * @param mode Reporter mode to declare with
     167             :    *
     168             :    * @see ReporterTransferInterface
     169             :    */
     170             :   virtual void declareClone(ReporterData & r_data,
     171             :                             const ReporterName & r_name,
     172             :                             const ReporterMode & mode,
     173             :                             const MooseObject & producer) const = 0;
     174             : 
     175             :   /**
     176             :    * Helper for declaring new vector reporter values based on this context
     177             :    *
     178             :    * @param r_data The ReporterData on the app that this value is being declared
     179             :    * @param r_name The name of the Reporter value being declared
     180             :    * @param mode Reporter mode to declare with
     181             :    *
     182             :    * @see ReporterTransferInterface
     183             :    */
     184             :   virtual void declareVectorClone(ReporterData & r_data,
     185             :                                   const ReporterName & r_name,
     186             :                                   const ReporterMode & mode,
     187             :                                   const MooseObject & producer) const = 0;
     188             : 
     189             :   /**
     190             :    * Helper for resizing vector data
     191             :    *
     192             :    * @param local_size Number of elements to resize vector to
     193             :    */
     194             :   virtual void resize(dof_id_type local_size) = 0;
     195             : 
     196             :   /**
     197             :    * Helper for clearing vector data
     198             :    */
     199             :   virtual void clear() = 0;
     200             : 
     201             :   /**
     202             :    * Helper for summing reporter value.
     203             :    */
     204             :   virtual void vectorSum() = 0;
     205             : 
     206             : protected:
     207             :   /**
     208             :    * Helper for checking whether or not the state \p state has only the modes \p modes.
     209             :    */
     210             :   void requiresConsumerModes(const ReporterStateBase & state,
     211             :                              const std::set<ReporterMode> & modes) const;
     212             : 
     213             :   /// The MooseObject that is producing this Reporter
     214             :   const MooseObject & _producer;
     215             : 
     216             :   /// Defines how the Reporter value can be produced and how it is being produced
     217             :   ReporterProducerEnum _producer_enum;
     218             : };
     219             : 
     220             : /**
     221             :  * General context that is called by all Reporter values to manage the old values.
     222             :  *
     223             :  * This is the default context object, the communication aspect includes inspecting the produced
     224             :  * mode against the consumed mode to be sure that the data is compatible or if automatic
     225             :  * communication can be done to make them compatible.
     226             :  */
     227             : template <typename T>
     228             : class ReporterContext : public ReporterContextBase
     229             : {
     230             : public:
     231             :   /**
     232             :    * Options for automatic parallel operations to perform by the default context
     233             :    */
     234             :   enum class AutoOperation
     235             :   {
     236             :     NONE,
     237             :     BROADCAST
     238             :   };
     239             : 
     240             :   ReporterContext(const libMesh::ParallelObject & other,
     241             :                   const MooseObject & producer,
     242             :                   ReporterState<T> & state);
     243             :   ReporterContext(const libMesh::ParallelObject & other,
     244             :                   const MooseObject & producer,
     245             :                   ReporterState<T> & state,
     246             :                   const T & default_value);
     247             : 
     248             :   /**
     249             :    * Return the name of the Reporter value
     250             :    */
     251      499440 :   const ReporterName & name() const override final { return _state.getReporterName(); }
     252             : 
     253             :   /**
     254             :    * Return a reference to the ReporterState object that is storing the Reporter value
     255             :    */
     256       60295 :   const ReporterState<T> & state() const { return _state; }
     257             : 
     258             :   /**
     259             :    * Return the type being stored by the associated ReporterState object.
     260             :    *
     261             :    * @see ReporterContext::storeInfo
     262             :    */
     263        4126 :   virtual std::string type() const override { return MooseUtils::prettyCppType<T>(); }
     264             : 
     265             :   /**
     266             :    * Perform automatic parallel communication based on the producer/consumer modes
     267             :    */
     268             :   virtual void finalize() override;
     269             : 
     270             :   /**
     271             :    * Perform type specific transfer
     272             :    *
     273             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     274             :    *       know of a better solution, if you have one please implement it.
     275             :    */
     276             :   virtual void transfer(ReporterData & r_data,
     277             :                         const ReporterName & r_name,
     278             :                         unsigned int time_index = 0) const override;
     279             : 
     280             :   /**
     281             :    * Perform type specific transfer to a vector
     282             :    *
     283             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     284             :    *       know of a better solution, if you have one please implement it.
     285             :    */
     286             :   virtual void transferToVector(ReporterData & r_data,
     287             :                                 const ReporterName & r_name,
     288             :                                 dof_id_type index,
     289             :                                 unsigned int time_index = 0) const override;
     290             : 
     291             :   /**
     292             :    * Perform type specific transfer from a vector
     293             :    *
     294             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     295             :    *       know of a better solution, if you have one please implement it.
     296             :    */
     297             :   virtual void transferFromVector(ReporterData & r_data,
     298             :                                   const ReporterName & r_name,
     299             :                                   dof_id_type index,
     300             :                                   unsigned int time_index = 0) const override;
     301             : 
     302             : protected:
     303        1074 :   void broadcast()
     304             :   {
     305             :     if constexpr (MooseUtils::canBroadcast<T>::value)
     306        1074 :       this->comm().broadcast(this->_state.value());
     307             :     else
     308           0 :       mooseError("Cannot broadcast Reporter type '", MooseUtils::prettyCppType<T>(), "'");
     309        1074 :   }
     310             : 
     311             :   /// Output meta data to JSON, see JSONOutput
     312             :   virtual void storeInfo(nlohmann::json & json) const override;
     313             : 
     314             :   /// Output data to JSON, see JSONOutput
     315             :   virtual void store(nlohmann::json & json) const override;
     316             : 
     317             :   virtual std::string contextType() const override = 0;
     318             : 
     319             :   // The following are called by the ReporterData and are not indented for external use
     320             :   virtual void copyValuesBack() override;
     321             : 
     322             :   /// Restore state to its old values. @see ReporterState::restoreState
     323        5001 :   virtual bool restoreState() override { return _state.restoreState(); }
     324             : 
     325             :   /// The state on which this context object operates
     326             :   ReporterState<T> & _state;
     327             : };
     328             : 
     329             : template <typename T>
     330       81761 : ReporterContext<T>::ReporterContext(const libMesh::ParallelObject & other,
     331             :                                     const MooseObject & producer,
     332        1666 :                                     ReporterState<T> & state)
     333       80095 :   : ReporterContextBase(other, producer), _state(state)
     334             : {
     335       81761 :   _producer_enum.insert(REPORTER_MODE_ROOT, REPORTER_MODE_REPLICATED, REPORTER_MODE_DISTRIBUTED);
     336       81761 : }
     337             : 
     338             : template <typename T>
     339        3982 : ReporterContext<T>::ReporterContext(const libMesh::ParallelObject & other,
     340             :                                     const MooseObject & producer,
     341             :                                     ReporterState<T> & state,
     342             :                                     const T & default_value)
     343        3982 :   : ReporterContext(other, producer, state)
     344             : {
     345        3982 :   _state.value() = default_value;
     346        3982 : }
     347             : 
     348             : template <typename T>
     349             : void
     350      567087 : ReporterContext<T>::finalize()
     351             : {
     352             :   // Automatic parallel operation to perform
     353      567087 :   ReporterContext::AutoOperation auto_operation = ReporterContext::AutoOperation::NONE;
     354             : 
     355             :   // Set the default producer mode to ROOT
     356      567087 :   if (!_producer_enum.isValid())
     357       50737 :     _producer_enum.assign(REPORTER_MODE_ROOT);
     358             : 
     359             :   // Determine auto parallel operation to perform
     360      567087 :   const auto & producer = _producer_enum; // convenience
     361      814037 :   for (const auto & pair : _state.getConsumers())
     362             :   {
     363      246956 :     const ReporterMode consumer = pair.first;
     364      246956 :     const MooseObject * moose_object = pair.second;
     365             : 
     366             :     // The following sets up the automatic operations and performs error checking for the various
     367             :     // modes for the producer and consumer
     368             :     //
     369             :     // The data is correct and requires no operation for the following conditions (PRODUCER ->
     370             :     // CONSUMER)
     371             :     //            ROOT -> ROOT
     372             :     //      REPLICATED -> REPLICATED
     373             :     //     DISTRIBUTED -> DISTRIBUTED
     374             :     //      REPLICATED -> ROOT
     375             : 
     376             :     // Perform broadcast in the case
     377             :     //            ROOT -> REPLICATED
     378      246956 :     if (static_cast<int>(producer) == REPORTER_MODE_ROOT && consumer == REPORTER_MODE_REPLICATED)
     379         855 :       auto_operation = ReporterContext::AutoOperation::BROADCAST;
     380             : 
     381             :     // The following are not support and create an error
     382             :     //            ROOT -> DISTRIBUTED
     383             :     //      REPLICATED -> DISTRIBUTED
     384             :     //     DISTRIBUTED -> ROOT
     385             :     //     DISTRIBUTED -> REPLICATED
     386      246101 :     else if ((static_cast<int>(producer) == REPORTER_MODE_ROOT &&
     387      485572 :               consumer == REPORTER_MODE_DISTRIBUTED) ||
     388      245824 :              (static_cast<int>(producer) == REPORTER_MODE_REPLICATED &&
     389      251894 :               consumer == REPORTER_MODE_DISTRIBUTED) ||
     390      245824 :              (static_cast<int>(producer) == REPORTER_MODE_DISTRIBUTED &&
     391      491654 :               consumer == REPORTER_MODE_ROOT) ||
     392      245821 :              (static_cast<int>(producer) == REPORTER_MODE_DISTRIBUTED &&
     393           3 :               consumer == REPORTER_MODE_REPLICATED))
     394           6 :       mooseError("The Reporter value \"",
     395             :                  name(),
     396             :                  "\" is being produced in ",
     397             :                  producer,
     398             :                  " mode, but the ",
     399             :                  moose_object->typeAndName(),
     400             :                  " is requesting to consume it in ",
     401             :                  consumer,
     402             :                  " mode, which is not supported.");
     403             :   }
     404             : 
     405             :   // Perform desired auto parallel operation
     406      567081 :   if (auto_operation == ReporterContext::AutoOperation::BROADCAST)
     407         825 :     this->broadcast();
     408      567081 : }
     409             : 
     410             : template <typename T>
     411             : void
     412      237556 : ReporterContext<T>::copyValuesBack()
     413             : {
     414      237556 :   _state.copyValuesBack();
     415      237556 : }
     416             : 
     417             : template <typename T>
     418             : void
     419        4126 : ReporterContext<T>::storeInfo(nlohmann::json & json) const
     420             : {
     421        4126 :   json["type"] = this->type();
     422        4126 : }
     423             : 
     424             : template <typename T>
     425             : void
     426        6752 : ReporterContext<T>::store(nlohmann::json & json) const
     427             : {
     428        6752 :   nlohmann::to_json(json, this->_state.value());
     429        6752 : }
     430             : 
     431             : template <typename T>
     432             : class ReporterGeneralContext : public ReporterContext<T>
     433             : {
     434             : public:
     435       75427 :   ReporterGeneralContext(const libMesh::ParallelObject & other,
     436             :                          const MooseObject & producer,
     437        1135 :                          ReporterState<T> & state)
     438       74292 :     : ReporterContext<T>(other, producer, state)
     439             :   {
     440       75427 :   }
     441        3982 :   ReporterGeneralContext(const libMesh::ParallelObject & other,
     442             :                          const MooseObject & producer,
     443             :                          ReporterState<T> & state,
     444             :                          const T & default_value)
     445        3982 :     : ReporterContext<T>(other, producer, state, default_value)
     446             :   {
     447        3982 :   }
     448             : 
     449             :   /**
     450             :    * Declare a reporter value of same type as this context.
     451             :    *
     452             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     453             :    *       know of a better solution, if you have one please implement it.
     454             :    */
     455             :   virtual void declareClone(ReporterData & r_data,
     456             :                             const ReporterName & r_name,
     457             :                             const ReporterMode & mode,
     458             :                             const MooseObject & producer) const override;
     459             :   /**
     460             :    * Declare a reporter value that is a vector of the same type as this context.
     461             :    *
     462             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     463             :    *       know of a better solution, if you have one please implement it.
     464             :    */
     465             :   virtual void declareVectorClone(ReporterData & r_data,
     466             :                                   const ReporterName & r_name,
     467             :                                   const ReporterMode & mode,
     468             :                                   const MooseObject & producer) const override;
     469             : 
     470             :   virtual void resize(dof_id_type local_size) final;
     471             :   virtual void clear() final;
     472             :   virtual void vectorSum() final;
     473             : 
     474          66 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     475             : };
     476             : 
     477             : //  Needed for compile-time checking if T is a vector.
     478             : template <typename>
     479             : struct is_std_vector : std::false_type
     480             : {
     481             : };
     482             : 
     483             : template <typename T, typename A>
     484             : struct is_std_vector<std::vector<T, A>> : std::true_type
     485             : {
     486             : };
     487             : 
     488             : template <typename T>
     489             : void
     490          66 : ReporterGeneralContext<T>::resize(dof_id_type size)
     491             : {
     492             :   if constexpr (is_std_vector<T>::value)
     493          66 :     this->_state.value().resize(size);
     494             :   else
     495             :   {
     496           0 :     libmesh_ignore(size);
     497           0 :     mooseError("Cannot resize non vector-type reporter values.");
     498             :   }
     499          66 : }
     500             : template <typename T>
     501             : void
     502          66 : ReporterGeneralContext<T>::clear()
     503             : {
     504             :   if constexpr (is_std_vector<T>::value)
     505          66 :     this->_state.value().clear();
     506             :   else
     507           0 :     mooseError("Cannot clear non vector-type reporter values.");
     508          66 : }
     509             : 
     510             : template <typename T>
     511             : void
     512          66 : ReporterGeneralContext<T>::vectorSum()
     513             : {
     514             :   // Case 1: T is a numeric type that we can sum (excluding bool)
     515             :   if constexpr (std::is_arithmetic<T>::value && !std::is_same<T, bool>::value)
     516             :   {
     517             :     // Perform summation of the scalar value across all processors
     518           0 :     this->comm().sum(this->_state.value());
     519           0 :     return;
     520             :   }
     521             :   // Case 2: T is a vector type
     522             :   else if constexpr (is_std_vector<T>::value)
     523             :   {
     524             :     using VectorValueType = typename T::value_type;
     525             : 
     526             :     // Check if the vector elements are of a numeric type
     527             :     if constexpr (std::is_arithmetic<VectorValueType>::value &&
     528             :                   !std::is_same<VectorValueType, bool>::value)
     529             :     {
     530             :       // Perform summation of the vector elements across all processors
     531          33 :       this->comm().sum(this->_state.value());
     532          33 :       return;
     533             :     }
     534             :     // Check if the vector elements are also vectors
     535             :     else if constexpr (is_std_vector<VectorValueType>::value)
     536             :     {
     537             :       using InnerValueType = typename VectorValueType::value_type;
     538             : 
     539             :       // Check if the inner vector elements are of a numeric type
     540             :       if constexpr (std::is_arithmetic<InnerValueType>::value &&
     541             :                     !std::is_same<InnerValueType, bool>::value)
     542             :       {
     543             : #ifdef DEBUG
     544             :         auto vec_size = this->_state.value().size();
     545             :         this->comm().max(vec_size);
     546             :         // Assert only passes on all ranks if they are all the same size.
     547             :         mooseAssert(this->_state.value().size() == vec_size,
     548             :                     "Reporter vector have different sizes on different ranks.");
     549             : #endif
     550             :         // Iterate over each inner vector in the outer vector
     551         165 :         for (auto & innerVector : this->_state.value())
     552             :         {
     553             :           // Get the maximum size of the inner vector across all processors
     554         132 :           dof_id_type maxInnerSize = innerVector.size();
     555         132 :           this->comm().max(maxInnerSize);
     556             : 
     557             :           // Resize the inner vector to the maximum size
     558         132 :           innerVector.resize(maxInnerSize);
     559             : 
     560             :           // Perform summation of the inner vector elements across all processors
     561         132 :           this->comm().sum(innerVector);
     562             :         }
     563          33 :         return;
     564             :       }
     565             :     }
     566             :   }
     567             : 
     568           0 :   mooseError("Cannot perform sum operation on non-numeric or unsupported vector types.");
     569             : }
     570             : 
     571             : /**
     572             :  * A context that broadcasts the Reporter value from the root processor
     573             :  */
     574             : template <typename T>
     575             : class ReporterBroadcastContext : public ReporterGeneralContext<T>
     576             : {
     577             : public:
     578             :   ReporterBroadcastContext(const libMesh::ParallelObject & other,
     579             :                            const MooseObject & producer,
     580             :                            ReporterState<T> & state);
     581             :   ReporterBroadcastContext(const libMesh::ParallelObject & other,
     582             :                            const MooseObject & producer,
     583             :                            ReporterState<T> & state,
     584             :                            const T & default_value);
     585             :   virtual void finalize() override;
     586           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     587             : };
     588             : 
     589             : template <typename T>
     590          90 : ReporterBroadcastContext<T>::ReporterBroadcastContext(const libMesh::ParallelObject & other,
     591             :                                                       const MooseObject & producer,
     592             :                                                       ReporterState<T> & state)
     593          90 :   : ReporterGeneralContext<T>(other, producer, state)
     594             : {
     595          90 :   this->_producer_enum.clear();
     596          90 :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     597          90 : }
     598             : 
     599             : template <typename T>
     600             : ReporterBroadcastContext<T>::ReporterBroadcastContext(const libMesh::ParallelObject & other,
     601             :                                                       const MooseObject & producer,
     602             :                                                       ReporterState<T> & state,
     603             :                                                       const T & default_value)
     604             :   : ReporterGeneralContext<T>(other, producer, state, default_value)
     605             : {
     606             :   this->_producer_enum.clear();
     607             :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     608             : }
     609             : 
     610             : template <typename T>
     611             : void
     612         249 : ReporterBroadcastContext<T>::finalize()
     613             : {
     614         996 :   this->requiresConsumerModes(this->_state, {REPORTER_MODE_UNSET, REPORTER_MODE_REPLICATED});
     615         249 :   this->broadcast();
     616         498 : }
     617             : 
     618             : /**
     619             :  * A context that scatters the Reporter value from the root processor
     620             :  */
     621             : template <typename T>
     622             : class ReporterScatterContext : public ReporterGeneralContext<T>
     623             : {
     624             : public:
     625             :   ReporterScatterContext(const libMesh::ParallelObject & other,
     626             :                          const MooseObject & producer,
     627             :                          ReporterState<T> & state,
     628             :                          const std::vector<T> & values);
     629             :   ReporterScatterContext(const libMesh::ParallelObject & other,
     630             :                          const MooseObject & producer,
     631             :                          ReporterState<T> & state,
     632             :                          const T & default_value,
     633             :                          const std::vector<T> & values);
     634             : 
     635             :   virtual void finalize() override;
     636           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     637             : 
     638             : private:
     639             :   /// The values to scatter
     640             :   const std::vector<T> & _values;
     641             : };
     642             : 
     643             : template <typename T>
     644          90 : ReporterScatterContext<T>::ReporterScatterContext(const libMesh::ParallelObject & other,
     645             :                                                   const MooseObject & producer,
     646             :                                                   ReporterState<T> & state,
     647             :                                                   const std::vector<T> & values)
     648          90 :   : ReporterGeneralContext<T>(other, producer, state), _values(values)
     649             : {
     650          90 :   this->_producer_enum.clear();
     651          90 :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     652          90 : }
     653             : 
     654             : template <typename T>
     655             : ReporterScatterContext<T>::ReporterScatterContext(const libMesh::ParallelObject & other,
     656             :                                                   const MooseObject & producer,
     657             :                                                   ReporterState<T> & state,
     658             :                                                   const T & default_value,
     659             :                                                   const std::vector<T> & values)
     660             :   : ReporterGeneralContext<T>(other, producer, state, default_value), _values(values)
     661             : {
     662             :   this->_producer_enum.clear();
     663             :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     664             : }
     665             : 
     666             : template <typename T>
     667             : void
     668         243 : ReporterScatterContext<T>::finalize()
     669             : {
     670         972 :   this->requiresConsumerModes(this->_state, {REPORTER_MODE_UNSET, REPORTER_MODE_REPLICATED});
     671             : 
     672             :   mooseAssert(this->processor_id() == 0 ? _values.size() == this->n_processors() : true,
     673             :               "Vector to be scattered must be sized to match the number of processors");
     674             :   mooseAssert(
     675             :       this->processor_id() > 0 ? _values.size() == 0 : true,
     676             :       "Vector to be scattered must be sized to zero on processors except for the root processor");
     677         243 :   this->comm().scatter(_values, this->_state.value());
     678         486 : }
     679             : 
     680             : /**
     681             :  * A context that gathers the Reporter value to the root processor
     682             :  */
     683             : template <typename T>
     684             : class ReporterGatherContext : public ReporterGeneralContext<T>
     685             : {
     686             : public:
     687             :   ReporterGatherContext(const libMesh::ParallelObject & other,
     688             :                         const MooseObject & producer,
     689             :                         ReporterState<T> & state);
     690             :   ReporterGatherContext(const libMesh::ParallelObject & other,
     691             :                         const MooseObject & producer,
     692             :                         ReporterState<T> & state,
     693             :                         const T & default_value);
     694             : 
     695             :   virtual void finalize() override;
     696           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     697             : };
     698             : 
     699             : template <typename T>
     700         120 : ReporterGatherContext<T>::ReporterGatherContext(const libMesh::ParallelObject & other,
     701             :                                                 const MooseObject & producer,
     702             :                                                 ReporterState<T> & state)
     703         120 :   : ReporterGeneralContext<T>(other, producer, state)
     704             : {
     705         120 :   this->_producer_enum.clear();
     706         120 :   this->_producer_enum.insert(REPORTER_MODE_DISTRIBUTED);
     707         120 : }
     708             : 
     709             : template <typename T>
     710             : ReporterGatherContext<T>::ReporterGatherContext(const libMesh::ParallelObject & other,
     711             :                                                 const MooseObject & producer,
     712             :                                                 ReporterState<T> & state,
     713             :                                                 const T & default_value)
     714             :   : ReporterGeneralContext<T>(other, producer, state, default_value)
     715             : {
     716             :   this->_producer_enum.clear();
     717             :   this->_producer_enum.insert(REPORTER_MODE_DISTRIBUTED);
     718             : }
     719             : 
     720             : template <typename T>
     721             : void
     722         273 : ReporterGatherContext<T>::finalize()
     723             : {
     724        1092 :   this->requiresConsumerModes(this->_state, {REPORTER_MODE_UNSET, REPORTER_MODE_ROOT});
     725         273 :   this->comm().gather(0, this->_state.value());
     726         546 : }
     727             : 
     728             : /**
     729             :  * This context is specific for vector types of reporters, mainly for declaring a vector
     730             :  * of the type from another context. As well as resizing the vector of data.
     731             :  *
     732             :  * @see ReporterGeneralContext::declareVectorClone and ReporterTransferInterface
     733             :  */
     734             : template <typename T>
     735             : class ReporterVectorContext : public ReporterContext<std::vector<T>>
     736             : {
     737             : public:
     738             :   ReporterVectorContext(const libMesh::ParallelObject & other,
     739             :                         const MooseObject & producer,
     740             :                         ReporterState<std::vector<T>> & state);
     741             :   ReporterVectorContext(const libMesh::ParallelObject & other,
     742             :                         const MooseObject & producer,
     743             :                         ReporterState<std::vector<T>> & state,
     744             :                         const std::vector<T> & default_value);
     745             : 
     746             :   /**
     747             :    * This simply throws an error to avoid infinite instantiations.
     748             :    * It is defined in ReporterData.h to avoid cyclic included.
     749             :    */
     750             :   virtual void declareClone(ReporterData & r_data,
     751             :                             const ReporterName & r_name,
     752             :                             const ReporterMode & mode,
     753             :                             const MooseObject & producer) const final;
     754             : 
     755             :   /**
     756             :    * This simply throws an error to avoid infinite instantiations.
     757             :    * It is defined in ReporterData.h to avoid cyclic included.
     758             :    */
     759             :   virtual void declareVectorClone(ReporterData & r_data,
     760             :                                   const ReporterName & r_name,
     761             :                                   const ReporterMode & mode,
     762             :                                   const MooseObject & producer) const final;
     763             : 
     764             :   /**
     765             :    * Since we know that the _state value is a vector type, we can resize it based
     766             :    * on @param local_size
     767             :    */
     768         377 :   virtual void resize(dof_id_type local_size) override { this->_state.value().resize(local_size); }
     769             : 
     770             :   /**
     771             :    * Since we know that the _state value is a vector type, we can clear it.
     772             :    */
     773           0 :   virtual void clear() override { this->_state.value().clear(); }
     774             : 
     775           0 :   virtual void vectorSum() override
     776             :   {
     777             :     // Case 1: T is type that we can sum
     778             :     if constexpr (std::is_arithmetic<T>::value &&
     779             :                   !std::is_same<T, bool>::value) // We can't sum bools.
     780             :     {
     781             :       // Resize vector to max size
     782           0 :       dof_id_type vec_size = this->_state.value().size();
     783           0 :       this->comm().max(vec_size);
     784           0 :       this->_state.value().resize(vec_size);
     785             : 
     786           0 :       this->comm().sum(this->_state.value());
     787           0 :       return;
     788             :     }
     789             :     // Case 2: T is a vector
     790             :     else if constexpr (is_std_vector<T>::value)
     791             :     {
     792             :       // Resize vector to max size
     793           0 :       dof_id_type vec_size = this->_state.value().size();
     794           0 :       this->comm().max(vec_size);
     795           0 :       this->_state.value().resize(vec_size);
     796             : 
     797             :       using ValueType = typename T::value_type;
     798             :       // Check if the ValueType is a vector
     799             :       if constexpr (std::is_arithmetic<ValueType>::value && !std::is_same<ValueType, bool>::value)
     800             :       {
     801             : #ifdef DEBUG
     802             :         auto vec_size = this->_state.value().size();
     803             :         this->comm().max(vec_size);
     804             :         // Assert only passes on all ranks if they are all the same size.
     805             :         mooseAssert(this->_state.value().size() == vec_size,
     806             :                     "Reporter vector have different sizes on different ranks.");
     807             : #endif
     808           0 :         for (auto & val_vec : this->_state.value())
     809             :         {
     810             :           // Resize vector to max size
     811           0 :           dof_id_type val_vec_size = val_vec.size();
     812           0 :           this->comm().max(val_vec_size);
     813           0 :           val_vec.resize(val_vec_size);
     814             : 
     815           0 :           this->comm().sum(val_vec);
     816             :         }
     817           0 :         return;
     818             :       }
     819             :     }
     820             :     // If we don't perform a summing operation, error out.
     821           0 :     mooseError("Cannot perform sum operation on non-numeric or unsupported vector types.");
     822             :   }
     823             : 
     824           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     825             : };
     826             : 
     827             : template <typename T>
     828        2352 : ReporterVectorContext<T>::ReporterVectorContext(const libMesh::ParallelObject & other,
     829             :                                                 const MooseObject & producer,
     830           2 :                                                 ReporterState<std::vector<T>> & state)
     831        2350 :   : ReporterContext<std::vector<T>>(other, producer, state)
     832             : {
     833        2352 : }
     834             : 
     835             : template <typename T>
     836             : ReporterVectorContext<T>::ReporterVectorContext(const libMesh::ParallelObject & other,
     837             :                                                 const MooseObject & producer,
     838             :                                                 ReporterState<std::vector<T>> & state,
     839             :                                                 const std::vector<T> & default_value)
     840             :   : ReporterContext<std::vector<T>>(other, producer, state, default_value)
     841             : {
     842             : }

Generated by: LCOV version 1.14