MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
FreundlichIsotherm.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b
5  use constantsmodule, only: dzero
6 
7  Implicit None
8  Private
9  Public :: freundlichisothermtype
10 
11  !> @brief Freundlich isotherm implementation of `IsothermType`.
12  !>
13  !> Sorbed concentration is cs = Kf*c^a.
14  !>
15  !> However, this expression has a singularity at c = 0 when a < 1,
16  !> leading to infinite derivative. To avoid this, the Freundlich isotherm
17  !> is modified as follows.
18  !>
19  !> Modified Sorbed concentration is cs = Kf*(c + eps)^a - Kf*eps^a
20  !> where eps = (K/(a*Kf))^(1/(a-1)) and K is a large constant (default 10).
21  !> This ensures that the derivative at c = 0 is below K.
22  !<
24  real(dp), pointer, dimension(:) :: kf => null() !< Freundlich constant
25  real(dp), pointer, dimension(:) :: a => null() !< Freundlich exponent
26  contains
27  procedure :: value
28  procedure :: derivative
29  end type freundlichisothermtype
30 
31  interface freundlichisothermtype
32  module procedure constructor
33  end interface freundlichisothermtype
34 
35 contains
36 
37  !> @brief Constructor for Freundlich isotherm
38  !<
39  function constructor(Kf, a) Result(isotherm)
40  type(freundlichisothermtype) :: isotherm
41  ! -- dummy
42  real(dp), pointer, dimension(:), intent(in) :: kf
43  real(dp), pointer, dimension(:), intent(in) :: a
44  ! -- local
45  isotherm%Kf => kf
46  isotherm%a => a
47 
48  end function constructor
49 
50  !> @brief Evaluate the isotherm at a given node
51  !<
52  function value(this, c, n) result(val)
53  ! -- return
54  real(dp) :: val !< isotherm value
55  ! -- dummy
56  class(freundlichisothermtype), intent(in) :: this
57  real(dp), dimension(:), intent(in) :: c !< concentration array
58  integer(I4B), intent(in) :: n !< node index
59  real(dp), parameter :: k = 10.0_dp !< constant to limit derivative at c=0
60  real(dp) :: eps !< small concentration offset
61 
62  eps = (k / (this%a(n) * this%Kf(n)))**(1.0_dp / (this%a(n) - 1.0_dp))
63 
64  if (c(n) > dzero) then
65  val = this%Kf(n) * (c(n) + eps)**this%a(n) - this%Kf(n) * eps**this%a(n)
66  else
67  val = 0.0_dp
68  end if
69  end function value
70 
71  !> @brief Evaluate derivative of the isotherm at a given node
72  !<
73  function derivative(this, c, n) result(derv)
74  ! -- return
75  real(dp) :: derv !< derivative d(value)/dc evaluated at c
76  ! -- dummy
77  class(freundlichisothermtype), intent(in) :: this
78  real(dp), dimension(:), intent(in) :: c !< concentration array
79  integer(I4B), intent(in) :: n !< node index
80  real(dp), parameter :: k = 10.0_dp !< constant to limit derivative at c=0
81  real(dp) :: eps !< small concentration offset
82 
83  eps = (k / (this%a(n) * this%Kf(n)))**(1.0_dp / (this%a(n) - 1.0_dp))
84 
85  if (c(n) > dzero) then
86  derv = this%a(n) * this%Kf(n) * ((c(n) + eps)**(this%a(n) - 1.0_dp))
87  else
88  derv = 0.0_dp
89  end if
90  end function derivative
91 
92 end module freundlichisothermmodule
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
real(dp) function value(this, c, n)
Evaluate the isotherm at a given node.
real(dp) function derivative(this, c, n)
Evaluate derivative of the isotherm at a given node.
type(freundlichisothermtype) function constructor(Kf, a)
Constructor for Freundlich isotherm.
This module defines variable data types.
Definition: kind.f90:8
Freundlich isotherm implementation of IsothermType.