wolfhece 2.1.127__py3-none-any.whl → 2.1.128__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/PyDraw.py +52 -3
- wolfhece/PyPalette.py +36 -0
- wolfhece/PyParams.py +2 -2
- wolfhece/PyVertexvectors.py +527 -63
- wolfhece/apps/version.py +1 -1
- wolfhece/coupling/hydrology_2d.py +295 -192
- wolfhece/eikonal.py +13 -3
- wolfhece/hydrology/Catchment.py +48 -48
- wolfhece/hydrology/PyWatershed.py +93 -93
- wolfhece/lagrange_multiplier.py +205 -0
- wolfhece/math_parser/calculator.py +1 -0
- wolfhece/pybridges.py +2 -2
- wolfhece/pypolygons_scen.py +2 -2
- wolfhece/wolf_array.py +834 -40
- wolfhece/wolfresults_2D.py +204 -13
- {wolfhece-2.1.127.dist-info → wolfhece-2.1.128.dist-info}/METADATA +2 -3
- {wolfhece-2.1.127.dist-info → wolfhece-2.1.128.dist-info}/RECORD +20 -19
- {wolfhece-2.1.127.dist-info → wolfhece-2.1.128.dist-info}/WHEEL +1 -1
- {wolfhece-2.1.127.dist-info → wolfhece-2.1.128.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.127.dist-info → wolfhece-2.1.128.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
import numpy as np
|
2
|
+
|
3
|
+
def junction_q_lagrangemult(q:np.ndarray):
|
4
|
+
""" Compute the junction flow rate q_junction
|
5
|
+
from the flow rates q of the branches.
|
6
|
+
|
7
|
+
:param q: np.ndarray, estimated signed flow rates of the branches
|
8
|
+
"""
|
9
|
+
|
10
|
+
# Number of incoming branches
|
11
|
+
n = q.size
|
12
|
+
|
13
|
+
# Compute the flow rate ensuring mass conservation
|
14
|
+
# using the Lagrange multiplier method
|
15
|
+
#
|
16
|
+
# We minimize the following function:
|
17
|
+
# sum_{i=1}^{n} 1/2 * (qnew_i - q_i) ** 2
|
18
|
+
# subject to the constraint:
|
19
|
+
# sum_{i=1}^{n} qnew_i
|
20
|
+
#
|
21
|
+
# The solution is given by inversing the matrix A
|
22
|
+
# A = [1 1 1 ... 1 0]
|
23
|
+
# [1 0 0 ... 0 1]
|
24
|
+
# [0 1 0 ... 0 1]
|
25
|
+
# [0 0 1 ... 0 1]
|
26
|
+
# ...
|
27
|
+
# [0 0 0 ... 1 1]
|
28
|
+
#
|
29
|
+
# [lambda qnew] = A^(-1) * [0 q1 q2 ... qn]
|
30
|
+
|
31
|
+
# Create the matrix A
|
32
|
+
A = np.zeros((n+1, n+1))
|
33
|
+
A[0, :-1] = 1
|
34
|
+
A[1:, :-1] = np.eye(n)
|
35
|
+
A[1:, -1] = 1
|
36
|
+
|
37
|
+
# Compute the inverse of A
|
38
|
+
A_inv = np.linalg.inv(A)
|
39
|
+
|
40
|
+
# Compute the new flow rates
|
41
|
+
qnew = A_inv @ np.concatenate(([0], q))
|
42
|
+
|
43
|
+
# Return the junction flow rates and the lambda
|
44
|
+
return qnew[:n], qnew[-1]
|
45
|
+
|
46
|
+
def junction_wse_head_lagrangemult(q:np.ndarray,
|
47
|
+
a:np.ndarray,
|
48
|
+
h_width_froma,
|
49
|
+
z:np.ndarray,
|
50
|
+
epsilon:float=1e-6,
|
51
|
+
energy:bool=False):
|
52
|
+
""" Compute the new area at the junction a_junction
|
53
|
+
from the flow rates q of the branches and the area a.
|
54
|
+
|
55
|
+
We ensure a same water elevation (z+h) at the junction in each branch
|
56
|
+
or a same head if energy is True.
|
57
|
+
|
58
|
+
:param q: np.ndarray, estimated signed flow rates of the branches
|
59
|
+
:param a: np.ndarray, estimated area of the branches
|
60
|
+
:param h_l_froma: function converting area to water height and width
|
61
|
+
:param z: np.ndarray, elevation of the branches
|
62
|
+
:param epsilon: float, tolerance of the method
|
63
|
+
:param energy: bool, if True, ensure the same energy at the junction
|
64
|
+
"""
|
65
|
+
|
66
|
+
n = q.size
|
67
|
+
|
68
|
+
# Compute the area ensuring the same water elevation at the junction
|
69
|
+
# using the Lagrange multiplier method
|
70
|
+
#
|
71
|
+
# We minimize the following function:
|
72
|
+
# sum_{i=1}^{n} 1/2 * (anew_i - a_i) ** 2
|
73
|
+
# subject to the constraint:
|
74
|
+
# (Z_i + h_i) - (Z_i+1 + h_i+1) = 0
|
75
|
+
# or
|
76
|
+
# (Z_i + h_i + 1/2 * (q_i / a_i) ^2 / g) - (Z_i+1 + h_i+1 + 1/2 * (q_i+1 / a_i+1) ^2 / g) = 0
|
77
|
+
#
|
78
|
+
# The problem is generally non-linear, we use the Newton-Raphson method to solve it.
|
79
|
+
#
|
80
|
+
# The Jacobian of the system is:
|
81
|
+
# dH_i / da_i = 1 / width_i
|
82
|
+
# dH_i / da_i+1 = -1 / width_i+1
|
83
|
+
# dZ_i / da_i = 0
|
84
|
+
# dZ_i / da_i+1 = 0
|
85
|
+
# if energy is True:
|
86
|
+
# d1/2 * (q_i / a_i) ^2 / g) / da_i = -q_i^2 / (a_i^3 * g)
|
87
|
+
# d1/2 * (q_i+1 / a_i+1) ^2 / g) / da_i+1 = q_i+1^2 / (a_i+1^3 * g)
|
88
|
+
#
|
89
|
+
# The system is solved iteratively using the Newton-Raphson method.
|
90
|
+
|
91
|
+
|
92
|
+
KITERMAX=100
|
93
|
+
GRAVITY = 9.81
|
94
|
+
|
95
|
+
ncompl = 2*n-1
|
96
|
+
|
97
|
+
# !Mise en correspondance deux par deux des altitudes de surface ou des énérgies
|
98
|
+
kiter = 0
|
99
|
+
error = 1.
|
100
|
+
|
101
|
+
while error > epsilon and kiter<KITERMAX:
|
102
|
+
|
103
|
+
A = np.zeros((ncompl, ncompl))
|
104
|
+
A[:n, :n] = np.eye(n)
|
105
|
+
b = np.zeros(ncompl)
|
106
|
+
|
107
|
+
kiter=kiter+1
|
108
|
+
if kiter>100:
|
109
|
+
print('Max iteration in junction')
|
110
|
+
|
111
|
+
h, width = h_width_froma(a)
|
112
|
+
|
113
|
+
# imposition des contraintes
|
114
|
+
if energy:
|
115
|
+
for i in range(n-1):
|
116
|
+
ipos = n + i
|
117
|
+
jpos = i + 1
|
118
|
+
|
119
|
+
# Termes suppl si égalisation d'énergie
|
120
|
+
v1_carre = (q[i] / a[i])**2. / GRAVITY
|
121
|
+
v2_carre = (q[jpos] / a[jpos])**2. / GRAVITY
|
122
|
+
|
123
|
+
A[ipos,i] = 1./width[i] - v1_carre / a[i]
|
124
|
+
A[ipos,jpos] = -1./width[jpos] + v2_carre / a[jpos]
|
125
|
+
A[i,ipos] = -A[ipos,i]
|
126
|
+
A[jpos,ipos] = -A[ipos,jpos]
|
127
|
+
|
128
|
+
b[ipos] = (v2_carre/2.0 + z[jpos] + h[jpos]) - (v1_carre/2.0 + z[i] + h[i])
|
129
|
+
|
130
|
+
else:
|
131
|
+
for i in range(n-1):
|
132
|
+
ipos = n + i
|
133
|
+
jpos = i + 1
|
134
|
+
|
135
|
+
# !dérivée de H vis-à-vis de la section --> largeur courante
|
136
|
+
A[ipos,i] = 1.0/width[i]
|
137
|
+
A[ipos,jpos] = -1.0/width[jpos]
|
138
|
+
A[i,ipos] = -A[ipos,i]
|
139
|
+
A[jpos,ipos] = -A[ipos,jpos]
|
140
|
+
|
141
|
+
# membre de droite --> delta d'altitude de fond
|
142
|
+
b[ipos] = (z[jpos]+h[jpos]) - (z[i]+h[i])
|
143
|
+
|
144
|
+
# résolution du système
|
145
|
+
incr = np.linalg.solve(A, b)
|
146
|
+
|
147
|
+
# mise à jour de l'inconnue de section sur base des incréments
|
148
|
+
a = a + incr[:n]
|
149
|
+
|
150
|
+
# mise à jour des propriétés indirectes
|
151
|
+
h, width = h_width_froma(a)
|
152
|
+
|
153
|
+
# calcul de l'erreur résiduelle
|
154
|
+
error = np.sum(np.abs(incr[:n]))
|
155
|
+
|
156
|
+
return a
|
157
|
+
|
158
|
+
if __name__ == "__main__":
|
159
|
+
# Test the function
|
160
|
+
q = np.array([-1, 2, 3, -4])
|
161
|
+
q_junction, lambda_ = junction_q_lagrangemult(q)
|
162
|
+
print("q_junction:", q_junction)
|
163
|
+
print("lambda:", lambda_)
|
164
|
+
|
165
|
+
# Test the function
|
166
|
+
q = np.array([-1.1, 2.2, 3.001, -3.99])
|
167
|
+
q_junction, lambda_ = junction_q_lagrangemult(q)
|
168
|
+
print("q_junction:", q_junction)
|
169
|
+
print("lambda:", lambda_)
|
170
|
+
|
171
|
+
def h_width_froma(a:np.ndarray):
|
172
|
+
L = 5.
|
173
|
+
h = a / L
|
174
|
+
dl = np.ones(a.shape) * L
|
175
|
+
return h, dl
|
176
|
+
|
177
|
+
a = np.array([1, 2, 3, 4])
|
178
|
+
z = np.array([0, 0, 0, 0])
|
179
|
+
|
180
|
+
a_junction = junction_wse_head_lagrangemult(q, a, h_width_froma, z, energy=False)
|
181
|
+
print("a_junction:", a_junction + z)
|
182
|
+
|
183
|
+
a = a_junction
|
184
|
+
a_junction = junction_wse_head_lagrangemult(q, a, h_width_froma, z, energy=True)
|
185
|
+
print("a_junction:", a_junction)
|
186
|
+
|
187
|
+
L = 5.
|
188
|
+
z = np.array([0, -1, .5, -.5])
|
189
|
+
a = (1. - z) * L
|
190
|
+
|
191
|
+
a_junction = junction_wse_head_lagrangemult(q, a, h_width_froma, z, energy=False)
|
192
|
+
h, width = h_width_froma(a_junction)
|
193
|
+
print("wse:", h + z)
|
194
|
+
|
195
|
+
z = np.array([0, -1, .5, -.5])
|
196
|
+
a = (1. - z)*5.
|
197
|
+
a[0] += 0.1
|
198
|
+
a[1] += 0.1
|
199
|
+
a[2] -= 0.1
|
200
|
+
a[3] -= 0.1
|
201
|
+
|
202
|
+
a_junction = junction_wse_head_lagrangemult(q, a, h_width_froma, z, energy=False)
|
203
|
+
h, width = h_width_froma(a_junction)
|
204
|
+
print("wse:", h + z)
|
205
|
+
pass
|
wolfhece/pybridges.py
CHANGED
@@ -1009,11 +1009,11 @@ class Bridges(Element_To_Draw):
|
|
1009
1009
|
|
1010
1010
|
return self.active_elt
|
1011
1011
|
|
1012
|
-
def find_inside_poly(self,
|
1012
|
+
def find_inside_poly(self, vec:vector)->list:
|
1013
1013
|
"""
|
1014
1014
|
Find bridges inside polygon/vector
|
1015
1015
|
"""
|
1016
|
-
polyls =
|
1016
|
+
polyls = vec.polygon
|
1017
1017
|
bridges = list(self.myelts.values())
|
1018
1018
|
|
1019
1019
|
mysel=[]
|
wolfhece/pypolygons_scen.py
CHANGED
@@ -408,7 +408,7 @@ class Polygons_Analyze(Zones):
|
|
408
408
|
self.polygons_meanxy = {}
|
409
409
|
for curvert in self.polygons_zone.myvectors:
|
410
410
|
# Centre du polygone
|
411
|
-
centroid = curvert.
|
411
|
+
centroid = curvert.centroid
|
412
412
|
self.polygons_meanxy[curvert.myname] = (centroid.x, centroid.y)
|
413
413
|
|
414
414
|
for vec in self.polygons_zone.myvectors:
|
@@ -536,7 +536,7 @@ class Polygons_Analyze(Zones):
|
|
536
536
|
|
537
537
|
for curvert in self.polygons_zone.myvectors:
|
538
538
|
# Centre du polygone
|
539
|
-
centroid = curvert.
|
539
|
+
centroid = curvert.centroid
|
540
540
|
self.polygons_curvi[curvert.myname] = poly.project(Point([centroid.x, centroid.y]))
|
541
541
|
|
542
542
|
def find_values_inside_parts(self, linked_arrays:Union[dict,list]):
|