wolfhece 2.1.98__py3-none-any.whl → 2.1.100__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 +506 -35
- wolfhece/PyParams.py +18 -8
- wolfhece/PyVertex.py +12 -5
- wolfhece/PyVertexvectors.py +27 -16
- wolfhece/Results2DGPU.py +23 -7
- wolfhece/acceptability/Parallels.py +2 -2
- wolfhece/acceptability/_add_path.py +23 -0
- wolfhece/acceptability/acceptability.py +594 -563
- wolfhece/acceptability/acceptability_gui.py +564 -331
- wolfhece/acceptability/cli.py +307 -120
- wolfhece/acceptability/func.py +1743 -1597
- wolfhece/analyze_vect.py +177 -0
- wolfhece/apps/version.py +1 -1
- wolfhece/bernoulli/losses.py +75 -22
- wolfhece/bernoulli/losses_jax.py +143 -0
- wolfhece/bernoulli/pipe.py +7 -2
- wolfhece/math_parser/__init__.py +4 -4
- wolfhece/math_parser/calculator.py +50 -9
- wolfhece/matplotlib_fig.py +1980 -0
- wolfhece/mesh2d/simple_2d.py +2399 -0
- wolfhece/mesh2d/wolf2dprev.py +1 -1
- wolfhece/pidcontroller.py +131 -0
- wolfhece/pywalous.py +7 -7
- wolfhece/scenario/config_manager.py +191 -83
- wolfhece/wolf_array.py +162 -109
- wolfhece/wolf_vrt.py +108 -7
- wolfhece/wolfresults_2D.py +109 -4
- wolfhece/xyz_file.py +91 -51
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/METADATA +1 -1
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/RECORD +33 -27
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/WHEEL +1 -1
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/top_level.txt +0 -0
wolfhece/analyze_vect.py
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
|
2
|
+
from pathlib import Path
|
3
|
+
import numpy as np
|
4
|
+
from shapely.geometry import Polygon, Point, LineString
|
5
|
+
from shapely import prepare, is_prepared, destroy_prepared
|
6
|
+
|
7
|
+
import wx
|
8
|
+
import logging
|
9
|
+
from tqdm import tqdm
|
10
|
+
|
11
|
+
from .PyTranslate import _
|
12
|
+
from .PyVertexvectors import Zones, zone, vector, wolfvertex
|
13
|
+
from .matplotlib_fig import Matplotlib_Figure as mpl_plot, Matplotlib_ax_properties as mpl_ax, Matplolib_line_properties as mpl_line, Matplotlib_figure_properties as mpl_fig
|
14
|
+
from .matplotlib_fig import PRESET_LAYOUTS
|
15
|
+
from .wolf_array import WolfArray
|
16
|
+
from .wolfresults_2D import Wolfresults_2D
|
17
|
+
from .Results2DGPU import wolfres2DGPU
|
18
|
+
|
19
|
+
class Compare_vectors():
|
20
|
+
""" Compare multiple vectors """
|
21
|
+
|
22
|
+
def __init__(self) -> None:
|
23
|
+
|
24
|
+
self.fig:mpl_plot = None
|
25
|
+
|
26
|
+
self._reference:vector = None
|
27
|
+
self._reference_ls:LineString = None
|
28
|
+
self._ref_s:np.ndarray = None
|
29
|
+
self._ref_obj:dict[str, WolfArray | wolfres2DGPU | Wolfresults_2D] = {}
|
30
|
+
self._ref_values:zone = None
|
31
|
+
|
32
|
+
self._to_compare:dict[vector, list[WolfArray | wolfres2DGPU | Wolfresults_2D]] = {}
|
33
|
+
self._compare_values:dict[vector, zone] = {}
|
34
|
+
|
35
|
+
@property
|
36
|
+
def layout(self):
|
37
|
+
""" Layout of the figure """
|
38
|
+
return self.fig.layout
|
39
|
+
|
40
|
+
@layout.setter
|
41
|
+
def layout(self, value:dict | tuple | list | str):
|
42
|
+
""" Set layout of the figure """
|
43
|
+
self.fig = mpl_plot(value)
|
44
|
+
self.fig.Show()
|
45
|
+
|
46
|
+
@property
|
47
|
+
def reference(self):
|
48
|
+
""" Reference vector """
|
49
|
+
return self._reference
|
50
|
+
|
51
|
+
@reference.setter
|
52
|
+
def reference(self, value:vector):
|
53
|
+
""" Set reference vector """
|
54
|
+
if not isinstance(value, vector):
|
55
|
+
logging.error(_('Reference must be a vector'))
|
56
|
+
return
|
57
|
+
|
58
|
+
self._reference = value
|
59
|
+
self._reference_ls = value.asshapely_ls()
|
60
|
+
prepare(self._reference_ls)
|
61
|
+
self._ref_s = self._reference.get_s2d()
|
62
|
+
|
63
|
+
def __del__(self):
|
64
|
+
""" Destructor """
|
65
|
+
|
66
|
+
if self._reference_ls is not None:
|
67
|
+
if is_prepared(self._reference_ls):
|
68
|
+
destroy_prepared(self._reference_ls)
|
69
|
+
|
70
|
+
def add_ref_values(self, values:WolfArray | wolfres2DGPU | Wolfresults_2D):
|
71
|
+
""" Add values to the reference vector """
|
72
|
+
|
73
|
+
self._ref_obj[values.idx] = values
|
74
|
+
|
75
|
+
def del_ref_values(self, which:int | str):
|
76
|
+
""" Pop values from the reference vector """
|
77
|
+
|
78
|
+
if isinstance(which, str):
|
79
|
+
if which in self._ref_obj:
|
80
|
+
self._ref_obj.pop(which)
|
81
|
+
elif isinstance(which, int):
|
82
|
+
if which < len(self._ref_obj):
|
83
|
+
self._ref_obj.pop(list(self._ref_obj.keys())[which])
|
84
|
+
|
85
|
+
def reset_ref_values(self):
|
86
|
+
""" Reset reference values """
|
87
|
+
|
88
|
+
self._ref_obj = {}
|
89
|
+
|
90
|
+
def get_ref_values(self):
|
91
|
+
""" Retrieve reference values """
|
92
|
+
|
93
|
+
self._ref_values = self.reference.get_values_linked(self._ref_obj)
|
94
|
+
|
95
|
+
def add_compare(self, support:vector, values:list[WolfArray | wolfres2DGPU | Wolfresults_2D] = None):
|
96
|
+
""" Add values to compare """
|
97
|
+
|
98
|
+
if not isinstance(support, vector):
|
99
|
+
logging.error(_('Support must be a vector'))
|
100
|
+
return
|
101
|
+
|
102
|
+
if values is not None:
|
103
|
+
if not isinstance(values, list):
|
104
|
+
values = [values]
|
105
|
+
|
106
|
+
if isinstance(values, list):
|
107
|
+
if not all(isinstance(x, WolfArray | wolfres2DGPU | Wolfresults_2D) for x in values):
|
108
|
+
logging.error(_('Values must be a list of WolfArray, Wolfresults_2D or Wolfres2DGPU'))
|
109
|
+
return
|
110
|
+
|
111
|
+
if support in self._to_compare:
|
112
|
+
self._to_compare[support] += values
|
113
|
+
else:
|
114
|
+
self._to_compare[support] = values
|
115
|
+
|
116
|
+
def reset_compare(self):
|
117
|
+
""" Reset comparison values """
|
118
|
+
|
119
|
+
self._to_compare = {}
|
120
|
+
|
121
|
+
def del_compare(self, which:int | str):
|
122
|
+
""" Pop values from the comparison vector """
|
123
|
+
|
124
|
+
if isinstance(which, str):
|
125
|
+
if which in self._to_compare:
|
126
|
+
self._to_compare.pop(which)
|
127
|
+
elif isinstance(which, int):
|
128
|
+
if which < len(self._to_compare):
|
129
|
+
self._to_compare.pop(list(self._to_compare.keys())[which])
|
130
|
+
|
131
|
+
def get_compare_values(self):
|
132
|
+
""" Retrieve comparison values """
|
133
|
+
|
134
|
+
for curvect in self._to_compare:
|
135
|
+
self._compare_values[curvect] = curvect.get_values_linked({cur.idx: cur for cur in self._to_compare[curvect]})
|
136
|
+
|
137
|
+
def plot_ref(self, axis:int = 0):
|
138
|
+
""" Plot reference vector """
|
139
|
+
|
140
|
+
if self.fig is None:
|
141
|
+
logging.error(_('No figure layout defined'))
|
142
|
+
return
|
143
|
+
|
144
|
+
for curvect in self._ref_values.myvectors:
|
145
|
+
xyz = curvect.asnparray3d()
|
146
|
+
x = [self._reference_ls.project(Point(x,y)) for x,y in xyz[:,0:2]]
|
147
|
+
y = xyz[:,2]
|
148
|
+
|
149
|
+
self.fig.plot(x=x, y=y, ax=axis, label=curvect.myname)
|
150
|
+
|
151
|
+
def plot_compare(self, axis:int = 0):
|
152
|
+
""" Plot comparison vectors along reference vector.
|
153
|
+
|
154
|
+
We must project comparison vectors on the reference vector and plot them.
|
155
|
+
"""
|
156
|
+
|
157
|
+
if self.fig is None:
|
158
|
+
logging.error(_('No figure layout defined'))
|
159
|
+
return
|
160
|
+
|
161
|
+
for curvect in self._compare_values:
|
162
|
+
for curval in self._compare_values[curvect].myvectors:
|
163
|
+
xyz = curval.asnparray3d()
|
164
|
+
x = [self._reference_ls.project(Point(x,y)) for x,y in xyz[:,0:2]]
|
165
|
+
y = xyz[:,2]
|
166
|
+
|
167
|
+
self.fig.plot(x=x, y=y, ax=axis, label=curval.myname)
|
168
|
+
|
169
|
+
def set_x_bounds(self, smin:float, smax:float, axis:int = 0):
|
170
|
+
""" Set x bounds for the figure """
|
171
|
+
|
172
|
+
self.fig.set_x_bounds(smin, smax, axis)
|
173
|
+
|
174
|
+
def set_y_bounds(self, ymin:float, ymax:float, axis:int = 0):
|
175
|
+
""" Set y bounds for the figure """
|
176
|
+
|
177
|
+
self.fig.set_y_bounds(ymin, ymax, axis)
|
wolfhece/apps/version.py
CHANGED
wolfhece/bernoulli/losses.py
CHANGED
@@ -10,13 +10,15 @@ copying or distribution of this file, via any medium, is strictly prohibited.
|
|
10
10
|
|
11
11
|
import numpy as np
|
12
12
|
from math import pi
|
13
|
-
from scipy.optimize import
|
13
|
+
from scipy.optimize import newton, root, root_scalar, fsolve
|
14
14
|
import matplotlib.pyplot as plt
|
15
|
-
from jax import grad, jit, numpy as jnp
|
15
|
+
# from jax import grad, jit, numpy as jnp, Array
|
16
|
+
from numba import jit
|
17
|
+
from jax.scipy.optimize import minimize
|
16
18
|
import timeit
|
17
19
|
|
18
20
|
@jit
|
19
|
-
def _colebrook_white(f, k, diameter, reynolds):
|
21
|
+
def _colebrook_white(f:float, k:float, diameter:float, reynolds:float) -> float:
|
20
22
|
"""
|
21
23
|
Colebrook-White equation for friction factor
|
22
24
|
|
@@ -25,14 +27,17 @@ def _colebrook_white(f, k, diameter, reynolds):
|
|
25
27
|
@param diameter: float, diameter of the pipe [m]
|
26
28
|
@param reynolds: float, Reynolds number [-]
|
27
29
|
"""
|
28
|
-
|
30
|
+
ret = 1. / np.sqrt(f) + 2. * np.log10(k / (3.7 * diameter) + 2.51 / (reynolds * np.sqrt(f)))
|
31
|
+
return ret
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
@jit
|
34
|
+
def _grad_colebrook_white(f, k, diameter, reynolds):
|
35
|
+
|
36
|
+
term1 = -0.5 * f**(-1.5)
|
37
|
+
term2 = 2. * (2.51 / (reynolds * np.sqrt(f))) * (-0.5 * f**(-1.5)) / (k / (3.7 * diameter) + 2.51 / (reynolds * np.sqrt(f)))
|
38
|
+
return term1 + term2
|
34
39
|
|
35
|
-
def f_colebrook_white(f, k, diameter, reynolds):
|
40
|
+
def f_colebrook_white(f:float, k:float, diameter:float, reynolds:float) -> float:
|
36
41
|
"""
|
37
42
|
Solve the Colebrook-White equation using Newton's method
|
38
43
|
|
@@ -41,11 +46,12 @@ def f_colebrook_white(f, k, diameter, reynolds):
|
|
41
46
|
@param diameter: float, diameter of the pipe [m]
|
42
47
|
@param reynolds: float, Reynolds number [-]
|
43
48
|
"""
|
44
|
-
f_sol = newton(_colebrook_white, f, grad_colebrook_white, args=(k, diameter, reynolds), rtol=1e-6)
|
45
|
-
return f_sol.item()
|
46
49
|
|
50
|
+
f_sol = fsolve(_colebrook_white, f, args=(k, diameter, reynolds), xtol=1e-14, fprime=_grad_colebrook_white)
|
51
|
+
return f_sol[0]
|
47
52
|
|
48
53
|
# Test multiple solvers
|
54
|
+
|
49
55
|
def test_colebrook_fsolve():
|
50
56
|
""" Test the Colebrook-White equation using Scipy fsolve """
|
51
57
|
|
@@ -58,7 +64,7 @@ def test_colebrook_fsolve():
|
|
58
64
|
reynolds = velocity * diam / viscosity
|
59
65
|
|
60
66
|
f_guess = 0.02 # Initial guess for the friction factor
|
61
|
-
f_sol = fsolve(_colebrook_white, f_guess, args=(k, diam, reynolds), xtol=1e-
|
67
|
+
f_sol = fsolve(_colebrook_white, f_guess, args=(k, diam, reynolds), xtol=1e-6)
|
62
68
|
return f_sol[0]
|
63
69
|
|
64
70
|
def test_colebrook_root_scalar():
|
@@ -73,7 +79,7 @@ def test_colebrook_root_scalar():
|
|
73
79
|
reynolds = velocity * diam / viscosity
|
74
80
|
|
75
81
|
f_guess = 0.02 # Initial guess for the friction factor
|
76
|
-
f_sol = root_scalar(_colebrook_white, method='brentq', bracket=[
|
82
|
+
f_sol = root_scalar(_colebrook_white, method='brentq', bracket=[1e-10,10.], x0 = f_guess, args=(k, diam, reynolds)) #, fprime = grad_colebrook_white, fprime2 = grad2_colebrook_white, xtol=1e-6)
|
77
83
|
return f_sol.root
|
78
84
|
|
79
85
|
def test_colebrook_newton():
|
@@ -89,22 +95,69 @@ def test_colebrook_newton():
|
|
89
95
|
|
90
96
|
f_guess = 0.02 # Initial guess for the friction factor
|
91
97
|
|
92
|
-
f_sol = newton(_colebrook_white, f_guess,
|
98
|
+
f_sol = newton(_colebrook_white, f_guess, _grad_colebrook_white, args=(k, diam, reynolds), rtol=1e-6)
|
93
99
|
return f_sol.item()
|
94
100
|
|
101
|
+
@jit
|
102
|
+
def dichotomy(f, a:float, b:float, args, tol=1e-10, max_iter=1000):
|
103
|
+
def cond_fun(val):
|
104
|
+
a, b, i = val
|
105
|
+
return (b - a) > tol
|
106
|
+
|
107
|
+
def body_fun(val):
|
108
|
+
a, b, i = val
|
109
|
+
c = (a + b) / 2.
|
110
|
+
k, diameter, reynolds = args
|
111
|
+
fa = f(a, k, diameter, reynolds)
|
112
|
+
fc = f(c, k, diameter, reynolds)
|
113
|
+
if fc == 0:
|
114
|
+
return (c, c, i + 1)
|
115
|
+
else:
|
116
|
+
if fa * fc < 0:
|
117
|
+
return (a, c, i + 1)
|
118
|
+
else:
|
119
|
+
return (c, b, i + 1)
|
120
|
+
|
121
|
+
i=0
|
122
|
+
while cond_fun((a, b, i)) and i < max_iter:
|
123
|
+
a, b, i = body_fun((a, b, 0))
|
124
|
+
|
125
|
+
return (a + b) / 2
|
126
|
+
|
127
|
+
def test_colebrook_dichotomy():
|
128
|
+
""" Test the Colebrook-White equation using Scipy root_scalar """
|
129
|
+
|
130
|
+
k= 1.e-4
|
131
|
+
diam = .5
|
132
|
+
viscosity = 1.e-6
|
133
|
+
area = pi * (diam/2.)**2.
|
134
|
+
discharge = 1.
|
135
|
+
velocity = discharge / area
|
136
|
+
reynolds = velocity * diam / viscosity
|
137
|
+
|
138
|
+
f_guess = 0.02 # Initial guess for the friction factor
|
139
|
+
f_sol = dichotomy(_colebrook_white, 1e-10, 10., (k, diam, reynolds))
|
140
|
+
return f_sol
|
141
|
+
|
95
142
|
|
96
143
|
if __name__ == '__main__':
|
97
144
|
|
98
|
-
trootscalar = timeit.timeit(test_colebrook_root_scalar, number = 1000)
|
99
|
-
tfsolve = timeit.timeit(test_colebrook_fsolve, number = 1000)
|
100
|
-
tnewton = timeit.timeit(test_colebrook_newton, number = 1000)
|
101
145
|
|
102
|
-
|
103
|
-
|
104
|
-
|
146
|
+
sol_newton_ref = f_colebrook_white(.02, 1.e-4, .5, 1/(pi*(.5/2.)**2.)*.5/1.e-6)
|
147
|
+
|
148
|
+
sol_rootscalar = test_colebrook_root_scalar()
|
149
|
+
sol_fsolve = test_colebrook_fsolve()
|
150
|
+
sol_newton = test_colebrook_newton()
|
151
|
+
sol_dicho = test_colebrook_dichotomy()
|
105
152
|
|
106
|
-
|
153
|
+
tfsolve = timeit.timeit(test_colebrook_fsolve, number = 10000)
|
154
|
+
tnewton = timeit.timeit(test_colebrook_newton, number = 10000)
|
155
|
+
trootscalar = timeit.timeit(test_colebrook_root_scalar, number = 10000)
|
156
|
+
tdichotomy = timeit.timeit(test_colebrook_dichotomy, number = 10000)
|
107
157
|
|
108
|
-
assert sol_newton
|
158
|
+
assert abs(sol_newton_ref - sol_newton) < 1e-8
|
159
|
+
assert abs(sol_newton_ref - sol_fsolve) < 1e-8
|
160
|
+
assert abs(sol_newton_ref - sol_rootscalar) < 1e-8
|
161
|
+
assert abs(sol_newton_ref - sol_dicho) < 1e-8
|
109
162
|
|
110
163
|
pass
|
@@ -0,0 +1,143 @@
|
|
1
|
+
"""
|
2
|
+
Author: HECE - University of Liege, Pierre Archambeau
|
3
|
+
Date: 2024
|
4
|
+
|
5
|
+
Copyright (c) 2024 University of Liege. All rights reserved.
|
6
|
+
|
7
|
+
This script and its content are protected by copyright law. Unauthorized
|
8
|
+
copying or distribution of this file, via any medium, is strictly prohibited.
|
9
|
+
"""
|
10
|
+
|
11
|
+
import jax
|
12
|
+
from jax import lax, jit, grad
|
13
|
+
import jax.numpy as jnp
|
14
|
+
from jax.scipy.optimize import minimize
|
15
|
+
from jax._src.scipy.optimize.bfgs import minimize_bfgs
|
16
|
+
from scipy.optimize import minimize as minimize_scipy
|
17
|
+
import timeit
|
18
|
+
from matplotlib import pyplot as plt
|
19
|
+
|
20
|
+
def dichotomy(f, abi:jnp.array, args:jnp.array, tol:jnp.array=jnp.array([1e-8]), max_iter:jnp.array=jnp.array([1000])):
|
21
|
+
""" Dichotomy algorithm to find the root of a function """
|
22
|
+
|
23
|
+
def cond_fun(val:jnp.array) -> bool:
|
24
|
+
""" Condition function for the while loop """
|
25
|
+
a, b, i = val
|
26
|
+
return jnp.any((b - a) > tol) & jnp.any(i < max_iter)
|
27
|
+
|
28
|
+
def body_fun(val:jnp.array) -> jnp.array:
|
29
|
+
""" Body function for the while loop """
|
30
|
+
a, b, i = val
|
31
|
+
c = (a + b) / 2.
|
32
|
+
fa = f(a, args)
|
33
|
+
fc = f(c, args)
|
34
|
+
return lax.cond(fc == 0,
|
35
|
+
lambda _: jnp.array([c, b, i + 1]),
|
36
|
+
lambda _: lax.cond(fa * fc < 0,
|
37
|
+
lambda _: jnp.array([a, c, i + 1]),
|
38
|
+
lambda _: jnp.array([c, b, i + 1]), None), None)
|
39
|
+
|
40
|
+
abi = lax.while_loop(cond_fun, body_fun, abi)
|
41
|
+
return (abi[0] + abi[1]) / 2
|
42
|
+
|
43
|
+
@jit
|
44
|
+
def _colebrook_white(f:jnp.array, args:jnp.array) -> jnp.array:
|
45
|
+
"""
|
46
|
+
Colebrook-White equation for friction factor
|
47
|
+
|
48
|
+
@param args: array containing, k = roughness of the pipe [m], diameter of the pipe [m], Reynolds number [-]
|
49
|
+
"""
|
50
|
+
k, diameter, reynolds = args
|
51
|
+
ret = 1. / jnp.sqrt(f) + 2. * jnp.log10(k / (3.7 * diameter) + 2.51 / (reynolds * jnp.sqrt(f)))
|
52
|
+
return ret
|
53
|
+
|
54
|
+
@jit
|
55
|
+
def _square_colebrook_white(f:jnp.array, args:jnp.array) -> jnp.array:
|
56
|
+
"""
|
57
|
+
Square of Colebrook-White equation for friction factor to be minimized
|
58
|
+
|
59
|
+
@param f: float, friction factor [-]
|
60
|
+
@param args: array containing, k = roughness of the pipe [m], diameter of the pipe [m], Reynolds number [-]
|
61
|
+
"""
|
62
|
+
return _colebrook_white(f,args)**2
|
63
|
+
|
64
|
+
@jit
|
65
|
+
def _scalar_exp_square_colebrook_white(g:jnp.array, args:jnp.array) -> jnp.array: #scalar
|
66
|
+
"""
|
67
|
+
Square of Colebrook-White equation for friction factor to be minimized.
|
68
|
+
|
69
|
+
Apply a transformation to the friction factor to avoid negative values.
|
70
|
+
Exponential transformation is used.
|
71
|
+
|
72
|
+
@param g: float, friction factor [-]
|
73
|
+
@param args: array containing, k = roughness of the pipe [m], diameter of the pipe [m], Reynolds number [-]
|
74
|
+
"""
|
75
|
+
f = jnp.exp(g)
|
76
|
+
return jnp.sum(_colebrook_white(f,args)**2)
|
77
|
+
|
78
|
+
_grad_scalar_colebrook_white = grad(_scalar_exp_square_colebrook_white)
|
79
|
+
|
80
|
+
@jit
|
81
|
+
def grad_colebrook_white(f:jnp.array, args:jnp.array) -> jnp.array:
|
82
|
+
"""
|
83
|
+
Gradient of the Colebrook-White equation for friction factor
|
84
|
+
|
85
|
+
@param f: float, friction factor [-]
|
86
|
+
@param args: array containing, k = roughness of the pipe [m], diameter of the pipe [m], Reynolds number [-]
|
87
|
+
"""
|
88
|
+
|
89
|
+
# We must apply the exponential transformation to the friction factor
|
90
|
+
# See : _scalar_exp_square_colebrook_white
|
91
|
+
return _grad_scalar_colebrook_white(jnp.log(f), args)
|
92
|
+
|
93
|
+
@jit
|
94
|
+
def _min_colebrook_white(f:jnp.array, args:jnp.array) -> jnp.array:
|
95
|
+
"""
|
96
|
+
Minimize the Colebrook-White equation using BFGS
|
97
|
+
|
98
|
+
@param f: float, initial guess for the friction factor [-]
|
99
|
+
@param args: array containing, k = roughness of the pipe [m], diameter of the pipe [m], Reynolds number [-]
|
100
|
+
"""
|
101
|
+
|
102
|
+
return jnp.sum(jnp.exp(minimize(_scalar_exp_square_colebrook_white, jnp.log(f), args=(args,), method='BFGS', tol=1e-8).x))
|
103
|
+
|
104
|
+
|
105
|
+
if __name__ == '__main__':
|
106
|
+
|
107
|
+
args = jnp.array([1.e-4, .5, 1/(jnp.pi*(.5/2.)**2.)*.5/1.e-6])
|
108
|
+
|
109
|
+
# Find the root of the Colebrook-White equation by dichotomy
|
110
|
+
root = dichotomy(_colebrook_white, jnp.array([0.,2.,0]), args)
|
111
|
+
print(f"The root of the function is approximately: {root}")
|
112
|
+
|
113
|
+
optimum = _min_colebrook_white(jnp.array([0.03]), args)
|
114
|
+
|
115
|
+
print(f"The optimum of the function is approximately: {optimum}")
|
116
|
+
print(f"Delta: {jnp.abs(root - optimum)}")
|
117
|
+
|
118
|
+
# Create a test function to compare the time of execution between dichotomy and BFGS
|
119
|
+
@jit
|
120
|
+
def test_dichotomy():
|
121
|
+
dichotomy(_colebrook_white, jnp.array([0.,2.,0]), args)
|
122
|
+
|
123
|
+
@jit
|
124
|
+
def test_bfgs():
|
125
|
+
_min_colebrook_white(jnp.array([0.03]), args)
|
126
|
+
|
127
|
+
time_dicho = timeit.timeit(test_dichotomy, number=10000)
|
128
|
+
time_bfgs = timeit.timeit(test_bfgs, number=10000)
|
129
|
+
print(f"Time for dichotomy: {time_dicho}")
|
130
|
+
print(f"Time for BFGS: {time_bfgs}")
|
131
|
+
|
132
|
+
# Plot the function and its gradient
|
133
|
+
tested_f = jnp.arange(0.01, 0.03, 0.0001)
|
134
|
+
optimum = _min_colebrook_white(jnp.array([0.03]), args)
|
135
|
+
all_f = _square_colebrook_white(tested_f, args)
|
136
|
+
all_grad_ret = grad_colebrook_white(tested_f, args)
|
137
|
+
|
138
|
+
fig,ax = plt.subplots()
|
139
|
+
ax.plot(tested_f, all_f)
|
140
|
+
ax.plot(tested_f, all_grad_ret)
|
141
|
+
ax.scatter(optimum, _square_colebrook_white(optimum, args), color='red', marker='o')
|
142
|
+
ax.scatter(root, _colebrook_white(root, args), color='green', marker='X')
|
143
|
+
plt.show()
|
wolfhece/bernoulli/pipe.py
CHANGED
@@ -98,7 +98,12 @@ class pipe():
|
|
98
98
|
def _solve_friction_factor(self):
|
99
99
|
""" Update the friction factor using the Colebrook-White equation """
|
100
100
|
|
101
|
-
|
101
|
+
if self.reynolds==0.: # No flow
|
102
|
+
self.f = 0.
|
103
|
+
else:
|
104
|
+
if self.f ==0.:
|
105
|
+
self.f = 0.02
|
106
|
+
self.f = f_colebrook_white(self.f, self.k, self.diameter, self.reynolds)
|
102
107
|
|
103
108
|
return self.f
|
104
109
|
|
@@ -113,7 +118,7 @@ class pipe():
|
|
113
118
|
def solve_flowrate(self):
|
114
119
|
|
115
120
|
def loc_bernoulli(flowrate):
|
116
|
-
self.flowrate = flowrate
|
121
|
+
self.flowrate = flowrate[0]
|
117
122
|
return self.bernoulli_error
|
118
123
|
|
119
124
|
flowrate_solution = fsolve(loc_bernoulli, self.flowrate)
|
wolfhece/math_parser/__init__.py
CHANGED
@@ -225,16 +225,16 @@ class Parser:
|
|
225
225
|
|
226
226
|
def add(self, a, b):
|
227
227
|
return a + b
|
228
|
-
|
228
|
+
|
229
229
|
def norm(self, a, b):
|
230
230
|
return math.sqrt(a * a + b * b)
|
231
|
-
|
231
|
+
|
232
232
|
def Froude(self, a, b, c):
|
233
233
|
|
234
234
|
return math.sqrt(a * a + b * b) / math.sqrt(9.81 * c)
|
235
|
-
|
235
|
+
|
236
236
|
def sto(self, a, b):
|
237
|
-
return
|
237
|
+
return {a : b}
|
238
238
|
|
239
239
|
def sub(self, a, b):
|
240
240
|
return a - b
|
@@ -12,10 +12,18 @@ import wx
|
|
12
12
|
import logging
|
13
13
|
from pathlib import Path
|
14
14
|
|
15
|
-
|
15
|
+
from ..PyTranslate import _
|
16
16
|
from . import Parser, Expression
|
17
17
|
|
18
18
|
class Calculator(wx.Frame):
|
19
|
+
"""
|
20
|
+
Calculator/Array creator
|
21
|
+
|
22
|
+
With this calculator, you can create arrays and perform operations on them.
|
23
|
+
It is possible because the operations are parsed and evaluated by the math_parser module
|
24
|
+
and mathematic operators are allowed directly on WolfArrays.
|
25
|
+
|
26
|
+
"""
|
19
27
|
|
20
28
|
def __init__(self, mapviewer=None):
|
21
29
|
|
@@ -23,7 +31,7 @@ class Calculator(wx.Frame):
|
|
23
31
|
|
24
32
|
super(Calculator, self).__init__(None, title='Calculator', size=(500, 300))
|
25
33
|
|
26
|
-
self._memory = {}
|
34
|
+
self._memory = {} # dictionary containing the arrays and local stored variables
|
27
35
|
|
28
36
|
self._parser = Parser()
|
29
37
|
self._parsed_command:Expression = None
|
@@ -37,7 +45,11 @@ class Calculator(wx.Frame):
|
|
37
45
|
self._disp = wx.TextCtrl(self, style=wx.TE_RIGHT|wx.TE_RICH2|wx.TE_MULTILINE)
|
38
46
|
|
39
47
|
self._comment = wx.TextCtrl(self, style=wx.TE_RIGHT|wx.TE_RICH2|wx.TE_MULTILINE)
|
40
|
-
self.
|
48
|
+
self._comment.SetToolTip(_('Comment block'))
|
49
|
+
|
50
|
+
self._memory_txtctrl = wx.TextCtrl(self, style=wx.TE_RIGHT|wx.TE_RICH2|wx.TE_MULTILINE)
|
51
|
+
self._memory_txtctrl.SetToolTip(_('Memory positions (contains the ids of the arrays and local variables)'))
|
52
|
+
|
41
53
|
self.btn_reset_memory = wx.Button(self, label='Reset Memory')
|
42
54
|
|
43
55
|
self.Bind(wx.EVT_BUTTON, lambda v: self.bt_press(v.EventObject.Label))
|
@@ -45,9 +57,9 @@ class Calculator(wx.Frame):
|
|
45
57
|
self._btns[-1][-2].SetDefault()
|
46
58
|
|
47
59
|
self.Bind(wx.EVT_CHAR_HOOK, self.char_press)
|
48
|
-
self.btn_reset_memory.Bind(wx.EVT_BUTTON,
|
60
|
+
self.btn_reset_memory.Bind(wx.EVT_BUTTON, self.memory_clear_event)
|
49
61
|
|
50
|
-
self.SetSizer(self.pack([self._disp] + [self.pack(x) for x in self._btns] + [self.pack([self._comment, self.btn_reset_memory, self.
|
62
|
+
self.SetSizer(self.pack([self._disp] + [self.pack(x) for x in self._btns] + [self.pack([self._comment, self.btn_reset_memory, self._memory_txtctrl])], orient=wx.VERTICAL))
|
51
63
|
|
52
64
|
self._disp.SetFocus()
|
53
65
|
|
@@ -56,6 +68,7 @@ class Calculator(wx.Frame):
|
|
56
68
|
icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
|
57
69
|
self.SetIcon(icon)
|
58
70
|
|
71
|
+
self.memory_clear()
|
59
72
|
self.Show()
|
60
73
|
|
61
74
|
def pack(self, items, orient=wx.HORIZONTAL):
|
@@ -79,7 +92,33 @@ class Calculator(wx.Frame):
|
|
79
92
|
|
80
93
|
@comment.setter
|
81
94
|
def comment(self, value):
|
82
|
-
self._comment.Value
|
95
|
+
self._comment.Value += str(value)
|
96
|
+
|
97
|
+
def reset_comment(self):
|
98
|
+
self._comment.Value = ''
|
99
|
+
|
100
|
+
@property
|
101
|
+
def memory_txt(self):
|
102
|
+
return self._memory_txtctrl.Value
|
103
|
+
|
104
|
+
@memory_txt.setter
|
105
|
+
def memory_txt(self, value):
|
106
|
+
self._memory_txtctrl.Value += str(value)+'\n'
|
107
|
+
|
108
|
+
def reset_memory(self):
|
109
|
+
self._memory_txtctrl.Value = ''
|
110
|
+
|
111
|
+
def memory_clear(self):
|
112
|
+
self.reset_memory()
|
113
|
+
self._memory.clear()
|
114
|
+
|
115
|
+
from ..PyDraw import draw_type
|
116
|
+
ids = self._mapviewer.get_list_keys(drawing_type=draw_type.ARRAYS, checked_state=None)
|
117
|
+
for id in ids:
|
118
|
+
self.memory_txt += id
|
119
|
+
|
120
|
+
def memory_clear_event(self, e):
|
121
|
+
self.memory_clear()
|
83
122
|
|
84
123
|
def check_command(self) -> bool:
|
85
124
|
""" Check if the command is valid """
|
@@ -121,14 +160,15 @@ class Calculator(wx.Frame):
|
|
121
160
|
|
122
161
|
ret = []
|
123
162
|
for command in commands:
|
163
|
+
if command == '': continue
|
124
164
|
self.command = command
|
125
165
|
ret.append(str(self.evaluate(mem_last_command=False)))
|
126
166
|
|
127
167
|
self.command = '\n'.join(ret)
|
128
168
|
|
129
|
-
|
130
169
|
def evaluate(self, mem_last_command=True):
|
131
170
|
""" Evaluate the command """
|
171
|
+
|
132
172
|
from ..PyDraw import WolfArray, draw_type
|
133
173
|
|
134
174
|
if mem_last_command:
|
@@ -146,9 +186,10 @@ class Calculator(wx.Frame):
|
|
146
186
|
|
147
187
|
for key, value in res.items():
|
148
188
|
self._memory[key] = value
|
149
|
-
comment += f'{key} = {value}\n'
|
150
189
|
|
151
|
-
|
190
|
+
self.comment += f'{key} = {value}\n'
|
191
|
+
self.memory_txt += key
|
192
|
+
|
152
193
|
self.command = ''
|
153
194
|
|
154
195
|
elif isinstance(res, str|int|float):
|