LCOV - code coverage report
Current view: top level - include/userobjects - FXIntegralBaseUserObject.h (source / functions) Hit Total Coverage
Test: idaholab/moose functional_expansion_tools: #31405 (292dce) with base fef103 Lines: 58 65 89.2 %
Date: 2025-09-04 07:53:29 Functions: 12 16 75.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             : #include "AuxiliarySystem.h"
      13             : #include "MooseError.h"
      14             : #include "MooseMesh.h"
      15             : #include "MooseVariable.h"
      16             : #include "UserObject.h"
      17             : 
      18             : #include "libmesh/quadrature.h"
      19             : 
      20             : #include "FunctionSeries.h"
      21             : #include "MutableCoefficientsInterface.h"
      22             : 
      23             : /**
      24             :  * This class interacts with a MooseApp through functional expansions. It is templated to allow the
      25             :  * inheritance of two dual classes that operate in a volume (FXVolumeUserObject) or on a boundary
      26             :  * (FXBoundaryFluxUserObject and FXBoundaryValueUserObject)
      27             :  *
      28             :  * It uses an instance of FunctionSeries to generate the orthonormal function series required to
      29             :  * generate the functional expansion coefficients.
      30             :  */
      31             : template <class IntegralBaseVariableUserObject>
      32             : class FXIntegralBaseUserObject : public IntegralBaseVariableUserObject,
      33             :                                  public MutableCoefficientsInterface
      34             : {
      35             : public:
      36             :   FXIntegralBaseUserObject(const InputParameters & parameters);
      37             : 
      38             :   static InputParameters validParams();
      39             : 
      40             :   /**
      41             :    * Return a reference to the underlying function series
      42             :    */
      43             :   const FunctionSeries & getFunctionSeries() const;
      44             : 
      45             :   // Override from <IntegralBaseVariableUserObject>
      46             :   virtual Real getValue() const final;
      47             : 
      48             :   // Overrides from UserObject
      49             :   virtual void finalize() final;
      50             :   virtual void initialize() final;
      51             :   virtual Real spatialValue(const Point & location) const final;
      52             :   virtual void threadJoin(const UserObject & sibling) final;
      53             : 
      54             : protected:
      55             :   // Policy-based design requires us to specify which inherited members we are using
      56             :   using IntegralBaseVariableUserObject::_communicator;
      57             :   using IntegralBaseVariableUserObject::_console;
      58             :   using IntegralBaseVariableUserObject::_coord;
      59             :   using IntegralBaseVariableUserObject::_integral_value;
      60             :   using IntegralBaseVariableUserObject::_JxW;
      61             :   using IntegralBaseVariableUserObject::_q_point;
      62             :   using IntegralBaseVariableUserObject::_qp;
      63             :   using IntegralBaseVariableUserObject::_variable;
      64             :   using IntegralBaseVariableUserObject::computeIntegral;
      65             :   using IntegralBaseVariableUserObject::computeQpIntegral;
      66             :   using IntegralBaseVariableUserObject::getFunction;
      67             :   using IntegralBaseVariableUserObject::name;
      68             : 
      69             :   // Override from <IntegralBaseVariableUserObject>
      70             :   virtual Real computeIntegral() final;
      71             : 
      72             :   /**
      73             :    * Get the centroid of the evaluated unit
      74             :    */
      75             :   virtual Point getCentroid() const = 0;
      76             : 
      77             :   /**
      78             :    * Get the volume of the evaluated unit
      79             :    */
      80             :   virtual Real getVolume() const = 0;
      81             : 
      82             :   /// History of the expansion coefficients for each solve
      83             :   std::vector<std::vector<Real>> _coefficient_history;
      84             : 
      85             :   /// Current coefficient partial sums
      86             :   std::vector<Real> _coefficient_partials;
      87             : 
      88             :   /// Reference to the underlying function series
      89             :   FunctionSeries & _function_series;
      90             : 
      91             :   /// Keep the expansion coefficients after each solve
      92             :   const bool _keep_history;
      93             : 
      94             :   /// Flag to prints the state of the zeroth instance in finalize()
      95             :   const bool _print_state;
      96             : 
      97             :   /// Volume of the standardized functional space of integration
      98             :   const Real _standardized_function_volume;
      99             : 
     100             :   /// Moose volume of evaluation
     101             :   Real _volume;
     102             : };
     103             : 
     104             : template <class IntegralBaseVariableUserObject>
     105             : InputParameters
     106         549 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::validParams()
     107             : {
     108         549 :   InputParameters params = IntegralBaseVariableUserObject::validParams();
     109         549 :   params += MutableCoefficientsInterface::validParams();
     110             : 
     111         549 :   params.addClassDescription(
     112             :       "This UserObject interacts with a MooseApp through functional expansions.");
     113             : 
     114        1098 :   params.addRequiredParam<FunctionName>("function",
     115             :                                         "The name of the FunctionSeries \"Function\" object with "
     116             :                                         "which to generate this functional expansion.");
     117             : 
     118        1098 :   params.addParam<bool>(
     119        1098 :       "keep_history", false, "Keep the expansion coefficients from previous solves");
     120             : 
     121        1098 :   params.addParam<bool>("print_state", false, "Print the state of the zeroth instance each solve");
     122             : 
     123         549 :   return params;
     124           0 : }
     125             : 
     126             : template <class IntegralBaseVariableUserObject>
     127         320 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::FXIntegralBaseUserObject(
     128             :     const InputParameters & parameters)
     129             :   : IntegralBaseVariableUserObject(parameters),
     130             :     MutableCoefficientsInterface(this, parameters),
     131         320 :     _function_series(
     132         320 :         FunctionSeries::checkAndConvertFunction(getFunction("function"), this->getBase(), name())),
     133         640 :     _keep_history(UserObject::getParam<bool>("keep_history")),
     134         640 :     _print_state(UserObject::getParam<bool>("print_state")),
     135         640 :     _standardized_function_volume(_function_series.getStandardizedFunctionVolume())
     136             : {
     137             :   // Size the coefficient arrays
     138         320 :   _coefficient_partials.resize(_function_series.getNumberOfTerms(), 0.0);
     139         320 :   _coefficients.resize(_function_series.getNumberOfTerms(), 0.0);
     140         320 :   _characteristics = _function_series.getOrders();
     141             : 
     142         320 :   if (!_keep_history)
     143         320 :     _coefficient_history.resize(0);
     144         320 : }
     145             : 
     146             : template <class IntegralBaseVariableUserObject>
     147             : Real
     148      142650 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::computeIntegral()
     149             : {
     150             :   Real sum = 0.0;
     151      142650 :   const Point centroid = getCentroid();
     152             : 
     153             :   // Check to see if this element/side is within the valid boundaries
     154      142650 :   if (!_function_series.isInPhysicalBounds(centroid))
     155             :     return 0.0;
     156             : 
     157             :   // Loop over the quadrature points
     158      421512 :   for (_qp = 0; _qp < _q_point.size(); ++_qp)
     159             :   {
     160             :     // Get the functional terms for a vectorized approach
     161      281008 :     _function_series.setLocation(_q_point[_qp]);
     162      281008 :     const std::vector<Real> & term_evaluations = _function_series.getGeneration();
     163             : 
     164             :     // Evaluate the functional expansion coefficients at each quadrature point
     165      281008 :     const Real local_contribution = computeQpIntegral();
     166      281008 :     const Real common_evaluation = local_contribution * _JxW[_qp] * _coord[_qp];
     167     1459440 :     for (std::size_t c = 0; c < _coefficient_partials.size(); ++c)
     168     1178432 :       _coefficient_partials[c] += term_evaluations[c] * common_evaluation;
     169             : 
     170      281008 :     sum += local_contribution;
     171             :   }
     172             : 
     173      140504 :   _volume += getVolume();
     174             : 
     175      140504 :   return sum;
     176             : }
     177             : 
     178             : template <class IntegralBaseVariableUserObject>
     179             : void
     180       14358 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::finalize()
     181             : {
     182             :   // Sum the coefficient arrays over all processes
     183       14358 :   _communicator.sum(_coefficient_partials);
     184       14358 :   _communicator.sum(_volume);
     185             : 
     186             :   // Normalize the volume of the functional expansion to the FX standard space
     187       14358 :   const Real volume_normalization = _standardized_function_volume / _volume;
     188       73900 :   for (auto & partial : _coefficient_partials)
     189       59542 :     partial *= volume_normalization;
     190             : 
     191             :   // We now have the completely evaluated coefficients
     192       14358 :   _coefficients = _coefficient_partials;
     193             : 
     194             :   // The average value is the same as the zeroth coefficient
     195       14358 :   _integral_value = _coefficient_partials[0];
     196             : 
     197       14358 :   if (_keep_history)
     198           0 :     _coefficient_history.push_back(_coefficients);
     199             : 
     200       14358 :   if (_print_state)
     201             :   {
     202        1626 :     _function_series.setCoefficients(_coefficients);
     203        2322 :     _console << COLOR_YELLOW << _function_series << COLOR_DEFAULT << std::endl;
     204             :   }
     205       14358 : }
     206             : 
     207             : template <class IntegralBaseVariableUserObject>
     208             : const FunctionSeries &
     209             : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::getFunctionSeries() const
     210             : {
     211             :   return _function_series;
     212             : }
     213             : 
     214             : template <class IntegralBaseVariableUserObject>
     215             : Real
     216           0 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::getValue() const
     217             : {
     218           0 :   return _integral_value;
     219             : }
     220             : 
     221             : template <class IntegralBaseVariableUserObject>
     222             : void
     223       18426 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::initialize()
     224             : {
     225       18426 :   IntegralBaseVariableUserObject::initialize();
     226             : 
     227             :   // Clear the partial sums
     228       96350 :   for (auto & partial : _coefficient_partials)
     229       77924 :     partial = 0;
     230             : 
     231       18426 :   _volume = 0;
     232       18426 : }
     233             : 
     234             : template <class IntegralBaseVariableUserObject>
     235             : void
     236        4068 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::threadJoin(const UserObject & s)
     237             : {
     238             :   const FXIntegralBaseUserObject<IntegralBaseVariableUserObject> & sibling =
     239             :       static_cast<const FXIntegralBaseUserObject<IntegralBaseVariableUserObject> &>(s);
     240             : 
     241       22450 :   for (std::size_t c = 0; c < _coefficient_partials.size(); ++c)
     242       18382 :     _coefficient_partials[c] += sibling._coefficient_partials[c];
     243             : 
     244        4068 :   _volume += sibling._volume;
     245        4068 : }
     246             : 
     247             : template <class IntegralBaseVariableUserObject>
     248             : Real
     249           0 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::spatialValue(const Point & location) const
     250             : {
     251           0 :   _function_series.setLocation(location);
     252             : 
     253           0 :   return _function_series.expand(_coefficients);
     254             : }

Generated by: LCOV version 1.14