MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
gwf-sfr-steady.f90
Go to the documentation of this file.
1 submodule(sfrmodule) sfrmodulesteady
2 contains
3 
4  !> @brief Method for solving for standard reaches
5  !!
6  !! Method to solve the continuity equation for a SFR package
7  !! reach using the standard approach.
8  !!
9  !<
10  module procedure sfr_calc_steady
11  integer(I4B) :: i
12  integer(I4B) :: isolve
13  integer(I4B) :: iic
14  integer(I4B) :: iic2
15  integer(I4B) :: iic3
16  integer(I4B) :: iic4
17  integer(I4B) :: ibflg
18  real(DP) :: qmp
19  real(DP) :: qsrc
20  real(DP) :: qsrcmp
21  real(DP) :: tp
22  real(DP) :: bt
23  real(DP) :: hsfr
24  real(DP) :: qc
25  real(DP) :: en1
26  real(DP) :: en2
27  real(DP) :: qen1
28  real(DP) :: f1
29  real(DP) :: f2
30  real(DP) :: qgwf1
31  real(DP) :: qgwf2
32  real(DP) :: qgwfp
33  real(DP) :: qgwfold
34  real(DP) :: fhstr1
35  real(DP) :: fhstr2
36  real(DP) :: d2
37  real(DP) :: dpp
38  real(DP) :: dx
39  real(DP) :: q1
40  real(DP) :: q2
41  real(DP) :: derv
42  real(DP) :: dlh
43  real(DP) :: dlhold
44  real(DP) :: fp
45  real(DP) :: err
46  real(DP) :: errold
47 
48  d2 = dzero
49  q1 = dzero
50  q2 = dzero
51  qsrc = dzero
52  qgwf = dzero
53  qgwfold = dzero
54 
55  ! calculate the flow at end of the reach
56  ! excluding groundwater leakage
57  qc = qu + qi + qr - qe + qro + qfrommvr
58 
59  ! calculate flow at the middle of the reach
60  ! excluding groundwater leakage
61  qsrcmp = qu + qi + qfrommvr + dhalf * (qr - qe + qro)
62  qmp = qsrcmp ! initial estimate flow at the midpoint
63 
64  ! calculate stream depth at the midpoint
65  call this%sfr_calc_reach_depth(n, qmp, d1)
66 
67  ! calculate sources/sinks for reach
68  ! excluding groundwater leakage
69  call this%sfr_calc_qsource(n, d1, qsrc)
70 
71  ! calculate initial reach stage, downstream flow,
72  ! and groundwater leakage
73  tp = this%strtop(n)
74  bt = tp - this%bthick(n)
75  hsfr = d1 + tp
76  qd = max(qsrc, dzero)
77  qgwf = dzero
78  ! set flag to skip iterations
79  isolve = 1
80  if (hsfr <= tp .and. hgwf <= tp) isolve = 0
81  if (hgwf <= tp .and. qc < dem30) isolve = 0
82  if (this%sfr_gwf_conn(n) == 0) isolve = 0
83 
84  ! iterate to achieve solution
85  calc_solution: if (isolve /= 0) then
86 
87  ! estimate initial end points
88  en1 = dzero
89  if (d1 > dem30) then
90  if ((tp - hgwf) > dem30) then
91  en2 = dp9 * d1
92  else
93  en2 = d1p1 * d1 - (tp - hgwf)
94  end if
95  else if ((tp - hgwf) > dem30) then
96  en2 = done
97  else
98  en2 = dp99 * (hgwf - tp)
99  end if
100 
101  ! estimate flow at end points
102  ! end point 1
103  if (hgwf > tp) then
104  call this%sfr_calc_qgwf(n, dzero, hgwf, qgwf1)
105  qgwf1 = -qgwf1
106  qen1 = qmp - dhalf * qgwf1
107  else
108  qgwf1 = dzero
109  qen1 = qsrcmp
110  end if
111  if (hgwf > bt) then
112  call this%sfr_calc_qgwf(n, en2, hgwf, qgwf2)
113  qgwf2 = -qgwf2
114  else
115  call this%sfr_calc_qgwf(n, en2, bt, qgwf2)
116  qgwf2 = -qgwf2
117  end if
118  if (qgwf2 > qsrc) qgwf2 = qsrc
119 
120  ! calculate two depths
121  call this%sfr_calc_reach_depth(n, (qsrcmp - dhalf * qgwf1), d1)
122  call this%sfr_calc_reach_depth(n, (qsrcmp - dhalf * qgwf2), d2)
123 
124  ! determine roots
125  if (d1 > dem30) then
126  f1 = en1 - d1
127  else
128  en1 = dzero
129  f1 = en1 - dzero
130  end if
131  if (d2 > dem30) then
132  f2 = en2 - d2
133  if (f2 < dem30) en2 = d2
134  else
135  d2 = dzero
136  f2 = en2 - dzero
137  end if
138 
139  ! iterate to find a solution
140  dpp = dhalf * (en1 + en2)
141  dx = dpp
142  iic = 0
143  iic2 = 0
144  iic3 = 0
145  fhstr1 = dzero
146  fhstr2 = dzero
147  qgwfp = dzero
148  dlhold = dzero
149  do i = 1, this%maxsfrit
150  ibflg = 0
151  d1 = dpp
152  d2 = d1 + dtwo * this%deps
153  ! calculate q at midpoint at both end points
154  call this%sfr_calc_qman(n, d1, q1)
155  call this%sfr_calc_qman(n, d2, q2)
156  ! calculate groundwater leakage at both end points
157  call this%sfr_calc_qgwf(n, d1, hgwf, qgwf1)
158  qgwf1 = -qgwf1
159  call this%sfr_calc_qgwf(n, d2, hgwf, qgwf2)
160  qgwf2 = -qgwf2
161  !
162  if (qgwf1 >= qsrc) then
163  en2 = dpp
164  dpp = dhalf * (en1 + en2)
165  call this%sfr_calc_qgwf(n, dpp, hgwf, qgwfp)
166  qgwfp = -qgwfp
167  if (qgwfp > qsrc) qgwfp = qsrc
168  call this%sfr_calc_reach_depth(n, (qsrcmp - dhalf * qgwfp), dx)
169  ibflg = 1
170  else
171  fhstr1 = (qsrcmp - dhalf * qgwf1) - q1
172  fhstr2 = (qsrcmp - dhalf * qgwf2) - q2
173  end if
174  !
175  if (ibflg == 0) then
176  derv = dzero
177  if (abs(d1 - d2) > dzero) then
178  derv = (fhstr1 - fhstr2) / (d1 - d2)
179  end if
180  if (abs(derv) > dem30) then
181  dlh = -fhstr1 / derv
182  else
183  dlh = dzero
184  end if
185  dpp = d1 + dlh
186 
187  ! updated depth outside of endpoints - use bisection instead
188  if ((dpp >= en2) .or. (dpp <= en1)) then
189  if (abs(dlh) > abs(dlhold) .or. dpp < dem30) then
190  ibflg = 1
191  dpp = dhalf * (en1 + en2)
192  end if
193  end if
194 
195  ! check for slow convergence
196  ! set flags to determine if the Newton-Raphson method oscillates
197  ! or if convergence is slow
198  if (qgwf1 * qgwfold < dem30) then
199  iic2 = iic2 + 1
200  else
201  iic2 = 0
202  end if
203  if (qgwf1 < dem30) then
204  iic3 = iic3 + 1
205  else
206  iic3 = 0
207  end if
208  if (dlh * dlhold < dem30 .or. abs(dlh) > abs(dlhold)) then
209  iic = iic + 1
210  end if
211  iic4 = 0
212  if (iic3 > 7 .and. iic > 12) then
213  iic4 = 1
214  end if
215 
216  ! switch to bisection when the Newton-Raphson method oscillates
217  ! or when convergence is slow
218  if (iic2 > 7 .or. iic > 12 .or. iic4 == 1) then
219  ibflg = 1
220  dpp = dhalf * (en1 + en2)
221  end if
222  !
223  ! Calculate perturbed gwf flow
224  call this%sfr_calc_qgwf(n, dpp, hgwf, qgwfp)
225  qgwfp = -qgwfp
226  if (qgwfp > qsrc) then
227  qgwfp = qsrc
228  if (abs(en1 - en2) < this%dmaxchg * dem6) then
229  call this%sfr_calc_reach_depth(n, (qsrcmp - dhalf * qgwfp), dpp)
230  end if
231  end if
232  call this%sfr_calc_reach_depth(n, (qsrcmp - dhalf * qgwfp), dx)
233  end if
234 
235  ! bisection to update end points
236  fp = dpp - dx
237  if (ibflg == 1) then
238  dlh = fp
239  ! change end points
240  ! root is between f1 and fp
241  if (f1 * fp < dzero) then
242  en2 = dpp
243  f2 = fp
244  ! root is between fp and f2
245  else
246  en1 = dpp
247  f1 = fp
248  end if
249  err = min(abs(fp), abs(en2 - en1))
250  else
251  err = abs(dlh)
252  end if
253 
254  ! check for convergence and exit if converged
255  if (err < this%dmaxchg) then
256  d1 = dpp
257  qgwf = qgwfp
258  qd = qsrc - qgwf
259  exit
260  end if
261 
262  ! save iterates
263  errold = err
264  dlhold = dlh
265  if (ibflg == 1) then
266  qgwfold = qgwfp
267  else
268  qgwfold = qgwf1
269  end if
270 
271  end do
272  ! depth = 0 and hgwf < bt
273  else
274  call this%sfr_calc_qgwf(n, d1, hgwf, qgwf)
275  qgwf = -qgwf
276 
277  ! leakage exceeds inflow
278  if (qgwf > qsrc) then
279  d1 = dzero
280  call this%sfr_calc_qsource(n, d1, qsrc)
281  qgwf = qsrc
282  end if
283  qd = qsrc - qgwf
284  end if calc_solution
285 
286  end procedure sfr_calc_steady
287 end submodule
This module contains the SFR package methods.
Definition: gwf-sfr.f90:7