LCOV - code coverage report
Current view: top level - include/reporters - ReporterContext.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 97 125 77.6 %
Date: 2025-07-17 01:28:37 Functions: 245 618 39.6 %
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       73993 :   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         148 :   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      468564 :   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       56185 :   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        3490 :   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         993 :   void broadcast()
     304             :   {
     305             :     if constexpr (MooseUtils::canBroadcast<T>::value)
     306         993 :       this->comm().broadcast(this->_state.value());
     307             :     else
     308           0 :       mooseError("Cannot broadcast Reporter type '", MooseUtils::prettyCppType<T>(), "'");
     309         993 :   }
     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        9618 :   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       77625 : ReporterContext<T>::ReporterContext(const libMesh::ParallelObject & other,
     331             :                                     const MooseObject & producer,
     332             :                                     ReporterState<T> & state)
     333       77625 :   : ReporterContextBase(other, producer), _state(state)
     334             : {
     335       77625 :   _producer_enum.insert(REPORTER_MODE_ROOT, REPORTER_MODE_REPLICATED, REPORTER_MODE_DISTRIBUTED);
     336       77625 : }
     337             : 
     338             : template <typename T>
     339        3590 : ReporterContext<T>::ReporterContext(const libMesh::ParallelObject & other,
     340             :                                     const MooseObject & producer,
     341             :                                     ReporterState<T> & state,
     342             :                                     const T & default_value)
     343        3590 :   : ReporterContext(other, producer, state)
     344             : {
     345        3590 :   _state.value() = default_value;
     346        3590 : }
     347             : 
     348             : template <typename T>
     349             : void
     350      517956 : ReporterContext<T>::finalize()
     351             : {
     352             :   // Automatic parallel operation to perform
     353      517956 :   ReporterContext::AutoOperation auto_operation = ReporterContext::AutoOperation::NONE;
     354             : 
     355             :   // Set the default producer mode to ROOT
     356      517956 :   if (!_producer_enum.isValid())
     357       49314 :     _producer_enum.assign(REPORTER_MODE_ROOT);
     358             : 
     359             :   // Determine auto parallel operation to perform
     360      517956 :   const auto & producer = _producer_enum; // convenience
     361      751001 :   for (const auto & pair : _state.getConsumers())
     362             :   {
     363      233053 :     const ReporterMode consumer = pair.first;
     364      233053 :     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      233053 :     if (producer == REPORTER_MODE_ROOT && consumer == REPORTER_MODE_REPLICATED)
     379         765 :       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      458722 :     else if ((producer == REPORTER_MODE_ROOT && consumer == REPORTER_MODE_DISTRIBUTED) ||
     387      232288 :              (producer == REPORTER_MODE_REPLICATED && consumer == REPORTER_MODE_DISTRIBUTED) ||
     388      696860 :              (producer == REPORTER_MODE_DISTRIBUTED && consumer == REPORTER_MODE_ROOT) ||
     389      232284 :              (producer == REPORTER_MODE_DISTRIBUTED && consumer == REPORTER_MODE_REPLICATED))
     390           8 :       mooseError("The Reporter value \"",
     391             :                  name(),
     392             :                  "\" is being produced in ",
     393             :                  producer,
     394             :                  " mode, but the ",
     395             :                  moose_object->typeAndName(),
     396             :                  " is requesting to consume it in ",
     397             :                  consumer,
     398             :                  " mode, which is not supported.");
     399             :   }
     400             : 
     401             :   // Perform desired auto parallel operation
     402      517948 :   if (auto_operation == ReporterContext::AutoOperation::BROADCAST)
     403         735 :     this->broadcast();
     404      517948 : }
     405             : 
     406             : template <typename T>
     407             : void
     408      229607 : ReporterContext<T>::copyValuesBack()
     409             : {
     410      229607 :   _state.copyValuesBack();
     411      229607 : }
     412             : 
     413             : template <typename T>
     414             : void
     415        3490 : ReporterContext<T>::storeInfo(nlohmann::json & json) const
     416             : {
     417        3490 :   json["type"] = this->type();
     418        3490 : }
     419             : 
     420             : template <typename T>
     421             : void
     422        5730 : ReporterContext<T>::store(nlohmann::json & json) const
     423             : {
     424        5730 :   nlohmann::to_json(json, this->_state.value());
     425        5730 : }
     426             : 
     427             : template <typename T>
     428             : class ReporterGeneralContext : public ReporterContext<T>
     429             : {
     430             : public:
     431       71946 :   ReporterGeneralContext(const libMesh::ParallelObject & other,
     432             :                          const MooseObject & producer,
     433             :                          ReporterState<T> & state)
     434       71946 :     : ReporterContext<T>(other, producer, state)
     435             :   {
     436       71946 :   }
     437        3590 :   ReporterGeneralContext(const libMesh::ParallelObject & other,
     438             :                          const MooseObject & producer,
     439             :                          ReporterState<T> & state,
     440             :                          const T & default_value)
     441        3590 :     : ReporterContext<T>(other, producer, state, default_value)
     442             :   {
     443        3590 :   }
     444             : 
     445             :   /**
     446             :    * Declare a reporter value of same type as this context.
     447             :    *
     448             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     449             :    *       know of a better solution, if you have one please implement it.
     450             :    */
     451             :   virtual void declareClone(ReporterData & r_data,
     452             :                             const ReporterName & r_name,
     453             :                             const ReporterMode & mode,
     454             :                             const MooseObject & producer) const override;
     455             :   /**
     456             :    * Declare a reporter value that is a vector of the same type as this context.
     457             :    *
     458             :    * NOTE: This is defined in ReporterData.h to avoid cyclic includes that would arise. I don't
     459             :    *       know of a better solution, if you have one please implement it.
     460             :    */
     461             :   virtual void declareVectorClone(ReporterData & r_data,
     462             :                                   const ReporterName & r_name,
     463             :                                   const ReporterMode & mode,
     464             :                                   const MooseObject & producer) const override;
     465             : 
     466             :   virtual void resize(dof_id_type local_size) final;
     467             :   virtual void clear() final;
     468             :   virtual void vectorSum() final;
     469             : 
     470          74 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     471             : };
     472             : 
     473             : //  Needed for compile-time checking if T is a vector.
     474             : template <typename>
     475             : struct is_std_vector : std::false_type
     476             : {
     477             : };
     478             : 
     479             : template <typename T, typename A>
     480             : struct is_std_vector<std::vector<T, A>> : std::true_type
     481             : {
     482             : };
     483             : 
     484             : template <typename T>
     485             : void
     486          66 : ReporterGeneralContext<T>::resize(dof_id_type size)
     487             : {
     488             :   if constexpr (is_std_vector<T>::value)
     489          66 :     this->_state.value().resize(size);
     490             :   else
     491             :   {
     492           0 :     libmesh_ignore(size);
     493           0 :     mooseError("Cannot resize non vector-type reporter values.");
     494             :   }
     495          66 : }
     496             : template <typename T>
     497             : void
     498          66 : ReporterGeneralContext<T>::clear()
     499             : {
     500             :   if constexpr (is_std_vector<T>::value)
     501          66 :     this->_state.value().clear();
     502             :   else
     503           0 :     mooseError("Cannot clear non vector-type reporter values.");
     504          66 : }
     505             : 
     506             : template <typename T>
     507             : void
     508          66 : ReporterGeneralContext<T>::vectorSum()
     509             : {
     510             :   // Case 1: T is a numeric type that we can sum (excluding bool)
     511             :   if constexpr (std::is_arithmetic<T>::value && !std::is_same<T, bool>::value)
     512             :   {
     513             :     // Perform summation of the scalar value across all processors
     514           0 :     this->comm().sum(this->_state.value());
     515           0 :     return;
     516             :   }
     517             :   // Case 2: T is a vector type
     518             :   else if constexpr (is_std_vector<T>::value)
     519             :   {
     520             :     using VectorValueType = typename T::value_type;
     521             : 
     522             :     // Check if the vector elements are of a numeric type
     523             :     if constexpr (std::is_arithmetic<VectorValueType>::value &&
     524             :                   !std::is_same<VectorValueType, bool>::value)
     525             :     {
     526             :       // Perform summation of the vector elements across all processors
     527          33 :       this->comm().sum(this->_state.value());
     528          33 :       return;
     529             :     }
     530             :     // Check if the vector elements are also vectors
     531             :     else if constexpr (is_std_vector<VectorValueType>::value)
     532             :     {
     533             :       using InnerValueType = typename VectorValueType::value_type;
     534             : 
     535             :       // Check if the inner vector elements are of a numeric type
     536             :       if constexpr (std::is_arithmetic<InnerValueType>::value &&
     537             :                     !std::is_same<InnerValueType, bool>::value)
     538             :       {
     539             : #ifdef DEBUG
     540             :         auto vec_size = this->_state.value().size();
     541             :         this->comm().max(vec_size);
     542             :         // Assert only passes on all ranks if they are all the same size.
     543             :         mooseAssert(this->_state.value().size() == vec_size,
     544             :                     "Reporter vector have different sizes on different ranks.");
     545             : #endif
     546             :         // Iterate over each inner vector in the outer vector
     547         165 :         for (auto & innerVector : this->_state.value())
     548             :         {
     549             :           // Get the maximum size of the inner vector across all processors
     550         132 :           dof_id_type maxInnerSize = innerVector.size();
     551         132 :           this->comm().max(maxInnerSize);
     552             : 
     553             :           // Resize the inner vector to the maximum size
     554         132 :           innerVector.resize(maxInnerSize);
     555             : 
     556             :           // Perform summation of the inner vector elements across all processors
     557         132 :           this->comm().sum(innerVector);
     558             :         }
     559          33 :         return;
     560             :       }
     561             :     }
     562             :   }
     563             : 
     564           0 :   mooseError("Cannot perform sum operation on non-numeric or unsupported vector types.");
     565             : }
     566             : 
     567             : /**
     568             :  * A context that broadcasts the Reporter value from the root processor
     569             :  */
     570             : template <typename T>
     571             : class ReporterBroadcastContext : public ReporterGeneralContext<T>
     572             : {
     573             : public:
     574             :   ReporterBroadcastContext(const libMesh::ParallelObject & other,
     575             :                            const MooseObject & producer,
     576             :                            ReporterState<T> & state);
     577             :   ReporterBroadcastContext(const libMesh::ParallelObject & other,
     578             :                            const MooseObject & producer,
     579             :                            ReporterState<T> & state,
     580             :                            const T & default_value);
     581             :   virtual void finalize() override;
     582           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     583             : };
     584             : 
     585             : template <typename T>
     586          95 : ReporterBroadcastContext<T>::ReporterBroadcastContext(const libMesh::ParallelObject & other,
     587             :                                                       const MooseObject & producer,
     588             :                                                       ReporterState<T> & state)
     589          95 :   : ReporterGeneralContext<T>(other, producer, state)
     590             : {
     591          95 :   this->_producer_enum.clear();
     592          95 :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     593          95 : }
     594             : 
     595             : template <typename T>
     596             : ReporterBroadcastContext<T>::ReporterBroadcastContext(const libMesh::ParallelObject & other,
     597             :                                                       const MooseObject & producer,
     598             :                                                       ReporterState<T> & state,
     599             :                                                       const T & default_value)
     600             :   : ReporterGeneralContext<T>(other, producer, state, default_value)
     601             : {
     602             :   this->_producer_enum.clear();
     603             :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     604             : }
     605             : 
     606             : template <typename T>
     607             : void
     608         258 : ReporterBroadcastContext<T>::finalize()
     609             : {
     610         774 :   this->requiresConsumerModes(this->_state, {REPORTER_MODE_UNSET, REPORTER_MODE_REPLICATED});
     611         258 :   this->broadcast();
     612         516 : }
     613             : 
     614             : /**
     615             :  * A context that scatters the Reporter value from the root processor
     616             :  */
     617             : template <typename T>
     618             : class ReporterScatterContext : public ReporterGeneralContext<T>
     619             : {
     620             : public:
     621             :   ReporterScatterContext(const libMesh::ParallelObject & other,
     622             :                          const MooseObject & producer,
     623             :                          ReporterState<T> & state,
     624             :                          const std::vector<T> & values);
     625             :   ReporterScatterContext(const libMesh::ParallelObject & other,
     626             :                          const MooseObject & producer,
     627             :                          ReporterState<T> & state,
     628             :                          const T & default_value,
     629             :                          const std::vector<T> & values);
     630             : 
     631             :   virtual void finalize() override;
     632           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     633             : 
     634             : private:
     635             :   /// The values to scatter
     636             :   const std::vector<T> & _values;
     637             : };
     638             : 
     639             : template <typename T>
     640          95 : ReporterScatterContext<T>::ReporterScatterContext(const libMesh::ParallelObject & other,
     641             :                                                   const MooseObject & producer,
     642             :                                                   ReporterState<T> & state,
     643             :                                                   const std::vector<T> & values)
     644          95 :   : ReporterGeneralContext<T>(other, producer, state), _values(values)
     645             : {
     646          95 :   this->_producer_enum.clear();
     647          95 :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     648          95 : }
     649             : 
     650             : template <typename T>
     651             : ReporterScatterContext<T>::ReporterScatterContext(const libMesh::ParallelObject & other,
     652             :                                                   const MooseObject & producer,
     653             :                                                   ReporterState<T> & state,
     654             :                                                   const T & default_value,
     655             :                                                   const std::vector<T> & values)
     656             :   : ReporterGeneralContext<T>(other, producer, state, default_value), _values(values)
     657             : {
     658             :   this->_producer_enum.clear();
     659             :   this->_producer_enum.insert(REPORTER_MODE_ROOT);
     660             : }
     661             : 
     662             : template <typename T>
     663             : void
     664         250 : ReporterScatterContext<T>::finalize()
     665             : {
     666         750 :   this->requiresConsumerModes(this->_state, {REPORTER_MODE_UNSET, REPORTER_MODE_REPLICATED});
     667             : 
     668             :   mooseAssert(this->processor_id() == 0 ? _values.size() == this->n_processors() : true,
     669             :               "Vector to be scattered must be sized to match the number of processors");
     670             :   mooseAssert(
     671             :       this->processor_id() > 0 ? _values.size() == 0 : true,
     672             :       "Vector to be scattered must be sized to zero on processors except for the root processor");
     673         250 :   this->comm().scatter(_values, this->_state.value());
     674         500 : }
     675             : 
     676             : /**
     677             :  * A context that gathers the Reporter value to the root processor
     678             :  */
     679             : template <typename T>
     680             : class ReporterGatherContext : public ReporterGeneralContext<T>
     681             : {
     682             : public:
     683             :   ReporterGatherContext(const libMesh::ParallelObject & other,
     684             :                         const MooseObject & producer,
     685             :                         ReporterState<T> & state);
     686             :   ReporterGatherContext(const libMesh::ParallelObject & other,
     687             :                         const MooseObject & producer,
     688             :                         ReporterState<T> & state,
     689             :                         const T & default_value);
     690             : 
     691             :   virtual void finalize() override;
     692           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     693             : };
     694             : 
     695             : template <typename T>
     696         125 : ReporterGatherContext<T>::ReporterGatherContext(const libMesh::ParallelObject & other,
     697             :                                                 const MooseObject & producer,
     698             :                                                 ReporterState<T> & state)
     699         125 :   : ReporterGeneralContext<T>(other, producer, state)
     700             : {
     701         125 :   this->_producer_enum.clear();
     702         125 :   this->_producer_enum.insert(REPORTER_MODE_DISTRIBUTED);
     703         125 : }
     704             : 
     705             : template <typename T>
     706             : ReporterGatherContext<T>::ReporterGatherContext(const libMesh::ParallelObject & other,
     707             :                                                 const MooseObject & producer,
     708             :                                                 ReporterState<T> & state,
     709             :                                                 const T & default_value)
     710             :   : ReporterGeneralContext<T>(other, producer, state, default_value)
     711             : {
     712             :   this->_producer_enum.clear();
     713             :   this->_producer_enum.insert(REPORTER_MODE_DISTRIBUTED);
     714             : }
     715             : 
     716             : template <typename T>
     717             : void
     718         280 : ReporterGatherContext<T>::finalize()
     719             : {
     720         840 :   this->requiresConsumerModes(this->_state, {REPORTER_MODE_UNSET, REPORTER_MODE_ROOT});
     721         280 :   this->comm().gather(0, this->_state.value());
     722         560 : }
     723             : 
     724             : /**
     725             :  * This context is specific for vector types of reporters, mainly for declaring a vector
     726             :  * of the type from another context. As well as resizing the vector of data.
     727             :  *
     728             :  * @see ReporterGeneralContext::declareVectorClone and ReporterTransferInterface
     729             :  */
     730             : template <typename T>
     731             : class ReporterVectorContext : public ReporterContext<std::vector<T>>
     732             : {
     733             : public:
     734             :   ReporterVectorContext(const libMesh::ParallelObject & other,
     735             :                         const MooseObject & producer,
     736             :                         ReporterState<std::vector<T>> & state);
     737             :   ReporterVectorContext(const libMesh::ParallelObject & other,
     738             :                         const MooseObject & producer,
     739             :                         ReporterState<std::vector<T>> & state,
     740             :                         const std::vector<T> & default_value);
     741             : 
     742             :   /**
     743             :    * This simply throws an error to avoid infinite instantiations.
     744             :    * It is defined in ReporterData.h to avoid cyclic included.
     745             :    */
     746             :   virtual void declareClone(ReporterData & r_data,
     747             :                             const ReporterName & r_name,
     748             :                             const ReporterMode & mode,
     749             :                             const MooseObject & producer) const final;
     750             : 
     751             :   /**
     752             :    * This simply throws an error to avoid infinite instantiations.
     753             :    * It is defined in ReporterData.h to avoid cyclic included.
     754             :    */
     755             :   virtual void declareVectorClone(ReporterData & r_data,
     756             :                                   const ReporterName & r_name,
     757             :                                   const ReporterMode & mode,
     758             :                                   const MooseObject & producer) const final;
     759             : 
     760             :   /**
     761             :    * Since we know that the _state value is a vector type, we can resize it based
     762             :    * on @param local_size
     763             :    */
     764         387 :   virtual void resize(dof_id_type local_size) override { this->_state.value().resize(local_size); }
     765             : 
     766             :   /**
     767             :    * Since we know that the _state value is a vector type, we can clear it.
     768             :    */
     769           0 :   virtual void clear() override { this->_state.value().clear(); }
     770             : 
     771           0 :   virtual void vectorSum() override
     772             :   {
     773             :     // Case 1: T is type that we can sum
     774             :     if constexpr (std::is_arithmetic<T>::value &&
     775             :                   !std::is_same<T, bool>::value) // We can't sum bools.
     776             :     {
     777             :       // Resize vector to max size
     778           0 :       dof_id_type vec_size = this->_state.value().size();
     779           0 :       this->comm().max(vec_size);
     780           0 :       this->_state.value().resize(vec_size);
     781             : 
     782           0 :       this->comm().sum(this->_state.value());
     783           0 :       return;
     784             :     }
     785             :     // Case 2: T is a vector
     786             :     else if constexpr (is_std_vector<T>::value)
     787             :     {
     788             :       // Resize vector to max size
     789           0 :       dof_id_type vec_size = this->_state.value().size();
     790           0 :       this->comm().max(vec_size);
     791           0 :       this->_state.value().resize(vec_size);
     792             : 
     793             :       using ValueType = typename T::value_type;
     794             :       // Check if the ValueType is a vector
     795             :       if constexpr (std::is_arithmetic<ValueType>::value && !std::is_same<ValueType, bool>::value)
     796             :       {
     797             : #ifdef DEBUG
     798             :         auto vec_size = this->_state.value().size();
     799             :         this->comm().max(vec_size);
     800             :         // Assert only passes on all ranks if they are all the same size.
     801             :         mooseAssert(this->_state.value().size() == vec_size,
     802             :                     "Reporter vector have different sizes on different ranks.");
     803             : #endif
     804           0 :         for (auto & val_vec : this->_state.value())
     805             :         {
     806             :           // Resize vector to max size
     807           0 :           dof_id_type val_vec_size = val_vec.size();
     808           0 :           this->comm().max(val_vec_size);
     809           0 :           val_vec.resize(val_vec_size);
     810             : 
     811           0 :           this->comm().sum(val_vec);
     812             :         }
     813           0 :         return;
     814             :       }
     815             :     }
     816             :     // If we don't perform a summing operation, error out.
     817           0 :     mooseError("Cannot perform sum operation on non-numeric or unsupported vector types.");
     818             :   }
     819             : 
     820           0 :   virtual std::string contextType() const override { return MooseUtils::prettyCppType(this); }
     821             : };
     822             : 
     823             : template <typename T>
     824        2089 : ReporterVectorContext<T>::ReporterVectorContext(const libMesh::ParallelObject & other,
     825             :                                                 const MooseObject & producer,
     826             :                                                 ReporterState<std::vector<T>> & state)
     827        2089 :   : ReporterContext<std::vector<T>>(other, producer, state)
     828             : {
     829        2089 : }
     830             : 
     831             : template <typename T>
     832             : ReporterVectorContext<T>::ReporterVectorContext(const libMesh::ParallelObject & other,
     833             :                                                 const MooseObject & producer,
     834             :                                                 ReporterState<std::vector<T>> & state,
     835             :                                                 const std::vector<T> & default_value)
     836             :   : ReporterContext<std::vector<T>>(other, producer, state, default_value)
     837             : {
     838             : }

Generated by: LCOV version 1.14