wolfhece 2.0.43__py3-none-any.whl → 2.0.45__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@ from scipy.interpolate import interp1d
9
9
  import os
10
10
  import ctypes as ct
11
11
 
12
-
12
+ from .SubBasin import *
13
13
  from .Outlet import *
14
14
  from .Dumping import *
15
15
  from ..PyTranslate import _
@@ -26,8 +26,11 @@ class RetentionBasin():
26
26
  _outFlow:dict
27
27
  surfaceDrainedHydro:float # TO BUILD !!!!!!!!!!!!!!
28
28
  filledVolume:np.ndarray
29
+ intletsObj:dict
30
+ directFluxObj:dict
29
31
 
30
- def __init__(self, _dateBegin, _dateEnd, _deltaT, _time=None, _id='J1', _name='Default name', _type='', _dictRB={}, _directDictRB={}, _tz=0, _outletNames=[], withRBDict=True, _workingDir=""):
32
+ def __init__(self, _dateBegin=None, _dateEnd=None, _deltaT:int=None, _time=None, _id='J1', _name='Default name', _type='',
33
+ _dictRB={}, _directDictRB={}, _tz=0, _outletNames=[], withRBDict=True, _workingDir=""):
31
34
  print('Creation of a RetentionBasin!')
32
35
  self.iD = _id
33
36
  self.name = _name
@@ -359,15 +362,28 @@ class RetentionBasin():
359
362
  if(self.intletsObj != {}):
360
363
  nameOutFlow = list(self.intletsObj.items())[0][0]
361
364
  curObj = self.intletsObj[nameOutFlow]
362
- timeInlet = curObj.timeDelay
363
- deltaTr = timeInlet - self.timeDelay
365
+ # Compute the transfer time between modules
366
+ if type(curObj) is SubBasin:
367
+ timeInlet = curObj.timeDelay
368
+ deltaTr = timeInlet - self.timeDelay
369
+ else:
370
+ # Assumption the transfer time between the 2 RB is ambiguous
371
+ # Therefore, the transfer time is set to 0.0
372
+ deltaTr = 0.0
364
373
  self.inlets = curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)
365
374
  self.inletsRaw = curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)
366
375
  for i in range(1,len(list(self.intletsObj.items()))):
367
376
  nameOutFlow = list(self.intletsObj.items())[i][0]
368
377
  curObj = self.intletsObj[nameOutFlow]
369
378
  timeInlet = curObj.timeDelay
370
- deltaTr = timeInlet - self.timeDelay
379
+ if type(curObj) is SubBasin:
380
+ timeInlet = curObj.timeDelay
381
+ deltaTr = timeInlet - self.timeDelay
382
+ else:
383
+ # Assumption the transfer time between the 2 RB is ambiguous
384
+ # Therefore, the transfer time is set to 0.0
385
+ deltaTr = 0.0
386
+
371
387
  self.inlets += curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)
372
388
  self.inletsRaw += curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)
373
389
  elif(givenInlet != []):
@@ -394,6 +410,13 @@ class RetentionBasin():
394
410
  nameOutFlow = list(self.directFluxObj.items())[0][0]
395
411
  curObj = self.directFluxObj[nameOutFlow]
396
412
  timeInlet = curObj.timeDelay
413
+ if type(curObj) is SubBasin:
414
+ timeInlet = curObj.timeDelay
415
+ deltaTr = timeInlet - self.timeDelay
416
+ else:
417
+ # Assumption the transfer time between the 2 RB is ambiguous
418
+ # Therefore, the transfer time is set to 0.0
419
+ deltaTr = 0.0
397
420
  deltaTr = timeInlet - self.timeDelay
398
421
  self.directFluxInRB = curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)
399
422
  self.directFluxInRB_Raw = curObj.get_outFlow(typeOutFlow="Raw", whichOutFlow=nameOutFlow, lag=deltaTr)
@@ -401,7 +424,14 @@ class RetentionBasin():
401
424
  nameOutFlow = list(self.directFluxObj.items())[i][0]
402
425
  curObj = self.directFluxObj[nameOutFlow]
403
426
  timeInlet = curObj.timeDelay
404
- deltaTr = timeInlet - self.timeDelay
427
+ if type(curObj) is SubBasin:
428
+ timeInlet = curObj.timeDelay
429
+ deltaTr = timeInlet - self.timeDelay
430
+ else:
431
+ # Assumption the transfer time between the 2 RB is ambiguous
432
+ # Therefore, the transfer time is set to 0.0
433
+ deltaTr = 0.0
434
+
405
435
  try:
