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