2 ! Author(s)/Contact(s):
7 ! Parameters: <Specify typical arguments passed>
9 ! <list file names and briefly describe the data they include>
11 ! <list file names and briefly describe the information they include>
14 ! <list exit condition or error codes returned >
15 ! If appropriate, descriptive troubleshooting instructions or
16 ! likely causes for failures could be mentioned here with the
17 ! appropriate error code
19 ! User controllable options: <if applicable>
21 MODULE module_channel_routing
24 use MODULE_mpp_ReachLS, only : updatelinkv, &
25 ReachLS_write_io, gbcastvalue, &
29 use module_reservoir, only: reservoir
30 use module_RT_data, only: rt_domain
31 use module_hydro_stop, only: HYDRO_stop
33 use iso_fortran_env, only: int64
40 ! ------------------------------------------------
42 ! ------------------------------------------------
43 real function MUSKING(idx,qup,quc,qdp,dt,Km,X)
49 real :: Km !K travel time in hrs in reach
50 real :: X !weighting factors 0<=X<=0.5
51 real :: dt !routing period in hrs
52 real :: avgbf !average base flow for initial condition
53 real :: qup !inflow from previous timestep
54 real :: quc !inflow of current timestep
55 real :: qdp !outflow of previous timestep
56 real :: dth !timestep in hours
57 integer :: idx ! index
59 dth = dt/3600. !hours in timestep
60 C1 = (dth - 2.0 *Km*X)/(2.0*Km*(1.0-X)+dth)
61 C2 = (dth+2.0*Km*X)/(2.0*Km*(1.0-X)+dth)
62 C3 = (2.0*Km*(1.0-X)-dth)/(2.0*Km*(1.0-X)+dth)
63 MUSKING = (C1*quc)+(C2*qup)+(C3*qdp)
65 ! ----------------------------------------------------------------
67 ! ----------------------------------------------------------------
70 ! ------------------------------------------------
71 ! FUNCTION Diffusive wave
72 ! ------------------------------------------------
73 real function DIFFUSION(nod,z1,z20,h1,h2,dx,n, &
76 !-- channel geometry and characteristics
77 real :: Bw !-bottom width (meters)
78 real :: Cs !-Channel side slope slope
79 real :: dx !-channel lngth (m)
80 real,intent(in) :: n !-mannings coefficient
81 real :: R !-Hydraulic radius
82 real :: AREA !- wetted area
83 real :: h1,h2 !-tmp height variables
84 real :: z1,z2 !-z1 is 'from', z2 is 'to' elevations
85 real :: z !-channel side distance
86 real :: w !-upstream weight
87 real :: Ku,Kd !-upstream and downstream conveyance
88 real :: Kf !-final face conveyance
89 real :: Sf !-friction slope
91 integer :: nod !- node
94 ! added by Wei Yu for bad data.
97 if(dzx .lt. 0.002) then
104 if (n.le.0.0.or.Cs.le.0.or.Bw.le.0) then
105 print *, "Error in Diffusion function ->channel coefficients"
106 print *, "nod, n, Cs, Bw", nod, n, Cs, Bw
107 call hydro_stop("In DIFFUSION() - Error channel coefficients.")
110 ! Sf = ((z1+h1)-(z2+h2))/dx !-- compute the friction slope
112 ! Sf = ((z1-(z2-0.01))+(h1-h2))/dx !-- compute the friction slope
114 ! Sf = ((z1-z2)+(h1-h2))/dx !-- compute the friction slope
117 !modifieed by Wei Yu for false geography data
118 if(abs(z1-z2) .gt. 1.0E5) then
120 print*, "WARNING: huge slope rest to 0 for channel grid.", z1,z2
122 Sf = ((h1-h2))/dx !-- compute the friction slope
124 Sf = ((z1-z2)+(h1-h2))/dx !-- compute the friction slope
128 sgn = SGNf(Sf) !-- establish sign
130 w = 0.5*(sgn + 1.) !-- compute upstream or downstream weighting
132 z = 1.0/Cs !--channel side distance (m)
133 R = ((Bw + z*h1)*h1) / (Bw+ 2.0*h1*sqrt(1.0 + z*z)) !-- Hyd Radius
134 AREA = (Bw + z*h1)*h1 !-- Flow area
135 Ku = (1.0/n)*(R**(2./3.))*AREA !-- convenyance
137 R = ((Bw + z*h2)*h2)/(Bw + 2.0*h2*sqrt(1.0 + z*z)) !-- Hyd Radius
138 AREA = (Bw + z*h2)*h2 !-- Flow area
139 Kd = (1.0/n)*(R**(2.0/3.0))*AREA !-- convenyance
141 Kf = (1.0-w)*Kd + w*Ku !-- conveyance
142 DIFFUSION = Kf * sqrt(abs(Sf))*sgn
145 100 format('z1,z2,h1,h2,kf,Dif, Sf, sgn ',f8.3,2x,f8.3,2x,f8.4,2x,f8.4,2x,f8.3,2x,f8.3,2x,f8.3,2x,f8.0)
147 end function DIFFUSION
148 ! ----------------------------------------------------------------
150 subroutine SUBMUSKINGCUNGE( &
151 qdc, vel, qloss, idx, qup, quc, &
152 qdp, ql, dt, So, dx, &
153 n, Cs, Bw, Tw, TwCC, &
157 use module_RT_data, only: rt_domain !! JLM: this is only used in a c3 paramter diagnostic print
162 REAL, intent(IN) :: dt ! routing period in seconds
163 REAL, intent(IN) :: qup ! flow upstream previous timestep
164 REAL, intent(IN) :: quc ! flow upstream current timestep
165 REAL, intent(IN) :: qdp ! flow downstream previous timestep
166 REAL, intent(INOUT) :: qdc ! flow downstream current timestep
167 REAL, intent(IN) :: ql ! lateral inflow through reach (m^3/sec)
168 REAL, intent(IN) :: Bw ! bottom width (meters)
169 REAL, intent(IN) :: Tw ! top width before bankfull (meters)
170 REAL, intent(IN) :: TwCC ! top width of Compund (meters)
171 REAL, intent(IN) :: nCC ! mannings of compund
172 REAL, intent(IN) :: ChannK ! Channel conductivity (m/s)
173 REAL, intent(IN) :: Cs ! Channel side slope slope
174 REAL, intent(IN) :: So ! Channel bottom slope %
175 REAL, intent(IN) :: dx ! channel lngth (m)
176 REAL, intent(IN) :: n ! mannings coefficient
177 REAL, intent(INOUT) :: vel ! velocity (m/s)
178 REAL, intent(INOUT) :: qloss ! channel infiltration (m^3/sec)
179 integer(kind=int64), intent(IN) :: idx ! channel id
180 REAL, intent(INOUT) :: depth ! depth of flow in channel
183 REAL :: C1, C2, C3, C4
184 REAL :: Km !K travel time in hrs in reach
185 REAL :: X !weighting factors 0<=X<=0.5
186 REAL :: Ck ! wave celerity (m/s)
188 !-- channel geometry and characteristics, local variables
189 REAL :: Twl ! top width at simulated flow (m)
190 REAL :: AREA,AREAC ! Cross sectional area channel and compound m^2
191 REAL :: Z ! trapezoid distance (m)
192 REAL :: R,RC ! Hydraulic radius of channel and compound
193 REAL :: WP,WPC ! wetted perimmeter of channel and compound
194 REAL :: h ! depth of flow in channel
195 REAL :: h_0,h_1 ! secant method estimates
196 REAL :: bfd ! bankfull depth (m)
197 REAL :: Qj_0 ! secant method estimates
198 REAL :: Qj ! intermediate flow estimate
199 REAL :: D,D1 ! diffusion coeff
200 REAL :: dtr ! required timestep, minutes
201 REAL :: aerror,rerror ! absolute and relative error
202 REAL :: hp ! courant, previous height
203 INTEGER :: iter, maxiter ! maximum number of iterations
205 !-- additional channel infiltration parameters
206 REAL :: WPk ! KINEROS2 modified wetted perimeter
207 REAL :: modK ! KINEROS2 constant (set to 0.15, line )
209 !-- local variables.. needed if channel is sub-divded
211 REAL :: mindepth ! minimum depth in channel
212 INTEGER :: i,tries !-- channel segment counter
214 !TML-- Hard code KINEROS2 Modification Parameter
215 !TML-- Set to 0.15, consistent with USDA-ARS
218 c = 0.52 !-- coefficnets for finding dx/Ckdt
227 !------------- locals
228 if(Cs .eq. 0.00000000) then
231 z = 1.0/Cs !channel side distance (m)
234 if(Bw .gt. Tw) then !effectively infinite deep bankful
236 elseif (Bw .eq. Tw) then
237 bfd = Bw/(2.0*z) !bankfull depth is effectively
239 bfd = (Tw - Bw)/(2.0*z) !bankfull depth (m)
241 !qC = quc + ql !current upstream in reach
243 if (n .le. 0.0 .or. So .le. 0.0 .or. z .le. 0.0 .or. Bw .le. 0.0) then
244 print*, "Error in channel coefficients -> Muskingum cunge", n, So, z, Bw
245 call hydro_stop("In MUSKINGCUNGE() - Error in channel coefficients")
248 !------------- Secant Method
249 depth = max(depth, 0.0)
250 h = (depth * 1.33) + mindepth !1.50 of depth
251 h_0 = (depth * 0.67) !0.50 of depth
253 if(ql .gt. 0.0 .or. qup .gt. 0.0 .or. qdp .gt. 0.0) then !only solve if there's water to flux
257 Qj_0 = 0.0 !- initial flow of lower interval
260 do while (rerror .gt. 0.01 .and. aerror .ge. mindepth .and. iter .le. maxiter)
265 !----- lower interval --------------------
267 Twl = Bw + 2.0*z*h_0 !--top surface water width of the channel inflow
269 if ( (h_0 .gt. bfd) .and. (TwCC .gt. 0.0) .and. (nCC .gt. 0.0) ) then !water outside of defined channel
270 AREA = (Bw + bfd * z) * bfd
271 AREAC = (TwCC * (h_0 -bfd)) !assume compound component is rect. chan, that's 3 times the Tw
272 WP = (Bw + 2.0 * bfd * sqrt(1.0 + z*z))
273 WPC = TwCC + (2.0 * (h_0-bfd)) !WPC is 2 times the Tw
274 WPk = WP + WPC*MIN((h_0/(modK*SQRT(Bw))),1.0) ! KINEROS2 Mod.
275 R = (AREA + AREAC)/(WP +WPC) ! hydraulic radius
277 AREA = (Bw + h_0 * z ) * h_0
278 WP = (Bw + 2.0 * h_0 * sqrt(1.0 + z*z))
279 WPk = WP*MIN((h_0/(modK*SQRT(Bw))),1.0) ! KINEROS2 Mod.
288 if ( (h_0 .gt. bfd) .and. (TwCC .gt. 0.0) .and. (nCC .gt. 0.0) ) then !water outside of defined channel
289 !weight the celerity by the contributing area, and assume that the mannings
290 !of the spills is 2x the manning of the channel
291 Ck = max(0.0,((sqrt(So)/n)*((5./3.)*R**(2./3.) - &
292 ((2./3.)*R**(5./3.)*(2.0*sqrt(1.0 + z*z)/(Bw+2.0*bfd*z))))*AREA &
293 + ((sqrt(So)/(nCC))*(5./3.)*(h_0-bfd)**(2./3.))*AREAC)/(AREA+AREAC))
295 if(h_0 .gt. 0.0) then
296 Ck = max(0.0,(sqrt(So)/n)*((5./3.)*R**(2./3.) - &
297 ((2./3.)*R**(5./3.)*(2.0*sqrt(1.0 + z*z)/(Bw+2.0*h_0*z)))))
303 if(Ck .gt. 0.000000) then
309 if ( (h_0 .gt. bfd) .and. (TwCC .gt. 0.0) .and. (nCC .gt. 0.0) .and. (Ck .gt. 0.0) ) then
310 !water outside of defined channel
311 X = min(0.5,max(0.0,0.5*(1-(Qj_0/(2.0*TwCC*So*Ck*dx)))))
314 X = min(0.5,max(0.0,0.5*(1-(Qj_0/(2.0*Twl*So*Ck*dx)))))
320 D = (Km*(1.000 - X) + dt/2.0000) !--seconds
322 print *, "FATAL ERROR: D is 0 in MUSKINGCUNGE", Km, X, dt,D
323 call hydro_stop("In MUSKINGCUNGE() - D is 0.")
326 C1 = (Km*X + dt/2.000000)/D
327 C2 = (dt/2.0000 - Km*X)/D
328 C3 = (Km*(1.00000000-X)-dt/2.000000)/D
329 ! C1 = max(0.0,min(1.0,1.0-C3))
330 if(ChannK .le. 0.0) then ! Disable channel loss for zero ChannK
333 !C4 = (ql*dt)/D - (ChannK * dx * WPk) !-- DY & LKR lat inflow + channel loss
334 C4 = ((ql - (ChannK * dx * WPk))*dt)/D !-- TML: Loss adjusted by dt/D, closes water balance
337 if((WP+WPC) .gt. 0.0) then !avoid divide by zero
338 ! Another sanity check, prevent channel loss from exceeding flow
339 if( (C4 .lt. 0.0) .and. (abs(C4) .gt. (C1*qup)+(C2*quc)+(C3*qdp)) ) then
340 C4 = -((C1*qup)+(C2*quc)+(C3*qdp))
342 Qj_0 = ((C1*qup)+(C2*quc)+(C3*qdp) + C4) - ((1/(((WP*n)+(WPC*nCC))/(WP+WPC))) * &
343 (AREA+AREAC) * (R**(2./3.)) * sqrt(So)) !f0(x)
345 ! WPk = WP*MIN((h/(modK*SQRT(Bw))),1.0) ! KINEROS2 Mod. This shouldn't be HERE.
347 !--upper interval -----------
351 Twl = Bw + 2.0*z*h !--top width of the channel inflow
353 if ( (h .gt. bfd) .and. (TwCC .gt. 0.0) .and. (nCC .gt. 0.0) ) then !water outside of defined channel
354 AREA = (Bw + bfd * z) * bfd
355 AREAC = (TwCC * (h-bfd)) !assume compound component is rect. chan, that's 3 times the Tw
356 WP = (Bw + 2.0 * bfd * sqrt(1.0 + z*z))
357 WPC = TwCC + (2.0*(h-bfd)) !the additional wetted perimeter
358 WPk = WP + WPC*MIN((h/(modK*SQRT(Bw))),1.0) ! KINEROS2 Mod.
359 R = (AREA + AREAC)/(WP +WPC)
362 AREA = (Bw + h * z ) * h
363 WP = (Bw + 2.0 * h * sqrt(1.000000 + z*z))
364 WPk = WP*MIN((h/(modK*SQRT(Bw))),1.0) ! KINEROS2 Mod.
372 if ( (h .gt. bfd) .and. (TwCC .gt. 0.0) .and. (nCC .gt. 0.0) ) then
373 !water outside of defined channel, assumed rectangular, 3x TW and n = 3x
374 Ck = max(0.0,((sqrt(So)/n)*((5./3.)*R**(2./3.) - &
375 ((2./3.)*R**(5./3.)*(2.0*sqrt(1.0 + z*z)/(Bw + 2.0*bfd*z))))*AREA &
376 + ((sqrt(So)/(nCC))*(5./3.)*(h-bfd)**(2./3.))*AREAC)/(AREA+AREAC))
378 if(h .gt. 0.0) then !avoid divide by zero
379 Ck = max(0.0,(sqrt(So)/n)*((5./3.)*R**(2./3.) - &
380 ((2./3.)*R**(5./3.)*(2.0 * sqrt(1.0 + z*z)/(Bw + 2.0*h*z)))))
392 if ( (h .gt. bfd) .and. (TwCC .gt. 0.0) .and. (nCC .gt. 0.0) .and. (Ck .gt. 0.0) ) then
393 !water outside of defined channel
394 X = min(0.5,max(0.25,0.5*(1-(((C1*qup)+(C2*quc)+(C3*qdp) + C4)/(2.0*TwCC*So*Ck*dx)))))
397 X = min(0.5,max(0.25,0.5*(1-(((C1*qup)+(C2*quc)+(C3*qdp) + C4)/(2.0*Twl*So*Ck*dx)))))
403 D = (Km*(1 - X) + dt/2) !--seconds
405 print *, "FATAL ERROR: D is 0 in MUSKINGCUNGE", Km, X, dt,D
406 call hydro_stop("In MUSKINGCUNGE() - D is 0.")
409 C1 = (Km*X + dt/2.000000)/D
410 C2 = (dt/2.000000 - Km*X)/D
411 C3 = (Km*(1.000000-X)-dt/2.000000)/D
412 ! C1 = max(0.0,min(1.0,1.0-C3)) !! eliminate influence of upstream current
413 if(ChannK .le. 0.0) then ! Disable channel loss for zero ChannK
416 !C4 = (ql*dt)/D - (ChannK * dx * WPk) !-- (loss units: m/s * m * m)
417 C4 = ((ql - (ChannK * dx * WPk))*dt)/D !-- TML: Loss adjusted by dt/D, closes water balance
420 if( (C4 .lt. 0.0) .and. (abs(C4) .gt. (C1*qup)+(C2*quc)+(C3*qdp))) then
421 C4 = -((C1*qup)+(C2*quc)+(C3*qdp))
424 if((WP+WPC) .gt. 0.0) then
425 if( (C4 .lt. 0.0) .and. (abs(C4) .gt. (C1*qup)+(C2*quc)+(C3*qdp))) then
426 C4 = -((C1*qup)+(C2*quc)+(C3*qdp))
428 Qj = ((C1*qup)+(C2*quc)+(C3*qdp) + C4) - ((1.0000000/(((WP*n)+(WPC*nCC))/(WP+WPC))) * &
429 (AREA+AREAC) * (R**(2./3.)) * sqrt(So)) !f(x)
432 if(Qj_0-Qj .ne. 0.0) then
433 h_1 = h - ((Qj * (h_0 - h))/(Qj_0 - Qj)) !update h, 3rd estimate
434 if(h_1 .lt. 0.0) then
442 rerror = abs((h_1 - h)/h) !relative error is new estatimate and 2nd estimate
443 aerror = abs(h_1 -h) !absolute error
449 ! if(idx .eq. 6276407) then
450 ! print*, "err,itr,hs", rerror, iter, depth, h_0, h, h_1
457 if( h .lt. mindepth) then ! exit loop if depth is very small
463 ! if(idx .eq. 6276407) then
464 ! print*, "id,itr,err,h", idx, iter, rerror, h
469 if(iter .ge. maxiter) then
472 if(tries .le. 4) then ! expand the search space
475 maxiter = maxiter + 25 !and increase the number of allowable iterations
479 print*, "Musk Cunge WARNING: Failure to converge"
480 print*, 'RouteLink index:', idx + linkls_s(my_id+1) - 1
481 print*, "id,err,iters,tries", idx, rerror, iter, tries
482 print*, "Ck,X,dt,Km",Ck,X,dt,Km
483 print*, "So,dx,h",So,dx,h
484 print*, "qup,quc,qdp,ql", qup,quc,qdp,ql
485 print*, "bfd,Bw,Tw,Twl", bfd,Bw,Tw,Twl
486 print*, "Qmc,Qmn", (C1*qup)+(C2*quc)+(C3*qdp) + C4,((1/(((WP*n)+(WPC*nCC))/(WP+WPC))) * &
487 (AREA+AREAC) * (R**(2./3.)) * sqrt(So))
492 !! Getting information on c3.
493 !if(rt_domain(1)%gages(idx + linkls_s(my_id+1) - 1) .ne. rt_domain(1)%gageMiss) then
494 ! print*, rt_domain(1)%gages(idx+linkls_s(my_id+1)-1)
495 ! if(rt_domain(1)%gages(idx) .ne. rt_domain(1)%gageMiss) then
496 ! print*, rt_domain(1)%gages(idx)
497 ! print*,'JLM submuskcunge idx, C3, C, D:', idx + linkls_s(my_id+1) - 1, C3, dt/(2*Km), X
502 !DY and LKR Added to update for channel loss
503 if(((C1*qup)+(C2*quc)+(C3*qdp) + C4) .lt. 0.0) then
504 ! MUSKINGCUNGE = MAX( ( (C1*qup)+(C2*quc) + C4),((C1*qup)+(C3*qdp) + C4) )
505 if( (C4 .lt. 0.0) .and. (abs(C4) .gt. (C1*qup)+(C2*quc)+(C3*qdp)) ) then ! channel loss greater than water in chan
508 qdc = MAX( ( (C1*qup)+(C2*quc) + C4),((C1*qup)+(C3*qdp) + C4) )
511 ! MUSKINGCUNGE = ((C1*qup)+(C2*quc)+(C3*qdp) + C4) !-- pg 295 Bedient huber
512 qdc = ((C1*qup)+(C2*quc)+(C3*qdp) + C4) !-- pg 295 Bedient huber
517 R = (h*(Bw + Twl) / 2.0) / (Bw + 2.0*(((Twl - Bw) / 2.0)**2.0 + h**2)**0.5)
518 vel = (1./n) * (R **(2.0/3.0)) * sqrt(So) ! average velocity in m/s
521 else ! no flow to route
526 qloss = (ChannK * dx * WPk) ! TML -- Compute qloss to pass
528 !TML:Added print statement to test qlos function;
529 !comment out to prevent excessive file sizes when running model
530 !print*, "qloss,dx,WP,WPk,depth,ChannK,qdc,ql,dt,D", qloss,dx,WP,WPk,depth,ChannK,qdc,ql,dt,D
531 if((qloss*dt)/D > ((ql*dt)/D - C4)) then
532 qloss = ql - C4*(D/dt)
534 print*, 'WARNING CHANNEL LOSS IS NEGATIVE',qloss
538 ! ----------------------------------------------------------------
539 END SUBROUTINE SUBMUSKINGCUNGE
540 ! ----------------------------------------------------------------
542 ! ------------------------------------------------
544 ! ------------------------------------------------
545 REAL FUNCTION KINEMATIC()
549 ! -------- DECLARATIONS -----------------------
551 ! REAL, INTENT(OUT), DIMENSION(IXRT,JXRT) :: OVRGH
554 !----------------------------------------------------------------
555 END FUNCTION KINEMATIC
556 !----------------------------------------------------------------
559 ! ------------------------------------------------
560 ! SUBROUTINE drive_CHANNEL
561 ! ------------------------------------------------
562 ! ------------------------------------------------
563 Subroutine drive_CHANNEL(did, latval,lonval,KT, IXRT,JXRT, SUBRTSWCRT, &
564 QSUBRT, LAKEINFLORT, QSTRMVOLRT, TO_NODE, FROM_NODE, &
565 TYPEL, ORDER, MAXORDER, NLINKS, CH_NETLNK, CH_NETRT, CH_LNKRT, &
566 LAKE_MSKRT, DT, DTCT, DTRT_CH,MUSK, MUSX, QLINK, &
568 HLINK, ELRT, CHANLEN, MannN, So, ChSSlp, Bw, Tw, Tw_CC, n_CC, &
570 ZELEV, CVOL, NLAKES, QLAKEI, QLAKEO, LAKENODE, &
571 dist, QINFLOWBASE, CHANXI, CHANYJ, channel_option, RETDEP_CHAN, &
572 NLINKSL, LINKID, node_area &
574 , lake_index,link_location,mpp_nlinks,nlinks_index,yw_mpp_nlinks &
576 , gtoNode,toNodeInd,nToNodeInd &
579 ,gwBaseSwCRT, gwHead, qgw_chanrt, gwChanCondSw, gwChanCondConstIn, &
580 gwChanCondConstOut, velocity, qloss)
585 ! -------- DECLARATIONS ------------------------
586 INTEGER, INTENT(IN) :: did, IXRT,JXRT,channel_option
587 INTEGER, INTENT(IN) :: NLINKS,NLAKES, NLINKSL
588 integer, INTENT(INOUT) :: KT ! flag of cold start (1) or continue run.
589 REAL, INTENT(IN), DIMENSION(IXRT,JXRT) :: QSUBRT
590 REAL, INTENT(IN), DIMENSION(IXRT,JXRT) :: QSTRMVOLRT
591 REAL, INTENT(IN), DIMENSION(IXRT,JXRT) :: LAKEINFLORT
592 REAL, INTENT(IN), DIMENSION(IXRT,JXRT) :: ELRT
593 REAL, INTENT(IN), DIMENSION(IXRT,JXRT) :: QINFLOWBASE
594 INTEGER(kind=int64), INTENT(IN), DIMENSION(IXRT,JXRT) :: CH_NETLNK
596 INTEGER, INTENT(IN), DIMENSION(IXRT,JXRT) :: CH_NETRT
597 INTEGER(kind=int64), INTENT(IN), DIMENSION(IXRT,JXRT) :: CH_LNKRT
598 INTEGER(kind=int64), INTENT(IN), DIMENSION(IXRT,JXRT) :: CH_LNKRT_SL
600 real , dimension(ixrt,jxrt):: latval,lonval
602 INTEGER, INTENT(IN), DIMENSION(IXRT,JXRT) :: LAKE_MSKRT
603 INTEGER, INTENT(IN), DIMENSION(NLINKS) :: ORDER, TYPEL !--link
604 INTEGER(kind=int64), INTENT(IN), DIMENSION(NLINKS) :: TO_NODE, FROM_NODE
605 INTEGER, INTENT(IN), DIMENSION(NLINKS) :: CHANXI, CHANYJ
606 REAL, INTENT(IN), DIMENSION(NLINKS) :: ZELEV !--elevation of nodes
607 REAL, INTENT(INOUT), DIMENSION(NLINKS) :: CVOL
608 REAL, INTENT(IN), DIMENSION(NLINKS) :: MUSK, MUSX
609 REAL, INTENT(IN), DIMENSION(NLINKS) :: CHANLEN
610 REAL, INTENT(IN), DIMENSION(NLINKS) :: So, MannN
611 REAL, INTENT(IN), DIMENSION(NLINKS) :: ChSSlp,Bw,Tw !--properties of nodes or links
612 REAL, INTENT(IN), DIMENSION(NLINKS) :: Tw_CC, n_CC !properties of compund channel
613 REAL, INTENT(IN), DIMENSION(NLINKS) :: ChannK !--Channel Infiltration
615 REAL , INTENT(INOUT), DIMENSION(:,:) :: QLINK
616 REAL , DIMENSION(NLINKS,2) :: tmpQLINK
617 REAL , INTENT(INOUT), DIMENSION(NLINKS) :: HLINK
618 REAL, dimension(NLINKS), intent(inout) :: QLateral !--lateral flow
619 REAL, INTENT(IN) :: DT !-- model timestep
620 REAL, INTENT(IN) :: DTRT_CH !-- routing timestep
621 REAL, INTENT(INOUT) :: DTCT
622 real :: minDTCT !BF minimum routing timestep
623 REAL :: dist(ixrt,jxrt,9)
625 INTEGER, INTENT(IN) :: MAXORDER, SUBRTSWCRT, &
626 gwBaseSwCRT, gwChanCondSw
627 real, intent(in) :: gwChanCondConstIn, gwChanCondConstOut ! aquifer-channel conductivity constant from namelist
628 REAL , INTENT(IN), DIMENSION(NLINKS) :: node_area
629 real, dimension(:), INTENT(inout) :: velocity, qloss
632 !DJG GW-chan coupling variables...
633 REAL, DIMENSION(NLINKS) :: dzGwChanHead
634 REAL, DIMENSION(NLINKS) :: Q_GW_CHAN_FLUX !DJG !!! Change 'INTENT' to 'OUT' when ready to update groundwater state...
635 REAL, DIMENSION(IXRT,JXRT) :: ZWATTBLRT !DJG !!! Match with subsfce/gw routing & Change 'INTENT' to 'INOUT' when ready to update groundwater state...
636 REAL, INTENT(INOUT), DIMENSION(:,:), allocatable :: gwHead !DJG !!! groundwater head from Fersch-2d gw implementation...units (m ASL)
637 REAL, INTENT(INOUT), DIMENSION(:,:), allocatable :: qgw_chanrt !DJG !!! Channel-gw flux as used in Fersch 2d gw implementation...units (m^3/s)...Change 'INTENT' to 'OUT' when ready to update groundwater state...
642 REAL, INTENT(INOUT), DIMENSION(NLAKES) :: RESHT !-- reservoir height (m)
643 REAL*8, DIMENSION(NLAKES) :: QLAKEI8 !-- lake inflow (cms)
644 REAL, INTENT(INOUT), DIMENSION(NLAKES) :: QLAKEI !-- lake inflow (cms)
645 REAL, DIMENSION(NLAKES) :: QLAKEIP !-- lake inflow previous timestep (cms)
646 REAL, INTENT(INOUT), DIMENSION(NLAKES) :: QLAKEO !-- outflow from lake used in diffusion scheme
647 INTEGER(kind=int64), INTENT(IN), DIMENSION(NLINKS) :: LAKENODE !-- outflow from lake used in diffusion scheme
648 INTEGER(kind=int64), INTENT(IN), DIMENSION(NLINKS) :: LINKID !-- id of channel elements for linked scheme
649 !REAL, DIMENSION(NLINKS) :: QLateral !--lateral flow
650 REAL, DIMENSION(NLINKS) :: QSUM !--mass bal of node
651 REAL*8, DIMENSION(NLINKS) :: QSUM8 !--mass bal of node
652 REAL, DIMENSION(NLAKES) :: QLLAKE !-- lateral inflow to lake in diffusion scheme
653 REAL*8, DIMENSION(NLAKES) :: QLLAKE8 !-- lateral inflow to lake in diffusion scheme
656 INTEGER :: i,j,k,t,m,jj,kk,KRT,node
657 INTEGER :: DT_STEPS !-- number of timestep in routing
658 REAL :: Qup,Quc !--Q upstream Previous, Q Upstream Current, downstream Previous
659 REAL :: bo !--critical depth, bnd outflow just for testing
660 REAL :: AREA,WP !--wetted area and perimiter for MuskingC. routing
662 REAL ,DIMENSION(NLINKS) :: HLINKTMP,CVOLTMP !-- temporarily store head values and volume values
663 REAL ,DIMENSION(NLINKS) :: CD !-- critical depth
664 real, DIMENSION(IXRT,JXRT) :: tmp
665 real, dimension(nlinks) :: tmp2
668 integer lake_index(nlakes)
669 integer nlinks_index(nlinks)
670 integer mpp_nlinks, iyw, yw_mpp_nlinks
671 integer(kind=int64) link_location(ixrt,jxrt)
672 real ywtmp(ixrt,jxrt)
674 real*8, dimension(LNLINKSL) :: LQLateral
675 ! real*4, dimension(LNLINKSL) :: LQLateral
676 integer, dimension(:) :: toNodeInd
677 integer(kind=int64), dimension(:,:) :: gtoNode
678 integer :: nToNodeInd
679 real, dimension(nToNodeInd,2) :: gQLINK
681 real*8, dimension(NLINKS) :: LQLateral !--lateral flow
685 integer :: n, kk2, nt, nsteps ! tmp
698 !yw print *, "DRIVE_channel,option,nlinkl,nlinks!!", channel_option,NLINKSL,NLINKS
699 ! print *, "DRIVE_channel, RESHT", RESHT
704 IF(channel_option .ne. 3) then !--muskingum methods ROUTE ON DT timestep, not DTRT!!
706 nsteps = (DT+0.5)/DTRT_CH
709 LQLateral = 0 !-- initial lateral flow to 0 for this reach
710 DO iyw = 1,yw_MPP_NLINKS
711 jj = nlinks_index(iyw)
712 !--------river grid points, convert depth in mm to rate across reach in m^3/sec
713 if( .not. ( (CHANXI(jj) .eq. 1 .and. left_id .ge. 0) .or. &
714 (CHANXI(jj) .eq. ixrt .and. right_id .ge. 0) .or. &
715 (CHANYJ(jj) .eq. 1 .and. down_id .ge. 0) .or. &
716 (CHANYJ(jj) .eq. jxrt .and. up_id .ge. 0) &
718 if (CH_LNKRT_SL(CHANXI(jj),CHANYJ(jj)) .gt. 0) then
719 k = CH_LNKRT_SL(CHANXI(jj),CHANYJ(jj))
720 LQLateral(k) = LQLateral(k)+((QSTRMVOLRT(CHANXI(jj),CHANYJ(jj))+QINFLOWBASE(CHANXI(jj),CHANYJ(jj)))/1000 &
722 elseif ( (LAKE_MSKRT(CHANXI(jj),CHANYJ(jj)) .gt. 0)) then !-lake grid
723 k = LAKE_MSKRT(CHANXI(jj),CHANYJ(jj))
724 LQLateral(k) = LQLateral(k) +((LAKEINFLORT(CHANXI(jj),CHANYJ(jj))+QINFLOWBASE(CHANXI(jj),CHANYJ(jj)))/1000 &
731 ! assign LQLATERAL to QLATERAL
732 call updateLinkV(LQLateral, QLateral(1:NLINKSL))
736 LQLateral = 0 !-- initial lateral flow to 0 for this reach
738 !--------river grid points, convert depth in mm to rate across reach in m^3/sec
740 if (CH_LNKRT_SL(CHANXI(jj),CHANYJ(jj)) .gt. 0 ) then
741 k = CH_LNKRT_SL(CHANXI(jj),CHANYJ(jj))
742 LQLateral(k) = LQLateral(k)+((QSTRMVOLRT(CHANXI(jj),CHANYJ(jj))+QINFLOWBASE(CHANXI(jj),CHANYJ(jj)))/1000 &
744 elseif ( (LAKE_MSKRT(CHANXI(jj),CHANYJ(jj)) .gt. 0)) then !-lake grid
745 k = LAKE_MSKRT(CHANXI(jj),CHANYJ(jj))
746 LQLateral(k) = LQLateral(k) +((LAKEINFLORT(CHANXI(jj),CHANYJ(jj))+QINFLOWBASE(CHANXI(jj),CHANYJ(jj)))/1000 &
755 ! QLateral = QLateral / nsteps
759 !Per Yates, this check is not needed. Commenting out for now.
760 !---------- route order 1 reaches which have no upstream inflow
762 ! if (ORDER(k) .eq. 1) then !-- first order stream has no headflow
765 ! if(TYPEL(k) .eq. 1) then !-- level pool route of reservoir
766 ! !CALL LEVELPOOL(1,0.0, 0.0, qd, QLINK(k,2), QLateral(k), &
767 ! ! DT, RESHT(k), HRZAREA(k), LAKEMAXH(k), &
768 ! ! WEIRC(k), WEIRL(k), ORIFICEE(i), ORIFICEC(k), ORIFICEA(k) )
769 ! elseif (channel_option .eq. 1) then
772 ! QLINK(k,2) = MUSKING(k,0.0, QLateral(k), QLINK(k,1), DTRT_CH, Km, X) !--current outflow
773 ! elseif (channel_option .eq. 2) then !-- upstream is assumed constant initial condition
775 ! call SUBMUSKINGCUNGE(QLINK(k,2), velocity(k), k, &
776 ! 0.0,0.0, QLINK(k,1), QLateral(k), DTRT_CH, So(k), &
777 ! CHANLEN(k), MannN(k), ChSSlp(k), Bw(k), Tw(k) )
780 ! print *, "FATAL ERROR: No channel option selected"
781 ! call hydro_stop("In drive_CHANNEL() -No channel option selected ")
788 call gbcastReal2(toNodeInd,nToNodeInd,QLINK(1:NLINKSL,2), NLINKSL, gQLINK(:,2))
789 call gbcastReal2(toNodeInd,nToNodeInd,QLINK(1:NLINKSL,1), NLINKSL, gQLINK(:,1))
792 !---------- route other reaches, with upstream inflow
795 ! if (ORDER(k) .gt. 1 ) then !-- exclude first order stream
801 do n = 1, gtoNODE(k,1)
803 !yw if (LINKID(k) .eq. m) then
804 Quc = Quc + gQLINK(m,2) !--accum of upstream inflow of current timestep (2)
805 Qup = Qup + gQLINK(m,1) !--accum of upstream inflow of previous timestep (1)
807 ! if(LINKID(k) .eq. 3259 .or. LINKID(k) .eq. 3316 .or. LINKID(k) .eq. 3219) then
808 ! write(6,*) "id,Uc,Up",LINKID(k),Quc,Qup
817 if (LINKID(k) .eq. TO_NODE(m)) then
818 Quc = Quc + QLINK(m,2) !--accum of upstream inflow of current timestep (2)
819 Qup = Qup + QLINK(m,1) !--accum of upstream inflow of previous timestep (1)
824 if(TYPEL(k) .eq. 1) then !--link is a reservoir
826 ! CALL LEVELPOOL(1,QLINK(k,1), Qup, QLINK(k,1), QLINK(k,2), &
827 ! QLateral(k), DT, RESHT(k), HRZAREA(k), LAKEMAXH(k), &
828 ! WEIRC(k), WEIRL(k),ORIFICEE(k), ORIFICEC(k), ORIFICEA(k))
830 elseif (channel_option .eq. 1) then !muskingum routing
833 tmpQLINK(k,2) = MUSKING(k,Qup,(Quc+QLateral(k)),QLINK(k,1),DTRT_CH,Km,X) !upstream plust lateral inflow
834 elseif (channel_option .eq. 2) then ! muskingum cunge
836 call SUBMUSKINGCUNGE(tmpQLINK(k,2), velocity(k), qloss(k), LINKID(k), &
837 Qup,Quc, QLINK(k,1), QLateral(k), DTRT_CH, So(k), &
838 CHANLEN(k), MannN(k), ChSSlp(k), Bw(k), Tw(k),Tw_CC(k), n_CC(k), HLINK(k), ChannK(k) )
841 print *, "FATAL ERROR: no channel option selected"
842 call hydro_stop("In drive_CHANNEL() - no channel option selected")
844 ! endif !!! order(1) .ne. 1
849 ! call ReachLS_write_io(tmpQLINK(:,2), gQLINK(:,2))
850 ! call ReachLS_write_io(tmpQLINK(:,1), gQLINK(:,1))
851 ! write(6,*) " io_id = ", io_id
852 ! if(my_id .eq. io_id) then
853 ! write(71,*) gQLINK(:,1)
859 if(TYPEL(k) .ne. 1) then
860 QLINK(k,2) = tmpQLINK(k,2)
862 QLINK(k,1) = QLINK(k,2) !assing link flow of current to be previous for next time step
868 print *, "END OF ALL REACHES...",KRT,DT_STEPS
871 ! END DO !-- krt timestep for muksingumcunge routing
873 elseif(channel_option .eq. 3) then !--- route using the diffusion scheme on nodes not links
876 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,HLINK,NLINKS,99)
877 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,CVOL,NLINKS,99)
880 KRT = 0 !-- initialize the time counter
881 minDTCT = 0.01 ! define minimum routing sub-timestep (s), simulation will end with smaller timestep
882 DTCT = min(max(DTCT*2.0, minDTCT),DTRT_CH)
884 HLINKTMP = HLINK !-- temporary storage of the water elevations (m)
885 CVOLTMP = CVOL !-- temporary storage of the volume of water in channel (m^3)
886 QLAKEIP = QLAKEI !-- temporary lake inflow from previous timestep (cms)
888 ! call check_channel(77,HLINKTMP,1,nlinks)
889 ! call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,ZELEV,NLINKS,99)
890 crnt: DO !-- loop on the courant condition
891 QSUM = 0. !-- initialize the total flow out of each cell to zero
892 QSUM8 = 0. !-- initialize the total flow out of each cell to zero
893 QLAKEI8 = 0. !-- set the lake inflow as zero
894 QLAKEI = 0. !-- set the lake inflow as zero
895 QLLAKE = 0. !-- initialize each lake's lateral inflow to zero
896 QLLAKE8 = 0. !-- initialize each lake's lateral inflow to zero
897 DT_STEPS = INT(DT/DTCT) !-- fix the timestep
899 !DJG GW-chan coupling variables...
900 if(gwBaseSwCRT == 3) then
905 ! ZWATTBLRT=1.0 !--HARDWIRE, remove this and pass in from subsfc/gw routing routines...
909 !---------------------
911 DO iyw = 1,yw_MPP_NLINKS
912 i = nlinks_index(iyw)
917 if(node_area(i) .eq. 0) then
918 write(6,*) "FATAL ERROR: node_area(i) is zero. i=", i
919 call hydro_stop("In drive_CHANNEL() - Error node_area")
924 nodeType:if((CH_NETRT(CHANXI(i), CHANYJ(i) ) .eq. 0) .and. &
925 (LAKE_MSKRT(CHANXI(i),CHANYJ(i)) .lt.0) ) then !--a reg. node
927 gwOption: if(gwBaseSwCRT == 3) then
929 ! determine potential gradient between groundwater head and channel stage
931 dzGwChanHead(i) = gwHead(CHANXI(i),CHANYJ(i)) - (HLINK(i)+ZELEV(i))
933 if(gwChanCondSw .eq. 0) then
935 qgw_chanrt(CHANXI(i),CHANYJ(i)) = 0.
937 else if(gwChanCondSw .eq. 1 .and. dzGwChanHead(i) > 0) then
939 ! channel bed interface, units in (m^3/s), flux into channel...
940 ! BF todo: consider channel width
941 qgw_chanrt(CHANXI(i),CHANYJ(i)) = gwChanCondConstIn * dzGwChanHead(i) &
944 else if(gwChanCondSw .eq. 1 .and. dzGwChanHead(i) < 0) then
946 ! channel bed interface, units in (m^3/s), flux out of channel...
947 ! BF todo: consider channel width
948 qgw_chanrt(CHANXI(i),CHANYJ(i)) = max(-0.005, gwChanCondConstOut * dzGwChanHead(i) &
950 ! else if(gwChanCondSw .eq. 2 .and. dzGwChanHead(i) > 0) then TBD: exponential dependency
951 ! else if(gwChanCondSw .eq. 2 .and. dzGwChanHead(i) > 0) then
955 qgw_chanrt(CHANXI(i),CHANYJ(i)) = 0.
959 Q_GW_CHAN_FLUX(i) = qgw_chanrt(CHANXI(i),CHANYJ(i))
960 ! if ( i .eq. 1001 ) then
961 ! print *, Q_GW_CHAN_FLUX(i), dzGwChanHead(i), ELRT(CHANXI(i),CHANYJ(i)), HLINK(i), ZELEV(i)
963 ! if ( Q_GW_CHAN_FLUX(i) .lt. 0. ) then !-- temporary hardwire for only allowing flux into channel...REMOVE later...
964 ! Q_GW_CHAN_FLUX(i) = 0.
965 ! qgw_chanrt(CHANXI(i),CHANYJ(i)) = 0.
969 Q_GW_CHAN_FLUX(i) = 0.
973 QLateral(CH_NETLNK(CHANXI(i),CHANYJ(i))) = &
974 !DJG awaiting gw-channel exchg... Q_GW_CHAN_FLUX(i)+& ...obsolete-> ((QSUBRT(CHANXI(i),CHANYJ(i))+&
976 ((QSTRMVOLRT(CHANXI(i),CHANYJ(i))+&
977 QINFLOWBASE(CHANXI(i),CHANYJ(i))) &
978 /DT_STEPS*node_area(i)/1000/DTCT)
979 if((QLateral(CH_NETLNK(CHANXI(i),CHANYJ(i))).lt.0.) .and. (gwChanCondSw == 0)) then
981 print*, "i, CHANXI(i),CHANYJ(i) = ", i, CHANXI(i),CHANYJ(i)
982 print *, "NEGATIVE Lat inflow...",QLateral(CH_NETLNK(CHANXI(i),CHANYJ(i))), &
983 QSUBRT(CHANXI(i),CHANYJ(i)),QSTRMVOLRT(CHANXI(i),CHANYJ(i)), &
984 QINFLOWBASE(CHANXI(i),CHANYJ(i))
986 elseif (QLateral(CH_NETLNK(CHANXI(i),CHANYJ(i))) .gt. 1.0) then
988 ! print *, "LatIn(Ql,Qsub,Qstrmvol)..",i,QLateral(CH_NETLNK(CHANXI(i),CHANYJ(i))), &
989 ! QSUBRT(CHANXI(i),CHANYJ(i)),QSTRMVOLRT(CHANXI(i),CHANYJ(i))
993 elseif(LAKE_MSKRT(CHANXI(i),CHANYJ(i)) .gt. 0 .and. &
994 ! (LAKE_MSKRT(CHANXI(i),CHANYJ(i)) .ne. -9999)) then !--a lake node
995 (CH_NETRT(CHANXI(i),CHANYJ(i)) .le. 0)) then !--a lake node
996 QLLAKE8(LAKE_MSKRT(CHANXI(i),CHANYJ(i))) = &
997 QLLAKE8(LAKE_MSKRT(CHANXI(i),CHANYJ(i))) + &
998 (LAKEINFLORT(CHANXI(i),CHANYJ(i))+ &
999 QINFLOWBASE(CHANXI(i),CHANYJ(i))) &
1000 /DT_STEPS*node_area(i)/1000/DTCT
1001 elseif(CH_NETRT(CHANXI(i),CHANYJ(i)) .gt. 0) then !pour out of lake
1002 QLateral(CH_NETLNK(CHANXI(i),CHANYJ(i))) = &
1003 QLAKEO(CH_NETRT(CHANXI(i),CHANYJ(i))) !-- previous timestep
1010 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,QLateral,NLINKS,99)
1011 if(NLAKES .gt. 0) then
1012 !yw call MPP_CHANNEL_COM_REAL(LAKE_MSKRT ,ixrt,jxrt,QLLAKE,NLAKES,99)
1013 call sum_real8(QLLAKE8,NLAKES)
1018 !-- compute conveyances, with known depths (just assign to QLINK(,1)
1019 !--QLINK(,2) will not be used), QLINK is the flow across the node face
1020 !-- units should be m3/second.. consistent with QL (lateral flow)
1023 DO iyw = 1,yw_MPP_NLINKS
1024 i = nlinks_index(iyw)
1028 if (TYPEL(i) .eq. 0 .AND. HLINKTMP(FROM_NODE(i)) .gt. RETDEP_CHAN) then
1029 if(from_node(i) .ne. to_node(i) .and. (to_node(i) .gt. 0) .and.(from_node(i) .gt. 0) ) & ! added by Wei Yu
1030 QLINK(i,1)=DIFFUSION(i,ZELEV(FROM_NODE(i)),ZELEV(TO_NODE(i)), &
1031 HLINKTMP(FROM_NODE(i)),HLINKTMP(TO_NODE(i)), &
1032 CHANLEN(i), MannN(i), Bw(i), ChSSlp(i))
1033 else !-- we are just computing critical depth for outflow points
1039 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,QLINK(:,1),NLINKS,99)
1043 !-- compute total flow across face, into node
1045 DO iyw = 1,yw_mpp_nlinks
1046 i = nlinks_index(iyw)
1048 DO i = 1,NLINKS !-- inflow to node across each face
1050 if(TYPEL(i) .eq. 0) then !-- only regular nodes have to attribute
1051 QSUM8(TO_NODE(i)) = QSUM8(TO_NODE(i)) + QLINK(i,1)
1056 call MPP_CHANNEL_COM_REAL8(Link_location,ixrt,jxrt,qsum8,NLINKS,0)
1063 do iyw = 1,yw_mpp_nlinks
1064 i = nlinks_index(iyw)
1066 do i = 1,NLINKS !-- outflow from node across each face
1068 QSUM(FROM_NODE(i)) = QSUM(FROM_NODE(i)) - QLINK(i,1)
1071 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,qsum,NLINKS,99)
1079 do iyw = 1,yw_MPP_NLINKS
1080 i = nlinks_index(iyw)
1082 do i = 1, NLINKS !--- compute volume and depth at each node
1085 if( TYPEL(i).eq.0 .and. CVOLTMP(i) .ge. 0.001 .and.(CVOLTMP(i)-QSUM(i)*DTCT)/CVOLTMP(i) .le. -0.01 ) then
1088 write(6,*) "******* start diag ***************"
1089 write(6,*) "Unstable at node ",i, "i=",CHANXI(i),"j=",CHANYJ(i)
1090 write(6,*) "Unstatble at node ",i, "lat=",latval(CHANXI(i),CHANYJ(i)), "lon=",lonval(CHANXI(i),CHANYJ(i))
1091 write(6,*) "TYPEL, CVOLTMP, QSUM, QSUM*DTCT",TYPEL(i), CVOLTMP(i), QSUM(i), QSUM(i)*DTCT
1092 write(6,*) "qsubrt, qstrmvolrt,qlink",QSUBRT(CHANXI(i),CHANYJ(i)),QSTRMVOLRT(CHANXI(i),CHANYJ(i)),qlink(i,1),qlink(i,2)
1093 ! write(6,*) "current nodes, z, h", ZELEV(FROM_NODE(i)),HLINKTMP(FROM_NODE(i))
1094 ! if(TO_NODE(i) .gt. 0) then
1095 ! write(6,*) "to nodes, z, h", ZELEV(TO_NODE(i)), HLINKTMP(TO_NODE(i))
1097 ! write(6,*) "no to nodes "
1099 write(6,*) "CHANLEN(i), MannN(i), Bw(i), ChSSlp(i) ", CHANLEN(i), MannN(i), Bw(i), ChSSlp(i)
1100 write(6,*) "*******end of diag ***************"
1109 call mpp_same_int1(flag)
1113 if(flag < 0 .and. DTCT >0.1) then
1115 ! call smoth121(HLINK,nlinks,maxv_p,pnode,to_node)
1117 if(DTCT .gt. minDTCT) then !-- timestep in seconds
1118 DTCT = max(DTCT/2 , minDTCT) !-- 1/2 timestep
1119 KRT = 0 !-- restart counter
1120 HLINKTMP = HLINK !-- set head and vol to start value of timestep
1122 CYCLE crnt !-- start cycle over with smaller timestep
1124 write(6,*) "Courant error with smallest routing timestep DTCT: ",DTCT
1125 ! call hydro_stop("drive_CHANNEL")
1127 HLINKTMP = HLINK !-- set head and volume to start values of timestep
1137 do iyw = 1,yw_MPP_NLINKS
1138 i = nlinks_index(iyw)
1140 do i = 1, NLINKS !--- compute volume and depth at each node
1143 if(TYPEL(i) .eq. 0) then !-- regular channel grid point, compute volume
1144 CVOLTMP(i) = CVOLTMP(i) + (QSUM(i) + QLateral(i) )* DTCT
1145 if((CVOLTMP(i) .lt. 0) .and. (gwChanCondSw == 0)) then
1147 print *, "WARNING! channel volume less than 0:i,CVOL,QSUM,QLat", &
1148 i, CVOLTMP(i),QSUM(i),QLateral(i),HLINK(i)
1153 elseif(TYPEL(i) .eq. 1) then !-- pour point, critical depth downstream
1155 if (QSUM(i)+QLateral(i) .lt. 0) then
1158 !DJG remove to have const. flux b.c.... CD(i) =CRITICALDEPTH(i,abs(QSUM(i)+QLateral(i)), Bw(i), 1./ChSSlp(i))
1159 CD(i) = HLINKTMP(i) !This is a temp hardwire for flow depth for the pour point...
1162 ! change in volume is inflow, lateral flow, and outflow
1163 !yw DIFFUSION(i,ZELEV(i),ZELEV(i)-(So(i)*DXRT),HLINKTMP(i), &
1164 CVOLTMP(i) = CVOLTMP(i) + (QSUM(i) + QLateral(i) - &
1165 DIFFUSION(i,ZELEV(i),ZELEV(i)-(So(i)*CHANLEN(i)),HLINKTMP(i), &
1166 CD(i),CHANLEN(i), MannN(i), Bw(i), ChSSlp(i)) ) * DTCT
1167 elseif (TYPEL(i) .eq. 2) then !--- into a reservoir, assume critical depth
1168 if ((QSUM(i)+QLateral(i) .lt. 0) .and. (gwChanCondSw == 0)) then
1170 print *, i, 'CrtDpth Qsum+QLat into lake< 0',QSUM(i), QLateral(i)
1173 !DJG remove to have const. flux b.c.... CD(i) =CRITICALDEPTH(i,abs(QSUM(i)+QLateral(i)), Bw(i), 1./ChSSlp(i))
1174 CD(i) = HLINKTMP(i) !This is a temp hardwire for flow depth for the pour point...
1177 !-- compute volume in reach (m^3)
1178 CVOLTMP(i) = CVOLTMP(i) + (QSUM(i) + QLateral(i) - &
1179 DIFFUSION(i,ZELEV(i),ZELEV(i)-(So(i)*CHANLEN(i)),HLINKTMP(i), &
1180 CD(i) ,CHANLEN(i), MannN(i), Bw(i), ChSSlp(i)) ) * DTCT
1182 print *, "FATAL ERROR: This node does not have a type.. error TYPEL =", TYPEL(i)
1183 call hydro_stop("In drive_CHANNEL() - error TYPEL")
1186 if(TYPEL(i) == 0) then !-- regular channel node, finalize head and flow
1187 HLINKTMP(i) = HEAD(i, CVOLTMP(i)/CHANLEN(i),Bw(i),1/ChSSlp(i)) !--updated depth
1189 HLINKTMP(i) = CD(i) !!! CRITICALDEPTH(i,QSUM(i)+QLateral(i), Bw(i), 1./ChSSlp(i)) !--critical depth is head
1192 if(TO_NODE(i) .gt. 0) then
1193 if(LAKENODE(TO_NODE(i)) .gt. 0) then
1194 QLAKEI8(LAKENODE(TO_NODE(i))) = QLAKEI8(LAKENODE(TO_NODE(i))) + QLINK(i,1)
1198 END DO !--- done processing all the links
1201 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,CVOLTMP,NLINKS,99)
1202 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,CD,NLINKS,99)
1203 if(NLAKES .gt. 0) then
1204 ! call MPP_CHANNEL_COM_REAL(LAKE_MSKRT,ixrt,jxrt,QLAKEI,NLAKES,99)
1205 call sum_real8(QLAKEI8,NLAKES)
1208 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,HLINKTMP,NLINKS,99)
1210 ! call check_channel(83,CVOLTMP,1,nlinks)
1211 ! call check_channel(84,CD,1,nlinks)
1212 ! call check_channel(85,HLINKTMP,1,nlinks)
1213 ! call check_lake(86,QLAKEI,lake_index,nlakes)
1215 do i = 1, NLAKES !-- mass balances of lakes
1217 if(lake_index(i) .gt. 0) then
1220 ! Calls run for a single reservoir depending on its type as
1221 ! in whether it uses level pool, machine learning, or persistence.
1222 ! Inflow, lateral inflow, water elevation, and the routing period
1223 ! are passed in. Updated outflow and water elevation are returned.
1224 call rt_domain(did)%reservoirs(i)%ptr%run(QLAKEIP(i), QLAKEI(i), &
1225 QLLAKE(i), RESHT(i), QLAKEO(i), DTCT, rt_domain(did)%final_reservoir_type(i), &
1226 rt_domain(did)%reservoir_assimilated_value(i), rt_domain(did)%reservoir_assimilated_source_file(i))
1228 ! TODO: Encapsulate the lake state variable for water elevation (RESHT(i))
1229 ! inside the reservoir module, but it requires a redesign of the lake
1230 ! MPI communication model.
1232 QLAKEIP(i) = QLAKEI(i) !-- store total lake inflow for this timestep
1240 if(NLAKES .gt. 0) then
1241 !yw call MPP_CHANNEL_COM_REAL(LAKE_MSKRT,ixrt,jxrt,QLLAKE,NLAKES,99)
1242 !yw call MPP_CHANNEL_COM_REAL(LAKE_MSKRT,ixrt,jxrt,RESHT,NLAKES,99)
1243 !yw call MPP_CHANNEL_COM_REAL(LAKE_MSKRT,ixrt,jxrt,QLAKEO,NLAKES,99)
1244 !yw call MPP_CHANNEL_COM_REAL(LAKE_MSKRT,ixrt,jxrt,QLAKEI,NLAKES,99)
1245 !yw call MPP_CHANNEL_COM_REAL(LAKE_MSKRT,ixrt,jxrt,QLAKEIP,NLAKES,99)
1247 ! TODO: Change updateLake_grid calls below to updated distributed reservoir
1248 ! objects and not arrays as currently implemented.
1249 call updateLake_grid(QLLAKE, nlakes,lake_index)
1250 call updateLake_grid(RESHT, nlakes,lake_index)
1251 call updateLake_grid(QLAKEO, nlakes,lake_index)
1252 call updateLake_grid(QLAKEI, nlakes,lake_index)
1253 call updateLake_grid(QLAKEIP,nlakes,lake_index)
1259 do iyw = 1,yw_MPP_NLINKS
1260 i = nlinks_index(iyw)
1262 do i = 1, NLINKS !--- compute volume and depth at each node
1264 if(TYPEL(i) == 0) then !-- regular channel node, finalize head and flow
1265 QLINK(i,1)=DIFFUSION(i,ZELEV(FROM_NODE(i)),ZELEV(TO_NODE(i)), &
1266 HLINKTMP(FROM_NODE(i)),HLINKTMP(TO_NODE(i)), &
1267 CHANLEN(i), MannN(i), Bw(i), ChSSlp(i))
1272 call MPP_CHANNEL_COM_REAL(Link_location,ixrt,jxrt,QLINK(:,1),NLINKS,99)
1275 KRT = KRT + 1 !-- iterate on the timestep
1276 if(KRT .eq. DT_STEPS) exit crnt !-- up to the maximum time in interval
1278 end do crnt !--- DTCT timestep of DT_STEPS
1280 HLINK = HLINKTMP !-- update head based on final solution in timestep
1281 CVOL = CVOLTMP !-- update volume
1282 else !-- no channel option apparently selected
1283 print *, "FATAL ERROR: no channel option selected"
1284 call hydro_stop("In drive_CHANNEL() - no channel option selected")
1288 write(6,*) "finished call drive_CHANNEL"
1291 if (KT .eq. 1) KT = KT + 1
1294 end subroutine drive_CHANNEL
1295 ! ----------------------------------------------------------------
1297 !-=======================================
1298 REAL FUNCTION AREAf(AREA,Bw,h,z)
1299 REAL :: AREA, Bw, z, h
1300 AREAf = (Bw+z*h)*h-AREA !-- Flow area
1303 !-====critical depth function ==========
1304 REAL FUNCTION CDf(Q,Bw,h,z)
1307 print *, "FATAL ERROR: head is zero, will get division by zero error"
1308 call hydro_stop("In CDf() - head is zero")
1310 CDf = (Q/((Bw+z*h)*h))/(sqrt(9.81*(((Bw+z*h)*h)/(Bw + 2.0*z*h)))) - 1.0 !--critical depth function
1314 !=======find flow depth in channel with bisection Chapra pg. 131
1315 REAL FUNCTION HEAD(idx,AREA,Bw,z) !-- find the water elevation given wetted area,
1316 !--bottom widith and side channel.. index was for debuggin
1317 REAL :: Bw,z,AREA,test
1318 REAL :: hl, hu, hr, hrold
1319 REAL :: fl, fr,error !-- function evaluation
1320 INTEGER :: maxiter, idx
1324 hl = 0.00001 !-- minimum depth is small
1325 hu = 30. !-- assume maximum depth is 30 meters
1327 if (AREA .lt. 0.00001) then
1330 ! JLM: .gt. "0" is somewhat alarming. We really should have a constant like zero_r4
1331 do while ((AREAf(AREA,BW,hl,z)*AREAf(AREA,BW,hu,z)) .gt. 0.0 .and. maxiter .lt. 100)
1332 !-- allows for larger , smaller heads
1333 if(AREA .lt. 1.) then
1338 maxiter = maxiter + 1
1344 fl = AREAf(AREA,Bw,hl,z)
1345 do while (error .gt. 0.0001 .and. maxiter < 1000)
1348 fr = AREAf(AREA,Bw,hr,z)
1349 maxiter = maxiter + 1
1351 error = abs((hr - hrold)/hr)
1356 elseif (test.gt.0) then
1366 22 format("i,hl,hu,Area",i5,2x,f12.8,2x,f6.3,2x,f6.3,2x,f6.3,2x,f9.1,2x,i5)
1369 !=================================
1370 REAL FUNCTION MANNING(h1,n,Bw,Cs)
1373 REAL :: z, AREA,R,Kd
1376 R = ((Bw + z*h1)*h1)/(Bw + 2.0*h1*sqrt(1.0 + z*z)) !-- Hyd Radius
1377 AREA = (Bw + z*h1)*h1 !-- Flow area
1378 Kd = (1.0/n) * (R**(2.0/3.0))*AREA !-- convenyance
1380 print *,"head, kd", h1,Kd
1384 END FUNCTION MANNING
1386 !=======find flow depth in channel with bisection Chapra pg. 131
1387 REAL FUNCTION CRITICALDEPTH(lnk, Q, Bw, z) !-- find the critical depth
1388 REAL :: Bw, z, Q, test
1389 REAL :: hl, hu, hr, hrold
1390 REAL :: fl, fr, error !-- function evaluation
1396 hl = 1.0e-5 !-- minimum depth is 0.00001 meters
1397 ! hu = 35. !-- assume maximum critical depth 25 m
1398 hu = 100. !-- assume maximum critical depth 25 m
1400 if(CDf(Q, BW, hl, z) * CDf(Q, BW, hu, z) .gt. 0.0) then
1401 if(Q .gt. 0.001) then
1403 print *, "interval won't work to find CD of lnk ", lnk
1404 print *, "Q, hl, hu", Q, hl, hu
1405 print *, "cd lwr, upr", CDf(Q, BW, hl, z), CDf(Q, BW, hu, z)
1406 ! call hydro_stop("In CRITICALDEPTH()")
1407 CRITICALDEPTH = -9999
1416 fl = CDf(Q, Bw, hl, z)
1418 if (Q .eq. 0.0) then
1421 do while (error .gt. 0.0001 .and. maxiter < 1000)
1424 fr = CDf(Q, Bw, hr, z)
1425 maxiter = maxiter + 1
1426 if (hr .ne. 0.0) then
1427 error = abs((hr - hrold)/hr)
1430 if (test .lt. 0) then
1432 elseif (test .gt. 0) then
1443 END FUNCTION CRITICALDEPTH
1446 REAL FUNCTION SGNf(val) !-- function to return the sign of a number
1449 if (val .lt. 0) then
1451 elseif (val.gt.0) then
1458 !================================================
1460 REAL FUNCTION fnDX(qp,Tw,So,Ck,dx,dt) !-- find channel sub-length for MK method
1461 REAL :: qp,Tw,So,Ck,dx, dt,test
1462 REAL :: dxl, dxu, dxr, dxrold
1463 REAL :: fl, fr, error
1469 dxl = dx*0.9 !-- how to choose dxl???
1473 do while (fnDXCDT(qp,Tw,So,Ck,dxl,dt)*fnDXCDT(qp,Tw,So,Ck,dxu,dt) .gt. 0 &
1474 .and. dxl .gt. 10) !-- don't let dxl get too small
1479 fl = fnDXCDT(qp,Tw,So,Ck,dxl,dt)
1480 do while (error .gt. 0.0001 .and. maxiter < 1000)
1483 fr = fnDXCDT(qp,Tw,So,Ck,dxr,dt)
1484 maxiter = maxiter + 1
1485 if (dxr .ne. 0) then
1486 error = abs((dxr - dxrold)/dxr)
1491 elseif (test.gt.0) then
1501 !================================================
1502 REAL FUNCTION fnDXCDT(qp,Tw,So,Ck,dx,dt) !-- function to help find sub-length for MK method
1503 REAL :: qp,Tw,So,Ck,dx,dt,X
1504 REAL :: c,b !-- coefficients on dx/cdt log approximation function
1508 X = 0.5-(qp/(2.0*Tw*So*Ck*dx))
1509 if (X .le. 0.0) then
1510 fnDXCDT = -1.0 !0.115
1512 fnDXCDT = (dx/(Ck*dt)) - (c*LOG(X)+b) !-- this function needs to converge to 0
1514 END FUNCTION fnDXCDT
1515 ! ----------------------------------------------------------------------
1517 subroutine check_lake(unit,cd,lake_index,nlakes)
1518 use module_RT_data, only: rt_domain
1520 integer :: unit,nlakes,i,lake_index(nlakes)
1523 call write_lake_real(cd,lake_index,nlakes)
1528 end subroutine check_lake
1530 subroutine check_channel(unit,cd,did,nlinks)
1531 use module_RT_data, only: rt_domain
1536 integer :: unit,nlinks,i, did
1539 real g_cd(rt_domain(did)%gnlinks)
1540 call write_chanel_real(cd,rt_domain(did)%map_l2g,rt_domain(did)%gnlinks,nlinks,g_cd)
1541 if(my_id .eq. IO_id) then
1542 write(unit,*) "rt_domain(did)%gnlinks = ",rt_domain(did)%gnlinks
1551 end subroutine check_channel
1552 subroutine smoth121(var,nlinks,maxv_p,from_node,to_node)
1554 integer,intent(in) :: nlinks, maxv_p
1555 integer, intent(in), dimension(nlinks):: to_node
1556 integer, intent(in), dimension(nlinks):: from_node(nlinks,maxv_p)
1557 real, intent(inout), dimension(nlinks) :: var
1558 real, dimension(nlinks) :: vartmp
1559 integer :: i,j , k, from,to
1564 plen = from_node(i,1)
1565 if(plen .gt. 1) then
1567 from = from_node(i,k+1)
1569 vartmp(i) = vartmp(i)+0.25*(var(from)+2.*var(i)+var(to))
1571 vartmp(i) = vartmp(i)+(2.*var(i)+var(from))/3.0
1574 vartmp(i) = vartmp(i) /(plen-1)
1577 vartmp(i) = vartmp(i)+(2.*var(i)+var(to)/3.0)
1585 end subroutine smoth121
1587 ! SUBROUTINE drive_CHANNEL for NHDPLUS
1588 ! ------------------------------------------------
1590 subroutine drive_CHANNEL_RSL(did, UDMP_OPT,KT, IXRT,JXRT, &
1591 LAKEINFLORT, QSTRMVOLRT, TO_NODE, FROM_NODE, &
1592 TYPEL, ORDER, MAXORDER, CH_LNKRT, &
1593 LAKE_MSKRT, DT, DTCT, DTRT_CH,MUSK, MUSX, QLINK, &
1594 CHANLEN, MannN, So, ChSSlp, Bw, Tw, Tw_CC, n_CC, &
1595 ChannK, RESHT, CVOL, QLAKEI, QLAKEO, LAKENODE, &
1596 QINFLOWBASE, CHANXI, CHANYJ, channel_option, &
1597 nlinks,NLINKSL, LINKID, node_area, qout_gwsubbas, &
1598 LAKEIDA, LAKEIDM, NLAKES, LAKEIDX, &
1600 nlinks_index,mpp_nlinks,yw_mpp_nlinks, &
1602 gtoNode,toNodeInd,nToNodeInd, &
1604 CH_LNKRT_SL, landRunOff &
1605 #ifdef WRF_HYDRO_NUDGING
1608 , accSfcLatRunoff, accBucket &
1609 , qSfcLatRunoff, qBucket &
1610 , QLateral, velocity, qloss &
1612 , nsize , OVRTSWCRT, SUBRTSWCRT, channel_only, channelBucket_only, &
1615 use module_UDMAP, only: LNUMRSL, LUDRSL
1616 use config_base, only: nlst
1618 #ifdef WRF_HYDRO_NUDGING
1619 use module_RT_data, only: rt_domain
1620 use module_stream_nudging, only: setup_stream_nudging, &
1623 nudge_apply_upstream_muskingumCunge
1629 ! -------- DECLARATIONS ------------------------
1630 integer, intent(IN) :: did, IXRT,JXRT,channel_option, OVRTSWCRT, SUBRTSWCRT
1631 integer, intent(IN) :: NLAKES, NLINKSL, nlinks
1632 integer, intent(INOUT) :: KT ! flag of cold start (1) or continue run.
1633 real, intent(IN), dimension(IXRT,JXRT) :: QSTRMVOLRT
1634 real, intent(IN), dimension(IXRT,JXRT) :: LAKEINFLORT
1635 real, intent(IN), dimension(IXRT,JXRT) :: QINFLOWBASE
1636 real, dimension(ixrt,jxrt) :: landRunOff
1638 integer(kind=int64), intent(IN), dimension(IXRT,JXRT) :: CH_LNKRT
1639 integer(kind=int64), intent(IN), dimension(IXRT,JXRT) :: CH_LNKRT_SL
1641 integer, intent(IN), dimension(IXRT,JXRT) :: LAKE_MSKRT
1642 integer, intent(IN), dimension(:) :: ORDER, TYPEL !--link
1643 integer(kind=int64), intent(in), dimension(:) :: TO_NODE, FROM_NODE
1644 integer, intent(IN), dimension(:) :: CHANXI, CHANYJ
1645 real, intent(IN), dimension(:) :: MUSK, MUSX
1646 real, intent(IN), dimension(:) :: CHANLEN
1647 real, intent(IN), dimension(:) :: So, MannN
1648 real, intent(IN), dimension(:) :: ChSSlp,Bw,Tw !--properties of nodes or links
1649 real, intent(IN), dimension(:) :: Tw_CC, n_CC ! properties of compound channel
1650 real, intent(IN), dimension(:) :: ChannK !--channel infiltration
1652 real , intent(INOUT), dimension(:,:) :: QLINK
1653 real , intent(INOUT), dimension(:) :: HLINK
1655 logical, intent(in) :: channel_bypass
1657 #ifdef WRF_HYDRO_NUDGING
1658 !! inout for applying previous nudge to upstream components of flow at gages
1659 real, intent(inout), dimension(:) :: nudge
1662 real, dimension(:), intent(inout) :: QLateral !--lateral flow
1663 real, dimension(:), intent(out) :: velocity, qloss
1664 real*8, dimension(:), intent(inout) :: accSfcLatRunoff, accBucket
1665 real , dimension(:), intent(out) :: qSfcLatRunoff , qBucket
1667 real , dimension(NLINKSL,2) :: tmpQLINK
1668 real, intent(IN) :: DT !-- model timestep
1669 real, intent(IN) :: DTRT_CH !-- routing timestep
1670 real, intent(INOUT) :: DTCT
1671 real :: minDTCT !BF minimum routing timestep
1672 integer, intent(IN) :: MAXORDER
1673 real , intent(IN), dimension(:) :: node_area
1675 !DJG GW-chan coupling variables...
1676 real, dimension(NLINKS) :: dzGwChanHead
1677 real, dimension(NLINKS) :: Q_GW_CHAN_FLUX !DJG !!! Change 'INTENT' to 'OUT' when ready to update groundwater state...
1678 real, dimension(IXRT,JXRT) :: ZWATTBLRT !DJG !!! Match with subsfce/gw routing & Change 'INTENT' to 'INOUT' when ready to update groundwater state...
1681 integer(kind=int64), intent(IN), dimension(:) :: LAKEIDM !-- NHDPLUS lakeid for lakes to be modeled
1683 real, intent(INOUT), dimension(:) :: RESHT !-- reservoir height (m)
1684 real, intent(INOUT), dimension(:) :: QLAKEI !-- lake inflow (cms)
1685 real, dimension(NLAKES) :: QLAKEIP !-- lake inflow previous timestep (cms)
1686 real, intent(INOUT), dimension(NLAKES) :: QLAKEO !-- outflow from lake used in diffusion scheme
1688 integer(kind=int64), intent(IN), dimension(:) :: LAKENODE !-- outflow from lake used in diffusion scheme
1689 integer(kind=int64), intent(IN), dimension(:) :: LINKID !-- id of channel elements for linked scheme
1690 integer(kind=int64), intent(IN), dimension(:) :: LAKEIDA !-- (don't need) NHDPLUS lakeid for all lakes in domain
1691 integer, intent(IN), dimension(:) :: LAKEIDX !-- the sequential index of the lakes id by com id
1693 real, dimension(NLINKS) :: QSUM !--mass bal of node
1694 real, dimension(NLAKES) :: QLLAKE !-- lateral inflow to lake in diffusion scheme
1698 integer :: i,j,k,t,m,jj,ii,lakeid, kk,KRT,node, UDMP_OPT
1699 integer :: DT_STEPS !-- number of timestep in routing
1700 real :: Qup,Quc !--Q upstream Previous, Q Upstream Current, downstream Previous
1701 real :: bo !--critical depth, bnd outflow just for testing
1703 real ,dimension(NLINKS) :: CD !-- critical depth
1704 real, dimension(IXRT,JXRT) :: tmp
1705 real, dimension(nlinks) :: tmp2
1706 real, intent(INOUT), dimension(:) :: CVOL
1709 real*8, dimension(LNLINKSL) :: LQLateral
1710 real*8, dimension(LNLINKSL) :: tmpLQLateral
1711 real, dimension(NLINKSL) :: tmpQLateral
1713 integer nlinks_index(:)
1714 integer iyw, yw_mpp_nlinks, mpp_nlinks
1715 real ywtmp(ixrt,jxrt)
1717 integer, dimension(:) :: toNodeInd
1718 integer(kind=int64), dimension(:,:) :: gtoNode
1719 integer :: nToNodeInd
1720 real, dimension(nToNodeInd,2) :: gQLINK
1722 real*8, dimension(NLINKS) :: tmpLQLateral
1723 real, dimension(NLINKSL) :: tmpQLateral
1724 real, dimension(NLINKSL) :: LQLateral
1727 integer, intent(in) :: channel_only, channelBucket_only
1729 integer :: n, kk2, nt, nsteps ! tmp
1730 real, intent(in), dimension(:) :: qout_gwsubbas
1731 real, allocatable,dimension(:) :: tmpQLAKEO, tmpQLAKEI, tmpRESHT
1732 integer, allocatable, dimension(:) :: tmpFinalResType
1733 real, allocatable,dimension(:) :: tmpAssimilatedValue
1734 character(len=256), allocatable,dimension(:) :: tmpAssimilatedSourceFile
1737 if(my_id .eq. io_id) then
1739 allocate(tmpQLAKEO(NLAKES))
1740 allocate(tmpQLAKEI(NLAKES))
1741 allocate(tmpRESHT(NLAKES))
1742 allocate(tmpFinalResType(nlakes))
1753 nsteps = (DT+0.5)/DTRT_CH
1755 #ifdef WRF_HYDRO_NUDGING
1756 !! Initialize nudging for the current timestep.
1757 !! This establishes the data structure used to solve the nudges.
1758 call setup_stream_nudging(0) !! always zero b/c at beginning of hydro timestep
1759 #endif /* WRF_HYDRO_NUDGING */
1761 !---------------------------------------------
1762 if(channel_only .eq. 1 .or. channelBucket_only .eq. 1) then
1764 write(6,*) "channel_only or channelBucket_only is not zero. Special flux calculations."
1766 #endif /* HYDRO_D */
1768 ! if(nlst_rt(1)%output_channelBucket_influx .eq. 1 .or. &
1769 ! nlst_rt(1)%output_channelBucket_influx .eq. 2 ) &
1770 ! !! qScfLatRunoff = qLateral - qBucket
1771 ! qSfcLatRunoff(1:NLINKSL) = qLateral(1:NLINKSL) - qout_gwsubbas(1:NLINKSL)
1773 if(nlst(1)%output_channelBucket_influx .eq. 1 .or. &
1774 nlst(1)%output_channelBucket_influx .eq. 2 ) then
1776 if(channel_only .eq. 1) &
1777 !! qScfLatRunoff = qLateral - qBucket
1778 qSfcLatRunoff(1:NLINKSL) = qLateral(1:NLINKSL) - qout_gwsubbas(1:NLINKSL)
1780 if(channelBucket_only .eq. 1) &
1781 !! qScfLatRunoff = qLateral - qBucket
1782 qSfcLatRunoff(1:NLINKSL) = qLateral(1:NLINKSL)
1786 if(nlst(1)%output_channelBucket_influx .eq. 3) &
1787 accSfcLatRunoff(1:NLINKSL) = qSfcLatRunoff * DT
1791 QLateral = 0 !! the variable solved in this section. Channel only knows this already.
1792 LQLateral = 0 !-- initial lateral flow to 0 for this reach
1794 tmpQLateral = 0 !! WHY DOES THIS tmp variable EXIST?? Only for accumulations??
1798 if(OVRTSWCRT .eq. 0) then
1800 ! get from land grid runoff
1801 do m = 1, LUDRSL(k)%ncell
1802 ii = LUDRSL(k)%cell_i(m)
1803 jj = LUDRSL(k)%cell_j(m)
1804 LQLateral(k) = LQLateral(k)+landRunOff(ii,jj)*LUDRSL(k)%cellweight(m)/1000 &
1805 *LUDRSL(k)%cellArea(m)/DT
1806 tmpLQLateral(k) = tmpLQLateral(k)+landRunOff(ii,jj)*LUDRSL(k)%cellweight(m)/1000 &
1807 *LUDRSL(k)%cellArea(m)/DT
1812 call updateLinkV(tmpLQLateral, tmpQLateral)
1814 if(NLINKSL .gt. 0) then
1815 if (nlst(1)%output_channelBucket_influx .eq. 1 .or. &
1816 nlst(1)%output_channelBucket_influx .eq. 2 ) &
1817 qSfcLatRunoff(1:NLINKSL) = tmpQLateral(1:NLINKSL)
1818 if (nlst(1)%output_channelBucket_influx .eq. 3) &
1819 accSfcLatRunoff(1:NLINKSL) = accSfcLatRunoff(1:NLINKSL) + tmpQLateral(1:NLINKSL) * DT
1821 tmpLQLateral = 0 !! JLM:: These lines imply that squeege runoff does not count towards
1822 tmpQLateral = 0 !! JLM:: accumulated runoff to be output but it does for internal QLateral?
1823 !! JLM: But then the next accumulation is added to the amt before zeroing? result
1824 !! JLM: should be identical to LQLateral.... I'm totally mystified.
1827 !! JLM:: if ovrtswcrt=0 and subrtswcrt=1, then this accumulation is calculated twice for LQLateral???
1828 !! This impiles that if overland routing is off and subsurface routing is on, that
1829 !! qstrmvolrt represents only the subsurface contribution to the channel.
1830 if(OVRTSWCRT .ne. 0 .or. SUBRTSWCRT .ne. 0 ) then
1832 ! get from channel grid
1833 do m = 1, LUDRSL(k)%ngrids
1834 ii = LUDRSL(k)%grid_i(m)
1835 jj = LUDRSL(k)%grid_j(m)
1836 LQLateral(k) = LQLateral(k) + QSTRMVOLRT(ii,jj)*LUDRSL(k)%weight(m)/1000 &
1837 *LUDRSL(k)%nodeArea(m)/DT
1838 tmpLQLateral(k) = tmpLQLateral(k) + QSTRMVOLRT(ii,jj)*LUDRSL(k)%weight(m)/1000 &
1839 *LUDRSL(k)%nodeArea(m)/DT
1844 call updateLinkV(tmpLQLateral, tmpQLateral)
1847 !! JLM:: again why output in this conditional ?? why not just output QLateral
1848 !! after this section ????
1849 if(NLINKSL .gt. 0) then
1850 if(nlst(1)%output_channelBucket_influx .eq. 1 .OR. &
1851 nlst(1)%output_channelBucket_influx .eq. 2 ) &
1852 qSfcLatRunoff(1:NLINKSL) = tmpQLateral(1:NLINKSL)
1853 if(nlst(1)%output_channelBucket_influx .eq. 3) &
1854 accSfcLatRunoff(1:NLINKSL) = accSfcLatRunoff(1:NLINKSL) + tmpQLateral(1:NLINKSL) * DT
1860 call updateLinkV(LQLateral, QLateral(1:NLINKSL))
1862 call hydro_stop("fatal error: NHDPlus only works for parallel now.")
1863 QLateral = LQLateral
1865 endif !! (channel_only .eq. 1 .or. channelBucket_only .eq. 1) then; else; endif
1868 !---------------------------------------------
1869 !! If not running channelOnly, here is where the bucket model is picked up
1870 if(channel_only .eq. 1) then
1872 write(6,*) "channel_only is not zero. No bucket."
1874 #endif /* HYDRO_D */
1876 !! REQUIRE BUCKET MODEL ON HERE?
1877 if(NLINKSL .gt. 0) QLateral(1:NLINKSL) = QLateral(1:NLINKSL) + qout_gwsubbas(1:NLINKSL)
1878 endif !! if(channel_only .eq. 1) then; else; endif
1880 if(nlst(1)%output_channelBucket_influx .eq. 1 .or. &
1881 nlst(1)%output_channelBucket_influx .eq. 2 ) &
1882 qBucket(1:NLINKSL) = qout_gwsubbas(1:NLINKSL)
1884 if(nlst(1)%output_channelBucket_influx .eq. 3) &
1885 accBucket(1:NLINKSL) = accBucket(1:NLINKSL) + qout_gwsubbas(1:NLINKSL) * DT
1887 ! Skip this section if we are NOT running any actual channel routing
1888 if (.not. channel_bypass) then
1890 !---------------------------------------------
1891 ! QLateral = QLateral / nsteps
1896 call gbcastReal2(toNodeInd,nToNodeInd,QLINK(1:NLINKSL,2), NLINKSL, gQLINK(:,2))
1897 call gbcastReal2(toNodeInd,nToNodeInd,QLINK(1:NLINKSL,1), NLINKSL, gQLINK(:,1))
1898 !---------- route other reaches, with upstream inflow
1903 if(my_id .eq. io_id) then
1908 tmpFinalResType = rt_domain(did)%final_reservoir_type
1909 tmpAssimilatedValue = rt_domain(did)%reservoir_assimilated_value
1910 tmpAssimilatedSourceFile = rt_domain(did)%reservoir_assimilated_source_file
1921 !process as standard link or a lake inflow link, or lake outflow link
1922 ! link flowing out of lake, accumulate all the inflows with the revised TO_NODEs
1923 ! TYPEL = -999 stnd; TYPEL=1 outflow from lake; TYPEL = 3 inflow to a lake
1925 if(TYPEL(k) .ne. 2) then ! don't process internal lake links only
1928 !using mapping index
1929 do n = 1, gtoNODE(k,1)
1931 !! JLM - I think gQLINK(,2) is actually previous. Global array never sees current. Seeing
1932 !! current would require global communication at the end of each loop through k
1933 !! (=kth reach). Additionally, how do you synchronize to make sure the upstream are all
1934 !! done before doing the downstream?
1935 if(gQLINK(m,2) .gt. 0) Quc = Quc + gQLINK(m,2) !--accum of upstream inflow of current timestep (2)
1936 if(gQLINK(m,1) .gt. 0) Qup = Qup + gQLINK(m,1) !--accum of upstream inflow of previous timestep (1)
1940 if (LINKID(k) .eq. TO_NODE(m)) then
1941 Quc = Quc + QLINK(m,2) !--accum of upstream inflow of current timestep (2)
1942 Qup = Qup + QLINK(m,1) !--accum of upstream inflow of previous timestep (1)
1946 endif !note that we won't process type 2 links, since they are internal to a lake
1949 !yw ### process each link k,
1950 ! There is a situation that different k point to the same LAKEIDX
1951 ! if(TYPEL(k) .eq. 1 .and. LAKEIDX(k) .gt. 0) then !--link is a reservoir
1952 if(TYPEL(k) .eq. 1 ) then !--link is a reservoir
1955 if(lakeid .ge. 0) then
1957 ! Calls run for a single reservoir depending on its type as
1958 ! in whether it uses level pool, machine learning, or persistence.
1959 ! Inflow, lateral inflow, water elevation, and the routing period
1960 ! are passed in. Updated outflow and water elevation are returned.
1961 call rt_domain(did)%reservoirs(lakeid)%ptr%run(Qup, Quc, 0.0, &
1962 RESHT(lakeid), tmpQLINK(k,2), DTRT_CH, rt_domain(did)%final_reservoir_type(lakeid), &
1963 rt_domain(did)%reservoir_assimilated_value(lakeid), rt_domain(did)%reservoir_assimilated_source_file(lakeid))
1965 ! TODO: Encapsulate the lake state variable for water elevation (RESHT(lakeid))
1966 ! inside the reservoir module, but it requires a redesign of the lake
1967 ! MPI communication model.
1969 QLAKEO(lakeid) = tmpQLINK(k,2) !save outflow to lake
1970 QLAKEI(lakeid) = Quc !save inflow to lake
1975 elseif (channel_option .eq. 1) then !muskingum routing
1978 tmpQLINK(k,2) = MUSKING(k,Qup,(Quc+QLateral(k)),QLINK(k,1),DTRT_CH,Km,X) !upstream plust lateral inflow
1980 elseif (channel_option .eq. 2) then ! muskingum cunge, don't process internal lake nodes TYP=2
1981 ! tmpQLINK(k,2) = MUSKINGCUNGE(k,Qup, Quc, QLINK(k,1), &
1982 ! QLateral(k), DTRT_CH, So(k), CHANLEN(k), &
1983 ! MannN(k), ChSSlp(k), Bw(k), Tw(k) )
1985 #ifdef WRF_HYDRO_NUDGING
1986 call nudge_apply_upstream_muskingumCunge( Qup, Quc, nudge(k), k )
1989 call SUBMUSKINGCUNGE(&
1990 tmpQLINK(k,2), velocity(k), qloss(k), LINKID(k), Qup, Quc, QLINK(k,1), &
1991 QLateral(k), DTRT_CH, So(k), CHANLEN(k), &
1992 MannN(k), ChSSlp(k), Bw(k), Tw(k), Tw_CC(k), n_CC(k), HLINK(k), ChannK(k) )
1996 print *, " no channel option selected"
1998 call hydro_stop("drive_CHANNEL")
2005 call updateLake_seq(QLAKEO,nlakes,tmpQLAKEO)
2006 call updateLake_seq(QLAKEI,nlakes,tmpQLAKEI)
2007 call updateLake_seq(RESHT,nlakes,tmpRESHT)
2008 call updateLake_seqInt(rt_domain(did)%final_reservoir_type, nlakes, tmpFinalResType)
2009 call updateLake_seq(rt_domain(did)%reservoir_assimilated_value, nlakes, tmpAssimilatedValue)
2010 !call updateLake_seq_char(rt_domain(did)%reservoir_assimilated_source_file, nlakes, tmpAssimilatedSourceFile)
2013 do k = 1, NLINKSL !tmpQLINK?
2014 if(TYPEL(k) .ne. 2) then !only the internal lake nodes don't have info.. but need to save QLINK of lake out too
2015 QLINK(k,2) = tmpQLINK(k,2)
2017 QLINK(k,1) = QLINK(k,2) !assigng link flow of current to be previous for next time step
2021 #ifdef WRF_HYDRO_NUDGING
2022 if(.not. nudgeWAdvance) call nudge_term_all(qlink, nudge, int(nt*dtrt_ch))
2023 #endif /* WRF_HYDRO_NUDGING */
2027 ! print *, "END OF ALL REACHES...",KRT,DT_STEPS
2032 endif ! channel_bypass
2034 if (KT .eq. 1) KT = KT + 1
2037 if(my_id .eq. io_id) then
2038 if(allocated(tmpQLAKEO)) deallocate(tmpQLAKEO)
2039 if(allocated(tmpQLAKEI)) deallocate(tmpQLAKEI)
2040 if(allocated(tmpRESHT)) deallocate(tmpRESHT)
2041 if(allocated(tmpFinalResType)) deallocate(tmpFinalResType)
2045 if (KT .eq. 1) KT = KT + 1 ! redundant?
2047 end subroutine drive_CHANNEL_RSL
2049 ! ----------------------------------------------------------------
2051 end module module_channel_routing
2053 !! Is this outside the module scope on purpose?
2055 subroutine checkReach(ii, inVar)
2057 use module_RT_data, only: rt_domain
2058 use MODULE_mpp_ReachLS, only : updatelinkv, &
2059 ReachLS_write_io, gbcastvalue, &
2063 real,dimension(rt_domain(1)%nlinksl) :: inVar
2064 real:: g_var(rt_domain(1)%gnlinksl)
2065 call ReachLS_write_io(inVar, g_var)
2066 if(my_id .eq. io_id) then
2070 end subroutine checkReach