406
436
  self.directFluxInRB += curObj.get_outFlow(typeOutFlow="Net", whichOutFlow=nameOutFlow, lag=deltaTr)
407
437
  except:
@@ -448,8 +478,8 @@ class RetentionBasin():
448
478
  else:
449
479
  # self.directFluxInRB = np.zeros(len(self.time)-1)
450
480
  # self.directFluxInRB_Raw = np.zeros(len(self.time)-1)
451
- self.directFluxInRB = np.zeros(len(self.time))
452
- self.directFluxInRB_Raw = np.zeros(len(self.time))
481
+ self.directFluxInRB = np.zeros(len(self.time), dtype=ct.c_double, order='F')
482
+ self.directFluxInRB_Raw = np.zeros(len(self.time), dtype=ct.c_double, order='F')
453
483
 
454
484
 
455
485
  def plot(self, workingDir, plotRaw=True, axis="Hours",rangeData=[], deltaMajorTicks=24.0*3600.0, deltaMinorTicks=3600.0, tzPlot=0, unitReservoir="[m^3]"):
@@ -648,7 +678,7 @@ class RetentionBasin():
648
678
 
649
679
 
650
680
  def plot_outlet(self, Measures=None, rangeData=[], yrangeRain=[], yrangeData=[], ylabel=[],addData=[], dt_addData=[], beginDates_addData=[], endDates_addData=[],\
651
- label_addData=[], color_addData=[],factor=1.5, graph_title='', withEvap=False, writeFile='', withDelay=True, deltaMajorTicks=-1,deltaMinorTicks=-1, tzPlot=0):
681
+ label_addData=[], color_addData=[],factor=1.5, graph_title='', withEvap=False, writeFile='', withDelay=True, deltaMajorTicks=-1,deltaMinorTicks=-1, tzPlot=0, figure=None):
652
682
 
653
683
  print("plot_outlet() function for RB -> TO DO !!!")
654
684
 
@@ -819,10 +849,9 @@ class RetentionBasin():
819
849
  logging.warning("Therefore, lag will be imposed to zero!")
820
850
  lag = 0.0
821
851
 
822
- if(self.type == "HelleRB"):
823
- if "delta time" in self._outFlow[whichOutFlow]:
824
- timeDelta = self._outFlow[whichOutFlow]["delta time"]
825
- lag = timeDelta
852
+ if "delta time" in self._outFlow[nameOutFlow]:
853
+ timeDelta = self._outFlow[nameOutFlow]["delta time"]
854
+ lag += timeDelta
826
855
 
827
856
 
828
857
  index = math.floor(lag/(self.time[1]-self.time[0]))
@@ -921,13 +950,14 @@ class RetentionBasin():
921
950
  return self.get_outFlow(whichOutFlow=whichOutFlow, typeOutFlow="Raw", unit=unit)
922
951
 
923
952
 
924
- def get_inlets_noDelay(self, unit='m3/s'):
953
+ def get_inlets_noDelay(self, unit='m3/s')->np.ndarray:
925
954
  """
926
955
  This function returns the total inlets of the basin and considers t0=0 at the outlet of the
927
956
  subbasin without considering timeDelay (the time of the real outlet of the whole potential catchment)
928
957
  """
929
958
 
930
959
  logging.warning("This function 'get_inlets_noDelay()' is operational but obsolate since version" + str(cst.VERSION_WOLFHYDRO_2023_1))
960
+ logging.warning("Please use the function 'get_inlets()' instead")
931
961
 
932
962
  # nameOut = list(self.outFlow.items())[0][0]
933
963
  # myInlets = self.inlets
@@ -984,6 +1014,36 @@ class RetentionBasin():
984
1014
  return myInlet
985
1015
 
986
1016
 
