Skip to content

Commit d88f6cd

Browse files
author
Cinzia Mazzetti
committed
Moved integration on control volume to inner loop in mct.
1 parent d68f42c commit d88f6cd

File tree

1 file changed

+92
-37
lines changed

1 file changed

+92
-37
lines changed

src/lisflood/hydrological_modules/routing.py

+92-37
Original file line numberDiff line numberDiff line change
@@ -577,24 +577,29 @@ def initialMCT(self):
577577

578578
# cmcheck
579579
# Initialisation for MCT routing
580-
PrevQMCTin = loadmap('PrevQMCTinInitValue') # instant input discharge for MCT
580+
PrevQMCTin = loadmap('PrevQMCTinInitValue') # instant input discharge for MCT at previouse step
581581
self.var.PrevQMCTin = np.where(PrevQMCTin == -9999, maskinfo.in_zero(), PrevQMCTin) # np
582582
# MCT inflow (x) to MCT pixel at time t0
583583

584-
PrevQMCTout = loadmap('PrevQMCToutInitValue') # instant output discharge for MCT
584+
#cmcheck
585+
# this is probable not necessary, I can use ChanQ
586+
PrevQMCTout = loadmap('PrevQMCToutInitValue') # instant output discharge for MCT at previous step
585587
self.var.PrevQMCTout = np.where(PrevQMCTout == -9999, maskinfo.in_zero(), PrevQMCTout) #np
586588
# MCT outflow (x+dx) from MCT pixel at time t0
587589

590+
self.var.ChanQ = np.where(self.var.IsChannelKinematic, self.var.ChanQ, self.var.PrevQMCTout)
591+
# Initialise instantaneous outflow for kinematic and MCT grid cells at previous time step t0 (q10)
592+
593+
# #cmcheck
594+
# self.var.ChanQAvgDt is average outflow during previous step and it is initialised with kinematic routing
595+
588596
PrevCmMCT = loadmap('PrevCmMCTInitValue')
589597
self.var.PrevCm0 = np.where(PrevCmMCT == -9999, maskinfo.in_one(), PrevCmMCT) #np
590598
# Courant numnber (Cm) for MCT at previous time step t0
591599
PrevDmMCT = loadmap('PrevDmMCTInitValue')
592600
self.var.PrevDm0 = np.where(PrevDmMCT == -9999, maskinfo.in_zero(), PrevDmMCT) #np
593601
# Reynolds number (Dm) for MCT at previous time step t0
594602

595-
self.var.ChanQ = np.where(self.var.IsChannelKinematic, self.var.ChanQ, self.var.PrevQMCTout)
596-
# Initialise instantaneous outflow for kinematic and MCT grid cells at previous time step t0 (q10)
597-
598603

599604
# ************************************************************
600605
# ***** INITIALISE MUSKINGUM-CUNGE-TODINI WAVE ROUTER ********
@@ -823,10 +828,12 @@ def dynamic(self, NoRoutingExecuted):
823828

824829
# cmcheck
825830
# Calculate average outflow using water balance for channel grid cell
826-
ChanQKinAvgDt = (self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanM3 - ChanM3KinEnd + ChanM3KinStart) * self.var.InvDtRouting
831+
# Integration on control volume
832+
# THIS IS ONLY WORKING FOR HEAD GRID CELLS AND MUST BE MOVED TO INTERNAL LOOP
833+
ChanQKinOutAvgDt = (self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanM3 - ChanM3KinEnd + ChanM3KinStart) * self.var.InvDtRouting
827834
# if np.any(self.var.ChanQAvgDt < 0):
828835
# print("At least one value is less than 0.")
829-
ChanQKinAvgDt[ChanQKinAvgDt < 0] = 0
836+
ChanQKinOutAvgDt[ChanQKinOutAvgDt < 0] = 0
830837
# Average outflow (x+dx) QAvg during sub-routing step (average)
831838
# Qout_avg = Qin_avg -(Vend - Vini)
832839

@@ -865,12 +872,19 @@ def dynamic(self, NoRoutingExecuted):
865872
# Inflow (x) at time t instant (instant) q00
866873
# This is coming from upstream pixels
867874

875+
868876
# calling MCT routing
869877
# using ChanQKinOutEnd from Kinematic routing to have inflow from upstream kinematic pixels
870-
ChanQMCTOutEnd,ChanM3MCTEnd,Cmend, Dmend = self.MCTRoutingLoop(ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOutEnd,SideflowChanMCT,ChanM3MCTStart)
871-
# Outflow (x+dx) at time t+dt end of calculation step (instant)
872-
# Channel storage at time t+dt end of calculation step (instant)
878+
# using ChanQKinOutAvgDt from kinematic routing to have average outflow from upstream kinematic pixels
879+
ChanQMCTOutAvgDt,ChanQMCTOutEnd,ChanM3MCTEnd,Cmend, Dmend = self.MCTRoutingLoop(ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOutEnd,ChanQKinOutAvgDt,SideflowChanMCT,ChanM3MCTStart)
880+
# Average outflow (x+dx) during time dt step (average) q1m
881+
# Outflow (x+dx) at time t+dt end of calculation step (instant) q11
882+
# Channel storage at time t+dt end of calculation step (instant) V11
873883

