MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
gwf-sfr-transient.f90
Go to the documentation of this file.
1 submodule(sfrmodule) sfrmoduletransient
2 contains
3 
4  !> @brief Method for solving for transient reaches
5  !!
6  !! Method to solve the continuity equation for a SFR package
7  !! reach using the kinematic wave approximation.
8  !!
9  !<
10  module procedure sfr_calc_transient
11  use tdismodule, only: delt
12 
13  integer(I4B) :: igwfconn
14  integer(I4B) :: number_picard
15  integer(I4B) :: i
16  integer(I4B) :: j
17  real(DP) :: kinematic_residual
18  real(DP) :: kinematic_storage
19  real(DP) :: weight
20  real(DP) :: celerity
21  real(DP) :: courant
22  real(DP) :: dq
23  real(DP) :: qtol
24  real(DP) :: qsrc
25  real(DP) :: qlat
26  real(DP) :: da
27  real(DP) :: db
28  real(DP) :: dc
29  real(DP) :: dd
30  real(DP) :: qa
31  real(DP) :: qb
32  real(DP) :: qc
33  real(DP) :: xsa_a
34  real(DP) :: xsa_b
35  real(DP) :: xsa_c
36  real(DP) :: q
37  real(DP) :: q2
38  real(DP) :: d
39  real(DP) :: d2
40  real(DP) :: a
41  real(DP) :: a2
42  real(DP) :: d1old
43  real(DP) :: qd2
44  real(DP) :: ad
45  real(DP) :: ad2
46  real(DP) :: residual
47  real(DP) :: residual2
48  real(DP) :: residual_final
49  real(DP) :: qderv
50  real(DP) :: delq
51  real(DP) :: delh
52  real(DP) :: dd2
53 
54  weight = this%storage_weight
55  dq = this%deps
56  qtol = dq * dtwo
57 
58  celerity = dzero
59  qgwf = dzero
60 
61  qlat = qr + qro - qe
62 
63  this%usinflow(n) = qu + qi + qfrommvr
64 
65  qa = this%usinflowold(n)
66  qb = this%dsflowold(n)
67  call this%sfr_calc_reach_depth(n, qa, da)
68  call this%sfr_calc_reach_depth(n, qb, db)
69 
70  qc = this%usinflow(n)
71  call this%sfr_calc_reach_depth(n, qc, dc)
72 
73  xsa_a = this%calc_area_wet(n, da)
74  xsa_b = this%calc_area_wet(n, db)
75  xsa_c = this%calc_area_wet(n, dc)
76 
77  ! estimate qd
78  qd = this%dsflow(n)
79  if (qd == dzero) then
80  qd = (qc + qb) * dhalf
81  end if
82  call this%sfr_calc_reach_depth(n, qd, dd)
83  ad = this%calc_area_wet(n, dd)
84 
85  ! estimate the depth at the midpoint
86  d1 = (dc + dd) * dhalf
87  d1old = d1
88 
89  ! estimate qgwf
90  igwfconn = this%sfr_gwf_conn(n)
91  if (igwfconn == 1) then
92  q = qu + qi + qr - qe + qro + qfrommvr
93  call this%sfr_calc_qgwf(n, d1, hgwf, qgwf)
94  qgwf = -qgwf
95  if (qgwf > q) then
96  qgwf = q
97  end if
98  end if
99 
100  ! calculate maximum wave speed and courant number
101  q = qc + qlat - qgwf
102  call this%sfr_calc_reach_depth(n, q, d)
103  a = this%calc_area_wet(n, d)
104  if (d > dzero) then
105  q2 = q + dq
106  call this%sfr_calc_reach_depth(n, q2, d2)
107  a2 = this%calc_area_wet(n, d2)
108  celerity = (q2 - q) / (a2 - a)
109  courant = celerity * delt / this%length(n)
110  ! write(*,*) this%length(n), courant * delt
111  end if
112 
113  qlat = qlat / this%length(n)
114 
115  number_picard = this%maxsfrpicard
116  if (igwfconn == 1) then
117  number_picard = this%maxsfrpicard
118  else
119  number_picard = 1
120  end if
121 
122  kinematicpicard: do i = 1, number_picard
123  if (igwfconn == 1) then
124  q = qu + qi + qr - qe + qro + qfrommvr
125  call this%sfr_calc_qgwf(n, d1, hgwf, qgwf)
126  qgwf = -qgwf
127  if (qgwf > q) then
128  qgwf = q
129  end if
130  end if
131 
132  qsrc = qlat - qgwf / this%length(n)
133 
134  newton: do j = 1, this%maxsfrit
135  qd2 = qd + dq
136  call this%sfr_calc_reach_depth(n, qd2, dd2)
137  ad2 = this%calc_area_wet(n, dd2)
138 
139  residual = kinematic_residual(qa, qb, qc, qd, &
140  xsa_a, xsa_b, xsa_c, ad, &
141  qsrc, this%length(n), weight, delt, &
142  courant)
143 
144  residual2 = kinematic_residual(qa, qb, qc, qd2, &
145  xsa_a, xsa_b, xsa_c, ad2, &
146  qsrc, this%length(n), weight, delt, &
147  courant)
148  qderv = (residual2 - residual) / dq
149  if (qderv > dzero) then
150  delq = -residual / qderv
151  else
152  delq = dzero
153  end if
154 
155  if (qd + delq < dem30) then
156  delq = -qd
157  end if
158 
159  qd = qd + delq
160 
161  call this%sfr_calc_reach_depth(n, qd, dd)
162  ad = this%calc_area_wet(n, dd)
163  residual_final = kinematic_residual(qa, qb, qc, qd, &
164  xsa_a, xsa_b, xsa_c, ad, &
165  qsrc, this%length(n), weight, delt, &
166  courant)
167 
168  if (abs(delq) < qtol .and. abs(residual_final) < qtol) then
169  exit newton
170  end if
171 
172  end do newton
173 
174  qd = max(qd, dzero)
175  d1 = (dc + dd) * dhalf
176  delh = (d1 - d1old)
177 
178  if (i > 1 .and. abs(delh) < this%dmaxchg) then
179  exit kinematicpicard
180  end if
181 
182  end do kinematicpicard
183 
184  this%storage(n) = kinematic_storage(xsa_a, xsa_b, xsa_c, ad, &
185  this%length(n), delt, &
186  courant)
187 
188  end procedure sfr_calc_transient
189 
190 end submodule
real(dp) function kinematic_storage(aa, ab, ac, ad, length, delt, courant)
Kinematic routing equation storage term.
real(dp) function kinematic_residual(qa, qb, qc, qd, aa, ab, ac, ad, qsrc, length, weight, delt, courant)
Kinematic routing equation residual.
This module contains the SFR package methods.
Definition: gwf-sfr.f90:7
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:29