LCOV - code coverage report
Current view: top level - include/userobjects - UserObject.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 8601ad Lines: 33 35 94.3 %
Date: 2025-07-18 13:27:08 Functions: 23 25 92.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             : 
      10             : #pragma once
      11             : 
      12             : // MOOSE includes
      13             : #include "DistributionInterface.h"
      14             : #include "FunctionInterface.h"
      15             : #include "UserObjectInterface.h"
      16             : #include "PostprocessorInterface.h"
      17             : #include "VectorPostprocessorInterface.h"
      18             : #include "ReporterInterface.h"
      19             : #include "MeshChangedInterface.h"
      20             : #include "MeshDisplacedInterface.h"
      21             : #include "MooseObject.h"
      22             : #include "MooseTypes.h"
      23             : #include "Restartable.h"
      24             : #include "MeshMetaDataInterface.h"
      25             : #include "ScalarCoupleable.h"
      26             : #include "SetupInterface.h"
      27             : #include "PerfGraphInterface.h"
      28             : #include "SamplerInterface.h"
      29             : 
      30             : #include "libmesh/parallel.h"
      31             : 
      32             : class FEProblemBase;
      33             : class SubProblem;
      34             : class Assembly;
      35             : class SystemBase;
      36             : 
      37             : /**
      38             :  * Base class for user-specific data
      39             :  */
      40             : class UserObject : public MooseObject,
      41             :                    public SetupInterface,
      42             :                    protected FunctionInterface,
      43             :                    public UserObjectInterface,
      44             :                    protected PostprocessorInterface,
      45             :                    protected VectorPostprocessorInterface,
      46             :                    protected ReporterInterface,
      47             :                    protected DistributionInterface,
      48             :                    protected SamplerInterface,
      49             :                    protected Restartable,
      50             :                    protected MeshMetaDataInterface,
      51             :                    protected MeshChangedInterface,
      52             :                    protected MeshDisplacedInterface,
      53             :                    protected PerfGraphInterface,
      54             :                    public DependencyResolverInterface
      55             : {
      56             : public:
      57             :   static InputParameters validParams();
      58             : 
      59             :   UserObject(const InputParameters & params);
      60       70266 :   virtual ~UserObject() = default;
      61             : 
      62             :   /**
      63             :    * Execute method.
      64             :    */
      65             :   virtual void execute() = 0;
      66             : 
      67             :   /**
      68             :    * Called before execute() is ever called so that data can be cleared.
      69             :    */
      70             :   virtual void initialize() = 0;
      71             : 
      72             :   /**
      73             :    * Finalize.  This is called _after_ execute() and _after_ threadJoin()!  This is probably where
      74             :    * you want to do MPI communication!
      75             :    */
      76             :   virtual void finalize() = 0;
      77             : 
      78             :   /**
      79             :    * Returns a reference to the subproblem that
      80             :    * this postprocessor is tied to
      81             :    */
      82          22 :   SubProblem & getSubProblem() const { return _subproblem; }
      83             : 
      84             :   /**
      85             :    * Returns whether or not this user object should be executed twice during the initial condition
      86             :    * when depended upon by an IC.
      87             :    */
      88             :   bool shouldDuplicateInitialExecution() const { return _duplicate_initial_execution; }
      89             : 
      90             :   /**
      91             :    * Optional interface function for "evaluating" a UserObject at a spatial position.
      92             :    * If a UserObject overrides this function that UserObject can then be used in a
      93             :    * Transfer to transfer information from one domain to another.
      94             :    */
      95           4 :   virtual Real spatialValue(const Point & /*p*/) const
      96             :   {
      97           4 :     mooseError(name(), " does not satisfy the Spatial UserObject interface!");
      98             :   }
      99             : 
     100             :   /**
     101             :    * Optional interface function for providing the points at which a UserObject attains
     102             :    * spatial values. If a UserObject overrides this function, then other objects that
     103             :    * take both the UserObject and points can instead directly use the points specified
     104             :    * on the UserObject.
     105             :    */
     106           0 :   virtual const std::vector<Point> spatialPoints() const
     107             :   {
     108           0 :     mooseError("Spatial UserObject interface is not satisfied; spatialPoints() must be overridden");
     109             :   }
     110             : 
     111             :   /**
     112             :    * Must override.
     113             :    *
     114             :    * @param uo The UserObject to be joined into _this_ object.  Take the data from the uo object and
     115             :    * "add" it into the data for this object.
     116             :    */
     117             :   virtual void threadJoin(const UserObject & uo) = 0;
     118             : 
     119             :   /**
     120             :    * Gather the parallel sum of the variable passed in. It takes care of values across all threads
     121             :    * and CPUs (we DO hybrid parallelism!)
     122             :    *
     123             :    * After calling this, the variable that was passed in will hold the gathered value.
     124             :    */
     125             :   template <typename T>
     126      424775 :   void gatherSum(T & value)
     127             :   {
     128      424775 :     _communicator.sum(value);
     129      424775 :   }
     130             : 
     131             :   /**
     132             :    * Gather the parallel max of the variable passed in. It takes care of values across all threads
     133             :    * and CPUs (we DO hybrid parallelism!)
     134             :    *
     135             :    * After calling this, the variable that was passed in will hold the gathered value.
     136             :    */
     137             :   template <typename T>
     138         563 :   void gatherMax(T & value)
     139             :   {
     140         563 :     _communicator.max(value);
     141         563 :   }
     142             : 
     143             :   /**
     144             :    * Gather the parallel min of the variable passed in. It takes care of values across all threads
     145             :    * and CPUs (we DO hybrid parallelism!)
     146             :    *
     147             :    * After calling this, the variable that was passed in will hold the gathered value.
     148             :    */
     149             :   template <typename T>
     150        1674 :   void gatherMin(T & value)
     151             :   {
     152        1674 :     _communicator.min(value);
     153        1674 :   }
     154             : 
     155             :   /**
     156             :    * Deteremine the value of a variable according to the parallel
     157             :    * maximum of the provided proxy.
     158             :    * @param[in] proxy maximum proxy will be selected
     159             :    * @param[in] value value to be obtained corresponding to the location of maximum proxy
     160             :    */
     161             :   template <typename T1, typename T2>
     162             :   void gatherProxyValueMax(T1 & proxy, T2 & value);
     163             : 
     164             :   /**
     165             :    * Determine the value of a variable according to which process has the parallel
     166             :    * minimum of the provided proxy.
     167             :    * @param[in] proxy minimum proxy will be selected
     168             :    * @param[in] value value to be obtained corresponding to the location of minimum proxy
     169             :    */
     170             :   template <typename T1, typename T2>
     171             :   void gatherProxyValueMin(T1 & proxy, T2 & value);
     172             : 
     173             :   void setPrimaryThreadCopy(UserObject * primary);
     174             : 
     175      363043 :   UserObject * primaryThreadCopy() { return _primary_thread_copy; }
     176             : 
     177             :   /**
     178             :    * Recursively return a set of user objects this user object depends on
     179             :    * Note: this can be called only after all user objects are constructed.
     180             :    */
     181             :   std::set<UserObjectName> getDependObjects() const;
     182             : 
     183             :   /**
     184             :    * Whether or not a threaded copy of this object is needed when obtaining it in
     185             :    * another object, like via the UserObjectInterface.
     186             :    *
     187             :    * Derived classes should override this as needed.
     188             :    */
     189       82799 :   virtual bool needThreadedCopy() const { return false; }
     190             : 
     191      334373 :   const std::set<std::string> & getRequestedItems() override { return _depend_uo; }
     192             : 
     193      334373 :   const std::set<std::string> & getSuppliedItems() override { return _supplied_uo; }
     194             : 
     195             :   /**
     196             :    * @returns the number of the system associated with this object
     197             :    */
     198             :   unsigned int systemNumber() const;
     199             : 
     200             : protected:
     201             :   virtual void addPostprocessorDependencyHelper(const PostprocessorName & name) const override;
     202             :   virtual void
     203             :   addVectorPostprocessorDependencyHelper(const VectorPostprocessorName & name) const override;
     204             :   virtual void addUserObjectDependencyHelper(const UserObject & uo) const override;
     205             :   void addReporterDependencyHelper(const ReporterName & reporter_name) override;
     206             : 
     207             :   /// Reference to the Subproblem for this user object
     208             :   SubProblem & _subproblem;
     209             : 
     210             :   /// Reference to the FEProblemBase for this user object
     211             :   FEProblemBase & _fe_problem;
     212             : 
     213             :   /// Reference to the system object for this user object. This should correspond to a nonlinear
     214             :   /// system (either through the FEProblemBase or the DisplacedProblem)
     215             :   SystemBase & _sys;
     216             : 
     217             :   /// Thread ID of this postprocessor
     218             :   const THREAD_ID _tid;
     219             :   Assembly & _assembly;
     220             : 
     221             :   /// Coordinate system
     222             :   const Moose::CoordinateSystemType & _coord_sys;
     223             : 
     224             :   const bool _duplicate_initial_execution;
     225             : 
     226             :   /// Depend UserObjects that to be used both for determining user object sorting and by AuxKernel
     227             :   /// for finding the full UO dependency
     228             :   mutable std::set<std::string> _depend_uo;
     229             : 
     230             : private:
     231             :   UserObject * _primary_thread_copy = nullptr;
     232             : 
     233             :   /// A name of the "supplied" user objects, which is just this object
     234             :   std::set<std::string> _supplied_uo;
     235             : };
     236             : 
     237             : template <typename T1, typename T2>
     238             : void
     239        1752 : UserObject::gatherProxyValueMax(T1 & proxy, T2 & value)
     240             : {
     241             :   // Get all proxy, value pairs. _communicator.maxloc would be faster but leads to
     242             :   // partitioning dependent results if the maximum proxy is not unique.
     243        1752 :   std::vector<std::pair<T1, T2>> all(n_processors());
     244        1752 :   const auto pair = std::make_pair(proxy, value);
     245        1752 :   _communicator.allgather(pair, all);
     246             : 
     247             :   // find maximum, disambiguated by the value
     248        1752 :   const auto it = std::max_element(all.begin(), all.end());
     249        1752 :   proxy = it->first;
     250        1752 :   value = it->second;
     251        1752 : }
     252             : 
     253             : template <typename T1, typename T2>
     254             : void
     255         764 : UserObject::gatherProxyValueMin(T1 & proxy, T2 & value)
     256             : {
     257             :   // get all proxy, value pairs
     258         764 :   std::vector<std::pair<T1, T2>> all(n_processors());
     259         764 :   const auto pair = std::make_pair(proxy, value);
     260         764 :   _communicator.allgather(pair, all);
     261             : 
     262             :   // find minimum, disambiguated by the value
     263         764 :   const auto it = std::min_element(all.begin(), all.end());
     264         764 :   proxy = it->first;
     265         764 :   value = it->second;
     266         764 : }

Generated by: LCOV version 1.14