wolfhece 2.0.44__py3-none-any.whl → 2.0.46__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.
- wolfhece/GraphProfile.py +26 -13
- wolfhece/Model1D.py +1562 -319
- wolfhece/PyCrosssections.py +9 -8
- wolfhece/PyDraw.py +17 -10
- wolfhece/PyVertexvectors.py +39 -27
- wolfhece/apps/version.py +1 -1
- wolfhece/drawing_obj.py +10 -0
- wolfhece/hydrology/Catchment.py +329 -5
- wolfhece/hydrology/Comparison.py +34 -25
- wolfhece/hydrology/Optimisation.py +1049 -117
- wolfhece/hydrology/RetentionBasin.py +200 -45
- wolfhece/hydrology/SubBasin.py +614 -31
- wolfhece/hydrology/constant.py +2 -2
- wolfhece/hydrology/cst_exchanges.py +35 -0
- wolfhece/hydrology/plot_hydrology.py +17 -19
- wolfhece/hydrology/read.py +63 -4
- wolfhece/libs/WolfDll.dll +0 -0
- wolfhece/libs/WolfDll_debug.dll +0 -0
- wolfhece/pyGui1D.py +114 -42
- wolfhece/scenario/check_scenario.py +1 -1
- wolfhece/scenario/config_manager.py +46 -1
- {wolfhece-2.0.44.dist-info → wolfhece-2.0.46.dist-info}/METADATA +1 -1
- {wolfhece-2.0.44.dist-info → wolfhece-2.0.46.dist-info}/RECORD +26 -26
- {wolfhece-2.0.44.dist-info → wolfhece-2.0.46.dist-info}/WHEEL +0 -0
- {wolfhece-2.0.44.dist-info → wolfhece-2.0.46.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.0.44.dist-info → wolfhece-2.0.46.dist-info}/top_level.txt +0 -0
wolfhece/Model1D.py
CHANGED
@@ -8,6 +8,7 @@ import math
|
|
8
8
|
import matplotlib.pyplot as plt
|
9
9
|
import multiprocessing
|
10
10
|
import numpy as np
|
11
|
+
|
11
12
|
import os, warnings
|
12
13
|
import pandas as pd
|
13
14
|
import shutil
|
@@ -862,6 +863,343 @@ class Creator_1D:
|
|
862
863
|
znes.myzones.pop(id)
|
863
864
|
return znes
|
864
865
|
|
866
|
+
def place_minimum_altitude(self, zones: Zones, filename: str, save_as: str = '') -> Zones:
|
867
|
+
"""Return a Zones object in which all altitudes below a defined treshold
|
868
|
+
for specific vectors (sections specified in a csv file) are raised
|
869
|
+
to the new altitudes.
|
870
|
+
|
871
|
+
:param zones: Zones object containing the vectors
|
872
|
+
:type zones: Zones
|
873
|
+
:param filename: .csv file containing the sections and their minimum altitudes,
|
874
|
+
first column is the section name and second column is the minimum altitude.
|
875
|
+
:type filename: str
|
876
|
+
:param save_as: path to the the file where the modified Zones will be saved
|
877
|
+
if no path is given the results is not saved but only returned , defaults to ''
|
878
|
+
:type save_as: str, optional
|
879
|
+
:return: New Zones object with the modified altitudes
|
880
|
+
:rtype: Zones
|
881
|
+
"""
|
882
|
+
# Read the csv file as a pandas dataframe
|
883
|
+
# df_sections = self.read_csv_as_dataframe(filename, column_names=['section', 'altitude'])
|
884
|
+
df_sections = pd.read_csv(filename, names=['section', 'altitude'])
|
885
|
+
df_sections['section'] = df_sections['section'].astype(str)
|
886
|
+
# Replace the minimum altitude by comparing the altitude of each vertex to the minimum altitude
|
887
|
+
for zne in zones.myzones:
|
888
|
+
for vec in tqdm(zne.myvectors, desc='Replacing minimum altitude', colour= Colors.TQDM.value, unit='vector'):
|
889
|
+
if vec.myname in df_sections['section'].values:
|
890
|
+
index = df_sections.index[df_sections['section'] == vec.myname][0]
|
891
|
+
test = df_sections['altitude'][index]
|
892
|
+
for vert in vec.myvertices:
|
893
|
+
if vert.z < test:
|
894
|
+
vert.z = test
|
895
|
+
if self.wx_exists:
|
896
|
+
logging.info(f"Minimum altitude for {vec.myname} is now {test}")
|
897
|
+
else:
|
898
|
+
print(f"Minimum altitude for {vec.myname} is now {test}")
|
899
|
+
# Save the new Zones
|
900
|
+
zones.find_minmax(update=True)
|
901
|
+
if save_as:
|
902
|
+
zones.saveas(save_as)
|
903
|
+
return zones
|
904
|
+
|
905
|
+
def change_minimum_altitude(self, zones: Zones,filename: str, save_as: str = '') -> Zones:
|
906
|
+
"""Return a Zones object in which all altitudes below a defined treshold
|
907
|
+
for specific vectors (sections specified in a csv file) are raised
|
908
|
+
to the new altitudes.
|
909
|
+
|
910
|
+
:param zones: Zones object containing the vectors
|
911
|
+
:type zones: Zones
|
912
|
+
:param filename: .csv file containing the sections and their minimum altitudes,
|
913
|
+
first column is the section name and second column is the minimum altitude.
|
914
|
+
:type filename: str
|
915
|
+
:param save_as: path to the the file where the modified Zones will be saved
|
916
|
+
if no path is given the results is not saved but only returned , defaults to ''
|
917
|
+
:type save_as: str, optional
|
918
|
+
:return: New Zones object with the modified altitudes
|
919
|
+
:rtype: Zones
|
920
|
+
"""
|
921
|
+
# Read the csv file as a pandas dataframe
|
922
|
+
# df_sections = self.read_csv_as_dataframe(filename, column_names=['section', 'altitude'])
|
923
|
+
df_sections = pd.read_csv(filename, names=['section', 'altitude', 'new_altitude'])
|
924
|
+
df_sections['section'] = df_sections['section'].astype(str)
|
925
|
+
# Replace the minimum altitude by comparing the altitude of each vertex to the minimum altitude
|
926
|
+
for zne in zones.myzones:
|
927
|
+
for vec in tqdm(zne.myvectors, desc='Replacing minimum altitude', colour= Colors.TQDM.value, unit='vector'):
|
928
|
+
if vec.myname in df_sections['section'].values:
|
929
|
+
index = df_sections.index[df_sections['section'] == vec.myname][0]
|
930
|
+
test = df_sections['altitude'][index]
|
931
|
+
new_value = df_sections['new_altitude'][index]
|
932
|
+
for vert in vec.myvertices:
|
933
|
+
if vert.z < test:
|
934
|
+
vert.z =new_value
|
935
|
+
if self.wx_exists:
|
936
|
+
logging.info(f"Minimum altitude for {vec.myname} has been changed to {new_value}.")
|
937
|
+
else:
|
938
|
+
print(f"Minimum altitude for {vec.myname} has been changed to {new_value}.")
|
939
|
+
# Save the new Zones
|
940
|
+
zones.find_minmax(update=True)
|
941
|
+
if save_as:
|
942
|
+
zones.saveas(save_as)
|
943
|
+
return zones
|
944
|
+
|
945
|
+
def __change_minimum_altitude(self, zones: Zones,filename: str, save_as: str = '') -> Zones:
|
946
|
+
"""Return a Zones object in which all altitudes below a defined treshold
|
947
|
+
for specific vectors (sections specified in a csv file) are raised
|
948
|
+
to the new altitudes.
|
949
|
+
|
950
|
+
:param zones: Zones object containing the vectors
|
951
|
+
:type zones: Zones
|
952
|
+
:param filename: .csv file containing the sections and their minimum altitudes,
|
953
|
+
first column is the section name and second column is the minimum altitude.
|
954
|
+
:type filename: str
|
955
|
+
:param save_as: path to the the file where the modified Zones will be saved
|
956
|
+
if no path is given the results is not saved but only returned , defaults to ''
|
957
|
+
:type save_as: str, optional
|
958
|
+
:return: New Zones object with the modified altitudes
|
959
|
+
:rtype: Zones
|
960
|
+
"""
|
961
|
+
# Read the csv file as a pandas dataframe
|
962
|
+
# df_sections = self.read_csv_as_dataframe(filename, column_names=['section', 'altitude'])
|
963
|
+
df_sections = pd.read_csv(filename, names=['section', 'altitude', 'new_altitude'])
|
964
|
+
# Replace the minimum altitude by comparing the altitude of each vertex to the minimum altitude
|
965
|
+
for zne in zones.myzones:
|
966
|
+
for vec in tqdm(zne.myvectors, desc='Replacing minimum altitude', colour= Colors.TQDM.value, unit='vector'):
|
967
|
+
if vec.myname in df_sections['section'].values or int(vec.myname) in df_sections['section'].values:
|
968
|
+
|
969
|
+
try:
|
970
|
+
index = df_sections.index[df_sections['section'] == vec.myname][0]
|
971
|
+
except IndexError:
|
972
|
+
index = df_sections.index[df_sections['section'] == int(vec.myname)][0]
|
973
|
+
|
974
|
+
test = df_sections['altitude'][index]
|
975
|
+
new_value = df_sections['new_altitude'][index]
|
976
|
+
for vert in vec.myvertices:
|
977
|
+
if vert.z < test:
|
978
|
+
vert.z =new_value
|
979
|
+
if self.wx_exists:
|
980
|
+
logging.info(f"Minimum altitude for {vec.myname} has been changed to {new_value}.")
|
981
|
+
else:
|
982
|
+
print(f"Minimum altitude for {vec.myname} has been changed to {new_value}.")
|
983
|
+
# Save the new Zones
|
984
|
+
zones.find_minmax(update=True)
|
985
|
+
if save_as:
|
986
|
+
zones.saveas(save_as)
|
987
|
+
return zones
|
988
|
+
|
989
|
+
def reverse_sense_zones(self, zones: Zones, save_as: str = '') -> Zones:
|
990
|
+
"""Reverse the sense of the vectors in a Zones object.
|
991
|
+
|
992
|
+
:param zones: Zones object containing the vectors
|
993
|
+
:type zones: Zones
|
994
|
+
:param save_as: path to the the file where the modified Zones will be saved
|
995
|
+
if no path is given the results is not saved but only returned , defaults to ''
|
996
|
+
:type save_as: str, optional
|
997
|
+
:return: New Zones object with the reversed vectors
|
998
|
+
:rtype: Zones
|
999
|
+
"""
|
1000
|
+
znes = zones.deepcopy_zones()
|
1001
|
+
for zne in znes.myzones:
|
1002
|
+
for vec in zne.myvectors:
|
1003
|
+
vec.myvertices.reverse()
|
1004
|
+
znes.find_minmax(update=True)
|
1005
|
+
if save_as:
|
1006
|
+
znes.saveas(save_as)
|
1007
|
+
return znes
|
1008
|
+
|
1009
|
+
def v_shape_cross_section(self,
|
1010
|
+
cross_sections: crosssections,
|
1011
|
+
profile_name: str,
|
1012
|
+
increment:float = None,
|
1013
|
+
zmax:float = None,
|
1014
|
+
save_as:str ='') -> crosssections:
|
1015
|
+
"""Create a V shape profile from a given profile in a cross section object
|
1016
|
+
and return the new cross section object.
|
1017
|
+
"""
|
1018
|
+
|
1019
|
+
prof = cross_sections.get_profile(profile_name)
|
1020
|
+
self.v_shape(prof, increment, zmax)
|
1021
|
+
cross_sections.find_minmax(update=True)
|
1022
|
+
|
1023
|
+
if save_as:
|
1024
|
+
cross_sections.saveas(save_as)
|
1025
|
+
return cross_sections
|
1026
|
+
|
1027
|
+
def v_shape(self,
|
1028
|
+
prof: profile,
|
1029
|
+
increment = None,
|
1030
|
+
zmax = None) -> profile:
|
1031
|
+
sz = prof.get_sz()
|
1032
|
+
|
1033
|
+
# If the max height is not provided.
|
1034
|
+
if zmax is None:
|
1035
|
+
zmax = max(sz[1])
|
1036
|
+
zmin = min(sz[1])
|
1037
|
+
# Distance between point
|
1038
|
+
height = zmax - zmin
|
1039
|
+
|
1040
|
+
# To check if the number of vertices is odd or even
|
1041
|
+
modulus = len(sz[0]) % 2
|
1042
|
+
|
1043
|
+
# Odd case
|
1044
|
+
if modulus != 0:
|
1045
|
+
start = round(len(sz[0])/2)
|
1046
|
+
coords_mid = prof.myvertices[start -1]
|
1047
|
+
coords_mid.z = zmin
|
1048
|
+
# Even case
|
1049
|
+
elif modulus == 0:
|
1050
|
+
start = int(len(sz[0])/2)
|
1051
|
+
coords_mid = prof.myvertices[start - 1]
|
1052
|
+
coords_mid.z = zmin
|
1053
|
+
coords_mid_1 = prof.myvertices[start]
|
1054
|
+
coords_mid_1.z = zmin
|
1055
|
+
# in case the increment is not given,the height is divided equally
|
1056
|
+
if increment is None:
|
1057
|
+
number_of_increment = start
|
1058
|
+
increment = height/number_of_increment
|
1059
|
+
|
1060
|
+
for i in range(1, start):
|
1061
|
+
z = zmin + (increment*i)
|
1062
|
+
vert_1 = prof.myvertices[(start - 1) - i]
|
1063
|
+
if modulus == 0:
|
1064
|
+
vert_2 = prof.myvertices[(start ) + i]
|
1065
|
+
elif modulus != 0:
|
1066
|
+
vert_2 = prof.myvertices [(start - 1) + i]
|
1067
|
+
|
1068
|
+
vert_1.z = z
|
1069
|
+
vert_2.z = z
|
1070
|
+
|
1071
|
+
|
1072
|
+
prof.find_minmax()
|
1073
|
+
|
1074
|
+
def transform_to_rectangular_shape(self,
|
1075
|
+
prof: profile,
|
1076
|
+
nb_vertices: int,
|
1077
|
+
zmin: float = None,
|
1078
|
+
zmax: float = None):
|
1079
|
+
sz = prof.get_sz()
|
1080
|
+
if zmin is None:
|
1081
|
+
zmin = min(sz[1])
|
1082
|
+
if zmax is None:
|
1083
|
+
zmax = max(sz[1])
|
1084
|
+
modulus = len(sz[0]) % 2
|
1085
|
+
if modulus != 0:
|
1086
|
+
start = round(len(sz[0])/2)
|
1087
|
+
coords_mid = prof.myvertices[start -1]
|
1088
|
+
coords_mid.z = zmin
|
1089
|
+
|
1090
|
+
elif modulus == 0:
|
1091
|
+
start = int(len(sz[0])/2)
|
1092
|
+
coords_mid = prof.myvertices[start - 1]
|
1093
|
+
coords_mid.z = zmin
|
1094
|
+
coords_mid_1 = prof.myvertices[start]
|
1095
|
+
coords_mid_1.z = zmin
|
1096
|
+
|
1097
|
+
for i in range(1,start):
|
1098
|
+
vert_1 = prof.myvertices[(start - 1) - i]
|
1099
|
+
if modulus == 0:
|
1100
|
+
vert_2 = prof.myvertices[(start ) + i]
|
1101
|
+
elif modulus != 0:
|
1102
|
+
vert_2 = prof.myvertices [(start - 1) + i]
|
1103
|
+
if i < nb_vertices:
|
1104
|
+
vert_1.z = zmin
|
1105
|
+
vert_2.z = zmin
|
1106
|
+
else:
|
1107
|
+
vert_1.z = zmax
|
1108
|
+
vert_2.z = zmax
|
1109
|
+
|
1110
|
+
prof.find_minmax()
|
1111
|
+
|
1112
|
+
def rectangular_shape_cross_section(self,
|
1113
|
+
cross_sections: crosssections,
|
1114
|
+
profile_name: str,
|
1115
|
+
nb_vertices: int,
|
1116
|
+
zmin: float = None,
|
1117
|
+
zmax: float = None,
|
1118
|
+
save_as: str = '') -> crosssections:
|
1119
|
+
"""Create a rectangular shape profile from a given profile in a cross section object
|
1120
|
+
and return the new cross section object.
|
1121
|
+
"""
|
1122
|
+
prof = cross_sections.get_profile(profile_name)
|
1123
|
+
self.transform_to_rectangular_shape(prof, nb_vertices, zmin, zmax)
|
1124
|
+
cross_sections.find_minmax(update=True)
|
1125
|
+
if save_as:
|
1126
|
+
cross_sections.saveas(save_as)
|
1127
|
+
return cross_sections
|
1128
|
+
|
1129
|
+
def v_shape_vector(self,
|
1130
|
+
prof: vector,
|
1131
|
+
increment = None,
|
1132
|
+
zmax = None) -> vector:
|
1133
|
+
sz = prof.get_sz()
|
1134
|
+
if zmax is None:
|
1135
|
+
zmax = max(sz[1])
|
1136
|
+
zmin = min(sz[1])
|
1137
|
+
# Distance between point
|
1138
|
+
height = zmax - zmin
|
1139
|
+
# To check if the number of vertices is odd or even
|
1140
|
+
modulus = len(sz[0]) % 2
|
1141
|
+
|
1142
|
+
# Odd case
|
1143
|
+
if modulus != 0:
|
1144
|
+
start = round(len(sz[0])/2)
|
1145
|
+
sz[1][start] = zmin
|
1146
|
+
# Even case
|
1147
|
+
elif modulus == 0:
|
1148
|
+
start = int(len(sz[0])/2)
|
1149
|
+
sz[1][start] = zmin
|
1150
|
+
sz[1][start+1] = zmin
|
1151
|
+
|
1152
|
+
# in case the increment is not given,the height is divided equally
|
1153
|
+
if increment is None:
|
1154
|
+
number_of_increment = len(range(start))
|
1155
|
+
increment = height/number_of_increment
|
1156
|
+
|
1157
|
+
def _v_shape(self,
|
1158
|
+
prof: profile,
|
1159
|
+
increment = None,
|
1160
|
+
zmax = None) -> profile:
|
1161
|
+
sz = prof.get_sz()
|
1162
|
+
# If the max height is not provided.
|
1163
|
+
if zmax is None:
|
1164
|
+
zmax = max(sz[1])
|
1165
|
+
zmin = min(sz[1])
|
1166
|
+
# Distance between point
|
1167
|
+
height = zmax - zmin
|
1168
|
+
# Reshaping the profile
|
1169
|
+
origin = prof.get_xy_from_s(sz[0][0])
|
1170
|
+
end = prof.get_xy_from_s(sz[0][-1])
|
1171
|
+
sz[1] = 0
|
1172
|
+
trace = [[origin.x, origin.y], [end.x, end.y]]
|
1173
|
+
prof.set_sz(np.array([sz[0], sz[1]]), trace)
|
1174
|
+
# To check if the number of vertices is odd or even
|
1175
|
+
modulus = len(sz[0]) % 2
|
1176
|
+
# Odd case
|
1177
|
+
if modulus != 0:
|
1178
|
+
start = round(len(sz[0])/2)
|
1179
|
+
sz[1][start] = zmin
|
1180
|
+
# Even case
|
1181
|
+
else:
|
1182
|
+
start = int(len(sz[0])/2)
|
1183
|
+
sz[1][start] = zmin
|
1184
|
+
sz[1][start+1] = zmin
|
1185
|
+
|
1186
|
+
# in case the increment is not given,the height is divided equally
|
1187
|
+
if increment is None:
|
1188
|
+
number_of_increment = len(range(start))
|
1189
|
+
increment = height/number_of_increment
|
1190
|
+
|
1191
|
+
for i in range(start):
|
1192
|
+
sz[1][i] = zmax - increment*i
|
1193
|
+
sz[1][-i] = sz[1][i]
|
1194
|
+
origin = prof.get_xy_from_s(sz[0][0])
|
1195
|
+
end = prof.get_xy_from_s(sz[0][-1])
|
1196
|
+
# origin = prof.myvertices[0]
|
1197
|
+
# end = prof.myvertices[-1]
|
1198
|
+
trace = [[origin.x, origin.y], [end.x, end.y]]
|
1199
|
+
prof.set_sz(np.array([sz[0], sz[1]]), trace)
|
1200
|
+
|
1201
|
+
|
1202
|
+
|
865
1203
|
# --- Vectors - plotting methods ---
|
866
1204
|
#____________________________________
|
867
1205
|
|
@@ -944,11 +1282,23 @@ class Creator_1D:
|
|
944
1282
|
fig_width = 30,
|
945
1283
|
fig_height = 10,
|
946
1284
|
color = 'red',
|
947
|
-
linewidth = 2
|
1285
|
+
linewidth = 2,
|
1286
|
+
x_unit = '$m$',
|
1287
|
+
y_unit = '$m$') -> None:
|
948
1288
|
"""Plot the distance between 2 parallels (for instance river width)
|
949
1289
|
as a function of their mid-vector length.
|
950
1290
|
- Id : zone index
|
951
|
-
- The discretization step is chosen by the user
|
1291
|
+
- The discretization step is chosen by the user.
|
1292
|
+
|
1293
|
+
.. notes:: The procedure is the following:
|
1294
|
+
From the 3 vectors of the zone, the center vector is discretized
|
1295
|
+
based on the discretization step provided by the user (1 length unit by default).
|
1296
|
+
The number of points is calculated as the length of the center vector divided by the discretization step.
|
1297
|
+
the number of points selected is the smallest integer greater than the division result.
|
1298
|
+
The newpoints are then projected on the left and right vectors.
|
1299
|
+
The distance between the left and right vectors is then calculated,
|
1300
|
+
and plotted as a function of the distance along the center vector, after a postprocessing check using
|
1301
|
+
subtrings and vectors.
|
952
1302
|
|
953
1303
|
:param zones: `Zones` object containing the vectors,
|
954
1304
|
:type zones: Zones
|
@@ -961,7 +1311,7 @@ class Creator_1D:
|
|
961
1311
|
:param ticks_spacing: Discretization of the x axis, defaults to 1000
|
962
1312
|
:type ticks_spacing: int, optional
|
963
1313
|
|
964
|
-
.. notes:: FIXME Should be an option in GUI.
|
1314
|
+
.. notes:: FIXME Should be an option in GUI and check whether the substring step is necessary.
|
965
1315
|
.. todo:: 1) FIXME Add detailed information (legends, title, an so on) to the plot.
|
966
1316
|
.. todo:: 2) FIXME Think about a test for this method. could it be used in GUI?
|
967
1317
|
"""
|
@@ -977,21 +1327,51 @@ class Creator_1D:
|
|
977
1327
|
lsc = vec2.asshapely_ls()
|
978
1328
|
lsr = vec3.asshapely_ls()
|
979
1329
|
lss= [lsl,lsc,lsr] # FIXME
|
1330
|
+
|
1331
|
+
# Visual idea of the river as linestrings
|
1332
|
+
# lsl _________________________
|
1333
|
+
|
1334
|
+
# lsc -------------------------
|
1335
|
+
|
1336
|
+
# lsr _________________________
|
1337
|
+
|
980
1338
|
#Number of points
|
981
1339
|
nb = int(np.ceil(lsc.length/discretization))
|
982
1340
|
#Adimensional distances along center vector
|
983
1341
|
sloc = np.linspace(0.,1.,nb,endpoint=True)
|
1342
|
+
|
1343
|
+
# Visual idea of the adimendsional riverbed rediscretized with equidistant points
|
1344
|
+
# 0|-----|-----|-----|-----|1
|
1345
|
+
|
984
1346
|
#Points along center vector
|
985
1347
|
ptsc = [lsc.interpolate(curs,True) for curs in sloc]
|
1348
|
+
|
1349
|
+
# Visual idea of the riverbed rediscretized with equidistant points
|
1350
|
+
# lsc0|-----|-----|-----|-----|lscf
|
1351
|
+
|
986
1352
|
#Real distances along left, right and center vector
|
987
1353
|
sl = [lsl.project(curs) for curs in ptsc]
|
988
1354
|
sr = [lsr.project(curs) for curs in ptsc]
|
989
1355
|
sc = [lsc.project(curs) for curs in ptsc]
|
1356
|
+
|
1357
|
+
# Visual idea of the river rediscretized with equidistant points (projection of those points on banks)
|
1358
|
+
|
1359
|
+
# lsl0|_____|_____|_____|_____|lslf
|
1360
|
+
|
1361
|
+
# lsc0|-----|-----|-----|-----|lscf
|
1362
|
+
|
1363
|
+
# lsr0|_____|_____|_____|_____|lsrf
|
1364
|
+
|
990
1365
|
# Zones of polygones
|
991
1366
|
zonepoly1 = zone(name='polygons_1')
|
992
1367
|
zonepoly2 = zone(name='polygons_2')
|
993
1368
|
left = []
|
994
1369
|
right = []
|
1370
|
+
# For consistency reasons, the distance between 2 successive points is converted
|
1371
|
+
# to substring and then each point of the substring is stored as a vertex.
|
1372
|
+
# The operation is done at both banks at the same time,
|
1373
|
+
# therefore, each vertex has it corresponding point on the other bank.
|
1374
|
+
# The point are then stored in 2 vectors from which the distance is computed since the number of vertex is the same.
|
995
1375
|
|
996
1376
|
for i in range(len(sl)-1):
|
997
1377
|
#mean distance along center will be stored as Z value of each vertex
|
@@ -1049,8 +1429,8 @@ class Creator_1D:
|
|
1049
1429
|
|
1050
1430
|
ax.set_ylim(min(width)-0.5, max(width)+0.5)
|
1051
1431
|
ax.set_xlim(0,max(sc))
|
1052
|
-
ax.set_ylabel('Width
|
1053
|
-
ax.set_xlabel('Length
|
1432
|
+
ax.set_ylabel(f'Width [{y_unit}]', fontsize='large' )
|
1433
|
+
ax.set_xlabel(f'Length [{x_unit}]', fontsize='large')
|
1054
1434
|
ax.xaxis.set_major_locator(MultipleLocator(ticks_spacing))
|
1055
1435
|
ax.xaxis.set_major_formatter('{x:.0f}')
|
1056
1436
|
ax.xaxis.set_minor_locator(MultipleLocator(ticks_spacing/5))
|
@@ -1346,7 +1726,7 @@ class Creator_1D:
|
|
1346
1726
|
else:
|
1347
1727
|
raise Exception('An error occured while extracting the WolfArrays from the VRT file.')
|
1348
1728
|
|
1349
|
-
|
1729
|
+
|
1350
1730
|
|
1351
1731
|
# # --- Vector + Arrays Get values from array (Vector + Arrays) ---
|
1352
1732
|
#__________________________________________________________________
|
@@ -1968,6 +2348,7 @@ class Creator_1D:
|
|
1968
2348
|
"""
|
1969
2349
|
Return the HSPW relations (Initial Conditions) of all profiles
|
1970
2350
|
as a numpy arrray for a given water depth or a given altitude.
|
2351
|
+
np.array
|
1971
2352
|
|
1972
2353
|
:param crosses: List of cross sections
|
1973
2354
|
:type crosses: list[list[profile]]
|
@@ -2577,16 +2958,20 @@ class Creator_1D:
|
|
2577
2958
|
:rtype: None
|
2578
2959
|
"""
|
2579
2960
|
# Files
|
2961
|
+
# Implemented to write only the qini file
|
2580
2962
|
file_aini = self.initialize_file(save_as, fileExtensions.AINI.value)
|
2581
2963
|
file_zini = self.initialize_file(save_as, fileExtensions.ZINI.value)
|
2582
2964
|
file_hini = self.initialize_file(save_as, fileExtensions.HINI.value)
|
2583
2965
|
file_qini = self.initialize_file(save_as, fileExtensions.QINI.value)
|
2966
|
+
|
2584
2967
|
if '.aini' in file_choice:
|
2585
2968
|
self.write_file_from_np_array(file_aini, ic, [0, 1, 2, 3], nb_updates=nb_updates, desc= 'Writing aini:')
|
2586
2969
|
if '.zini' in file_choice:
|
2587
2970
|
self.write_file_from_np_array(file_zini, ic, [0, 1, 2, -1], nb_updates=nb_updates, desc ='Writing zini:')
|
2588
2971
|
if '.hini' in file_choice:
|
2589
2972
|
self.write_file_from_np_array(file_hini, ic, [0, 1, 2, -2], nb_updates=nb_updates, desc = 'Writing hini:')
|
2973
|
+
|
2974
|
+
# qini
|
2590
2975
|
self.write_file_from_np_array(file_qini, ic, [0, 1, 2], nb_updates=nb_updates, desc= 'Writing qini:', force_last=True, q=q)
|
2591
2976
|
|
2592
2977
|
def write_lengthsvecz_file(self,
|
@@ -2777,8 +3162,8 @@ class Creator_1D:
|
|
2777
3162
|
:rtype: list[list[list,list]]
|
2778
3163
|
"""
|
2779
3164
|
data = pd.read_csv(file,header=0, delimiter='\t',names=['time','discharge'])
|
2780
|
-
|
2781
|
-
return
|
3165
|
+
hydrograph = [[list(data['time']), list(data['discharge'])]]
|
3166
|
+
return hydrograph
|
2782
3167
|
|
2783
3168
|
def _write_infiltrations(self,
|
2784
3169
|
selected_profiles:list[str],
|
@@ -3216,6 +3601,7 @@ class Creator_1D:
|
|
3216
3601
|
"""
|
3217
3602
|
# FIXME add an option to select the middle of the crossection instead of just the bottom.
|
3218
3603
|
# FIXME delete discretization from all examples and from this method. It's not used
|
3604
|
+
|
3219
3605
|
# Creation of files
|
3220
3606
|
vecz_file = self.initialize_file(save_as,'.vecz')
|
3221
3607
|
vec_file = self.initialize_file(save_as,'.vec')
|
@@ -3331,8 +3717,10 @@ class Creator_1D:
|
|
3331
3717
|
|
3332
3718
|
assert prof.banksbed_postype == postype.BY_VERTEX
|
3333
3719
|
# FIXME insert a test checking the intersections between profiles and parallels.
|
3720
|
+
assert isinstance(left_inter, Point), f'The section: {prof.myname} - left intersection is not a Point but a {type(left_inter)}'
|
3334
3721
|
prof.bankleft = wolfvertex(left_inter.x, left_inter.y, left_inter.z)
|
3335
3722
|
prof.bed = wolfvertex(bed_inter.x, bed_inter.y, bed_inter.z)
|
3723
|
+
assert isinstance(right_inter, Point), f'The section: {prof.myname} - left intersection is not a Point but a {type(right_inter)}'
|
3336
3724
|
prof.bankright = wolfvertex(right_inter.x, right_inter.y, right_inter.z)
|
3337
3725
|
prof.find_minmax()
|
3338
3726
|
|
@@ -3987,8 +4375,8 @@ class Creator_1D:
|
|
3987
4375
|
"""
|
3988
4376
|
splitted_path = os.path.split(batch_file)
|
3989
4377
|
directory = splitted_path[0]
|
3990
|
-
command = f
|
3991
|
-
|
4378
|
+
command = f'start cmd.exe /k "{batch_file}"'
|
4379
|
+
subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
3992
4380
|
|
3993
4381
|
if self.wx_exists:
|
3994
4382
|
logging.info(f'{directory} Check the new shell window.\nThe simulation is running...')
|
@@ -4096,7 +4484,7 @@ class Creator_1D:
|
|
4096
4484
|
break
|
4097
4485
|
print(l)
|
4098
4486
|
|
4099
|
-
def _run_bat_files(self, bat_file, force_cwd = False):
|
4487
|
+
def _run_bat_files(self, bat_file, force_cwd = False, initial_condition = False):
|
4100
4488
|
"""
|
4101
4489
|
Run the .bat file in a windows shell
|
4102
4490
|
to start the computations (simulation).
|
@@ -4105,12 +4493,18 @@ class Creator_1D:
|
|
4105
4493
|
:type batch_file: str
|
4106
4494
|
:param force_cwd: Force current working directory, defaults to False
|
4107
4495
|
:type force_cwd: bool, optional
|
4108
|
-
FIXME Deprecated.
|
4109
4496
|
"""
|
4110
4497
|
splitted_path = os.path.split(bat_file)
|
4111
4498
|
directory = splitted_path[0]
|
4112
4499
|
simulation_name = splitted_path[1]
|
4113
|
-
|
4500
|
+
if initial_condition:
|
4501
|
+
if self.wx_exists:
|
4502
|
+
logging.info(f'{simulation_name} running... \nComputing initial conditions.')
|
4503
|
+
else:
|
4504
|
+
logging.warn(f'{simulation_name} running... \nComputing initial conditions.')
|
4505
|
+
else:
|
4506
|
+
logging.warn(f'{simulation_name} running... \nThe process may take time.')
|
4507
|
+
|
4114
4508
|
if force_cwd:
|
4115
4509
|
directory = os.path.split(bat_file)[0]
|
4116
4510
|
run = subprocess.run(bat_file, shell=True, capture_output= True, text=True,cwd=directory )
|
@@ -4864,10 +5258,9 @@ class Creator_1D:
|
|
4864
5258
|
bank_file = banks
|
4865
5259
|
bank_file.saveas(directory + '\\banks.vecz')
|
4866
5260
|
|
4867
|
-
|
5261
|
+
|
4868
5262
|
# FIXME is it necessery to have parallels (next round), is it only for cell size or a better used could be found?
|
4869
|
-
|
4870
|
-
polygons = self.create_polygons(parallels, discretisation, polygon_number, directory)
|
5263
|
+
|
4871
5264
|
|
4872
5265
|
# Write the tabulated relations of each cross section (profile)
|
4873
5266
|
write_relations = self.write_relations_profiles(sorted_crosssections, directory)
|
@@ -4884,7 +5277,10 @@ class Creator_1D:
|
|
4884
5277
|
# FIXME to be verified issue with the extent of profiles
|
4885
5278
|
# (the number of new polygons is different from the number of digitized profiles)
|
4886
5279
|
# May be a test should be implemented on each profiles (probable solution).
|
4887
|
-
|
5280
|
+
if isinstance(parallels, Zones):
|
5281
|
+
# Polygons
|
5282
|
+
polygons = self.create_polygons(parallels, discretisation, polygon_number, directory)
|
5283
|
+
roughnesses = self.roughness_from_polygons(roughness, polygons, mode=roughness_selection)
|
4888
5284
|
|
4889
5285
|
roughness_file = self.write_roughnesses(roughnesses, directory)
|
4890
5286
|
|
@@ -4913,6 +5309,11 @@ class Creator_1D:
|
|
4913
5309
|
# Write the .vec file (discretization file of the simulation topography - midriver)
|
4914
5310
|
vec_file2 = self.write_vector_files(sorted_crosssections, save_as=directory, which_type='vec')
|
4915
5311
|
|
5312
|
+
# Write the generic file
|
5313
|
+
genfile = self.write_generic_file(directory)
|
5314
|
+
|
5315
|
+
#-----------------------------------------------------------
|
5316
|
+
|
4916
5317
|
# Write the infiltrations
|
4917
5318
|
if isinstance(hydrographs, dict):
|
4918
5319
|
infil = self.write_infiltrations_from_dict(sorted_crosssections,
|
@@ -4928,6 +5329,35 @@ class Creator_1D:
|
|
4928
5329
|
writing_type_infiltration,
|
4929
5330
|
epsilon_infiltration)
|
4930
5331
|
|
5332
|
+
|
5333
|
+
|
5334
|
+
# Update the distribution of initial discharges from the infiltrations
|
5335
|
+
self.update_qini_file_from_infiltration_dict(hydrographs, directory)
|
5336
|
+
|
5337
|
+
# 22. Compute a steady state solution
|
5338
|
+
#---------------------------------------------------------------
|
5339
|
+
if steady == 'precomputation':
|
5340
|
+
# The first batch file is used to compute the steady state solution
|
5341
|
+
bat_file = self.write_batch_file(directory_of_executable = exe_file,
|
5342
|
+
directory_simulation= directory,
|
5343
|
+
simulation_name= simulation_name)
|
5344
|
+
self.start_from_steady_state(directory)
|
5345
|
+
batch_file = self.write_batch_file(directory_of_executable = exe_file,
|
5346
|
+
directory_simulation = directory,
|
5347
|
+
simulation_name = simulation_name,
|
5348
|
+
wetdry = wetdry,
|
5349
|
+
steady ='no precomputation',
|
5350
|
+
executable_type = executable_type)
|
5351
|
+
else:
|
5352
|
+
batch_file = self.write_batch_file(directory_of_executable = exe_file,
|
5353
|
+
directory_simulation = directory,
|
5354
|
+
simulation_name = simulation_name,
|
5355
|
+
wetdry = wetdry,
|
5356
|
+
steady = steady,
|
5357
|
+
executable_type = executable_type)
|
5358
|
+
|
5359
|
+
#------------------------------
|
5360
|
+
|
4931
5361
|
# write the simulation parameters
|
4932
5362
|
if write_in == 'times':
|
4933
5363
|
write_type = 2
|
@@ -4935,25 +5365,69 @@ class Creator_1D:
|
|
4935
5365
|
write_type = 1
|
4936
5366
|
if self.wx_exists == None:
|
4937
5367
|
param = self.write_parameters(directory, write_freq= output_frequency, write_type= write_type, max_time=time)
|
4938
|
-
# # if steady == 'precomputation' or steady == 'steady':
|
4939
|
-
# # self.correct_parameters(directory, from_steady=True)
|
4940
|
-
# # else:
|
4941
|
-
# # self.correct_parameters(directory)
|
4942
|
-
# self.correct_parameters(directory) FIXME for other cases when the GUI is not used
|
4943
5368
|
|
4944
|
-
|
4945
|
-
batch_file = self.write_batch_file(directory_of_executable = exe_file,
|
4946
|
-
directory_simulation = directory,
|
4947
|
-
simulation_name = simulation_name,
|
4948
|
-
wetdry = wetdry,
|
4949
|
-
steady = steady,
|
4950
|
-
executable_type = executable_type)
|
5369
|
+
|
4951
5370
|
if run_simulation == 'yes':
|
4952
5371
|
# logging.warn(f'{simulation_name} running... \nThe process may take time.')
|
4953
5372
|
self.run_bat_files(batch_file)
|
4954
5373
|
# logging.warn(f'{simulation_name} completed.')
|
4955
5374
|
return (directory,simulation_name, sorted_crosssections, ic_relations, nb_updates)
|
4956
5375
|
|
5376
|
+
def find_file_from_extension(self, directory:str, file_extension:str) -> str:
|
5377
|
+
"""Return a file in a directory based on its extension.
|
5378
|
+
|
5379
|
+
:param directory: file path to the folder
|
5380
|
+
:type directory: str
|
5381
|
+
:param file_extension: file extension
|
5382
|
+
:type file_extension: str
|
5383
|
+
:return: file path
|
5384
|
+
"""
|
5385
|
+
for file in os.listdir(directory):
|
5386
|
+
if file.endswith(file_extension):
|
5387
|
+
return os.path.join(directory, file)
|
5388
|
+
|
5389
|
+
raise Exception(f'No file with the extension {file_extension} was found in the directory {directory}.')
|
5390
|
+
|
5391
|
+
def start_from_steady_state(self, directory:str, plot = True):
|
5392
|
+
"""Compute the steady state solution and update the initial conditions based on the results.
|
5393
|
+
|
5394
|
+
:param directory: directory (simulation folder)
|
5395
|
+
:type directory: str
|
5396
|
+
:param plot: wheter the process should open a matplotlib figure
|
5397
|
+
containing the steady state solution or not, defaults to True
|
5398
|
+
:type plot: bool, optional
|
5399
|
+
"""
|
5400
|
+
self.write_parameters(directory, write_type= 2, max_time=0)
|
5401
|
+
bat_file = self.find_file_from_extension(directory, '.bat')
|
5402
|
+
self._run_bat_files(bat_file, initial_condition= True)
|
5403
|
+
# self.run_bat_files(bat_file)
|
5404
|
+
self.update_initial_conditions_from_results(directory, time_step=1, plot=plot)
|
5405
|
+
|
5406
|
+
def update_initial_conditions_from_results(self,
|
5407
|
+
directory:str,
|
5408
|
+
time_step:int =1,
|
5409
|
+
plot:bool = True):
|
5410
|
+
results = Wolfresults_1D(directory)
|
5411
|
+
|
5412
|
+
if plot:
|
5413
|
+
results.plot_variables(figures=['water level','discharge', 'froude','water depth','velocity','wetted section' ]
|
5414
|
+
,time_step=time_step, grid_x_m= 1000)
|
5415
|
+
self.log_message('Proposed initial conditions plotted.')
|
5416
|
+
|
5417
|
+
results.update_ic_from_time_steps(time_step)
|
5418
|
+
self.log_message('New initial conditions.')
|
5419
|
+
|
5420
|
+
def log_message(self, message:str):
|
5421
|
+
"""Message for the user.
|
5422
|
+
|
5423
|
+
:param message: message
|
5424
|
+
:type message: str
|
5425
|
+
"""
|
5426
|
+
if self.wx_exists:
|
5427
|
+
logging.info(message)
|
5428
|
+
else:
|
5429
|
+
print(message)
|
5430
|
+
|
4957
5431
|
def create_multiple_simulations_from_csv(self,
|
4958
5432
|
csv_filename:str,
|
4959
5433
|
folder_path:str,
|
@@ -5125,7 +5599,7 @@ class Creator_1D:
|
|
5125
5599
|
infiltrations.append(infiltration)
|
5126
5600
|
return infiltrations
|
5127
5601
|
|
5128
|
-
def
|
5602
|
+
def create_simulations_from_csv(self,
|
5129
5603
|
csv_filename:str,
|
5130
5604
|
folder_path:str,
|
5131
5605
|
cross_sections: crosssections,
|
@@ -5133,8 +5607,8 @@ class Creator_1D:
|
|
5133
5607
|
banks: Zones,
|
5134
5608
|
boundary_conditions: dict,
|
5135
5609
|
roughness:Union[float,WolfArray],
|
5136
|
-
hydrographs: list[list[list]],
|
5137
5610
|
exe_file:str,
|
5611
|
+
hydrographs: list[list[list]] = None,
|
5138
5612
|
topography: WolfArray = None,
|
5139
5613
|
initial_discharge:float = None,
|
5140
5614
|
simulation_name:str = 'simul',
|
@@ -5157,18 +5631,78 @@ class Creator_1D:
|
|
5157
5631
|
writing_type_infiltration: Literal['continuous', 'stepwise'] = 'continuous',
|
5158
5632
|
epsilon_infiltration:float = 0.01,
|
5159
5633
|
force_steady = True) -> None:
|
5160
|
-
"""
|
5161
|
-
|
5162
|
-
infiltrations = self.read_csv_as_infiltrations(csv_filename)
|
5163
|
-
names = self.read_csv_as_dataframe(csv_filename)
|
5634
|
+
"""
|
5635
|
+
Create simulations from a csv file.
|
5164
5636
|
|
5165
|
-
|
5166
|
-
|
5637
|
+
:param csv_filename: Csv filename
|
5638
|
+
:type csv_filename: str
|
5639
|
+
:param folder_path: Folder path
|
5640
|
+
:type folder_path: str
|
5641
|
+
:param cross_sections: Cross sections
|
5642
|
+
:type cross_sections: crosssections
|
5643
|
+
:param parallels: Parallels
|
5644
|
+
:type parallels: Zones
|
5645
|
+
:param banks: Banks
|
5646
|
+
:type banks: Zones
|
5647
|
+
:param boundary_conditions: Boundary conditions
|
5648
|
+
:type boundary_conditions: dict
|
5649
|
+
:param roughness: Roughness
|
5650
|
+
:type roughness: Union[float,WolfArray]
|
5651
|
+
:param exe_file: Exe file
|
5652
|
+
:type exe_file: str
|
5653
|
+
:param hydrographs: Hydrographs, defaults to None
|
5654
|
+
:type hydrographs: list[list[list]], optional
|
5655
|
+
:param topography: Topography, defaults to None
|
5656
|
+
:type topography: WolfArray, optional
|
5657
|
+
:param initial_discharge: Initial discharge, defaults to None
|
5658
|
+
:type initial_discharge: float, optional
|
5659
|
+
:param simulation_name: Simulation name, defaults to 'simul'
|
5660
|
+
:type simulation_name: str, optional
|
5661
|
+
:param discretisation: Discretisation, defaults to 10.
|
5662
|
+
:type discretisation: float, optional
|
5663
|
+
:param extrapolation_of_extremities: Extrapolation of extremities, defaults to 100.
|
5664
|
+
:type extrapolation_of_extremities: float, optional
|
5665
|
+
:param initial_depth: Initial depth, defaults to 1.
|
5666
|
+
:type initial_depth: float, optional
|
5667
|
+
:param write_in: Write in, defaults to 'times'
|
5668
|
+
:type write_in: Literal['iterations', 'times'], optional
|
5669
|
+
:param output_frequency: Output frequency, defaults to 900
|
5670
|
+
:type output_frequency: int, optional
|
5671
|
+
:param polygon_number: Polygon number, defaults to 1
|
5672
|
+
:type polygon_number: int, optional
|
5673
|
+
:param code_verbosity_profile: Code verbosity profile, defaults to [1]
|
5674
|
+
:type code_verbosity_profile: list, optional
|
5675
|
+
:param simulation_time: Simulation time, defaults to None
|
5676
|
+
:type simulation_time: int, optional
|
5677
|
+
:param roughness_option: Roughness option, defaults to 'under_profile'
|
5678
|
+
:type roughness_option: Literal['under_profile', 'under_polygons'], optional
|
5679
|
+
:param roughness_selection: Roughness selection, defaults to 'mean'
|
5680
|
+
:type roughness_selection: Literal['min','mean','median','max'], optional
|
5681
|
+
:param file_type_initial_cond: File type initial cond, defaults to '.aini'
|
5682
|
+
:type file_type_initial_cond: Literal['.aini','.hini','.zini'], optional
|
5683
|
+
:param infiltration_profiles: Infiltration profiles, defaults to ['1']
|
5684
|
+
:type infiltration_profiles: list, optional
|
5685
|
+
:param wetdry: Wetdry, defaults to 'evolutive'
|
5686
|
+
:type wetdry: Literal['fixed', 'evolutive'], optional
|
5687
|
+
:param steady: Steady, defaults to 'precomputation'
|
5688
|
+
:type steady: Literal['no precomputation', 'precomputation', 'steady'], optional
|
5689
|
+
:param executable_type: Executable type, defaults to 'wolfcli'
|
5690
|
+
:type executable_type: Literal['wolfcli', 'wolfclid'], optional
|
5691
|
+
:param run_simulation: Run simulation, defaults to 'no'
|
5692
|
+
:type run_simulation: Literal['yes', 'no'], optional
|
5693
|
+
:param writing_type_infiltration: Writing type infiltration, defaults to 'continuous'
|
5694
|
+
:type writing_type_infiltration: Literal['continuous', 'stepwise'], optional
|
5695
|
+
:param epsilon_infiltration: Epsilon infiltration, defaults to 0.01
|
5696
|
+
:type epsilon_infiltration: float, optional
|
5697
|
+
:param force_steady: Force steady, defaults to True
|
5698
|
+
:type force_steady: bool, optional
|
5699
|
+
"""
|
5700
|
+
df = self.read_csv_as_dataframe(csv_filename,column_names=['discharge'])
|
5701
|
+
discharge = df['discharge'][0]
|
5167
5702
|
# hydrograph = Hydrograph({0:discharge})
|
5168
5703
|
if force_steady:
|
5169
|
-
hydrographs = infiltrations[0]
|
5170
5704
|
# hydrographs = {}
|
5171
|
-
|
5705
|
+
hydrographs =[[[0],[discharge]]]
|
5172
5706
|
original_simulation =self.write_simulation_files_from_crosssections(folder_path,
|
5173
5707
|
cross_sections,
|
5174
5708
|
parallels,
|
@@ -5178,7 +5712,7 @@ class Creator_1D:
|
|
5178
5712
|
hydrographs,
|
5179
5713
|
exe_file,
|
5180
5714
|
topography,
|
5181
|
-
|
5715
|
+
discharge,
|
5182
5716
|
simulation_name,
|
5183
5717
|
discretisation,
|
5184
5718
|
extrapolation_of_extremities,
|
@@ -5200,15 +5734,19 @@ class Creator_1D:
|
|
5200
5734
|
epsilon_infiltration = epsilon_infiltration)
|
5201
5735
|
procedures =[]
|
5202
5736
|
|
5203
|
-
|
5204
|
-
|
5205
|
-
|
5206
|
-
|
5207
|
-
|
5737
|
+
new_sims =[]
|
5738
|
+
for new_discharge in list(df['discharge']):
|
5739
|
+
hydrographs =[[[0],[new_discharge]]]
|
5740
|
+
|
5741
|
+
extension =f'_Q{int(new_discharge)}'
|
5742
|
+
new_sim_name = original_simulation[0] + extension
|
5743
|
+
new_sim = self.copy_simulation_files(original_simulation[0],new_sim_name, ignore_filetype='*.bat')
|
5744
|
+
new_sims.append(new_sim)
|
5745
|
+
|
5208
5746
|
|
5209
5747
|
self.write_ini_files(original_simulation[3],
|
5210
5748
|
new_sim,
|
5211
|
-
|
5749
|
+
new_discharge,
|
5212
5750
|
original_simulation[4],
|
5213
5751
|
file_choice=file_type_initial_cond)
|
5214
5752
|
|
@@ -5224,7 +5762,6 @@ class Creator_1D:
|
|
5224
5762
|
new_name=simulation_name + extension)
|
5225
5763
|
procedures.append(new_batchfile)
|
5226
5764
|
|
5227
|
-
|
5228
5765
|
# # procedure = multiprocessing.Process(target= run_batch_file_multiprocess, args = (new_batchfile))
|
5229
5766
|
# # procedure.start()
|
5230
5767
|
# procedures.append(new_batchfile)
|
@@ -5232,48 +5769,762 @@ class Creator_1D:
|
|
5232
5769
|
# self.run_batch_file(new_batchfile)
|
5233
5770
|
# # procedure.start()
|
5234
5771
|
|
5772
|
+
batch_file_group = self.write_batch_simulations(directory_of_executable = exe_file,
|
5773
|
+
simulations_path=new_sims,
|
5774
|
+
wetdry = wetdry,
|
5775
|
+
steady = steady,
|
5776
|
+
executable_type = executable_type)
|
5777
|
+
|
5235
5778
|
if run_simulation == 'yes':
|
5236
|
-
runs=[self.run_batch_file(i) for i in tqdm(procedures,'Running simulations', colour= Colors.TQDM.value)]
|
5237
|
-
#
|
5779
|
+
# runs=[self.run_batch_file(i) for i in tqdm(procedures,'Running simulations', colour= Colors.TQDM.value)]
|
5780
|
+
# run = self.run_batch_file(batch_file_group)
|
5781
|
+
run = self.run_bat_files(batch_file_group)
|
5782
|
+
# # pool = multiprocessing.Pool(processes=len(procedures))
|
5783
|
+
# runs=[multiprocessing.Process(run_batch_file_multiprocess, args=i) for i in tqdm(procedures)]
|
5784
|
+
|
5785
|
+
def copy_simulation_files(self,
|
5786
|
+
simulation:str,
|
5787
|
+
save_as:str,
|
5788
|
+
ignore_filetype: Literal['.*qini','*.aini', '*.zini','*.hini','*.cl', '*.rough', 'infil*','*.inf'
|
5789
|
+
'*.infil','*.param','*.top','*.ptv','*.gtv','.log', '.count'
|
5790
|
+
'*.HEAD','*.RA', '*.RB','*.RQ','*.RS','*.vecz','*.vec','*.txt', '*.bat'] = '') -> str:
|
5791
|
+
"""
|
5792
|
+
Copy simulation files.
|
5793
|
+
|
5794
|
+
:param simulation: Simulation
|
5795
|
+
:type simulation: str
|
5796
|
+
:param save_as: Save as
|
5797
|
+
:type save_as: str
|
5798
|
+
:param ignore_filetype: Ignore filetype, defaults to ''
|
5799
|
+
:type ignore_filetype: str, optional
|
5800
|
+
:return: Copied directory
|
5801
|
+
:rtype: str
|
5802
|
+
"""
|
5803
|
+
if ignore_filetype != '':
|
5804
|
+
try:
|
5805
|
+
copied_directory = shutil.copytree(src = simulation, dst= save_as)
|
5806
|
+
except FileExistsError:
|
5807
|
+
# os.rmdir(save_as)
|
5808
|
+
# copied_directory = shutil.copytree(src = simulation, dst= save_as)
|
5809
|
+
raise Exception(f"The file named ({save_as}) exists already.\n Rename the new file or delete the existing file.")
|
5810
|
+
else:
|
5811
|
+
try:
|
5812
|
+
copied_directory = shutil.copytree(src = simulation, dst= save_as, ignore=shutil.ignore_patterns(ignore_filetype))
|
5813
|
+
except FileExistsError:
|
5814
|
+
# os.rmdir(save_as)
|
5815
|
+
# copied_directory = shutil.copytree(src = simulation, dst= save_as, ignore=shutil.ignore_patterns(ignore_filetype))
|
5816
|
+
raise Exception(f"The file named ({save_as}) exists already.\n Rename the new file or delete the existing file.")
|
5817
|
+
return copied_directory
|
5818
|
+
|
5819
|
+
def copy_multiple_simulations_from_csv(self, csv_filename:str, simulation:str) -> None:
|
5820
|
+
"""
|
5821
|
+
Copy multiple simulations from a csv file.
|
5822
|
+
|
5823
|
+
:param csv_filename: Csv filename
|
5824
|
+
:type csv_filename: str
|
5825
|
+
:param simulation: Simulation
|
5826
|
+
:type simulation: str
|
5827
|
+
"""
|
5828
|
+
|
5829
|
+
df = self.read_csv_as_dataframe(csv_filename,column_names=['discharge'])
|
5830
|
+
lgth = df.shape[0]
|
5831
|
+
for discharge in tqdm(df['discharge']):
|
5832
|
+
self.copy_simulation_files(simulation, simulation + f'_Q{discharge}')
|
5833
|
+
|
5834
|
+
def distribute_values_as_sum(self, array: np.ndarray) -> np.ndarray:
|
5835
|
+
"""Return a 1D array were the 0 are filled with the previous value in the table, and
|
5836
|
+
the existing values are replaced by their summed with the previous value in the table.
|
5837
|
+
|
5838
|
+
:param array: Array(1D) containing the vaalues of the initial discharge at specific profiles
|
5839
|
+
:type array: np.ndarray
|
5840
|
+
:return: Updated array
|
5841
|
+
:rtype: np.ndarray
|
5842
|
+
"""
|
5843
|
+
for i in range(len(array) - 1):
|
5844
|
+
j = i + 1
|
5845
|
+
if array[j] == 0:
|
5846
|
+
array[j] = array[i]
|
5847
|
+
elif array[i] != 0:
|
5848
|
+
array[j] += array[i]
|
5849
|
+
return array
|
5850
|
+
|
5851
|
+
def find_qini_values_from_infiltration_dict(self, infiltration:dict) -> dict:
|
5852
|
+
"""
|
5853
|
+
Return a dictionnary containing the infiltration profiles and their initial discharge (first value).
|
5854
|
+
|
5855
|
+
These dictionnary can be used
|
5856
|
+
|
5857
|
+
:param infiltration: Infiltration
|
5858
|
+
:type infiltration: dict
|
5859
|
+
:return: Initial infiltrations
|
5860
|
+
:rtype: dict
|
5861
|
+
"""
|
5862
|
+
|
5863
|
+
keys = []
|
5864
|
+
values =[]
|
5865
|
+
initial_infiltrations = {}
|
5866
|
+
for key in infiltration:
|
5867
|
+
if isinstance(infiltration[key], Hydrograph):
|
5868
|
+
qini = infiltration[key].values[0]
|
5869
|
+
elif isinstance(infiltration[key], (list,tuple)):
|
5870
|
+
qini = infiltration[key][0]
|
5871
|
+
elif isinstance(infiltration[key], (float,int)):
|
5872
|
+
qini = infiltration[key]
|
5873
|
+
else:
|
5874
|
+
raise Exception('The initial discharge is not well defined.')
|
5875
|
+
initial_infiltrations[int(key)-1] = qini
|
5876
|
+
|
5877
|
+
return initial_infiltrations
|
5878
|
+
|
5879
|
+
def compute_qini_values_from_infiltrations_dict(self,
|
5880
|
+
infiltrations: dict,
|
5881
|
+
nb_cells: int) -> np.ndarray:
|
5882
|
+
"""Compute the initial discharge from a dictionary of infiltrations.
|
5883
|
+
The method returns an array of initial discharges. The array values are
|
5884
|
+
distributed from the distribution (linear sum) of the first infiltration values.
|
5885
|
+
|
5886
|
+
:param infiltrations: Infiltrations (dictionnary of hydrographs)
|
5887
|
+
:type infiltrations: dict
|
5888
|
+
:param nb_cells: Number of cells
|
5889
|
+
:type nb_cells: int
|
5890
|
+
:return: Initial discharges
|
5891
|
+
:rtype: np.ndarray
|
5892
|
+
"""
|
5893
|
+
qini_values = np.zeros(nb_cells)
|
5894
|
+
initial_infiltrations = self.find_qini_values_from_infiltration_dict(infiltrations)
|
5895
|
+
for key in initial_infiltrations:
|
5896
|
+
qini_values[key] = initial_infiltrations[key]
|
5897
|
+
|
5898
|
+
qini_values = self.distribute_values_as_sum(qini_values)
|
5899
|
+
# print(qini_values)
|
5900
|
+
return qini_values
|
5901
|
+
|
5902
|
+
def update_qini_file_from_infiltration_dict(self,
|
5903
|
+
infiltrations: dict,
|
5904
|
+
directory:str):
|
5905
|
+
"""Upadte the qini file from a dictionary of infiltrations.
|
5906
|
+
|
5907
|
+
:param infiltrations: Infiltrations
|
5908
|
+
:type infiltrations: dict
|
5909
|
+
:param directory: Directory (folder)
|
5910
|
+
:type directory: str
|
5911
|
+
"""
|
5912
|
+
# Find the qini file from the simulation directory
|
5913
|
+
qini_file = self.find_file_from_extension(directory, '.qini')
|
5914
|
+
# Read the qini file as a pandas dataframe
|
5915
|
+
qini_dataframe = self.read_ini_file_as_dataframe(qini_file)
|
5916
|
+
# Find the number of cells in the simulation
|
5917
|
+
number_of_cells = len(qini_dataframe['value'])
|
5918
|
+
# Compute the qini values from the infiltrations dictionary
|
5919
|
+
qini = self.compute_qini_values_from_infiltrations_dict(infiltrations, number_of_cells)
|
5920
|
+
# Update the qini file with the computed values
|
5921
|
+
self.update_ini_file(qini_file, qini)
|
5922
|
+
|
5923
|
+
def read_ini_file_as_dataframe(self, ini_file:str):
|
5924
|
+
"""Read an ini file and return a pandas dataframe.
|
5925
|
+
|
5926
|
+
:param ini_file: File of initial conditions
|
5927
|
+
:type ini_file: str
|
5928
|
+
:return: Pandas dataframe
|
5929
|
+
:rtype: pd.DataFrame
|
5930
|
+
"""
|
5931
|
+
dataframe = pd.read_csv(ini_file,
|
5932
|
+
sep= Constants.SEPARATOR.value,
|
5933
|
+
skiprows=1,
|
5934
|
+
names=['skeleton', 'zone', 'segment','value']
|
5935
|
+
)
|
5936
|
+
return dataframe
|
5937
|
+
|
5938
|
+
def update_ini_file(self, ini_file:str, new_values: np.ndarray)-> None:
|
5939
|
+
"""Update the initial condition file with new values.
|
5940
|
+
The method reads the initial condition file as a pandas dataframe,
|
5941
|
+
then replace old the values by the new values.
|
5942
|
+
|
5943
|
+
:param ini_file: File of initial condition
|
5944
|
+
:type ini_file: str
|
5945
|
+
:param new_values: New values
|
5946
|
+
:type new_values: np.ndarray
|
5947
|
+
"""
|
5948
|
+
df = self.read_ini_file_as_dataframe(ini_file)
|
5949
|
+
lgth_values = len(df['value'])
|
5950
|
+
lgth_new_values = len(new_values)
|
5951
|
+
assert lgth_values == lgth_new_values,\
|
5952
|
+
f"The length of the new values - {lgth_new_values} is not consistent with the initial condition file - {lgth_values}."
|
5953
|
+
|
5954
|
+
df['value'] = new_values
|
5955
|
+
sep = Constants.SEPARATOR.value
|
5956
|
+
with open(ini_file, 'w') as f:
|
5957
|
+
f.write(f"{lgth_new_values}\n")
|
5958
|
+
for i in range(lgth_values):
|
5959
|
+
f.write(f"{df['skeleton'][i]}{sep}{df['zone'][i]}{sep}{df['segment'][i]}{sep}{str(df['value'][i])}\n")
|
5960
|
+
|
5961
|
+
# Implement a clever way of writing or updating this file from ic or existing files.
|
5962
|
+
# check wolfresults_1D update ini file or find another way to update the file.
|
5963
|
+
|
5964
|
+
|
5965
|
+
# --- Outdated methods ---
|
5966
|
+
#_________________________
|
5967
|
+
|
5968
|
+
def __write_batch_file(self,
|
5969
|
+
directory_of_executable:str,
|
5970
|
+
directory_simulation:str,
|
5971
|
+
simulation_name:str,
|
5972
|
+
wetdry:Literal['fixed', 'evolutive']='evolutive',
|
5973
|
+
steady:Literal['no precomputation', 'precomputation', 'steady'] = 'precomputation',
|
5974
|
+
executable_type: Literal['wolfcli', 'wolfclid'] = 'wolfcli',
|
5975
|
+
different_names=False,
|
5976
|
+
new_name:str =''
|
5977
|
+
) -> str:
|
5978
|
+
if different_names:
|
5979
|
+
batch_file =self.initialize_file(directory_of_executable, f'{new_name}.bat','') # To avoid simul name FIXME make it clean
|
5980
|
+
else:
|
5981
|
+
batch_file =self.initialize_file(directory_of_executable, '.bat')
|
5982
|
+
|
5983
|
+
|
5984
|
+
|
5985
|
+
if wetdry == 'fixed':
|
5986
|
+
wtd = 0
|
5987
|
+
elif wetdry == 'evolutive':
|
5988
|
+
wtd= 1
|
5989
|
+
|
5990
|
+
if steady== 'precomputation':
|
5991
|
+
std= 1
|
5992
|
+
elif steady == 'no precomputation':
|
5993
|
+
std = 0
|
5994
|
+
elif steady == 'steady':
|
5995
|
+
std=2
|
5996
|
+
|
5997
|
+
find_full_path ='%~dp0'
|
5998
|
+
with open(batch_file,'w') as bat:
|
5999
|
+
bat.write(f'cd "{directory_of_executable}"\n')
|
6000
|
+
# bat.write(f'{executable_type} run_wolf1d dirin="%~dp0{simulation_name}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6001
|
+
if different_names:
|
6002
|
+
bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{new_name}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6003
|
+
# if directory_simulation[0] =='.':
|
6004
|
+
# bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{directory_simulation}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6005
|
+
# else:
|
6006
|
+
# bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{directory_simulation}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6007
|
+
|
6008
|
+
else:
|
6009
|
+
bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{simulation_name}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6010
|
+
|
6011
|
+
return batch_file
|
6012
|
+
|
6013
|
+
def match_ends_2vectors_outdated(self,
|
6014
|
+
zones1: Zones,
|
6015
|
+
zones2: Zones,
|
6016
|
+
id1:int = 0,
|
6017
|
+
id2:int = 0) -> Zones:
|
6018
|
+
"""
|
6019
|
+
Aligns the vertices of 2 successive zone
|
6020
|
+
containing each 3 vectors (1 vector and its 2 parallels),
|
6021
|
+
so that, the end of each vector matches the begining of its corresponding in the other zone.
|
6022
|
+
- id1: zone id in zones1.myzones,
|
6023
|
+
- id2: zone id in zones2.myzones.
|
6024
|
+
"""
|
6025
|
+
znes1 = zones1
|
6026
|
+
znes2 = zones2
|
6027
|
+
vector1_1 = znes1.myzones[id1].myvectors[0]
|
6028
|
+
vector1_2 = znes1.myzones[id1].myvectors[1]
|
6029
|
+
vector1_3 = znes1.myzones[id1].myvectors[2]
|
6030
|
+
vector2_1 = znes2.myzones[id2].myvectors[0]
|
6031
|
+
vector2_2 = znes2.myzones[id2].myvectors[1]
|
6032
|
+
vector2_3 = znes2.myzones[id2].myvectors[2]
|
6033
|
+
i = vector1_1.myvertices
|
6034
|
+
j = vector2_1.myvertices
|
6035
|
+
|
6036
|
+
distance1 = math.sqrt(((i[-1].x - j[0].x)**2) + ((i[-1].y - j[0].y)**2)) #last point - first point
|
6037
|
+
distance2 = math.sqrt(((i[-1].x - j[-1].x)**2) + ((i[-1].y - j[-1].y)**2)) #last point - last point
|
6038
|
+
distance1_r = math.sqrt(((i[0].x - j[0].x)**2) + ((i[0].y - j[0].y)**2)) # first point - first point
|
6039
|
+
distance2_r = math.sqrt(((i[0].x - j[-1].x)**2) + ((i[0].y - j[-1].y)**2)) #first point - last point
|
6040
|
+
|
6041
|
+
all = [distance1, distance2, distance1_r, distance2_r]
|
6042
|
+
|
6043
|
+
if min(all) == distance2:
|
6044
|
+
vector2_1.myvertices.reverse()
|
6045
|
+
vector2_2.myvertices.reverse()
|
6046
|
+
vector2_3.myvertices.reverse()
|
6047
|
+
|
6048
|
+
elif min(all) == distance1_r:
|
6049
|
+
vector1_1.myvertices.reverse()
|
6050
|
+
vector1_2.myvertices.reverse()
|
6051
|
+
vector1_3.myvertices.reverse()
|
6052
|
+
|
6053
|
+
elif min(all) ==distance2_r:
|
6054
|
+
vector1_1.myvertices.reverse()
|
6055
|
+
vector1_2.myvertices.reverse()
|
6056
|
+
vector1_3.myvertices.reverse()
|
6057
|
+
vector2_1.myvertices.reverse()
|
6058
|
+
vector2_2.myvertices.reverse()
|
6059
|
+
vector2_3.myvertices.reverse()
|
6060
|
+
|
6061
|
+
return znes1, znes2
|
6062
|
+
|
6063
|
+
def __save_as_1D_crossections(self,
|
6064
|
+
zones: Zones,
|
6065
|
+
format ='vecz',
|
6066
|
+
save_as: str='') -> crosssections:
|
6067
|
+
znes = zones
|
6068
|
+
path = save_as + 'profiles' + id +'.vecz'
|
6069
|
+
index = 1
|
6070
|
+
for vec in znes.myzones[0].myvectors:
|
6071
|
+
vec.myname = '%s'%(index)
|
6072
|
+
index+=1
|
6073
|
+
|
6074
|
+
znes.find_minmax()
|
6075
|
+
znes.saveas(path)
|
6076
|
+
cross= crosssections(mydata= path,format='vecz')
|
6077
|
+
cross.format = format
|
6078
|
+
if save_as:
|
6079
|
+
cross.saveas(save_as)
|
6080
|
+
return cross
|
6081
|
+
|
6082
|
+
def __update_qini_file_from_infiltration_dict(self,
|
6083
|
+
infiltrations: dict,
|
6084
|
+
directory:str):
|
6085
|
+
"""Deprecating due to the last for loop (it's obviously a code duplication)."""
|
6086
|
+
|
6087
|
+
qini_file = self.find_file_from_extension(directory, '.qini')
|
6088
|
+
qini_dataframe = self.read_ini_file_as_dataframe(qini_file)
|
6089
|
+
number_of_cells = len(qini_dataframe['value'])
|
6090
|
+
qini = self.compute_qini_values_from_infiltrations_dict(infiltrations, number_of_cells)
|
6091
|
+
for file in os.listdir(directory):
|
6092
|
+
if file.endswith('.qini'):
|
6093
|
+
qini_file = os.path.join(directory, file)
|
6094
|
+
self.update_ini_file(qini_file, qini)
|
6095
|
+
|
6096
|
+
def _create_simulations_from_csv(self,
|
6097
|
+
csv_filename:str,
|
6098
|
+
folder_path:str,
|
6099
|
+
cross_sections: crosssections,
|
6100
|
+
parallels: Zones,
|
6101
|
+
banks: Zones,
|
6102
|
+
boundary_conditions: dict,
|
6103
|
+
roughness:Union[float,WolfArray],
|
6104
|
+
hydrographs: list[list[list]],
|
6105
|
+
exe_file:str,
|
6106
|
+
topography: WolfArray = None,
|
6107
|
+
initial_discharge:float = None,
|
6108
|
+
simulation_name:str = 'simul',
|
6109
|
+
discretisation:float = 10.,
|
6110
|
+
extrapolation_of_extremities:float = 100.,
|
6111
|
+
initial_depth:float = 1.,
|
6112
|
+
write_in: Literal['iterations', 'times'] = 'times',
|
6113
|
+
output_frequency:int = 900,
|
6114
|
+
polygon_number:int = 1,
|
6115
|
+
code_verbosity_profile: list = [1],
|
6116
|
+
simulation_time:int = None,
|
6117
|
+
roughness_option: Literal['under_profile', 'under_polygons']= 'under_profile',
|
6118
|
+
roughness_selection:Literal['min','mean','median','max'] = 'mean',
|
6119
|
+
file_type_initial_cond: Literal['.aini','.hini','.zini'] = '.aini',
|
6120
|
+
infiltration_profiles:list =['1'],
|
6121
|
+
wetdry:Literal['fixed', 'evolutive']='evolutive',
|
6122
|
+
steady:Literal['no precomputation', 'precomputation', 'steady'] = 'precomputation',
|
6123
|
+
executable_type: Literal['wolfcli', 'wolfclid'] = 'wolfcli',
|
6124
|
+
run_simulation: Literal['yes', 'no'] = 'no',
|
6125
|
+
writing_type_infiltration: Literal['continuous', 'stepwise'] = 'continuous',
|
6126
|
+
epsilon_infiltration:float = 0.01,
|
6127
|
+
force_steady = True) -> None:
|
6128
|
+
"""Deprecated"""
|
6129
|
+
|
6130
|
+
infiltrations = self.read_csv_as_infiltrations(csv_filename)
|
6131
|
+
names = self.read_csv_as_dataframe(csv_filename)
|
6132
|
+
|
6133
|
+
# # df = self.read_csv_as_dataframe(csv_filename,column_names=['discharge'])
|
6134
|
+
# # discharge = df['discharge'][0]
|
6135
|
+
# hydrograph = Hydrograph({0:discharge})
|
6136
|
+
if force_steady:
|
6137
|
+
hydrographs = infiltrations[0]
|
6138
|
+
# hydrographs = {}
|
6139
|
+
# hydrographs =[[[0],[discharge]]]
|
6140
|
+
original_simulation =self.write_simulation_files_from_crosssections(folder_path,
|
6141
|
+
cross_sections,
|
6142
|
+
parallels,
|
6143
|
+
banks,
|
6144
|
+
boundary_conditions,
|
6145
|
+
roughness,
|
6146
|
+
hydrographs,
|
6147
|
+
exe_file,
|
6148
|
+
topography,
|
6149
|
+
initial_discharge,
|
6150
|
+
simulation_name,
|
6151
|
+
discretisation,
|
6152
|
+
extrapolation_of_extremities,
|
6153
|
+
initial_depth,
|
6154
|
+
write_in,
|
6155
|
+
output_frequency,
|
6156
|
+
polygon_number,
|
6157
|
+
code_verbosity_profile,
|
6158
|
+
simulation_time,
|
6159
|
+
roughness_option,
|
6160
|
+
roughness_selection,
|
6161
|
+
file_type_initial_cond,
|
6162
|
+
infiltration_profiles,
|
6163
|
+
wetdry,
|
6164
|
+
steady,
|
6165
|
+
executable_type,
|
6166
|
+
run_simulation ='no',
|
6167
|
+
writing_type_infiltration = writing_type_infiltration,
|
6168
|
+
epsilon_infiltration = epsilon_infiltration)
|
6169
|
+
procedures =[]
|
6170
|
+
|
6171
|
+
for new_infiltration in infiltrations:
|
6172
|
+
hydrographs = new_infiltration
|
6173
|
+
values = list(new_infiltration.values())
|
6174
|
+
extension =f'_Q{int(values[0])}' # FIXME
|
6175
|
+
new_sim = self.copy_simulation_files(original_simulation[0],original_simulation[0] + extension)
|
6176
|
+
|
6177
|
+
self.write_ini_files(original_simulation[3],
|
6178
|
+
new_sim,
|
6179
|
+
new_infiltration,
|
6180
|
+
original_simulation[4],
|
6181
|
+
file_choice=file_type_initial_cond)
|
6182
|
+
|
6183
|
+
self.write_infiltrations(infiltration_profiles,original_simulation[2],hydrographs,new_sim)
|
6184
|
+
|
6185
|
+
new_batchfile = self.write_batch_file(directory_of_executable = exe_file,
|
6186
|
+
directory_simulation = new_sim,
|
6187
|
+
simulation_name = simulation_name,
|
6188
|
+
wetdry = wetdry,
|
6189
|
+
steady = steady,
|
6190
|
+
executable_type = executable_type,
|
6191
|
+
different_names= True,
|
6192
|
+
new_name=simulation_name + extension)
|
6193
|
+
procedures.append(new_batchfile)
|
6194
|
+
|
6195
|
+
|
6196
|
+
# # procedure = multiprocessing.Process(target= run_batch_file_multiprocess, args = (new_batchfile))
|
6197
|
+
# # procedure.start()
|
6198
|
+
# procedures.append(new_batchfile)
|
6199
|
+
# if run_simulation == 'yes':
|
6200
|
+
# self.run_batch_file(new_batchfile)
|
6201
|
+
# # procedure.start()
|
6202
|
+
|
6203
|
+
if run_simulation == 'yes':
|
6204
|
+
runs=[self.run_batch_file(i) for i in tqdm(procedures,'Running simulations', colour= Colors.TQDM.value)]
|
6205
|
+
# # pool = multiprocessing.Pool(processes=len(procedures))
|
5238
6206
|
# runs=[multiprocessing.Process(run_batch_file_multiprocess, args=i) for i in tqdm(procedures)]
|
5239
6207
|
|
5240
|
-
def
|
5241
|
-
|
5242
|
-
|
5243
|
-
|
5244
|
-
|
5245
|
-
|
5246
|
-
|
5247
|
-
|
5248
|
-
|
5249
|
-
|
5250
|
-
|
5251
|
-
|
5252
|
-
|
5253
|
-
|
5254
|
-
|
5255
|
-
|
5256
|
-
|
5257
|
-
|
5258
|
-
|
5259
|
-
|
5260
|
-
|
5261
|
-
|
5262
|
-
|
5263
|
-
|
5264
|
-
|
5265
|
-
|
5266
|
-
|
5267
|
-
|
5268
|
-
|
5269
|
-
|
5270
|
-
|
5271
|
-
|
6208
|
+
def _start_from_steady_state(self,
|
6209
|
+
profile:str,
|
6210
|
+
infiltrations:dict,
|
6211
|
+
list_of_sorted_cross: list,
|
6212
|
+
directory,
|
6213
|
+
plot = True,
|
6214
|
+
):
|
6215
|
+
qini = infiltrations[profile]
|
6216
|
+
if isinstance(qini, Hydrograph):
|
6217
|
+
qini = qini.values[0]
|
6218
|
+
elif isinstance(qini, (list,tuple)):
|
6219
|
+
# FIXME to be verified
|
6220
|
+
qini = qini[0]
|
6221
|
+
elif qini == float:
|
6222
|
+
qini = qini
|
6223
|
+
else:
|
6224
|
+
raise ValueError('The initial discharge is not well defined.')
|
6225
|
+
|
6226
|
+
hydrograph = Hydrograph({0:qini})
|
6227
|
+
|
6228
|
+
new_infiltrations = {profile:hydrograph}
|
6229
|
+
self.write_infiltrations_from_dict(list_of_sorted_cross, new_infiltrations, directory)
|
6230
|
+
self.write_parameters(directory, write_type= 2, max_time=0)
|
6231
|
+
bat_file = self.find_file_from_extension(directory, '.bat')
|
6232
|
+
self._run_bat_files(bat_file, initial_condition= True)
|
6233
|
+
# self.run_bat_files(bat_file)
|
6234
|
+
self.update_initial_conditions_from_results(directory, time_step=1, plot=plot)
|
6235
|
+
|
6236
|
+
def __write_simulation_files_from_crosssections(self,
|
6237
|
+
folder_path:str,
|
6238
|
+
cross_sections: crosssections,
|
6239
|
+
parallels: Zones,
|
6240
|
+
banks: Zones,
|
6241
|
+
boundary_conditions: dict,
|
6242
|
+
roughness:Union[float,WolfArray],
|
6243
|
+
hydrographs: list[list[list]],
|
6244
|
+
exe_file:str,
|
6245
|
+
topography: WolfArray = None,
|
6246
|
+
initial_discharge:float = None,
|
6247
|
+
simulation_name:str = 'simul',
|
6248
|
+
discretisation:float = 10.,
|
6249
|
+
extrapolation_of_extremities:float = 100.,
|
6250
|
+
initial_depth:float = 1.,
|
6251
|
+
write_in: Literal['iterations', 'times'] = 'times',
|
6252
|
+
output_frequency:int = 900,
|
6253
|
+
polygon_number:int = 1,
|
6254
|
+
code_verbosity_profile: list = [1],
|
6255
|
+
simulation_time:int = None,
|
6256
|
+
roughness_option: Literal['under_profile', 'under_polygons']= 'under_profile',
|
6257
|
+
roughness_selection:Literal['min','mean','median','max'] = 'mean',
|
6258
|
+
file_type_initial_cond: Literal['.aini','.hini','.zini'] = '.aini',
|
6259
|
+
infiltration_profiles:list =['1'],
|
6260
|
+
wetdry:Literal['fixed', 'evolutive']='evolutive',
|
6261
|
+
steady:Literal['no precomputation', 'precomputation', 'steady'] = 'precomputation',
|
6262
|
+
executable_type: Literal['wolfcli', 'wolfclid'] = 'wolfcli',
|
6263
|
+
run_simulation: Literal['yes', 'no'] = 'no',
|
6264
|
+
writing_type_infiltration: Literal['continuous', 'stepwise'] = 'continuous',
|
6265
|
+
epsilon_infiltration:float = 0.01,
|
6266
|
+
new_directory = '',
|
6267
|
+
force_steady = True
|
6268
|
+
) -> tuple:
|
6269
|
+
"""
|
6270
|
+
Write the simulation files (the 1D model) from the cross sections and the other parameters with one line of code.
|
6271
|
+
|
6272
|
+
:param folder_path: Folder path
|
6273
|
+
:type folder_path: str
|
6274
|
+
:param cross_sections: Cross sections
|
6275
|
+
:type cross_sections: crosssections
|
6276
|
+
:param parallels: Parallels
|
6277
|
+
:type parallels: Zones
|
6278
|
+
:param banks: Banks
|
6279
|
+
:type banks: Zones
|
6280
|
+
:param boundary_conditions: Boundary conditions
|
6281
|
+
:type boundary_conditions: dict
|
6282
|
+
:param roughness: Roughness
|
6283
|
+
:type roughness: Union[float,WolfArray]
|
6284
|
+
:param hydrographs: Hydrographs
|
6285
|
+
:type hydrographs: list[list[list]]
|
6286
|
+
:param exe_file: Exe file
|
6287
|
+
:type exe_file: str
|
6288
|
+
:param topography: Topography, defaults to None
|
6289
|
+
:type topography: WolfArray, optional
|
6290
|
+
:param initial_discharge: Initial discharge, defaults to None
|
6291
|
+
:type initial_discharge: float, optional
|
6292
|
+
:param simulation_name: Simulation name, defaults to 'simul'
|
6293
|
+
:type simulation_name: str, optional
|
6294
|
+
:param discretisation: Discretisation, defaults to 10.
|
6295
|
+
:type discretisation: float, optional
|
6296
|
+
:param extrapolation_of_extremities: Extrapolation of extremities, defaults to 100.
|
6297
|
+
:type extrapolation_of_extremities: float, optional
|
6298
|
+
:param initial_depth: Initial depth, defaults to 1.
|
6299
|
+
:type initial_depth: float, optional
|
6300
|
+
:param write_in: Write in, defaults to 'times'
|
6301
|
+
:type write_in: Literal['iterations', 'times'], optional
|
6302
|
+
:param output_frequency: Output frequency, defaults to 900
|
6303
|
+
:type output_frequency: int, optional
|
6304
|
+
:param polygon_number: Polygon number, defaults to 1
|
6305
|
+
:type polygon_number: int, optional
|
6306
|
+
:param code_verbosity_profile: Code verbosity profile, defaults to [1]
|
6307
|
+
:type code_verbosity_profile: list, optional
|
6308
|
+
:param simulation_time: Simulation time, defaults to None
|
6309
|
+
:type simulation_time: int, optional
|
6310
|
+
:param roughness_option: Roughness option, defaults to 'under_profile'
|
6311
|
+
:type roughness_option: Literal['under_profile', 'under_polygons'], optional
|
6312
|
+
:param roughness_selection: Roughness selection, defaults to 'mean'
|
6313
|
+
:type roughness_selection: Literal['min','mean','median','max'], optional
|
6314
|
+
:param file_type_initial_cond: File type initial cond, defaults to '.aini'
|
6315
|
+
:type file_type_initial_cond: Literal['.aini','.hini','.zini'], optional
|
6316
|
+
:param infiltration_profiles: Infiltration profiles, defaults to ['1']
|
6317
|
+
:type infiltration_profiles: list, optional
|
6318
|
+
:param wetdry: Wetdry, defaults to 'evolutive'
|
6319
|
+
:type wetdry: Literal['fixed', 'evolutive'], optional
|
6320
|
+
:param steady: Steady, defaults to 'precomputation'
|
6321
|
+
:type steady: Literal['no precomputation', 'precomputation', 'steady'], optional
|
6322
|
+
:param executable_type: Executable type, defaults to 'wolfcli'
|
6323
|
+
:type executable_type: Literal['wolfcli', 'wolfclid'], optional
|
6324
|
+
:param run_simulation: Run simulation, defaults to 'no'
|
6325
|
+
:type run_simulation: Literal['yes', 'no'], optional
|
6326
|
+
:param writing_type_infiltration: Writing type infiltration, defaults to 'continuous'
|
6327
|
+
:type writing_type_infiltration: Literal['continuous', 'stepwise'], optional
|
6328
|
+
:param epsilon_infiltration: Epsilon infiltration, defaults to 0.01
|
6329
|
+
:type epsilon_infiltration: float, optional
|
6330
|
+
:param new_directory: New directory, defaults to ''
|
6331
|
+
:type new_directory: str, optional
|
6332
|
+
:param force_steady: Force steady, defaults to True
|
6333
|
+
:type force_steady: bool, optional
|
6334
|
+
:return: tuple
|
6335
|
+
:rtype: tuple
|
6336
|
+
"""
|
6337
|
+
|
6338
|
+
|
6339
|
+
# Simulation directory (contains all simulation files)
|
6340
|
+
if new_directory != '':
|
6341
|
+
directory = new_directory
|
6342
|
+
else:
|
6343
|
+
directory = self.create_simulation_directory(folder_path,simulation_name)
|
6344
|
+
|
6345
|
+
# The extremities of each profile is extrapolated to avoid negative water depths in case of high discharges
|
6346
|
+
extrapolated_cross_sections = self.extrapolate_extremities(cross_sections,
|
6347
|
+
extrapolation_of_extremities,
|
6348
|
+
directory)
|
6349
|
+
# The crossection are sorted based on the river bed (middle parallel)
|
6350
|
+
sorted_crosssections = self.sort_crossections_list([extrapolated_cross_sections], banks)
|
6351
|
+
#
|
6352
|
+
if simulation_time:
|
6353
|
+
time = simulation_time
|
6354
|
+
else:
|
6355
|
+
# FIXME Multiple hydrographs
|
6356
|
+
if isinstance(hydrographs,dict):
|
6357
|
+
times = []
|
6358
|
+
for hydro, prof in hydrographs.items():
|
6359
|
+
if isinstance(prof, Hydrograph):
|
6360
|
+
times.append(max(prof.index))
|
6361
|
+
elif isinstance(prof, list):
|
6362
|
+
latest_time = prof[0][-1]
|
6363
|
+
times.append(latest_time)
|
6364
|
+
|
6365
|
+
time = max(times)
|
6366
|
+
|
6367
|
+
else:
|
6368
|
+
if isinstance(hydrographs[0], Hydrograph):
|
6369
|
+
time = max(hydrographs[0].index)
|
6370
|
+
elif isinstance(hydrographs[0], list):
|
6371
|
+
time = hydrographs[0][0][-1]
|
6372
|
+
|
6373
|
+
if initial_discharge:
|
6374
|
+
q_ini = initial_discharge
|
6375
|
+
else:
|
6376
|
+
if isinstance(hydrographs,dict):
|
6377
|
+
discharges = []
|
6378
|
+
for hydro, prof in hydrographs.items():
|
6379
|
+
if isinstance(prof, Hydrograph):
|
6380
|
+
first_discharge = prof.values[0]
|
6381
|
+
discharges.append(first_discharge)
|
6382
|
+
elif isinstance(prof, list):
|
6383
|
+
first_discharge = prof[0][0]
|
6384
|
+
discharges.append(first_discharge)
|
6385
|
+
q_ini = min(discharges)
|
6386
|
+
else:
|
6387
|
+
if isinstance(hydrographs[0], Hydrograph):
|
6388
|
+
q_ini = hydrographs[0].values[0]
|
6389
|
+
elif isinstance(hydrographs[0], list):
|
6390
|
+
q_ini = hydrographs[0][1][0]
|
6391
|
+
|
6392
|
+
# Bank file
|
6393
|
+
if banks.is2D:
|
6394
|
+
bank_file = self.get_values_from_array(banks, topography, directory + '\\banks.vecz')
|
6395
|
+
else:
|
6396
|
+
bank_file = banks
|
6397
|
+
bank_file.saveas(directory + '\\banks.vecz')
|
6398
|
+
|
6399
|
+
# Polygons
|
6400
|
+
# FIXME is it necessery to have parallels (next round), is it only for cell size or a better used could be found?
|
6401
|
+
if isinstance(parallels, Zones):
|
6402
|
+
polygons = self.create_polygons(parallels, discretisation, polygon_number, directory)
|
6403
|
+
|
6404
|
+
# Write the tabulated relations of each cross section (profile)
|
6405
|
+
write_relations = self.write_relations_profiles(sorted_crosssections, directory)
|
6406
|
+
|
6407
|
+
# Write roughnesses
|
6408
|
+
if isinstance(roughness, float) or isinstance(roughness, int):
|
6409
|
+
roughnesses = self.roughness_from_value(sorted_crosssections, value = roughness)
|
6410
|
+
|
6411
|
+
elif isinstance(roughness, WolfArray):
|
6412
|
+
if roughness_option == 'under_profile':
|
6413
|
+
roughnesses = self.roughness_from_profiles(roughness, sorted_crosssections, mode=roughness_selection)
|
6414
|
+
|
6415
|
+
elif roughness_option == 'under_polygons':
|
6416
|
+
# FIXME to be verified issue with the extent of profiles
|
6417
|
+
# (the number of new polygons is different from the number of digitized profiles)
|
6418
|
+
# May be a test should be implemented on each profiles (probable solution).
|
6419
|
+
roughnesses = self.roughness_from_polygons(roughness, polygons, mode=roughness_selection)
|
6420
|
+
|
6421
|
+
roughness_file = self.write_roughnesses(roughnesses, directory)
|
6422
|
+
|
6423
|
+
# Compute & write the intial conditions
|
6424
|
+
ic_relations, nb_updates = self.ic_relations_hspw(sorted_crosssections, initial_depth)
|
6425
|
+
|
6426
|
+
# The simulation is initialized based on the wetted area (more practical)
|
6427
|
+
ini_files = self.write_ini_files(ic_relations,
|
6428
|
+
directory,
|
6429
|
+
q = q_ini,
|
6430
|
+
nb_updates= nb_updates,
|
6431
|
+
file_choice=[file_type_initial_cond])
|
6432
|
+
|
6433
|
+
# Write the boundary conditions
|
6434
|
+
cl_file = self.write_cl_file(sorted_crosssections, boundary_conditions, directory)
|
6435
|
+
|
6436
|
+
# Write .top file (topography)
|
6437
|
+
top_file = self.write_top_file(sorted_crosssections,directory)
|
6438
|
+
|
6439
|
+
# Write the .vec file (discretization file of the simulation topography - lowest riverbed point)
|
6440
|
+
vec_file1 = self.write_vector_files(sorted_crosssections, save_as=directory,which_type='vecz')
|
6441
|
+
|
6442
|
+
# Sets the predefined river banks and bed on each cross sections
|
6443
|
+
set_bank = self.set_banksbed_vectors(bank_file)
|
6444
|
+
|
6445
|
+
# Write the .vec file (discretization file of the simulation topography - midriver)
|
6446
|
+
vec_file2 = self.write_vector_files(sorted_crosssections, save_as=directory, which_type='vec')
|
6447
|
+
|
6448
|
+
# Write the infiltrations
|
6449
|
+
if isinstance(hydrographs, dict):
|
6450
|
+
infil = self.write_infiltrations_from_dict(sorted_crosssections,
|
6451
|
+
hydrographs,
|
6452
|
+
directory,
|
6453
|
+
writing_type_infiltration,
|
6454
|
+
epsilon_infiltration)
|
6455
|
+
elif isinstance(hydrographs,list):
|
6456
|
+
infil = self.write_infiltrations(infiltration_profiles,
|
6457
|
+
sorted_crosssections,
|
6458
|
+
hydrographs,
|
6459
|
+
directory,
|
6460
|
+
writing_type_infiltration,
|
6461
|
+
epsilon_infiltration)
|
6462
|
+
|
6463
|
+
# write the simulation parameters
|
6464
|
+
if write_in == 'times':
|
6465
|
+
write_type = 2
|
6466
|
+
elif write_in =='iterations':
|
6467
|
+
write_type = 1
|
6468
|
+
if self.wx_exists == None:
|
6469
|
+
param = self.write_parameters(directory, write_freq= output_frequency, write_type= write_type, max_time=time)
|
6470
|
+
# # if steady == 'precomputation' or steady == 'steady':
|
6471
|
+
# # self.correct_parameters(directory, from_steady=True)
|
6472
|
+
# # else:
|
6473
|
+
# # self.correct_parameters(directory)
|
6474
|
+
# self.correct_parameters(directory) FIXME for other cases when the GUI is not used
|
6475
|
+
|
6476
|
+
genfile = self.write_generic_file(directory)
|
6477
|
+
batch_file = self.write_batch_file(directory_of_executable = exe_file,
|
6478
|
+
directory_simulation = directory,
|
6479
|
+
simulation_name = simulation_name,
|
6480
|
+
wetdry = wetdry,
|
6481
|
+
steady = steady,
|
6482
|
+
executable_type = executable_type)
|
6483
|
+
if run_simulation == 'yes':
|
6484
|
+
# logging.warn(f'{simulation_name} running... \nThe process may take time.')
|
6485
|
+
self.run_bat_files(batch_file)
|
6486
|
+
# logging.warn(f'{simulation_name} completed.')
|
6487
|
+
return (directory,simulation_name, sorted_crosssections, ic_relations, nb_updates)
|
6488
|
+
|
6489
|
+
def ____write_simulation_files_from_crosssections(self,
|
6490
|
+
folder_path:str,
|
6491
|
+
cross_sections: crosssections,
|
6492
|
+
parallels: Zones,
|
6493
|
+
banks: Zones,
|
6494
|
+
boundary_conditions: dict,
|
6495
|
+
roughness:Union[float,WolfArray],
|
6496
|
+
hydrographs: list[list[list]],
|
6497
|
+
exe_file:str,
|
6498
|
+
topography: WolfArray = None,
|
6499
|
+
initial_discharge:float = None,
|
6500
|
+
simulation_name:str = 'simul',
|
6501
|
+
discretisation:float = 10.,
|
6502
|
+
extrapolation_of_extremities:float = 100.,
|
6503
|
+
initial_depth:float = 1.,
|
6504
|
+
write_in: Literal['iterations', 'times'] = 'times',
|
6505
|
+
output_frequency:int = 900,
|
6506
|
+
polygon_number:int = 1,
|
6507
|
+
code_verbosity_profile: list = [1],
|
6508
|
+
simulation_time:int = None,
|
6509
|
+
roughness_option: Literal['under_profile', 'under_polygons']= 'under_profile',
|
6510
|
+
roughness_selection:Literal['min','mean','median','max'] = 'mean',
|
6511
|
+
file_type_initial_cond: Literal['.aini','.hini','.zini'] = '.aini',
|
6512
|
+
infiltration_profiles:list =['1'],
|
6513
|
+
wetdry:Literal['fixed', 'evolutive']='evolutive',
|
6514
|
+
steady:Literal['no precomputation', 'precomputation', 'steady'] = 'precomputation',
|
6515
|
+
executable_type: Literal['wolfcli', 'wolfclid'] = 'wolfcli',
|
6516
|
+
run_simulation: Literal['yes', 'no'] = 'no',
|
6517
|
+
writing_type_infiltration: Literal['continuous', 'stepwise'] = 'continuous',
|
6518
|
+
epsilon_infiltration:float = 0.01,
|
6519
|
+
new_directory = '',
|
6520
|
+
steady_state_profile = '',
|
6521
|
+
force_steady = True,
|
6522
|
+
start_from_steady_state = False,
|
6523
|
+
plot_steady_state = True
|
6524
|
+
) -> tuple:
|
5272
6525
|
"""
|
5273
|
-
|
6526
|
+
Write the simulation files (the 1D model) from the cross sections and the other parameters with one line of code.
|
5274
6527
|
|
5275
|
-
:param csv_filename: Csv filename
|
5276
|
-
:type csv_filename: str
|
5277
6528
|
:param folder_path: Folder path
|
5278
6529
|
:type folder_path: str
|
5279
6530
|
:param cross_sections: Cross sections
|
@@ -5286,10 +6537,10 @@ class Creator_1D:
|
|
5286
6537
|
:type boundary_conditions: dict
|
5287
6538
|
:param roughness: Roughness
|
5288
6539
|
:type roughness: Union[float,WolfArray]
|
6540
|
+
:param hydrographs: Hydrographs
|
6541
|
+
:type hydrographs: list[list[list]]
|
5289
6542
|
:param exe_file: Exe file
|
5290
6543
|
:type exe_file: str
|
5291
|
-
:param hydrographs: Hydrographs, defaults to None
|
5292
|
-
:type hydrographs: list[list[list]], optional
|
5293
6544
|
:param topography: Topography, defaults to None
|
5294
6545
|
:type topography: WolfArray, optional
|
5295
6546
|
:param initial_discharge: Initial discharge, defaults to None
|
@@ -5332,260 +6583,181 @@ class Creator_1D:
|
|
5332
6583
|
:type writing_type_infiltration: Literal['continuous', 'stepwise'], optional
|
5333
6584
|
:param epsilon_infiltration: Epsilon infiltration, defaults to 0.01
|
5334
6585
|
:type epsilon_infiltration: float, optional
|
6586
|
+
:param new_directory: New directory, defaults to ''
|
6587
|
+
:type new_directory: str, optional
|
5335
6588
|
:param force_steady: Force steady, defaults to True
|
5336
6589
|
:type force_steady: bool, optional
|
5337
|
-
|
5338
|
-
|
5339
|
-
|
5340
|
-
|
5341
|
-
|
5342
|
-
|
5343
|
-
|
5344
|
-
|
5345
|
-
cross_sections,
|
5346
|
-
parallels,
|
5347
|
-
banks,
|
5348
|
-
boundary_conditions,
|
5349
|
-
roughness,
|
5350
|
-
hydrographs,
|
5351
|
-
exe_file,
|
5352
|
-
topography,
|
5353
|
-
discharge,
|
5354
|
-
simulation_name,
|
5355
|
-
discretisation,
|
5356
|
-
extrapolation_of_extremities,
|
5357
|
-
initial_depth,
|
5358
|
-
write_in,
|
5359
|
-
output_frequency,
|
5360
|
-
polygon_number,
|
5361
|
-
code_verbosity_profile,
|
5362
|
-
simulation_time,
|
5363
|
-
roughness_option,
|
5364
|
-
roughness_selection,
|
5365
|
-
file_type_initial_cond,
|
5366
|
-
infiltration_profiles,
|
5367
|
-
wetdry,
|
5368
|
-
steady,
|
5369
|
-
executable_type,
|
5370
|
-
run_simulation ='no',
|
5371
|
-
writing_type_infiltration = writing_type_infiltration,
|
5372
|
-
epsilon_infiltration = epsilon_infiltration)
|
5373
|
-
procedures =[]
|
5374
|
-
|
5375
|
-
new_sims =[]
|
5376
|
-
for new_discharge in list(df['discharge']):
|
5377
|
-
hydrographs =[[[0],[new_discharge]]]
|
5378
|
-
|
5379
|
-
extension =f'_Q{int(new_discharge)}'
|
5380
|
-
new_sim_name = original_simulation[0] + extension
|
5381
|
-
new_sim = self.copy_simulation_files(original_simulation[0],new_sim_name, ignore_filetype='*.bat')
|
5382
|
-
new_sims.append(new_sim)
|
5383
|
-
|
5384
|
-
|
5385
|
-
self.write_ini_files(original_simulation[3],
|
5386
|
-
new_sim,
|
5387
|
-
new_discharge,
|
5388
|
-
original_simulation[4],
|
5389
|
-
file_choice=file_type_initial_cond)
|
5390
|
-
|
5391
|
-
self.write_infiltrations(infiltration_profiles,original_simulation[2],hydrographs,new_sim)
|
5392
|
-
|
5393
|
-
new_batchfile = self.write_batch_file(directory_of_executable = exe_file,
|
5394
|
-
directory_simulation = new_sim,
|
5395
|
-
simulation_name = simulation_name,
|
5396
|
-
wetdry = wetdry,
|
5397
|
-
steady = steady,
|
5398
|
-
executable_type = executable_type,
|
5399
|
-
different_names= True,
|
5400
|
-
new_name=simulation_name + extension)
|
5401
|
-
procedures.append(new_batchfile)
|
5402
|
-
|
5403
|
-
# # procedure = multiprocessing.Process(target= run_batch_file_multiprocess, args = (new_batchfile))
|
5404
|
-
# # procedure.start()
|
5405
|
-
# procedures.append(new_batchfile)
|
5406
|
-
# if run_simulation == 'yes':
|
5407
|
-
# self.run_batch_file(new_batchfile)
|
5408
|
-
# # procedure.start()
|
5409
|
-
|
5410
|
-
batch_file_group = self.write_batch_simulations(directory_of_executable = exe_file,
|
5411
|
-
simulations_path=new_sims,
|
5412
|
-
wetdry = wetdry,
|
5413
|
-
steady = steady,
|
5414
|
-
executable_type = executable_type)
|
5415
|
-
|
5416
|
-
if run_simulation == 'yes':
|
5417
|
-
# runs=[self.run_batch_file(i) for i in tqdm(procedures,'Running simulations', colour= Colors.TQDM.value)]
|
5418
|
-
# run = self.run_batch_file(batch_file_group)
|
5419
|
-
run = self.run_bat_files(batch_file_group)
|
5420
|
-
# # pool = multiprocessing.Pool(processes=len(procedures))
|
5421
|
-
# runs=[multiprocessing.Process(run_batch_file_multiprocess, args=i) for i in tqdm(procedures)]
|
5422
|
-
|
5423
|
-
def copy_simulation_files(self,
|
5424
|
-
simulation:str,
|
5425
|
-
save_as:str,
|
5426
|
-
ignore_filetype: Literal['.*qini','*.aini', '*.zini','*.hini','*.cl', '*.rough', 'infil*','*.inf'
|
5427
|
-
'*.infil','*.param','*.top','*.ptv','*.gtv','.log', '.count'
|
5428
|
-
'*.HEAD','*.RA', '*.RB','*.RQ','*.RS','*.vecz','*.vec','*.txt', '*.bat'] = '') -> str:
|
5429
|
-
"""
|
5430
|
-
Copy simulation files.
|
5431
|
-
|
5432
|
-
:param simulation: Simulation
|
5433
|
-
:type simulation: str
|
5434
|
-
:param save_as: Save as
|
5435
|
-
:type save_as: str
|
5436
|
-
:param ignore_filetype: Ignore filetype, defaults to ''
|
5437
|
-
:type ignore_filetype: str, optional
|
5438
|
-
:return: Copied directory
|
5439
|
-
:rtype: str
|
5440
|
-
"""
|
5441
|
-
if ignore_filetype != '':
|
5442
|
-
try:
|
5443
|
-
copied_directory = shutil.copytree(src = simulation, dst= save_as)
|
5444
|
-
except FileExistsError:
|
5445
|
-
# os.rmdir(save_as)
|
5446
|
-
# copied_directory = shutil.copytree(src = simulation, dst= save_as)
|
5447
|
-
raise Exception(f"The file named ({save_as}) exists already.\n Rename the new file or delete the existing file.")
|
6590
|
+
:return: tuple
|
6591
|
+
:rtype: tuple
|
6592
|
+
"""
|
6593
|
+
|
6594
|
+
|
6595
|
+
# Simulation directory (contains all simulation files)
|
6596
|
+
if new_directory != '':
|
6597
|
+
directory = new_directory
|
5448
6598
|
else:
|
5449
|
-
|
5450
|
-
copied_directory = shutil.copytree(src = simulation, dst= save_as, ignore=shutil.ignore_patterns(ignore_filetype))
|
5451
|
-
except FileExistsError:
|
5452
|
-
# os.rmdir(save_as)
|
5453
|
-
# copied_directory = shutil.copytree(src = simulation, dst= save_as, ignore=shutil.ignore_patterns(ignore_filetype))
|
5454
|
-
raise Exception(f"The file named ({save_as}) exists already.\n Rename the new file or delete the existing file.")
|
5455
|
-
return copied_directory
|
6599
|
+
directory = self.create_simulation_directory(folder_path,simulation_name)
|
5456
6600
|
|
5457
|
-
|
5458
|
-
|
5459
|
-
|
6601
|
+
# The extremities of each profile is extrapolated to avoid negative water depths in case of high discharges
|
6602
|
+
extrapolated_cross_sections = self.extrapolate_extremities(cross_sections,
|
6603
|
+
extrapolation_of_extremities,
|
6604
|
+
directory)
|
6605
|
+
# The crossection are sorted based on the river bed (middle parallel)
|
6606
|
+
sorted_crosssections = self.sort_crossections_list([extrapolated_cross_sections], banks)
|
6607
|
+
#
|
6608
|
+
if simulation_time:
|
6609
|
+
time = simulation_time
|
6610
|
+
else:
|
6611
|
+
# FIXME Multiple hydrographs
|
6612
|
+
if isinstance(hydrographs,dict):
|
6613
|
+
times = []
|
6614
|
+
for hydro, prof in hydrographs.items():
|
6615
|
+
if isinstance(prof, Hydrograph):
|
6616
|
+
times.append(max(prof.index))
|
6617
|
+
elif isinstance(prof, list):
|
6618
|
+
latest_time = prof[0][-1]
|
6619
|
+
times.append(latest_time)
|
5460
6620
|
|
5461
|
-
|
5462
|
-
:type csv_filename: str
|
5463
|
-
:param simulation: Simulation
|
5464
|
-
:type simulation: str
|
5465
|
-
"""
|
6621
|
+
time = max(times)
|
5466
6622
|
|
5467
|
-
|
5468
|
-
|
5469
|
-
|
5470
|
-
|
6623
|
+
else:
|
6624
|
+
if isinstance(hydrographs[0], Hydrograph):
|
6625
|
+
time = max(hydrographs[0].index)
|
6626
|
+
elif isinstance(hydrographs[0], list):
|
6627
|
+
time = hydrographs[0][0][-1]
|
5471
6628
|
|
5472
|
-
|
5473
|
-
|
6629
|
+
if initial_discharge:
|
6630
|
+
q_ini = initial_discharge
|
6631
|
+
else:
|
6632
|
+
if isinstance(hydrographs,dict):
|
6633
|
+
discharges = []
|
6634
|
+
for hydro, prof in hydrographs.items():
|
6635
|
+
if isinstance(prof, Hydrograph):
|
6636
|
+
first_discharge = prof.values[0]
|
6637
|
+
discharges.append(first_discharge)
|
6638
|
+
elif isinstance(prof, list):
|
6639
|
+
first_discharge = prof[0][0]
|
6640
|
+
discharges.append(first_discharge)
|
6641
|
+
q_ini = min(discharges)
|
6642
|
+
else:
|
6643
|
+
if isinstance(hydrographs[0], Hydrograph):
|
6644
|
+
q_ini = hydrographs[0].values[0]
|
6645
|
+
elif isinstance(hydrographs[0], list):
|
6646
|
+
q_ini = hydrographs[0][1][0]
|
5474
6647
|
|
5475
|
-
|
5476
|
-
|
5477
|
-
|
5478
|
-
simulation_name:str,
|
5479
|
-
wetdry:Literal['fixed', 'evolutive']='evolutive',
|
5480
|
-
steady:Literal['no precomputation', 'precomputation', 'steady'] = 'precomputation',
|
5481
|
-
executable_type: Literal['wolfcli', 'wolfclid'] = 'wolfcli',
|
5482
|
-
different_names=False,
|
5483
|
-
new_name:str =''
|
5484
|
-
) -> str:
|
5485
|
-
if different_names:
|
5486
|
-
batch_file =self.initialize_file(directory_of_executable, f'{new_name}.bat','') # To avoid simul name FIXME make it clean
|
6648
|
+
# Bank file
|
6649
|
+
if banks.is2D:
|
6650
|
+
bank_file = self.get_values_from_array(banks, topography, directory + '\\banks.vecz')
|
5487
6651
|
else:
|
5488
|
-
|
6652
|
+
bank_file = banks
|
6653
|
+
bank_file.saveas(directory + '\\banks.vecz')
|
5489
6654
|
|
6655
|
+
# Polygons
|
6656
|
+
# FIXME is it necessery to have parallels (next round), is it only for cell size or a better used could be found?
|
6657
|
+
if isinstance(parallels, Zones):
|
6658
|
+
polygons = self.create_polygons(parallels, discretisation, polygon_number, directory)
|
5490
6659
|
|
6660
|
+
# Write the tabulated relations of each cross section (profile)
|
6661
|
+
write_relations = self.write_relations_profiles(sorted_crosssections, directory)
|
5491
6662
|
|
5492
|
-
|
5493
|
-
|
5494
|
-
|
5495
|
-
wtd= 1
|
6663
|
+
# Write roughnesses
|
6664
|
+
if isinstance(roughness, float) or isinstance(roughness, int):
|
6665
|
+
roughnesses = self.roughness_from_value(sorted_crosssections, value = roughness)
|
5496
6666
|
|
5497
|
-
|
5498
|
-
|
5499
|
-
|
5500
|
-
std = 0
|
5501
|
-
elif steady == 'steady':
|
5502
|
-
std=2
|
6667
|
+
elif isinstance(roughness, WolfArray):
|
6668
|
+
if roughness_option == 'under_profile':
|
6669
|
+
roughnesses = self.roughness_from_profiles(roughness, sorted_crosssections, mode=roughness_selection)
|
5503
6670
|
|
5504
|
-
|
5505
|
-
|
5506
|
-
|
5507
|
-
|
5508
|
-
|
5509
|
-
bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{new_name}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
5510
|
-
# if directory_simulation[0] =='.':
|
5511
|
-
# bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{directory_simulation}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
5512
|
-
# else:
|
5513
|
-
# bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{directory_simulation}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6671
|
+
elif roughness_option == 'under_polygons':
|
6672
|
+
# FIXME to be verified issue with the extent of profiles
|
6673
|
+
# (the number of new polygons is different from the number of digitized profiles)
|
6674
|
+
# May be a test should be implemented on each profiles (probable solution).
|
6675
|
+
roughnesses = self.roughness_from_polygons(roughness, polygons, mode=roughness_selection)
|
5514
6676
|
|
5515
|
-
|
5516
|
-
bat.write(f'{executable_type} run_wolf1d dirin="{find_full_path}{simulation_name}" in="{simulation_name}" wetdry={wtd} steady={std}')
|
6677
|
+
roughness_file = self.write_roughnesses(roughnesses, directory)
|
5517
6678
|
|
5518
|
-
|
6679
|
+
# Compute & write the intial conditions
|
6680
|
+
ic_relations, nb_updates = self.ic_relations_hspw(sorted_crosssections, initial_depth)
|
5519
6681
|
|
5520
|
-
|
5521
|
-
|
5522
|
-
|
5523
|
-
|
5524
|
-
|
5525
|
-
|
5526
|
-
Aligns the vertices of 2 successive zone
|
5527
|
-
containing each 3 vectors (1 vector and its 2 parallels),
|
5528
|
-
so that, the end of each vector matches the begining of its corresponding in the other zone.
|
5529
|
-
- id1: zone id in zones1.myzones,
|
5530
|
-
- id2: zone id in zones2.myzones.
|
5531
|
-
"""
|
5532
|
-
znes1 = zones1
|
5533
|
-
znes2 = zones2
|
5534
|
-
vector1_1 = znes1.myzones[id1].myvectors[0]
|
5535
|
-
vector1_2 = znes1.myzones[id1].myvectors[1]
|
5536
|
-
vector1_3 = znes1.myzones[id1].myvectors[2]
|
5537
|
-
vector2_1 = znes2.myzones[id2].myvectors[0]
|
5538
|
-
vector2_2 = znes2.myzones[id2].myvectors[1]
|
5539
|
-
vector2_3 = znes2.myzones[id2].myvectors[2]
|
5540
|
-
i = vector1_1.myvertices
|
5541
|
-
j = vector2_1.myvertices
|
6682
|
+
# The simulation is initialized based on the wetted area (more practical)
|
6683
|
+
ini_files = self.write_ini_files(ic_relations,
|
6684
|
+
directory,
|
6685
|
+
q = q_ini,
|
6686
|
+
nb_updates= nb_updates,
|
6687
|
+
file_choice=[file_type_initial_cond])
|
5542
6688
|
|
5543
|
-
|
5544
|
-
|
5545
|
-
distance1_r = math.sqrt(((i[0].x - j[0].x)**2) + ((i[0].y - j[0].y)**2)) # first point - first point
|
5546
|
-
distance2_r = math.sqrt(((i[0].x - j[-1].x)**2) + ((i[0].y - j[-1].y)**2)) #first point - last point
|
6689
|
+
# Write the boundary conditions
|
6690
|
+
cl_file = self.write_cl_file(sorted_crosssections, boundary_conditions, directory)
|
5547
6691
|
|
5548
|
-
|
6692
|
+
# Write .top file (topography)
|
6693
|
+
top_file = self.write_top_file(sorted_crosssections,directory)
|
5549
6694
|
|
5550
|
-
|
5551
|
-
|
5552
|
-
vector2_2.myvertices.reverse()
|
5553
|
-
vector2_3.myvertices.reverse()
|
6695
|
+
# Write the .vec file (discretization file of the simulation topography - lowest riverbed point)
|
6696
|
+
vec_file1 = self.write_vector_files(sorted_crosssections, save_as=directory,which_type='vecz')
|
5554
6697
|
|
5555
|
-
|
5556
|
-
|
5557
|
-
vector1_2.myvertices.reverse()
|
5558
|
-
vector1_3.myvertices.reverse()
|
6698
|
+
# Sets the predefined river banks and bed on each cross sections
|
6699
|
+
set_bank = self.set_banksbed_vectors(bank_file)
|
5559
6700
|
|
5560
|
-
|
5561
|
-
|
5562
|
-
|
5563
|
-
|
5564
|
-
|
5565
|
-
|
5566
|
-
|
6701
|
+
# Write the .vec file (discretization file of the simulation topography - midriver)
|
6702
|
+
vec_file2 = self.write_vector_files(sorted_crosssections, save_as=directory, which_type='vec')
|
6703
|
+
# write the generic file
|
6704
|
+
genfile = self.write_generic_file(directory)
|
6705
|
+
# Write the batch file
|
6706
|
+
batch_file = self.write_batch_file(directory_of_executable = exe_file,
|
6707
|
+
directory_simulation = directory,
|
6708
|
+
simulation_name = simulation_name,
|
6709
|
+
wetdry = wetdry,
|
6710
|
+
steady = steady,
|
6711
|
+
executable_type = executable_type)
|
5567
6712
|
|
5568
|
-
|
6713
|
+
# Update initial conditions
|
6714
|
+
if start_from_steady_state:
|
6715
|
+
self.start_from_steady_state(directory, plot = plot_steady_state)
|
6716
|
+
|
6717
|
+
# # if profile == '':
|
6718
|
+
# # profile = '1'
|
6719
|
+
# # self.start_from_steady_state(profile=steady_state_profile,
|
6720
|
+
# # infiltrations= hydrographs,
|
6721
|
+
# # list_of_sorted_cross= sorted_crosssections,
|
6722
|
+
# # directory= directory,
|
6723
|
+
# # plot= plot_steady_state)
|
6724
|
+
|
6725
|
+
# Write the batch file
|
6726
|
+
batch_file = self.write_batch_file(directory_of_executable = exe_file,
|
6727
|
+
directory_simulation = directory,
|
6728
|
+
simulation_name = simulation_name,
|
6729
|
+
wetdry = wetdry,
|
6730
|
+
steady = 'no precomputation',
|
6731
|
+
executable_type = executable_type)
|
5569
6732
|
|
5570
|
-
|
5571
|
-
|
5572
|
-
|
5573
|
-
|
5574
|
-
|
5575
|
-
|
5576
|
-
|
5577
|
-
|
5578
|
-
|
5579
|
-
|
6733
|
+
# Write the infiltrations
|
6734
|
+
if isinstance(hydrographs, dict):
|
6735
|
+
infil = self.write_infiltrations_from_dict(sorted_crosssections,
|
6736
|
+
hydrographs,
|
6737
|
+
directory,
|
6738
|
+
writing_type_infiltration,
|
6739
|
+
epsilon_infiltration)
|
6740
|
+
elif isinstance(hydrographs,list):
|
6741
|
+
infil = self.write_infiltrations(infiltration_profiles,
|
6742
|
+
sorted_crosssections,
|
6743
|
+
hydrographs,
|
6744
|
+
directory,
|
6745
|
+
writing_type_infiltration,
|
6746
|
+
epsilon_infiltration)
|
5580
6747
|
|
5581
|
-
|
5582
|
-
|
5583
|
-
|
5584
|
-
|
5585
|
-
|
5586
|
-
|
5587
|
-
|
6748
|
+
# write the simulation parameters
|
6749
|
+
if write_in == 'times':
|
6750
|
+
write_type = 2
|
6751
|
+
elif write_in =='iterations':
|
6752
|
+
write_type = 1
|
6753
|
+
if self.wx_exists == None:
|
6754
|
+
param = self.write_parameters(directory, write_freq= output_frequency, write_type= write_type, max_time=time)
|
5588
6755
|
|
6756
|
+
if run_simulation == 'yes':
|
6757
|
+
# logging.warn(f'{simulation_name} running... \nThe process may take time.')
|
6758
|
+
self.run_bat_files(batch_file)
|
6759
|
+
# logging.warn(f'{simulation_name} completed.')
|
6760
|
+
return (directory,simulation_name, sorted_crosssections, ic_relations, nb_updates)
|
5589
6761
|
|
5590
6762
|
# --- Wolf 1D results ---
|
5591
6763
|
#________________________
|
@@ -5703,11 +6875,14 @@ class Wolfresults_1D:
|
|
5703
6875
|
self.wetted_sections = np.roll(wetted_sections, 1, axis=0)
|
5704
6876
|
|
5705
6877
|
self.velocities = self.discharges/self.wetted_sections
|
5706
|
-
#
|
6878
|
+
# To avoid nan values, copy false means the original array is modified and returned.
|
6879
|
+
self.velocities = np.nan_to_num(self.velocities, copy=False)
|
5707
6880
|
if self.breath_file != None:
|
5708
6881
|
self.widths = np.loadtxt(self.breath_file)
|
5709
6882
|
if self.widths.shape == self.wetted_sections.shape:
|
5710
6883
|
self.froudes = self.discharges / (self.wetted_sections*np.sqrt(Constants.GRAVITATION.value*(self.wetted_sections/self.widths)))
|
6884
|
+
# To avoid nan values, copy false means the original array is modified and returned.
|
6885
|
+
self.froudes = np.nan_to_num(self.froudes, copy=False, nan=0.0, posinf=0.0,neginf=0.0)
|
5711
6886
|
# In case the model has written new results
|
5712
6887
|
else:
|
5713
6888
|
if self.breath_directory != None:
|
@@ -5743,6 +6918,63 @@ class Wolfresults_1D:
|
|
5743
6918
|
|
5744
6919
|
# print('done')
|
5745
6920
|
|
6921
|
+
def update_ic_from_time_steps(self, time_step:int = -1) -> np.ndarray:
|
6922
|
+
"""Return the simulated conditions (a,q,h, r) at a given time step as a `np.ndarray`.
|
6923
|
+
- a: Wetted section (index 0),
|
6924
|
+
- s: Wetted perimeter (index 1),
|
6925
|
+
- w: Top width (index 2),
|
6926
|
+
- r: Hydraulic radius (index 3).
|
6927
|
+
|
6928
|
+
:param time_step: the desired time steps, defaults to -1
|
6929
|
+
:type time_step: int, optional
|
6930
|
+
:return: the conditions at the specified time step
|
6931
|
+
:rtype: np.ndarray
|
6932
|
+
"""
|
6933
|
+
real_time_step = self.convert_time_step(time_step)
|
6934
|
+
for file in os.listdir(self.directory):
|
6935
|
+
if file.endswith(".aini"):
|
6936
|
+
aini_file = os.path.join(self.directory,file)
|
6937
|
+
wetted_sections = self.wetted_sections[:,real_time_step]
|
6938
|
+
self.update_ini_file(aini_file, wetted_sections)
|
6939
|
+
elif file.endswith(".hini"):
|
6940
|
+
hini_file = os.path.join(self.directory,file)
|
6941
|
+
depths = self.depths[:,real_time_step]
|
6942
|
+
self.update_ini_file(hini_file, depths)
|
6943
|
+
elif file.endswith(".zini"):
|
6944
|
+
zini_file = os.path.join(self.directory,file)
|
6945
|
+
water_level = self.water_levels[:,real_time_step]
|
6946
|
+
self.update_ini_file(zini_file, water_level)
|
6947
|
+
elif file.endswith(".qini"):
|
6948
|
+
qini_file = os.path.join(self.directory,file)
|
6949
|
+
discharges = self.discharges[:,real_time_step]
|
6950
|
+
self.update_ini_file(qini_file, discharges)
|
6951
|
+
|
6952
|
+
|
6953
|
+
# wetted_sections = self.wetted_sections[:,real_time_step]
|
6954
|
+
# discharges = self.discharges[:,real_time_step]
|
6955
|
+
# depths = self.depths[:,real_time_step]
|
6956
|
+
# wetted_perimeters = self.wetted_sections[:,real_time_step] # FIXME not yet available
|
6957
|
+
# top_widths = self.widths[:,real_time_step] # FIXME not yet available
|
6958
|
+
|
6959
|
+
def update_ini_file(self, ini_file:str, new_values: np.ndarray)-> None:
|
6960
|
+
"""Update the initial condition file with new values."""
|
6961
|
+
df = pd.read_csv(ini_file,
|
6962
|
+
sep= Constants.SEPARATOR.value,
|
6963
|
+
skiprows=1,
|
6964
|
+
names=['skeleton', 'zone', 'segment','value']
|
6965
|
+
)
|
6966
|
+
lgth_values = len(df['value'])
|
6967
|
+
lgth_new_values = len(new_values)
|
6968
|
+
assert lgth_values == lgth_new_values,\
|
6969
|
+
f"The length of the new values - {lgth_new_values} is not consistent with the initial condition file - {lgth_values}."
|
6970
|
+
|
6971
|
+
df['value'] = new_values
|
6972
|
+
sep = Constants.SEPARATOR.value
|
6973
|
+
with open(ini_file, 'w') as f:
|
6974
|
+
f.write(f"{lgth_new_values}\n")
|
6975
|
+
for i in range(lgth_values):
|
6976
|
+
f.write(f"{df['skeleton'][i]}{sep}{df['zone'][i]}{sep}{df['segment'][i]}{sep}{str(df['value'][i])}\n")
|
6977
|
+
|
5746
6978
|
def plot_water_level(self,
|
5747
6979
|
figax:tuple = None,
|
5748
6980
|
time_step:int = 1,
|
@@ -7381,8 +8613,8 @@ class Wolfresults_1D:
|
|
7381
8613
|
banksbed,
|
7382
8614
|
landmark,
|
7383
8615
|
save_as,
|
7384
|
-
|
7385
|
-
|
8616
|
+
grid_x = grid_x_m,
|
8617
|
+
grid_y = grid_y_m,
|
7386
8618
|
convert_step=False,
|
7387
8619
|
steps_limit=steps_limit)
|
7388
8620
|
# axes_for_updates.append((wetted_section,ax4,fig))
|
@@ -7428,9 +8660,16 @@ class Wolfresults_1D:
|
|
7428
8660
|
|
7429
8661
|
fig.suptitle(f'Results - 1D model\n$Time: (step: {real_time_step+1} - $simulated: {self.simulated_times[real_time_step]:#.1f}s$ - real: {self.real_times[real_time_step]:#.1e} s)$',
|
7430
8662
|
fontsize= 'x-large', fontweight= 'bold')
|
8663
|
+
|
8664
|
+
plt.tight_layout()
|
8665
|
+
if save_as != '':
|
8666
|
+
plt.savefig(save_as)
|
7431
8667
|
if show:
|
7432
|
-
plt.tight_layout()
|
8668
|
+
# plt.tight_layout()
|
7433
8669
|
plt.show()
|
8670
|
+
|
8671
|
+
|
8672
|
+
|
7434
8673
|
return axes_for_updates
|
7435
8674
|
|
7436
8675
|
def animate_1D_plots(self,
|
@@ -7440,7 +8679,9 @@ class Wolfresults_1D:
|
|
7440
8679
|
landmark: Union[str,Zones]= '',
|
7441
8680
|
figsize:tuple = (20,10),
|
7442
8681
|
alpha:float = 0.3,
|
7443
|
-
save_as:str=''
|
8682
|
+
save_as:str='',
|
8683
|
+
grid_x = 1000,
|
8684
|
+
grid_y = 10):
|
7444
8685
|
"""
|
7445
8686
|
Animate the selected variables in figures, save them as a file and
|
7446
8687
|
return the information associated with their axes.
|
@@ -7471,6 +8712,8 @@ class Wolfresults_1D:
|
|
7471
8712
|
landmark= landmark,
|
7472
8713
|
figsize=figsize,
|
7473
8714
|
alpha=alpha,
|
8715
|
+
grid_x_m = grid_x,
|
8716
|
+
grid_y_m = grid_y,
|
7474
8717
|
show=False)
|
7475
8718
|
for charactetristic in animation_axes:
|
7476
8719
|
if len(charactetristic) == 3:
|