1017
+ def get_direct_insideRB_inlets(self, unit:str='m3/s', lag:float=0.0)->np.ndarray:
1018
+
1019
+ if lag < 0.0:
1020
+ logging.error("TimeDelay difference cannot be negative for a SubBasin!!")
1021
+ logging.warning("Therefore, lag will be imposed to zero! This might create some mistakes!")
1022
+ lag = 0.0
1023
+
1024
+ direct_inlets = np.zeros(len(self.directFluxInRB),dtype=ct.c_double, order='F')
1025
+ index = math.floor(lag/(self.time[1]-self.time[0]))
1026
+
1027
+ if(index==0):
1028
+ direct_inlets = self.directFluxInRB.copy()
1029
+ elif(index<len(direct_inlets)):
1030
+ direct_inlets[index:] = self.directFluxInRB[:-index].copy()
1031
+ else:
1032
+ logging.error("Warning: the simulation time is not long enough for this subbasin to be taken into account")
1033
+ logging.error("Error informations : ")
1034
+ logging.error("Function name : get_inlets()")
1035
+ logging.error("index = " + str(index))
1036
+ logging.error("len(myOutFlow) = " + str(len(direct_inlets)))
1037
+ logging.error("Lag = " + str(lag))
1038
+ return direct_inlets
1039
+
1040
+ if unit=='mm/h':
1041
+ logging.warning("Arguable way to convert in mm/h, there is ambiguity!")
1042
+ direct_inlets *= 3.6/self.surfaceDrainedHydro
1043
+
1044
+ return direct_inlets
1045
+
1046
+
987
1047
  def write_height_reservoir(self, workingDir):
988
1048
 
989
1049
  myH = np.zeros(len(self.filledVolume))
@@ -1015,11 +1075,12 @@ class RetentionBasin():
1015
1075
 
1016
1076
  # Artificial exit
1017
1077
  nameArtificialExit = list(self._outFlow.items())[1][0]
1018
- timeDelayNextRB = self.downstreamObj[nameArtificialExit].timeDelay
1019
- timeDelta = self._outFlow[nameArtificialExit]["delta time"]
1020
- newStep = self.convert_index_global_to_other_global(step,timeDelayOut=timeDelayNextRB,timeDelta=timeDelta)
1021
- if(newStep>0 and newStep<len(self._outFlow[nameArtificialExit]["Net"])):
1022
- self._outFlow[nameArtificialExit]["Net"][newStep] = Qstream
1078
+ self._outFlow[nameArtificialExit]["Net"][step] = Qstream
1079
+ # timeDelayNextRB = self.downstreamObj[nameArtificialExit].timeDelay
1080
+ # timeDelta = self._outFlow[nameArtificialExit]["delta time"]
1081
+ # newStep = self.convert_index_global_to_other_global(step,timeDelayOut=timeDelayNextRB,timeDelta=timeDelta)
1082
+ # if(newStep>0 and newStep<len(self._outFlow[nameArtificialExit]["Net"])):
1083
+ # self._outFlow[nameArtificialExit]["Net"][newStep] = Qstream
1023
1084
 
1024
1085
  else:
1025
1086
  self._outFlow[mainNameOut]["Net"][step] = Qstream + Qres
@@ -1095,13 +1156,13 @@ class RetentionBasin():
1095
1156
  relVol = self.relative_filledVolume
1096
1157
  for iOutFlow in range(1,len(list(self._outFlow.items()))):
1097
1158
  nameOut = list(self._outFlow.items())[iOutFlow][0]
1098
- self._outFlow[nameOut]["Raw"] = np.zeros(len(self.inletsRaw))
1159
+ self._outFlow[nameOut]["Raw"] = np.zeros(len(self.inletsRaw), dtype=ct.c_double, order='F')
1099
1160
 
1100
1161
  sizeOfHydro = len(self.time)
1101
1162
  for elOutFlow in self._outFlow:
1102
- self._outFlow[elOutFlow]["Net"] = np.zeros(sizeOfHydro)
1163
+ self._outFlow[elOutFlow]["Net"] = np.zeros(sizeOfHydro, dtype=ct.c_double, order='F')
1103
1164
 
1104
- outFlowReservoir = np.zeros(sizeOfHydro)
1165
+ outFlowReservoir = np.zeros(sizeOfHydro, dtype=ct.c_double, order='F')
1105
1166
  for i in range(1,sizeOfHydro):
1106
1167
 
1107
1168
  h = self.volume_to_h(self.filledVolume[i-1])
@@ -1278,13 +1339,33 @@ class RetentionBasin():
1278
1339
 
1279
1340
 
1280
1341
  def construct_surfaceDrainedHydro(self):
1342
+ """
1343
+ Calculates the total surface drained hydrology by summing up the surface drained hydrology values
1344
+ from the directFluxObj and intletsObj modules.
1345
+ Cautions: when there are several outflows in a module, the surfaceDrainedHydro is added only once,
1346
+ towards the natural outlet of the module (by convention the first outflow).
1347
+
1348
+ Returns:
1349
+ None
1350
+ """
1281
1351
 