884+
# mct_balance = np.where(self.var.IsChannelKinematic, 0., (self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanMCT * self.var.DtRouting - ChanM3MCTEnd + ChanM3MCTStart) * self.var.InvDtRouting) - ChanQMCTOutAvgDt
885+
# # cmcheck
886+
# if abs(mct_balance) > 1.e-12:
887+
# print('mct_balance error ',mct_balance)
874888

875889
# # update input (x) Q at t for next step (instant) q10 -> q00
876890
# ChanQMCTOutStartPcr = decompress(ChanQMCTOutStart) # pcr
@@ -883,19 +897,19 @@ def dynamic(self, NoRoutingExecuted):
883897
self.var.PrevCm0 = Cmend
884898
self.var.PrevDm0 = Dmend
885899

886-
# cmcheck
887-
888-
# calc average discharge outflow for MCT channels during routing sub step dt
889-
# Calculate average outflow using water balance for MCT channel grid cell over sub-routing step
890-
# ChanQMCTAvgDt = (self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanMCT * self.var.DtRouting - ChanM3MCTEnd + ChanM3MCTStart) * self.var.InvDtRouting
891-
ChanQMCTAvgDt = np.where(self.var.IsChannelKinematic, 0., (
892-
self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanMCT * self.var.DtRouting - ChanM3MCTEnd + ChanM3MCTStart) * self.var.InvDtRouting)
893-
894-
# if np.any(self.var.ChanQAvgDt < 0):
895-
# print("At least one value is less than 0.")
896-
ChanQMCTAvgDt[ChanQMCTAvgDt < 0] = 0
897-
# Average outflow (x+dx) QAvg during routing step (average)
898-
# Qout_avg = Qin_avg -(Vend - Vini)
900+
# # cmcheck
901+
#
902+
# # calc average discharge outflow for MCT channels during routing sub step dt
903+
# # Calculate average outflow using water balance for MCT channel grid cell over sub-routing step
904+
# # ChanQMCTAvgDt = (self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanMCT * self.var.DtRouting - ChanM3MCTEnd + ChanM3MCTStart) * self.var.InvDtRouting
905+
# ChanQMCTAvgDt = np.where(self.var.IsChannelKinematic, 0., (
906+
# self.var.ChanQAvgInDt * self.var.DtRouting + SideflowChanMCT * self.var.DtRouting - ChanM3MCTEnd + ChanM3MCTStart) * self.var.InvDtRouting)
907+
#
908+
# # if np.any(self.var.ChanQAvgDt < 0):
909+
# # print("At least one value is less than 0.")
910+
# ChanQMCTAvgDt[ChanQMCTAvgDt < 0] = 0
911+
# # Average outflow (x+dx) QAvg during routing step (average)
912+
# # Qout_avg = Qin_avg -(Vend - Vini)
899913

900914

901915
# combine results from Kinematic and MCT pixels at x+dx t+dt (instant)
@@ -906,8 +920,9 @@ def dynamic(self, NoRoutingExecuted):
906920
# Channel storage V at the end of computation step t+dt (instant)
907921

908922
# combine results from Kinematic and MCT pixels average outflow during routing sub-step dt
909-
910-
self.var.ChanQAvgDt = np.where(self.var.IsChannelKinematic, ChanQKinAvgDt, ChanQMCTAvgDt)
923+
#cmcheck
924+
# THIS works for head cells only for kinematic
925+
self.var.ChanQAvgDt = np.where(self.var.IsChannelKinematic, ChanQKinOutAvgDt, ChanQMCTOutAvgDt)
911926
# Average channel outflow (x+dx) QAvg during routing step (average)
912927

913928

@@ -916,9 +931,9 @@ def dynamic(self, NoRoutingExecuted):
916931
self.var.PrevQMCTin = compressArray(upstream(self.var.LddChan, ChanQMCTStartPcr))
917932
# using LddChan here because we need to input from upstream pixels to include kinematic pixels
918933

