LCOV - code coverage report
Current view: top level - include/userobjects - FXIntegralBaseUserObject.h (source / functions) Hit Total Coverage
Test: idaholab/moose functional_expansion_tools: #32971 (54bef8) with base c6cf66 Lines: 58 65 89.2 %
Date: 2026-05-29 20:36:43 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         283 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::validParams()
     107             : {
     108         283 :   InputParameters params = IntegralBaseVariableUserObject::validParams();
     109         283 :   params += MutableCoefficientsInterface::validParams();
     110             : 
     111         283 :   params.addClassDescription(
     112             :       "This UserObject interacts with a MooseApp through functional expansions.");
     113             : 
     114         566 :   params.addRequiredParam<FunctionName>("function",
     115             :                                         "The name of the FunctionSeries \"Function\" object with "
     116             :                                         "which to generate this functional expansion.");
     117             : 
     118         566 :   params.addParam<bool>(
     119         566 :       "keep_history", false, "Keep the expansion coefficients from previous solves");
     120             : 
     121         566 :   params.addParam<bool>("print_state", false, "Print the state of the zeroth instance each solve");
     122             : 
     123         283 :   return params;
     124           0 : }
     125             : 
     126             : template <class IntegralBaseVariableUserObject>
     127         164 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::FXIntegralBaseUserObject(
     128             :     const InputParameters & parameters)
     129             :   : IntegralBaseVariableUserObject(parameters),
     130             :     MutableCoefficientsInterface(this, parameters),
     131         164 :     _function_series(
     132         164 :         FunctionSeries::checkAndConvertFunction(getFunction("function"), this->getBase(), name())),
     133         328 :     _keep_history(UserObject::getParam<bool>("keep_history")),
     134         328 :     _print_state(UserObject::getParam<bool>("print_state")),
     135         328 :     _standardized_function_volume(_function_series.getStandardizedFunctionVolume())
     136             : {
     137             :   // Size the coefficient arrays
     138         164 :   _coefficient_partials.resize(_function_series.getNumberOfTerms(), 0.0);
     139         164 :   _coefficients.resize(_function_series.getNumberOfTerms(), 0.0);
     140         164 :   _characteristics = _function_series.getOrders();
     141             : 
     142         164 :   if (!_keep_history)
     143         164 :     _coefficient_history.resize(0);
     144         164 : }
     145             : 
     146             : template <class IntegralBaseVariableUserObject>
     147             : Real
     148       95220 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::computeIntegral()
     149             : {
     150             :   Real sum = 0.0;
     151       95220 :   const Point centroid = getCentroid();
     152             : 
     153             :   // Check to see if this element/side is within the valid boundaries
     154       95220 :   if (!_function_series.isInPhysicalBounds(centroid))
     155             :     return 0.0;
     156             : 
     157             :   // Loop over the quadrature points
     158      281364 :   for (_qp = 0; _qp < _q_point.size(); ++_qp)
     159             :   {
     160             :     // Get the functional terms for a vectorized approach
     161      187576 :     _function_series.setLocation(_q_point[_qp]);
     162      187576 :     const std::vector<Real> & term_evaluations = _function_series.getGeneration();
     163             : 
     164             :     // Evaluate the functional expansion coefficients at each quadrature point
     165      187576 :     const Real local_contribution = computeQpIntegral();
     166      187576 :     const Real common_evaluation = local_contribution * _JxW[_qp] * _coord[_qp];
     167      974280 :     for (std::size_t c = 0; c < _coefficient_partials.size(); ++c)
     168      786704 :       _coefficient_partials[c] += term_evaluations[c] * common_evaluation;
     169             : 
     170      187576 :     sum += local_contribution;
     171             :   }
     172             : 
     173       93788 :   _volume += getVolume();
     174             : 
     175       93788 :   return sum;
     176             : }
     177             : 
     178             : template <class IntegralBaseVariableUserObject>
     179             : void
     180        8214 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::finalize()
     181             : {
     182             :   // Sum the coefficient arrays over all processes
     183        8214 :   _communicator.sum(_coefficient_partials);
     184        8214 :   _communicator.sum(_volume);
     185             : 
     186             :   // Normalize the volume of the functional expansion to the FX standard space
     187        8214 :   const Real volume_normalization = _standardized_function_volume / _volume;
     188       42280 :   for (auto & partial : _coefficient_partials)
     189       34066 :     partial *= volume_normalization;
     190             : 
     191             :   // We now have the completely evaluated coefficients
     192        8214 :   _coefficients = _coefficient_partials;
     193             : 
     194             :   // The average value is the same as the zeroth coefficient
     195        8214 :   _integral_value = _coefficient_partials[0];
     196             : 
     197        8214 :   if (_keep_history)
     198           0 :     _coefficient_history.push_back(_coefficients);
     199             : 
     200        8214 :   if (_print_state)
     201             :   {
     202         930 :     _function_series.setCoefficients(_coefficients);
     203         930 :     _console << COLOR_YELLOW << _function_series << COLOR_DEFAULT << std::endl;
     204             :   }
     205        8214 : }
     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        9874 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::initialize()
     224             : {
     225        9874 :   IntegralBaseVariableUserObject::initialize();
     226             : 
     227             :   // Clear the partial sums
     228       51790 :   for (auto & partial : _coefficient_partials)
     229       41916 :     partial = 0;
     230             : 
     231        9874 :   _volume = 0;
     232        9874 : }
     233             : 
     234             : template <class IntegralBaseVariableUserObject>
     235             : void
     236        1660 : FXIntegralBaseUserObject<IntegralBaseVariableUserObject>::threadJoin(const UserObject & s)
     237             : {
     238             :   const FXIntegralBaseUserObject<IntegralBaseVariableUserObject> & sibling =
     239             :       static_cast<const FXIntegralBaseUserObject<IntegralBaseVariableUserObject> &>(s);
     240             : 
     241        9510 :   for (std::size_t c = 0; c < _coefficient_partials.size(); ++c)
     242        7850 :     _coefficient_partials[c] += sibling._coefficient_partials[c];
     243             : 
     244        1660 :   _volume += sibling._volume;
     245        1660 : }
     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