1282
1352
  self.surfaceDrainedHydro = 0.0
1283
- for element in self.directFluxObj:
1284
- self.surfaceDrainedHydro += self.directFluxObj[element].surfaceDrainedHydro
1285
1353
 
1286
- for element in self.intletsObj:
1287
- self.surfaceDrainedHydro += self.intletsObj[element].surfaceDrainedHydro
1354
+ for key, cur_module in self.directFluxObj.items():
1355
+ names = cur_module.get_outFlow_names()
1356
+ if len(names)==1:
1357
+ self.surfaceDrainedHydro += cur_module.surfaceDrainedHydro
1358
+ else:
1359
+ if names[0] == key:
1360
+ self.surfaceDrainedHydro += cur_module.surfaceDrainedHydro
1361
+
1362
+ for key, cur_module in self.intletsObj.items():
1363
+ names = cur_module.get_outFlow_names()
1364
+ if len(names)==1:
1365
+ self.surfaceDrainedHydro += cur_module.surfaceDrainedHydro
1366
+ else:
1367
+ if names[0] == key:
1368
+ self.surfaceDrainedHydro += cur_module.surfaceDrainedHydro
1288
1369
 
1289
1370
 
1290
1371
  def unuse(self, mask=[]):
@@ -1377,10 +1458,10 @@ class RetentionBasin():
1377
1458
  allInlets = []
1378
1459
 
1379
1460
  for element in self.intletsObj:
1380
- allInlets.append(self.intletsObj[element].name)
1461
+ allInlets.append(str(self.intletsObj[element].name))
1381
1462
 
1382
1463
  for element in self.directFluxObj:
1383
- allInlets.append(self.directFluxObj[element].name)
1464
+ allInlets.append(str(self.directFluxObj[element].name))
1384
1465
 
1385
1466
  return allInlets
1386
1467
 
@@ -1397,6 +1478,14 @@ class RetentionBasin():
1397
1478
 
1398
1479
  return timeDelays
1399
1480
 
1481
+ def get_timeDelays_inlets(self):
1482
+
1483
+
1484
+ all_timeDelays = {el.timeDelay-self.timeDelay for el in self.intletsObj.values()}
1485
+ all_timeDelays.update({el.timeDelay-self.timeDelay for el in self.directFluxObj.values()})
1486
+
1487
+ return all_timeDelays
1488
+
1400
1489
 
1401
1490
  ## This procedure save in a "transfer.param" file the timeDelay of the SubBasin and all its upstream elements
1402
1491
  def save_timeDelays(self):
@@ -1422,29 +1511,25 @@ class RetentionBasin():
1422
1511
  return self.timeDelayObj.get_iDSorted()
1423
1512
 
1424
1513
 
1425
- def get_outFlow_names(self)->list:
1426
-
1427
- names = []
1428
- for key in self._outFlow:
1429
- names.append(key)
1514
+ def get_outFlow_names(self)->list:
1430
1515
 
1431
- return names
1516
+ return list(self._outFlow.keys())
1432
1517
 
1433
1518
 
1434
1519
  ## This procedure is updating all the hydrographs of all upstream elements imposing limits
1435
1520
  # @var level_min integer that specify the potential level at which the update should be stopped.
1436
- def update_upstream_hydro(self, level_min:int=1):
1521
+ def update_upstream_hydro(self, level_min:int=1, update_upstream:bool=True):
1437
1522
 
1438
1523
  for key in self.intletsObj:
1439
1524
  curObj = self.intletsObj[key]
1440
1525
  if curObj.myLevel>=level_min:
1441
- curObj.update_hydro(update_upstream=True, level_min=level_min)
1526
+ curObj.update_hydro(update_upstream=update_upstream, level_min=level_min)
1442
1527
 
1443
1528
 
1444
1529
  for key in self.directFluxObj:
1445
1530
  curObj = self.directFluxObj[key]
1446
1531
  if curObj.myLevel>=level_min:
1447
- curObj.update_hydro(update_upstream=True, level_min=level_min)
1532
+ curObj.update_hydro(update_upstream=update_upstream, level_min=level_min)
1448
1533
 
1449
1534
 
1450
1535
 
@@ -1452,9 +1537,12 @@ class RetentionBasin():
1452
1537
  # @var update_upstream boolean that specify whether the upstream elements should also be updated
