LCOV - code coverage report
Current view: top level - src/distributions - Gamma.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: #31405 (292dce) with base fef103 Lines: 42 45 93.3 %
Date: 2025-09-04 07:57:52 Functions: 10 10 100.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             : #include "Gamma.h"
      11             : #include "math.h"
      12             : #include "libmesh/utility.h"
      13             : 
      14             : registerMooseObject("StochasticToolsApp", Gamma);
      15             : 
      16             : InputParameters
      17          68 : Gamma::validParams()
      18             : {
      19          68 :   InputParameters params = Distribution::validParams();
      20          68 :   params.addClassDescription("Gamma distribution");
      21         136 :   params.addRequiredRangeCheckedParam<Real>("shape", "shape > 0", "Shape parameter (k or alpha).");
      22         204 :   params.addRangeCheckedParam<Real>(
      23         136 :       "scale", 1.0, "scale > 0", "Scale parameter (theta or 1/beta).");
      24          68 :   return params;
      25           0 : }
      26             : 
      27          34 : Gamma::Gamma(const InputParameters & parameters)
      28         102 :   : Distribution(parameters), _alpha(getParam<Real>("shape")), _theta(getParam<Real>("scale"))
      29             : {
      30          34 : }
      31             : 
      32             : Real
      33          34 : Gamma::pdf(const Real & x, const Real & alpha, const Real & beta)
      34             : {
      35          34 :   if (x <= 0.0)
      36             :     return 0.0;
      37             :   else
      38          34 :     return std::pow(beta, alpha) * std::pow(x, alpha - 1.0) * std::exp(-beta * x) /
      39          34 :            std::tgamma(alpha);
      40             : }
      41             : 
      42             : Real
      43          34 : Gamma::cdf(const Real & x, const Real & alpha, const Real & beta)
      44             : {
      45          34 :   if (x <= 0.0)
      46             :     return 0.0;
      47             :   else
      48          34 :     return incompleteGamma(alpha, beta * x);
      49             : }
      50             : 
      51             : Real
      52          34 : Gamma::quantile(const Real & p, const Real & alpha, const Real & beta)
      53             : {
      54          34 :   return incompleteGammaInv(alpha, p) / beta;
      55             : }
      56             : 
      57             : Real
      58          34 : Gamma::pdf(const Real & x) const
      59             : {
      60          34 :   return pdf(x, _alpha, 1.0 / _theta);
      61             : }
      62             : 
      63             : Real
      64          34 : Gamma::cdf(const Real & x) const
      65             : {
      66          34 :   return cdf(x, _alpha, 1.0 / _theta);
      67             : }
      68             : 
      69             : Real
      70          34 : Gamma::quantile(const Real & p) const
      71             : {
      72          34 :   return quantile(p, _alpha, 1.0 / _theta);
      73             : }
      74             : 
      75             : Real
      76         204 : Gamma::incompleteGamma(const Real & a, const Real & x)
      77             : {
      78             :   const Real tol = 1e-14;
      79             :   const unsigned int max_iter = 1e6;
      80         204 :   const Real coef = std::pow(x, a) * std::exp(-x) / std::tgamma(a + 1.0);
      81             :   Real cn = 1.0;
      82             :   Real an = a;
      83             :   Real val = 1.0;
      84        4233 :   for (unsigned int i = 0; i < max_iter; ++i)
      85             :   {
      86        4233 :     an += 1.0;
      87        4233 :     cn *= x / an;
      88        4233 :     val += cn;
      89        4233 :     if (std::abs(cn / val) < tol)
      90         204 :       return coef * val;
      91             :   }
      92             : 
      93             :   mooseAssert(false, "Could not compute incomplete gamma function.");
      94           0 :   return coef * val;
      95             : }
      96             : 
      97             : Real
      98          34 : Gamma::incompleteGammaInv(const Real & a, const Real & p)
      99             : {
     100          34 :   Real x = a > 1.0 ? a : std::pow(p * std::tgamma(a + 1.0), 1.0 / a);
     101          34 :   const Real scale = std::tgamma(a);
     102             :   const Real tol = 1e-14;
     103             :   const unsigned int max_iter = 1e6;
     104             :   Real f;
     105             :   Real df;
     106         170 :   for (unsigned int i = 0; i < max_iter; ++i)
     107             :   {
     108         170 :     f = incompleteGamma(a, x) - p;
     109         170 :     if (std::abs(f) < tol)
     110          34 :       return x;
     111         136 :     df = std::pow(x, a - 1.0) * std::exp(-x) / scale;
     112         136 :     x -= f / df;
     113             :   }
     114             : 
     115             :   mooseAssert(false, "Could not find inverse of incomplete gamma function.");
     116           0 :   return x;
     117             : }

Generated by: LCOV version 1.14