919-
# Update average channel inflow (x) Qavg for next step
920-
ChanQAvgInDtPcr = decompress(self.var.ChanQAvgDt) # pcr
921-
self.var.ChanQAvgInDt = compressArray(upstream(self.var.LddChan, ChanQAvgInDtPcr))
934+
# # Update average channel inflow (x) Qavg for next step
935+
# ChanQAvgInDtPcr = decompress(self.var.ChanQAvgDt) # pcr
936+
# self.var.ChanQAvgInDt = compressArray(upstream(self.var.LddChan, ChanQAvgInDtPcr))
922937

923938
self.var.sumDisDay += self.var.ChanQAvgDt
924939
# sum of average outflow Q on model sub-steps to give accumulated total outflow volume
@@ -976,7 +991,8 @@ def dynamic(self, NoRoutingExecuted):
976991
# Total Mass Balance Error in m3 per catchment for Initial Run OR Kinematic routing (Split Routing OFF)
977992
MB =-np.sum(StorageStep)+np.sum(self.var.StorageStepINIT) - OutStepM3[0] -DischargeM3StructuresR[0] +self.var.AddedTRUN
978993

979-
if MB > 1.e-9:
994+
# cmcheck
995+
if MB > 1.e-12:
980996
print('Mass balance error MB=', MB)
981997

982998

@@ -1179,7 +1195,7 @@ def SplitRouting(self, SideflowChan):
11791195
return
11801196

11811197

