@@ -577,24 +577,29 @@ def initialMCT(self):
577
577
578
578
# cmcheck
579
579
# 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
581
581
self .var .PrevQMCTin = np .where (PrevQMCTin == - 9999 , maskinfo .in_zero (), PrevQMCTin ) # np
582
582
# MCT inflow (x) to MCT pixel at time t0
583
583
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
585
587
self .var .PrevQMCTout = np .where (PrevQMCTout == - 9999 , maskinfo .in_zero (), PrevQMCTout ) #np
586
588
# MCT outflow (x+dx) from MCT pixel at time t0
587
589
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
+
588
596
PrevCmMCT = loadmap ('PrevCmMCTInitValue' )
589
597
self .var .PrevCm0 = np .where (PrevCmMCT == - 9999 , maskinfo .in_one (), PrevCmMCT ) #np
590
598
# Courant numnber (Cm) for MCT at previous time step t0
591
599
PrevDmMCT = loadmap ('PrevDmMCTInitValue' )
592
600
self .var .PrevDm0 = np .where (PrevDmMCT == - 9999 , maskinfo .in_zero (), PrevDmMCT ) #np
593
601
# Reynolds number (Dm) for MCT at previous time step t0
594
602
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
-
598
603
599
604
# ************************************************************
600
605
# ***** INITIALISE MUSKINGUM-CUNGE-TODINI WAVE ROUTER ********
@@ -823,10 +828,12 @@ def dynamic(self, NoRoutingExecuted):
823
828
824
829
# cmcheck
825
830
# 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
827
834
# if np.any(self.var.ChanQAvgDt < 0):
828
835
# print("At least one value is less than 0.")
829
- ChanQKinAvgDt [ ChanQKinAvgDt < 0 ] = 0
836
+ ChanQKinOutAvgDt [ ChanQKinOutAvgDt < 0 ] = 0
830
837
# Average outflow (x+dx) QAvg during sub-routing step (average)
831
838
# Qout_avg = Qin_avg -(Vend - Vini)
832
839
@@ -865,12 +872,19 @@ def dynamic(self, NoRoutingExecuted):
865
872
# Inflow (x) at time t instant (instant) q00
866
873
# This is coming from upstream pixels
867
874
875
+
868
876
# calling MCT routing
869
877
# 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
873
883
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)
874
888
875
889
# # update input (x) Q at t for next step (instant) q10 -> q00
876
890
# ChanQMCTOutStartPcr = decompress(ChanQMCTOutStart) # pcr
@@ -883,19 +897,19 @@ def dynamic(self, NoRoutingExecuted):
883
897
self .var .PrevCm0 = Cmend
884
898
self .var .PrevDm0 = Dmend
885
899
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)
899
913
900
914
901
915
# combine results from Kinematic and MCT pixels at x+dx t+dt (instant)
@@ -906,8 +920,9 @@ def dynamic(self, NoRoutingExecuted):
906
920
# Channel storage V at the end of computation step t+dt (instant)
907
921
908
922
# 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 )
911
926
# Average channel outflow (x+dx) QAvg during routing step (average)
912
927
913
928
@@ -916,9 +931,9 @@ def dynamic(self, NoRoutingExecuted):
916
931
self .var .PrevQMCTin = compressArray (upstream (self .var .LddChan , ChanQMCTStartPcr ))
917
932
# using LddChan here because we need to input from upstream pixels to include kinematic pixels
918
933
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))
922
937
923
938
self .var .sumDisDay += self .var .ChanQAvgDt
924
939
# sum of average outflow Q on model sub-steps to give accumulated total outflow volume
@@ -976,7 +991,8 @@ def dynamic(self, NoRoutingExecuted):
976
991
# Total Mass Balance Error in m3 per catchment for Initial Run OR Kinematic routing (Split Routing OFF)
977
992
MB = - np .sum (StorageStep )+ np .sum (self .var .StorageStepINIT ) - OutStepM3 [0 ] - DischargeM3StructuresR [0 ] + self .var .AddedTRUN
978
993
979
- if MB > 1.e-9 :
994
+ # cmcheck
995
+ if MB > 1.e-12 :
980
996
print ('Mass balance error MB=' , MB )
981
997
982
998
@@ -1179,7 +1195,7 @@ def SplitRouting(self, SideflowChan):
1179
1195
return
1180
1196
1181
1197
1182
- def MCTRoutingLoop (self ,ChanQMCTOutStart ,ChanQMCTInStart ,ChanQKinOut ,SideflowChanMCT ,ChanM3Start ):
1198
+ def MCTRoutingLoop (self ,ChanQMCTOutStart ,ChanQMCTInStart ,ChanQKinOut ,ChanQKinOutAvgDt , SideflowChanMCT ,ChanM3Start ):
1183
1199
"""This function implements Muskingum-Cunge-Todini routing method
1184
1200
MCT routing is calculated on MCT pixels only but gets inflow from both KIN and MCT upstream pixels.
1185
1201
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
1224
1240
q10 = self .get_mct_pix (ChanQMCTOutStart )
1225
1241
1226
1242
# 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
1227
1244
ChanQMCTPcr = decompress (ChanQKinOut ) #pcr
1228
-
1229
1245
ChanQMCTUp1 = compressArray (upstream (self .var .LddChan ,ChanQMCTPcr ))
1230
1246
# Inflow at time t+1
1231
1247
# I(t+dt)
1232
1248
# dim=mct pixels
1233
1249
q01 = self .get_mct_pix (ChanQMCTUp1 )
1234
1250
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
+
1235
1263
# Outflow (x+1) at time t+1
1236
1264
# O(t+dt)
1237
1265
# dim=mct pixels
1238
1266
# set to zero at beginning of computation
1239
1267
q11 = np .zeros_like (q01 )
1240
- # qout_ave = np.zeros_like(q01)
1268
+ q1m = np .zeros_like (q01 )
1241
1269
V11 = np .zeros_like (q01 )
1242
1270
1243
1271
# Lateral flow Ql (average) during interval dt [m3/s]
@@ -1250,15 +1278,18 @@ def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,SideflowCha
1250
1278
# Pixels in the same order are independent and can be routed in parallel.
1251
1279
# Orders must be processed in series, starting from order 0.
1252
1280
# 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
1254
1282
ChanQOut = ChanQKinOut .copy ()
1283
+ ChanQOutAvg = ChanQKinOutAvgDt .copy ()
1255
1284
# Initialise outflow (x+dx) at t+dt using outflow from kinematic pixels
1256
1285
# Then update outflow from mct pixels as different orders are calculated
1257
1286
1258
1287
num_orders = self .mct_river_router .order_start_stop .shape [0 ]
1288
+ # loop on orders
1259
1289
for order in range (num_orders ):
1260
1290
first = self .mct_river_router .order_start_stop [order , 0 ]
1261
1291
last = self .mct_river_router .order_start_stop [order , 1 ]
1292
+ # loop on pixels in the order
1262
1293
for index in range (first , last ):
1263
1294
# get pixel ID
1264
1295
idpix = self .mct_river_router .pixels_ordered [index ]
@@ -1281,44 +1312,68 @@ def MCTRoutingLoop(self,ChanQMCTOutStart,ChanQMCTInStart,ChanQKinOut,SideflowCha
1281
1312
# # Set outflow to be the same as inflow in MCT grid cells ('tanto entra tanto esce')
1282
1313
# V11[idpix] = ChanM3MCT0[idpix]
1283
1314
# # Set end volume to be the same as initial volume in MCT grid cells ('tanto entra tanto esce')
1284
- # #cmcheck - aggiusto il bilancio
1285
1315
# V11[idpix] = ChanM3MCT0[idpix] + q01[idpix] + ql[idpix] - q11[idpix]
1286
1316
1287
1317
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
+
1288
1326
1289
1327
# Update contribution from upstream pixels at time t+1 (dim=all pixels) using the newly calculated q11
1290
1328
# I want to update q01 (inflow at t+1) for cells downstream of idpix using the newly calculated q11
1291
1329
# It can be a mix of kinematic and mct pixels. I want to update the contribution from mct pixels
1292
1330
Q11 = self .put_mct_pix (q11 )
1293
1331
# explode mct pixels to all catchment pixels
1294
1332
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
+
1295
1342
# combine results in pixels from this order (mct pixels) with results in pixels from upstream orders (kin and mct)
1296
1343
# pixels that are not MCT get value zero in Q11 from put_mct_pix (see above)
1297
1344
ChanQOut = np .where (Q11 == 0 , ChanQOut , Q11 )
1345
+ ChanQOutAvg = np .where (Q1m == 0 , ChanQOutAvg , Q1m )
1298
1346
1299
1347
# for each pixel in the catchment, calc contribution from upstream pixels
1300
1348
# outflow (x+dx) at t+dt for both kin and mct upstream pixels is stored in ChanQOut
1301
1349
QupPcr = decompress (ChanQOut ) #pcr
1302
1350
Qup01 = compressArray (upstream (self .var .LddChan ,QupPcr ))
1303
1351
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
+
1304
1358
# slice the MCT pixels
1305
1359
# Inflow at time t+1
1306
1360
# I(t+dt)
1307
1361
# dim=mct pixels
1308
1362
q01 = self .get_mct_pix (Qup01 )
1363
+ q0m = self .get_mct_pix (Qup0m )
1309
1364
1310
1365
# repeat for next order of pixels
1311
1366
1312
- ### end pixels loop ###
1367
+ ### end order loop - all pixels are calculated ###
1313
1368
1314
1369
# explode arrays with MCT results on all catchment pixels
1315
1370
ChanQMCTOut = self .put_mct_pix (q11 )
1316
1371
Cmout = self .put_mct_pix (Cm0 )
1317
1372
Dmout = self .put_mct_pix (Dm0 )
1318
1373
ChanM3MCTOut = self .put_mct_pix (V11 )
1319
- #ChanQMCTOutAve = self.put_mct_pix(qout_ave )
1374
+ ChanQMCTOutAvg = self .put_mct_pix (q1m )
1320
1375
1321
- return ChanQMCTOut , ChanM3MCTOut , Cmout , Dmout
1376
+ return ChanQMCTOutAvg , ChanQMCTOut , ChanM3MCTOut , Cmout , Dmout
1322
1377
1323
1378
1324
1379
def MCTRouting_single (self , V00 , q10 , q01 , q00 , ql , Cm0 , Dm0 , dt , xpix , s0 , Balv , ANalv , Nalv ):
0 commit comments