1453
1538
  # @var level_min integer that specify the potential level at which the update should be stopped.
1454
1539
  def update_hydro(self, update_upstream:bool=True, level_min:int=1):
1455
-
1456
- if update_upstream:
1457
- self.update_upstream_hydro(level_min=level_min)
1540
+
1541
+ # !!! (ALERT) : So far, we consider that a RB object will always need to update its upstream elements
1542
+ # TODO : a potiential future need will require only an optimisation of the RB and fixed upstream elements!
1543
+ # if update_upstream:
1544
+ # self.update_upstream_hydro(level_min=level_min)
1545
+ self.update_upstream_hydro(update_upstream=update_upstream,level_min=level_min)
1458
1546
 
1459
1547
  self.compute_hydro()
1460
1548
 
@@ -1529,4 +1617,71 @@ class RetentionBasin():
1529
1617
  imax = min(np.argmin(mask[imin:]), nbT)
1530
1618
  self.filledVolume = volume[imin:imax+1]
1531
1619
 
1532
- return
1620
+ return
1621
+
1622
+
1623
+ def evaluate_objective_function(self, unit="mm/h")->np.ndarray:
1624
+ # unit = "m3/s"
1625
+
1626
+ return self.get_direct_insideRB_inlets(unit=unit)
1627
+
1628
+
1629
+ def update_from_RBdict(self, dict_RB={}):
1630
+
1631
+ self.type = self.dictRB['type'][key_Param.VALUE]
1632
+ if('stagnant height' in self.dictRB):
1633
+ self.hStagn = float(self.dictRB['stagnant height'][key_Param.VALUE])
1634
+ if(self.type == 'HighwayRB'):
1635
+ self.surface = float(self.dictRB['surface'][key_Param.VALUE])
1636
+ self.hBank = float(self.dictRB['height 2'][key_Param.VALUE])
1637
+ self.volume = self.surface * self.hBank
1638
+ elif(self.type == 'RobiernuRB'):
1639
+ self.volume = float(self.dictRB['volume'][key_Param.VALUE])
1640
+ elif(self.type == 'OrbaisRB'):
1641
+ self.volume = float(self.dictRB['volume'][key_Param.VALUE])
1642
+ try:
1643
+ zvFile = self.dictRB['Z-V file'][key_Param.VALUE]
1644
+ except:
1645
+ zvFile = ""
1646
+ if(zvFile!=""):
1647
+ zvFile = zvFile.replace("\\", "/")
1648
+ self.read_zv(zvFile)
1649
+
1650
+ elif(self.type == 'ForcedDam'):
1651
+ self.volume = float(self.dictRB['volume'][key_Param.VALUE])
1652
+ self.hi = float(self.dictRB['initial height'][key_Param.VALUE])
1653
+ self.vi = self.h_to_volume(self.hi)
1654
+
1655
+ try:
1656
+ zvFile = self.dictRB['Z-V file'][key_Param.VALUE]
1657
+ except:
1658
+ zvFile = ""
1659
+ if(zvFile!=""):
1660
+ zvFile = zvFile.replace("\\", "/")
1661
+
1662
+ #FIXME : Blinder la gestion des noms relatifs via une fonction
1663
+ if os.path.isabs(zvFile):
1664
+ self.read_zv(zvFile)
1665
+ else:
1666
+ self.read_zv(os.path.join(self.fileNameRead,zvFile))
1667
+
1668
+ if("time delay" in self.dictRB):
1669
+ self.timeDelay = float(self.dictRB["time delay"][key_Param.VALUE])
1670
+ elif(self.type == "HelleRB"):
1671
+ self.volume = float(self.dictRB['volume'][key_Param.VALUE])
1672
+ try:
1673
+ zvFile = self.dictRB['Z-V file'][key_Param.VALUE]
1674
+ isOk, zvFile = check_path(zvFile, self.fileNameRead, applyCWD=True)
1675
+ if isOk<0:
1676
+ print("ERROR : Problem in the Z-V file!")
1677
+ zvFile = ""
1678
+ except:
1679
+ zvFile = ""
1680
+ if(zvFile!=""):
1681
+ zvFile = zvFile.replace("\\", "/")
1682
+ self.read_zv(zvFile)
1683
+
1684
+ else:
1685
+ print("WARNING: This type RB was not recognised! Please check the RetentionBasin.postPro file.")
1686
+
1687
+