43 real(dp),
dimension(:),
pointer :: phi
45 integer(I4B) :: limiter_id = 2
46 real(dp),
dimension(:, :),
allocatable :: cached_node_distance
63 result(interpolation_scheme)
69 class(
igradienttype),
allocatable,
intent(in),
target :: gradient
71 interpolation_scheme%dis => dis
72 interpolation_scheme%fmi => fmi
74 interpolation_scheme%gradient => gradient
77 allocate (interpolation_scheme%cached_node_distance(dis%njas, 3))
86 deallocate (this%cached_node_distance)
99 real(DP),
intent(in),
dimension(:),
pointer :: phi
102 call this%gradient%set_field(phi)
103 call this%min_max_phi%set_field(phi)
106 function compute(this, n, m, iposnm)
result(phi_face)
111 integer(I4B),
intent(in) :: n
112 integer(I4B),
intent(in) :: m
113 integer(I4B),
intent(in) :: iposnm
115 integer(I4B) :: iup, idn, isympos
117 real(dp),
pointer :: coef_up, coef_dn
118 real(dp),
dimension(3) :: grad_c
119 real(dp),
dimension(3) :: dnm
123 real(dp) :: relative_distance
124 real(dp) :: c_virtual
125 real(dp),
pointer :: min_phi, max_phi
127 isympos = this%dis%con%jas(iposnm)
128 qnm = this%fmi%gwfflowja(iposnm)
131 if (qnm >
dzero)
then
136 cl1 = this%dis%con%cl2(isympos)
137 cl2 = this%dis%con%cl1(isympos)
139 coef_up => phi_face%c_m
140 coef_dn => phi_face%c_n
145 cl1 = this%dis%con%cl1(isympos)
146 cl2 = this%dis%con%cl2(isympos)
148 coef_up => phi_face%c_n
149 coef_dn => phi_face%c_m
158 dnm = -this%cached_node_distance(isympos, :)
160 dnm = this%cached_node_distance(isympos, :)
169 if (abs(this%phi(idn) - this%phi(iup)) <
dsame)
return
172 grad_c = this%gradient%get(iup)
175 c_virtual = this%phi(idn) - 2.0_dp * (dot_product(grad_c, dnm))
180 min_phi => this%min_max_phi%get_min(iup)
181 max_phi => this%min_max_phi%get_max(iup)
183 if (c_virtual > max_phi)
then
187 if (c_virtual < max(min_phi,
dzero))
then
188 c_virtual = max(min_phi,
dzero)
192 smooth = (this%phi(iup) - c_virtual) / (this%phi(idn) - this%phi(iup))
195 alimiter = this%limiter(smooth)
198 relative_distance = cl1 / (cl1 + cl2)
199 phi_face%rhs = -relative_distance * alimiter * (this%phi(idn) - this%phi(iup))
217 select case (this%limiter_id)
219 theta = max(0.0_dp, min((r + dabs(r)) / (1.0_dp + dabs(r)), 2.0_dp))
221 theta = max(0.0_dp, min(2.0_dp * r, &
222 1.0_dp / 3.0_dp + 2.0_dp / 3.0_dp * r, 2.0_dp))
224 theta = max(0.0_dp, min(2.0_dp * r, 1.0_dp), min(r, 2.0_dp))
226 theta = max(0.0_dp, (r * r + r) / (r * r + 1.0_dp))
228 theta = max(0.0_dp, min(4.0_dp * r * r + r, &
229 1.0_dp / 3.0_dp + 2.0_dp / 3.0_dp * r, 2.0_dp))
239 integer(I4B) :: n, m, ipos, isympos
241 this%cached_node_distance = 0.0_dp
242 do n = 1, this%dis%nodes
243 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
244 m = this%dis%con%ja(ipos)
247 isympos = this%dis%con%jas(ipos)
248 this%cached_node_distance(isympos, :) =
node_distance(this%dis, n, m)
This module contains simulation constants.
real(dp), parameter dsame
real constant for values that are considered the same based on machine precision
real(dp), parameter dhalf
real constant 1/2
real(dp), parameter dzero
real constant zero
real(dp), parameter done
real constant 1
real(dp) function, dimension(3), public node_distance(dis, n, m)
Returns the vector distance from cell n to cell m.
This module defines variable data types.
type(coefficientstype) function, target compute(this, n, m, iposnm)
subroutine set_field(this, phi)
Set the scalar field for which interpolation will be computed.
subroutine destructor(this)
type(utvdschemetype) function constructor(dis, fmi, gradient)
subroutine compute_node_distance(this)
real(dp) function limiter(this, r)
Abstract interface for cell-based gradient computation.
Computes and caches local extrema for each cell and its connected neighbors.
Total Variation Diminishing (TVD) interpolation scheme.