1182-
def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,SideflowChanMCT,ChanM3Start):
1198+
def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,ChanQKinOutAvgDt,SideflowChanMCT,ChanM3Start):
11831199
"""This function implements Muskingum-Cunge-Todini routing method
11841200
MCT routing is calculated on MCT pixels only but gets inflow from both KIN and MCT upstream pixels.
11851201
Function get_mct_pix is used to compress arrays with all river channel pixels to arrays containing MCT pixels only.
@@ -1224,20 +1240,32 @@ def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,SideflowCha
12241240
q10 = self.get_mct_pix(ChanQMCTOutStart)
12251241

12261242
# calc contribution from upstream pixels at time t+1 (dim=all pixels because we need to include both MCT and KIN pixels at the same time)
1243+
# First order (aka order 0) of mct pixels have inflow and average inflow from kin pixels only
12271244
ChanQMCTPcr=decompress(ChanQKinOut) #pcr
1228-
12291245
ChanQMCTUp1=compressArray(upstream(self.var.LddChan,ChanQMCTPcr))
12301246
# Inflow at time t+1
12311247
# I(t+dt)
12321248
# dim=mct pixels
12331249
q01 = self.get_mct_pix(ChanQMCTUp1)
12341250

1251+
# cmcheck
1252+
# THIS IS WHERE i NEED TO CALCULATE
1253+
# calc average discharge from upstream pixels during step dt
1254+
# First order (aka order 0) of mct pixels have inflow and average inflow from kin pixels only
1255+
# I have already calculated outflow for all kin pixels for this step
1256+
ChanQKinOutAvgDtPcr=decompress(ChanQKinOutAvgDt) #pcr
1257+
ChanQKinOutAvgDtUp1=compressArray(upstream(self.var.LddChan,ChanQKinOutAvgDtPcr))
1258+
# Average Inflow at time dt
1259+
# I average (t+dt)
1260+
# dim=mct pixels
1261+
q0m = self.get_mct_pix(ChanQKinOutAvgDtUp1)
1262+
12351263
# Outflow (x+1) at time t+1
12361264
# O(t+dt)
12371265
# dim=mct pixels
12381266
# set to zero at beginning of computation
12391267
q11 = np.zeros_like(q01)
1240-
# qout_ave = np.zeros_like(q01)
1268+
q1m = np.zeros_like(q01)
12411269
V11 = np.zeros_like(q01)
12421270

12431271
# Lateral flow Ql (average) during interval dt [m3/s]
@@ -1250,15 +1278,18 @@ def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,SideflowCha
12501278
# Pixels in the same order are independent and can be routed in parallel.
12511279
# Orders must be processed in series, starting from order 0.
12521280
# Outflow from MCT pixels can only go to a MCT pixel
1253-
# First order of mct pixels have inflow from kin pixels only
1281+
# First order (aka order 0) of mct pixels have inflow and average inflow from kin pixels only
12541282
ChanQOut = ChanQKinOut.copy()
1283+
ChanQOutAvg = ChanQKinOutAvgDt.copy()
12551284
# Initialise outflow (x+dx) at t+dt using outflow from kinematic pixels
12561285
# Then update outflow from mct pixels as different orders are calculated
12571286

12581287
num_orders = self.mct_river_router.order_start_stop.shape[0]
1288+
# loop on orders
12591289
for order in range(num_orders):
12601290
first = self.mct_river_router.order_start_stop[order, 0]
12611291
last = self.mct_river_router.order_start_stop[order, 1]
1292+
# loop on pixels in the order
12621293
for index in range(first, last):
12631294
# get pixel ID
12641295
idpix = self.mct_river_router.pixels_ordered[index]
@@ -1281,44 +1312,68 @@ def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,SideflowCha
12811312
# # Set outflow to be the same as inflow in MCT grid cells ('tanto entra tanto esce')
12821313
# V11[idpix] = ChanM3MCT0[idpix]
12831314
# # Set end volume to be the same as initial volume in MCT grid cells ('tanto entra tanto esce')
1284-
# #cmcheck - aggiusto il bilancio
12851315
# V11[idpix] = ChanM3MCT0[idpix] + q01[idpix] + ql[idpix] - q11[idpix]
12861316

12871317

1318+
# #cmcheck
1319+
# THIS IS WHERE I DO THE INTEGRATION ON THE CONTROL VOLUME
1320+
# calc average discharge outflow q1m for MCT channels during routing sub step dt
1321+
# Calculate average outflow using water balance for MCT channel grid cell over sub-routing step
1322+
1323+
q1m[idpix] = q0m[idpix] + ql[idpix] + (V00[idpix] - V11[idpix]) / dt
1324+
1325+
12881326

12891327
# Update contribution from upstream pixels at time t+1 (dim=all pixels) using the newly calculated q11
12901328
# I want to update q01 (inflow at t+1) for cells downstream of idpix using the newly calculated q11
12911329
# It can be a mix of kinematic and mct pixels. I want to update the contribution from mct pixels
12921330
Q11 = self.put_mct_pix(q11)
12931331
# explode mct pixels to all catchment pixels
12941332

1333+
# cmcheck
1334+
# THIS IS WHERE I UPDATE THE AVERAGE INFLOW FROM UPSTREAM
1335+
# Update average contribution from upstream pixels at time t+1 (dim=all pixels) using the newly calculated q1m
1336+
# I want to update q0m (avergae inflow at t+1) for cells downstream of this order using the newly calculated q1m, because
1337+
# downstream pixels receive outflow from this order and from mct pixels in this order.
1338+
# It can be a mix of kinematic and mct pixels. I want to update the contribution from mct pixels
1339+
Q1m = self.put_mct_pix(q1m)
1340+
# explode mct pixels to all catchment pixels
1341+
12951342
# combine results in pixels from this order (mct pixels) with results in pixels from upstream orders (kin and mct)
12961343
# pixels that are not MCT get value zero in Q11 from put_mct_pix (see above)
12971344
ChanQOut = np.where(Q11 == 0, ChanQOut, Q11)
1345+
ChanQOutAvg = np.where(Q1m == 0, ChanQOutAvg, Q1m)
12981346

12991347
# for each pixel in the catchment, calc contribution from upstream pixels
13001348
# outflow (x+dx) at t+dt for both kin and mct upstream pixels is stored in ChanQOut
13011349
QupPcr=decompress(ChanQOut) #pcr
13021350
Qup01=compressArray(upstream(self.var.LddChan,QupPcr))
13031351

1352+
# for each pixel in the catchment, calc average contribution from upstream pixels
1353+
# average outflow (x+dx) at t+dt for both kin and mct upstream pixels is stored in ChanQOutAvg
1354+
QupAvgPcr=decompress(ChanQOutAvg) #pcr
1355+
Qup0m=compressArray(upstream(self.var.LddChan,QupAvgPcr))
1356+
1357+
13041358
# slice the MCT pixels
13051359
# Inflow at time t+1
13061360
# I(t+dt)
13071361
# dim=mct pixels
13081362
q01 = self.get_mct_pix(Qup01)
1363+
q0m = self.get_mct_pix(Qup0m)
13091364

13101365
# repeat for next order of pixels
13111366

1312-
### end pixels loop ###
1367+
### end order loop - all pixels are calculated ###
13131368

13141369
# explode arrays with MCT results on all catchment pixels
13151370
ChanQMCTOut = self.put_mct_pix(q11)
13161371
Cmout = self.put_mct_pix(Cm0)
13171372
Dmout = self.put_mct_pix(Dm0)
13181373
ChanM3MCTOut = self.put_mct_pix(V11)
1319-
#ChanQMCTOutAve = self.put_mct_pix(qout_ave)
1374+
ChanQMCTOutAvg = self.put_mct_pix(q1m)
13201375

1321-
return ChanQMCTOut, ChanM3MCTOut, Cmout, Dmout
1376+
return ChanQMCTOutAvg, ChanQMCTOut, ChanM3MCTOut, Cmout, Dmout
13221377

13231378

13241379
def MCTRouting_single(self, V00, q10, q01, q00, ql, Cm0, Dm0, dt, xpix, s0, Balv, ANalv, Nalv):

0 commit comments

Comments
 (0)