LCOV - code coverage report
Current view: top level - include/samplers - Sampler.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 1 4 25.0 %
Date: 2026-05-29 20:35:17 Functions: 1 3 33.3 %
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             : 
      10             : #pragma once
      11             : 
      12             : #include "Shuffle.h"
      13             : #include "DenseMatrix.h"
      14             : #include "MooseObject.h"
      15             : #include "MooseRandom.h"
      16             : #include "SetupInterface.h"
      17             : #include "DistributionInterface.h"
      18             : #include "PerfGraphInterface.h"
      19             : #include "SamplerInterface.h"
      20             : #include "MultiApp.h"
      21             : #include "VectorPostprocessorInterface.h"
      22             : #include "ReporterInterface.h"
      23             : #include "MooseRandomStateless.h"
      24             : 
      25             : /**
      26             :  * This is the base class for Samplers as used within the Stochastic Tools module.
      27             :  *
      28             :  * A sampler is responsible for sampling distributions and providing an API for providing
      29             :  * the sample data to objects. The sampler is designed to handle any number of random number
      30             :  * generators.
      31             :  *
      32             :  * The main methods in this object is the getNextLocalRow/getSamples/getLocalSamples methods which
      33             :  * return the distribution samples. These methods will return the same results for each call
      34             :  * regardless of the number of calls, with getNextLocalRow being the exception because it is
      35             :  * designed be used in an iterative approach.
      36             :  *
      37             :  * Samplers support the use of "execute_on", which when called results in new set of random numbers,
      38             :  * thus after execute() calls to getSamples/getLocalSamples() methods will now produce a new set of
      39             :  * random numbers from calls prior to the execute() call.
      40             :  *
      41             :  * Not for MOOSE developers: Great care was taken to design the structure of this class to limit
      42             :  * access to the critical portions of this object while making it extensible. Please consider
      43             :  * carefully the impacts of altering the API.
      44             :  */
      45             : class Sampler : public MooseObject,
      46             :                 public SetupInterface,
      47             :                 public DistributionInterface,
      48             :                 public PerfGraphInterface,
      49             :                 public SamplerInterface,
      50             :                 public VectorPostprocessorInterface,
      51             :                 public ReporterInterface
      52             : {
      53             : public:
      54             :   enum class SampleMode
      55             :   {
      56             :     GLOBAL = 0,
      57             :     LOCAL = 1
      58             :   };
      59             : 
      60             :   static InputParameters validParams();
      61             :   Sampler(const InputParameters & parameters);
      62             : 
      63             :   // The public members define the API that is exposed to application developers that are using
      64             :   // Sampler objects to perform calculations, so be very careful when adding items here since
      65             :   // they are exposed to any other object via the SamplerInterface.
      66             :   //
      67             :   // It is also important to point out that when Sampler objects, when used, are not const. This is
      68             :   // due to the fact that calling the various get methods below must store various pieces of data as
      69             :   // well as control the state of the random number generators.
      70             : 
      71             :   ///@{
      72             :   /**
      73             :    * Return the sampled complete or distributed sample data.
      74             :    *
      75             :    * Use these with caution as they can result in a large amount of memory use, the preferred
      76             :    * method for accessing Sampler data is the getNextLocalRow() method.
      77             :    */
      78             :   DenseMatrix<Real> getGlobalSamples();
      79             :   DenseMatrix<Real> getLocalSamples();
      80             :   ///@}
      81             : 
      82             :   /**
      83             :    * Return the "next" local row. This is designed to be used within a loop using the
      84             :    * getLocalRowBegin/End methods as such:
      85             :    *
      86             :    * for (dof_id_type i = getLocalRowBegin(); i < getLocalRowEnd(); ++i)
      87             :    *     std::vector<Real> row = getNextLocalRow();
      88             :    *
      89             :    * This is the preferred method for accessing Sampler data.
      90             :    *
      91             :    * Calls to getNextLocalRow() will continue to return the next row of data until the last local
      92             :    * row has been reached, it will then start again at the beginning if called again. Also, calls
      93             :    * to getNextLocalRow() can be partial, followed by call(s) to getSamples or getLocalSamples.
      94             :    * Continued calls to getNextLocalRow() will still continue to give the next row as if the
      95             :    * other get calls were not made. However, when this occurs calls to restore and advance the
      96             :    * generators are made after each call to getSamples or getLocalSamples, so this generally
      97             :    * should be avoided.
      98             :    */
      99             :   std::vector<Real> getNextLocalRow();
     100             : 
     101             :   /**
     102             :    * Return the number of samples.
     103             :    * @return The total number of rows that exist in all DenseMatrix values from the
     104             :    * getSamples/getLocalSamples methods.
     105             :    */
     106             :   dof_id_type getNumberOfRows() const;
     107             :   dof_id_type getNumberOfCols() const;
     108             :   dof_id_type getNumberOfLocalRows() const;
     109             : 
     110             :   ///@{
     111             :   /**
     112             :    * Return the beginning/end local row index for this processor
     113             :    */
     114             :   dof_id_type getLocalRowBegin() const;
     115             :   dof_id_type getLocalRowEnd() const;
     116             :   ///@}
     117             : 
     118             :   /**
     119             :    * Reference to rank configuration defining the partitioning of the sampler matrix
     120             :    * This is primarily used by MultiApps to ensure consistent partitioning
     121             :    */
     122             :   const LocalRankConfig & getRankConfig(bool batch_mode) const
     123             :   {
     124             :     return batch_mode ? _rank_config.second : _rank_config.first;
     125             :   }
     126             : 
     127             :   /**
     128             :    * Returns true if the adaptive sampling is completed
     129             :    */
     130           0 :   virtual bool isAdaptiveSamplingCompleted() const
     131             :   {
     132           0 :     mooseError("This method should be overridden in adaptive sampling classes.");
     133             :     return false;
     134             :   }
     135             : 
     136             :   /**
     137             :    * Return the parallel communicator
     138             :    */
     139             :   libMesh::Parallel::Communicator & getLocalComm() { return _local_comm; }
     140             : 
     141             : protected:
     142             :   // The following methods are the basic methods that should be utilized my most application
     143             :   // developers that are creating a custom Sampler.
     144             : 
     145             :   ///@{
     146             :   /**
     147             :    * These methods must be called within the constructor of child classes to define the size of
     148             :    * the matrix to be created.
     149             :    */
     150             :   void setNumberOfRows(dof_id_type n_rows);
     151             :   void setNumberOfCols(dof_id_type n_cols);
     152             :   ///@}
     153             : 
     154             :   /**
     155             :    * Set the number of seeds required by the sampler. The Sampler will generate
     156             :    * additional seeds as needed. This function should be called in the constructor
     157             :    * of child objects.
     158             :    * @param number The required number of random seeds, by default this is called with 1.
     159             :    */
     160             :   void setNumberOfRandomSeeds(std::size_t number);
     161             : 
     162             :   /**
     163             :    * Get nth random number from the generator.
     164             :    * @param n 0-based index of the random number to generate
     165             :    * @param index The index of the seed, by default this is zero. To add additional seeds
     166             :    *              indices call the setNumberOfRequiedRandomSeeds method.
     167             :    *
     168             :    * @return A double for the random number, this is double because MooseRandom class uses double.
     169             :    */
     170             :   Real getRand(std::size_t n, unsigned int index = 0) const;
     171             : 
     172             :   /**
     173             :    * Get nth random integer from the generator within the specified range [lower, upper)
     174             :    * @param n 0-based index of the random number to generate
     175             :    * @param lower Lower bounds
     176             :    * @param upper Upper bounds
     177             :    * @param index The index of the seed, by default this is zero. To add additional seeds
     178             :    *              indices call the setNumberOfRequiedRandomSeeds method.
     179             :    *
     180             :    * @return A integer for the random number
     181             :    */
     182             :   unsigned int
     183             :   getRandl(std::size_t n, unsigned int lower, unsigned int upper, unsigned int index = 0) const;
     184             : 
     185             :   /**
     186             :    * Base class must override this method to supply the sample distribution data.
     187             :    * @param row_index The row index of sample value to compute.
     188             :    * @param col_index The column index of sample value to compute.
     189             :    * @return The value for the given row and column.
     190             :    */
     191             :   virtual Real computeSample(dof_id_type row_index, dof_id_type col_index) = 0;
     192             : 
     193             :   // The following methods are advanced methods that should not be needed by application developers,
     194             :   // but exist for special cases.
     195             : 
     196             :   ///@{
     197             :   /**
     198             :    * Methods to populate the global or local sample matrix.
     199             :    * @param matrix The correctly sized matrix of sample values to populate
     200             :    *
     201             :    * These methods should not be called directly, each is automatically called by the public
     202             :    * getGlobalSamples() or getLocalSamples() methods.
     203             :    */
     204             :   virtual void computeSampleMatrix(DenseMatrix<Real> & matrix);
     205             :   virtual void computeLocalSampleMatrix(DenseMatrix<Real> & matrix);
     206             :   ///@}
     207             : 
     208             :   ///@{
     209             :   /**
     210             :    * Method to populate a complete row of sample data.
     211             :    * @param i The global row index to compute
     212             :    * @param data The correctly sized vector of sample value to poplulate
     213             : 
     214             :    * This method should not be called directly, it is automatically called by the public
     215             :    * getGlobalSamples(), getLocalSamples(), or getNextLocalRow() methods.
     216             :    */
     217             :   virtual void computeSampleRow(dof_id_type i, std::vector<Real> & data);
     218             : 
     219             :   /**
     220             :    * Method for advancing the random number generator(s) by the supplied number or calls to rand().
     221             :    */
     222             :   virtual void advanceGenerators(const dof_id_type count);
     223             :   virtual void advanceGenerator(const unsigned int seed_index, const dof_id_type count);
     224             :   void setAutoAdvanceGenerators(const bool state);
     225             : 
     226             :   //@{
     227             :   /**
     228             :    * Callbacks for before and after execute.
     229             :    *
     230             :    * These were added to support of dynamic sampler sizes. Recall that execute is simply to advance
     231             :    * the state of the generators such that the next sample will be unique. These methods allow
     232             :    * operations before and after the call to generator advancement.
     233             :    */
     234           0 :   virtual void executeSetUp() {}
     235         271 :   virtual void executeTearDown() {}
     236             :   ///@}
     237             : 
     238             :   /**
     239             :    * This is where the sampler partitioning is defined. It is NOT recommended to
     240             :    * override this function unless you know EXACTLY what you are doing
     241             :    */
     242             :   virtual LocalRankConfig constructRankConfig(bool batch_mode) const;
     243             : 
     244             :   /// The minimum number of processors that are associated with a set of rows
     245             :   const dof_id_type _min_procs_per_row;
     246             :   /// The maximum number of processors that are associated with a set of rows
     247             :   const dof_id_type _max_procs_per_row;
     248             : 
     249             :   /// Communicator that was split based on samples that have rows
     250             :   libMesh::Parallel::Communicator _local_comm;
     251             : 
     252             : private:
     253             :   ///@{
     254             :   /**
     255             :    * Functions called by MOOSE to setup the Sampler for use. The primary purpose is to partition
     256             :    * the DenseMatrix rows for parallel distribution. A separate methods are required so that the
     257             :    * set methods can be called within the constructors of child objects, see
     258             :    * FEProblemBase::addSampler method. The reinit was added to support re-partitioning to allow
     259             :    * for dynamic changes in sampler size.
     260             :    *
     261             :    * This init() method is called by FEProblemBase::addSampler; it should not be called elsewhere.
     262             :    */
     263             :   void init();   // sets up MooseRandom
     264             :   void reinit(); // partitions sampler output
     265             :   ///@}
     266             :   friend void FEProblemBase::addSampler(const std::string & type,
     267             :                                         const std::string & name,
     268             :                                         InputParameters & parameters);
     269             :   /**
     270             :    * Advance MooseRandomStateless generators so that new calls to
     271             :    * sample methods will create new numbers.
     272             :    */
     273             :   void execute();
     274             :   friend void FEProblemBase::objectExecuteHelper<Sampler>(const std::vector<Sampler *> & objects);
     275             : 
     276             :   /**
     277             :    * Helper function for reinit() errors.
     278             :    **/
     279             :   void checkReinitStatus() const;
     280             : 
     281             :   /**
     282             :    * Advance method for internal use that considers the auto advance flag.
     283             :    */
     284             :   void advanceGeneratorsInternal(const dof_id_type count);
     285             : 
     286             :   /// Random number generators, don't give users access. Control it via the interface from this class.
     287             :   std::vector<std::unique_ptr<MooseRandomStateless>> _generators;
     288             : 
     289             :   /// Number of rows for this processor
     290             :   dof_id_type _n_local_rows;
     291             : 
     292             :   /// Global row index for start of data for this processor
     293             :   dof_id_type _local_row_begin;
     294             : 
     295             :   /// Global row index for end of data for this processor
     296             :   dof_id_type _local_row_end;
     297             : 
     298             :   /// Total number of rows in the sample matrix
     299             :   dof_id_type _n_rows;
     300             : 
     301             :   /// Total number of columns in the sample matrix
     302             :   dof_id_type _n_cols;
     303             : 
     304             :   /// Number of seeds
     305             :   std::size_t _n_seeds;
     306             : 
     307             :   /// Iterator index for getNextLocalRow method
     308             :   dof_id_type _next_local_row;
     309             : 
     310             :   /// Flag for restoring state during getNextLocalRow iteration
     311             :   bool _next_local_row_requires_state_restore;
     312             : 
     313             :   /// Flag to indicate if the init method for this class was called
     314             :   bool _initialized;
     315             : 
     316             :   /// Flag to indicate if the reinit method should be called during execute
     317             :   bool _needs_reinit;
     318             : 
     319             :   /// Flag for initial execute to allow the first set of random numbers to be always be the same
     320             :   bool _has_executed;
     321             : 
     322             :   /// Max number of entries for matrix returned by getGlobalSamples
     323             :   const dof_id_type _limit_get_global_samples;
     324             : 
     325             :   /// Max number of entries for matrix returned by getLocalSamples
     326             :   const dof_id_type _limit_get_local_samples;
     327             : 
     328             :   /// Max number of entries for matrix returned by getNextLocalRow
     329             :   const dof_id_type _limit_get_next_local_row;
     330             : 
     331             :   /// The partitioning of the sampler matrix, built in reinit()
     332             :   /// first is for normal mode and send is for batch mode
     333             :   std::pair<LocalRankConfig, LocalRankConfig> _rank_config;
     334             : 
     335             :   /// Flag for disabling automatic generator advancing
     336             :   bool _auto_advance_generators;
     337             : };

Generated by: LCOV version 1.14