LCOV - code coverage report
Current view: top level - src/utils - PorousFlowBroadbridgeWhite.C (source / functions) Hit Total Coverage
Test: idaholab/moose porous_flow: #31405 (292dce) with base fef103 Lines: 46 47 97.9 %
Date: 2025-09-04 07:55:56 Functions: 6 6 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 "PorousFlowBroadbridgeWhite.h"
      11             : 
      12             : namespace PorousFlowBroadbridgeWhite
      13             : {
      14             : Real
      15    13623558 : LambertW(Real z)
      16             : {
      17             :   /* Lambert W function.
      18             :      Was ~/C/LambertW.c written K M Briggs Keith dot Briggs at bt dot com 97 May 21.
      19             :      Revised KMB 97 Nov 20; 98 Feb 11, Nov 24, Dec 28; 99 Jan 13; 00 Feb 23; 01 Apr 09
      20             : 
      21             :      Computes Lambert W function, principal branch.
      22             :      See LambertW1.c for -1 branch.
      23             : 
      24             :      Returned value W(z) satisfies W(z)*exp(W(z))=z
      25             :      test data...
      26             :         W(1)= 0.5671432904097838730
      27             :         W(2)= 0.8526055020137254914
      28             :         W(20)=2.2050032780240599705
      29             :      To solve (a+b*R)*exp(-c*R)-d=0 for R, use
      30             :      R=-(b*W(-exp(-a*c/b)/b*d*c)+a*c)/b/c
      31             : 
      32             :      Test:
      33             :        gcc -DTESTW LambertW.c -o LambertW -lm && LambertW
      34             :      Library:
      35             :        gcc -O3 -c LambertW.c
      36             : 
      37             :      Modified trivially by Andy to use MOOSE things
      38             :   */
      39             :   mooseAssert(z > 0, "LambertW function in RichardsSeff1BWsmall called with negative argument");
      40             : 
      41             :   const Real eps = 4.0e-16; //, em1=0.3678794411714423215955237701614608;
      42             :   Real p, e, t, w;
      43             : 
      44             :   /* Uncomment this stuff is you ever need to call with a negative argument
      45             :   if (z < -em1)
      46             :     mooseError("LambertW: bad argument ", z, "\n");
      47             : 
      48             :   if (0.0 == z)
      49             :     return 0.0;
      50             :   if (z < -em1+1e-4)
      51             :   {
      52             :     // series near -em1 in sqrt(q)
      53             :     Real q=z+em1,r=std::sqrt(q),q2=q*q,q3=q2*q;
      54             :     return
      55             :      -1.0
      56             :      +2.331643981597124203363536062168*r
      57             :      -1.812187885639363490240191647568*q
      58             :      +1.936631114492359755363277457668*r*q
      59             :      -2.353551201881614516821543561516*q2
      60             :      +3.066858901050631912893148922704*r*q2
      61             :      -4.175335600258177138854984177460*q3
      62             :      +5.858023729874774148815053846119*r*q3
      63             :       -8.401032217523977370984161688514*q3*q;  // error approx 1e-16
      64             :   }
      65             :   */
      66             :   /* initial approx for iteration... */
      67    13623558 :   if (z < 1.0)
      68             :   {
      69             :     /* series near 0 */
      70     1860823 :     p = std::sqrt(2.0 * (2.7182818284590452353602874713526625 * z + 1.0));
      71     1860823 :     w = -1.0 + p * (1.0 + p * (-0.333333333333333333333 + p * 0.152777777777777777777777));
      72             :   }
      73             :   else
      74    11762735 :     w = std::log(z); /* asymptotic */
      75    13623558 :   if (z > 3.0)
      76    11391392 :     w -= std::log(w); /* useful? */
      77    46036416 :   for (unsigned int i = 0; i < 10; ++i)
      78             :   {
      79             :     /* Halley iteration */
      80    46036416 :     e = std::exp(w);
      81    46036416 :     t = w * e - z;
      82    46036416 :     p = w + 1.0;
      83    46036416 :     t /= e * p - 0.5 * (p + 1.0) * t / p;
      84    46036416 :     w -= t;
      85    46036416 :     if (std::abs(t) < eps * (1.0 + std::abs(w)))
      86    13623558 :       return w; /* rel-abs error */
      87             :   }
      88             :   /* should never get here */
      89           0 :   mooseError("LambertW: No convergence at z= ", z, "\n");
      90             : }
      91             : 
      92             : Real
      93     5524820 : effectiveSaturation(Real pressure, Real c, Real sn, Real ss, Real las)
      94             : {
      95     5524820 :   if (pressure >= 0.0)
      96             :     return 1.0;
      97     5475231 :   const Real x = (c - 1.0) * std::exp(c - 1.0 - c * pressure / las);
      98     5475231 :   const Real th = c / (1.0 + LambertW(x)); // use branch 0 for positive x
      99     5475231 :   return sn + (ss - sn) * th;
     100             : }
     101             : 
     102             : Real
     103     5482820 : dEffectiveSaturation(Real pressure, Real c, Real sn, Real ss, Real las)
     104             : {
     105     5482820 :   if (pressure >= 0.0)
     106             :     return 0.0;
     107     5433231 :   const Real x = (c - 1.0) * std::exp(c - 1.0 - c * pressure / las);
     108     5433231 :   const Real lamw = LambertW(x);
     109     5433231 :   return (ss - sn) * Utility::pow<2>(c) / las * lamw / Utility::pow<3>(1.0 + lamw);
     110             : }
     111             : 
     112             : Real
     113     2739714 : d2EffectiveSaturation(Real pressure, Real c, Real sn, Real ss, Real las)
     114             : {
     115     2739714 :   if (pressure >= 0.0)
     116             :     return 0.0;
     117     2715096 :   const Real x = (c - 1.0) * std::exp(c - 1.0 - c * pressure / las);
     118     2715096 :   const Real lamw = LambertW(x);
     119     2715096 :   return -(ss - sn) * Utility::pow<3>(c) / Utility::pow<2>(las) * lamw * (1.0 - 2.0 * lamw) /
     120     2715096 :          Utility::pow<5>(1.0 + lamw);
     121             : }
     122             : 
     123             : Real
     124     2743110 : dRelativePermeability(Real s, Real c, Real sn, Real ss, Real kn, Real ks)
     125             : {
     126     2743110 :   if (s <= sn)
     127             :     return 0.0;
     128             : 
     129     2743109 :   if (s >= ss)
     130             :     return 0.0;
     131             : 
     132     2718137 :   const Real coef = (ks - kn) * (c - 1.0);
     133     2718137 :   const Real th = (s - sn) / (ss - sn);
     134     2718137 :   const Real krelp = coef * (2.0 * th / (c - th) + Utility::pow<2>(th) / Utility::pow<2>(c - th));
     135     2718137 :   return krelp / (ss - sn);
     136             : }
     137             : 
     138             : Real
     139           3 : d2RelativePermeability(Real s, Real c, Real sn, Real ss, Real kn, Real ks)
     140             : {
     141           3 :   if (s <= sn)
     142             :     return 0.0;
     143             : 
     144           2 :   if (s >= ss)
     145             :     return 0.0;
     146             : 
     147           1 :   const Real coef = (ks - kn) * (c - 1.0);
     148           1 :   const Real th = (s - sn) / (ss - sn);
     149           1 :   const Real krelpp = coef * (2.0 / (c - th) + 4.0 * th / Utility::pow<2>(c - th) +
     150           1 :                               2.0 * Utility::pow<2>(th) / Utility::pow<3>(c - th));
     151           1 :   return krelpp / Utility::pow<2>(ss - sn);
     152             : }
     153             : }

Generated by: LCOV version 1.14