wolfhece 2.0.55__py3-none-any.whl → 2.1.1__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 +1 -1
- wolfhece/PyDraw.py +1197 -361
- wolfhece/PyGui.py +1924 -661
- wolfhece/PyPalette.py +47 -0
- wolfhece/PyParams.py +377 -76
- wolfhece/PyVertex.py +14 -1
- wolfhece/PyVertexvectors.py +171 -22
- wolfhece/Results2DGPU.py +1 -2
- wolfhece/apps/version.py +2 -2
- wolfhece/bernoulli/__init__.py +0 -0
- wolfhece/bernoulli/chamber.py +93 -0
- wolfhece/bernoulli/fluids.py +10 -0
- wolfhece/bernoulli/losses.py +100 -0
- wolfhece/bernoulli/network.py +128 -0
- wolfhece/bernoulli/pipe.py +194 -0
- wolfhece/lagrangian/example_domain.py +1 -1
- wolfhece/mesh2d/bc_manager.py +66 -5
- wolfhece/mesh2d/config_manager.py +1 -1
- wolfhece/mesh2d/cst_2D_boundary_conditions.py +59 -2
- wolfhece/mesh2d/wolf2dprev.py +11606 -2678
- wolfhece/models/walous_niv1.pal +29 -0
- wolfhece/models/walous_niv2.pal +77 -0
- wolfhece/pywalous.py +400 -46
- wolfhece/scenario/config_manager.py +14 -5
- wolfhece/wolf_array.py +1487 -458
- wolfhece/wolf_vrt.py +31 -8
- wolfhece/wolfresults_2D.py +230 -91
- {wolfhece-2.0.55.dist-info → wolfhece-2.1.1.dist-info}/METADATA +3 -2
- {wolfhece-2.0.55.dist-info → wolfhece-2.1.1.dist-info}/RECORD +32 -24
- {wolfhece-2.0.55.dist-info → wolfhece-2.1.1.dist-info}/WHEEL +0 -0
- {wolfhece-2.0.55.dist-info → wolfhece-2.1.1.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.0.55.dist-info → wolfhece-2.1.1.dist-info}/top_level.txt +0 -0
wolfhece/PyVertex.py
CHANGED
@@ -169,6 +169,19 @@ class wolfvertex:
|
|
169
169
|
self.y = max(self.y, bounds[1][0])
|
170
170
|
self.y = min(self.y, bounds[1][1])
|
171
171
|
|
172
|
+
def is_like(self, v:"wolfvertex", tol:float=1.e-6):
|
173
|
+
"""
|
174
|
+
Return True if the vertex is close to another one
|
175
|
+
|
176
|
+
:param v: vertex to compare
|
177
|
+
:param tol: tolerance
|
178
|
+
"""
|
179
|
+
|
180
|
+
if abs(self.x - v.x) < tol and abs(self.y - v.y) < tol and abs(self.z - v.z) < tol:
|
181
|
+
return True
|
182
|
+
else:
|
183
|
+
return False
|
184
|
+
|
172
185
|
class cloudproperties:
|
173
186
|
"""
|
174
187
|
Properties of a cloud of vertices
|
@@ -854,7 +867,7 @@ class cloud_vertices(Element_To_Draw):
|
|
854
867
|
curvert = self.myvertices[item]['vertex']
|
855
868
|
|
856
869
|
if curvert.x > xmin and curvert.x < xmax and curvert.y > ymin and curvert.y < ymax:
|
857
|
-
|
870
|
+
|
858
871
|
r,g,b = getRGBfromI(self.myprop.legendcolor)
|
859
872
|
|
860
873
|
curtxt_infos = Text_Infos(self.myprop.legendpriority,
|
wolfhece/PyVertexvectors.py
CHANGED
@@ -887,6 +887,7 @@ if :\n \
|
|
887
887
|
return 'SanSerif'
|
888
888
|
else:
|
889
889
|
return 'Arial'
|
890
|
+
|
890
891
|
class vector:
|
891
892
|
"""
|
892
893
|
Objet de gestion d'informations vectorielles
|
@@ -911,11 +912,14 @@ class vector:
|
|
911
912
|
|
912
913
|
def __init__(self, lines:list=[], is2D=True, name='NoName', parentzone:"zone"=None, fromshapely=None) -> None:
|
913
914
|
"""
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
915
|
+
|
916
|
+
:param lines: utile pour lecture de fichier
|
917
|
+
:param is2D: on interprète les 'vertices' comme 2D même si chaque 'wolfvertex' contient toujours x, y et z
|
918
|
+
:param name: nom du vecteur
|
919
|
+
:param parentzone: instance de type 'zone' qui contient le 'vector'
|
920
|
+
|
918
921
|
"""
|
922
|
+
|
919
923
|
self.myname=''
|
920
924
|
self.is2D = is2D
|
921
925
|
self.closed=False
|
@@ -1047,6 +1051,9 @@ class vector:
|
|
1047
1051
|
"""
|
1048
1052
|
Return tuple with :
|
1049
1053
|
- (lower-left corner), (upper-right corner)
|
1054
|
+
|
1055
|
+
If you want [[xmin,xmax],[ymin,ymax]], use get_bounds_xx_yy() instead.
|
1056
|
+
|
1050
1057
|
"""
|
1051
1058
|
if grid is None:
|
1052
1059
|
return ((self.xmin, self.ymin), (self.xmax, self.ymax))
|
@@ -1062,6 +1069,9 @@ class vector:
|
|
1062
1069
|
"""
|
1063
1070
|
Return tuple with :
|
1064
1071
|
- (xmin,xmax), (ymin, ymax)
|
1072
|
+
|
1073
|
+
If you want [[lower-left corner],[upper-right corner]], use get_bounds() instead.
|
1074
|
+
|
1065
1075
|
"""
|
1066
1076
|
if grid is None:
|
1067
1077
|
return ((self.xmin, self.xmax), (self.ymin, self.ymax))
|
@@ -1095,6 +1105,7 @@ class vector:
|
|
1095
1105
|
"""
|
1096
1106
|
Mise en évidence
|
1097
1107
|
"""
|
1108
|
+
|
1098
1109
|
self._oldcolor = self.myprop.color
|
1099
1110
|
self._oldwidth = self.myprop.color
|
1100
1111
|
|
@@ -1105,6 +1116,7 @@ class vector:
|
|
1105
1116
|
"""
|
1106
1117
|
Mise en retrait
|
1107
1118
|
"""
|
1119
|
+
|
1108
1120
|
try:
|
1109
1121
|
self.myprop.color = self._oldcolor
|
1110
1122
|
self.myprop.width = self._oldwidth
|
@@ -1367,12 +1379,12 @@ class vector:
|
|
1367
1379
|
# again checks that the vector is not closed; in the case where
|
1368
1380
|
# two vertices are not the same one but have the same coordinates)
|
1369
1381
|
|
1370
|
-
is_open = self.myvertices[-1] is
|
1371
|
-
(self.myvertices[-1].x
|
1372
|
-
self.myvertices[-1].y
|
1382
|
+
is_open = not((self.myvertices[-1] is self.myvertices[0]) or \
|
1383
|
+
(self.myvertices[-1].x==self.myvertices[0].x and \
|
1384
|
+
self.myvertices[-1].y==self.myvertices[0].y))
|
1373
1385
|
|
1374
1386
|
if not self.is2D :
|
1375
|
-
is_open = is_open
|
1387
|
+
is_open = is_open or self.myvertices[-1].z!=self.myvertices[0].z
|
1376
1388
|
|
1377
1389
|
if is_open:
|
1378
1390
|
self.add_vertex(self.myvertices[0])
|
@@ -1800,10 +1812,10 @@ class vector:
|
|
1800
1812
|
|
1801
1813
|
if length<1:
|
1802
1814
|
length*=1000.
|
1803
|
-
alls = np.linspace(0,
|
1815
|
+
alls = np.linspace(0, length, nb)
|
1804
1816
|
alls/=1000.
|
1805
1817
|
else:
|
1806
|
-
alls = np.linspace(0,
|
1818
|
+
alls = np.linspace(0, length, nb, endpoint=True)
|
1807
1819
|
|
1808
1820
|
pts = [myls.interpolate(curs) for curs in alls]
|
1809
1821
|
# pts = [(curpt.x, curpt.y) for curpt in pts]
|
@@ -2147,16 +2159,28 @@ class vector:
|
|
2147
2159
|
|
2148
2160
|
if name is None:
|
2149
2161
|
name = self.myname + "_copy"
|
2150
|
-
if parentzone:
|
2151
|
-
copied_vector = vector(name=name,parentzone=parentzone)
|
2152
|
-
else:
|
2153
|
-
copied_vector = vector(name=name)
|
2154
2162
|
|
2155
|
-
|
2156
|
-
|
2163
|
+
if parentzone:
|
2164
|
+
copied_vector = vector(name=name,parentzone=parentzone)
|
2165
|
+
else:
|
2166
|
+
copied_vector = vector(name=name)
|
2157
2167
|
|
2158
|
-
|
2168
|
+
copied_vector.myvertices = copy.deepcopy(self.myvertices)
|
2159
2169
|
|
2170
|
+
return copied_vector
|
2171
|
+
|
2172
|
+
def set_legend_to_centroid(self, text:str='', visible:bool=True):
|
2173
|
+
"""
|
2174
|
+
Positionne la légende au centre du vecteur
|
2175
|
+
"""
|
2176
|
+
self.myprop.legendvisible = visible
|
2177
|
+
|
2178
|
+
ls = self.asshapely_pol()
|
2179
|
+
centroid = ls.centroid
|
2180
|
+
|
2181
|
+
self.myprop.legendx = centroid.x
|
2182
|
+
self.myprop.legendy = centroid.y
|
2183
|
+
self.myprop.legendtext = text if text else self.myname
|
2160
2184
|
|
2161
2185
|
class zone:
|
2162
2186
|
"""
|
@@ -2369,8 +2393,13 @@ class zone:
|
|
2369
2393
|
def add_vector(self, addedvect:vector, index=-99999, forceparent=False):
|
2370
2394
|
"""
|
2371
2395
|
Ajout d'une instance 'vector'
|
2372
|
-
|
2396
|
+
|
2397
|
+
:param addedvect: instance 'vector' à ajouter
|
2398
|
+
:param index: position d'insertion
|
2399
|
+
:param forceparent: True = forcer le parent à être la zone dans lequel le vecteur est ajouté
|
2400
|
+
|
2373
2401
|
"""
|
2402
|
+
|
2374
2403
|
if index==-99999 or index >self.nbvectors:
|
2375
2404
|
self.myvectors.append(addedvect)
|
2376
2405
|
else:
|
@@ -2474,8 +2503,13 @@ class zone:
|
|
2474
2503
|
if self.idgllist!=-99999:
|
2475
2504
|
glCallList(self.idgllist)
|
2476
2505
|
else:
|
2506
|
+
self.has_legend = False
|
2507
|
+
self.has_image = False
|
2508
|
+
|
2477
2509
|
for curvect in self.myvectors:
|
2478
2510
|
curvect.plot()
|
2511
|
+
self.has_legend |= curvect.myprop.legendvisible
|
2512
|
+
self.has_image |= curvect.myprop.imagevisible
|
2479
2513
|
|
2480
2514
|
if self.has_legend:
|
2481
2515
|
for curvect in self.myvectors:
|
@@ -3657,6 +3691,14 @@ class zone:
|
|
3657
3691
|
if self.parent.mapviewer is not None:
|
3658
3692
|
self.prep_listogl()
|
3659
3693
|
self.parent.mapviewer.Refresh()
|
3694
|
+
|
3695
|
+
def set_legend_to_centroid(self):
|
3696
|
+
"""
|
3697
|
+
Set the legend to the centroid of the zone
|
3698
|
+
"""
|
3699
|
+
for curvec in self.myvectors:
|
3700
|
+
curvec.set_legend_to_centroid()
|
3701
|
+
|
3660
3702
|
class Zones(wx.Frame, Element_To_Draw):
|
3661
3703
|
"""
|
3662
3704
|
Objet de gestion d'informations vectorielles
|
@@ -4398,6 +4440,7 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
4398
4440
|
boxright.Add(self.capturevertices,0,wx.EXPAND)
|
4399
4441
|
boxright.Add(self.dynapar,0,wx.EXPAND)
|
4400
4442
|
boxright.Add(self.createapar,0,wx.EXPAND)
|
4443
|
+
boxright.Add(self.reverseorder,0,wx.EXPAND)
|
4401
4444
|
boxright.Add(self.modifyvertices,0,wx.EXPAND)
|
4402
4445
|
boxright.Add(self.insertvertices,0,wx.EXPAND)
|
4403
4446
|
boxright.Add(self.splitvertices,0,wx.EXPAND)
|
@@ -4699,8 +4742,56 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
4699
4742
|
"""
|
4700
4743
|
Remplissage de la structure wx
|
4701
4744
|
"""
|
4745
|
+
|
4746
|
+
def store_tree_state(tree:TreeListCtrl):
|
4747
|
+
|
4748
|
+
expended_items = []
|
4749
|
+
root = tree.GetRootItem()
|
4750
|
+
|
4751
|
+
if root is None:
|
4752
|
+
return
|
4753
|
+
|
4754
|
+
def traverse_and_store(item):
|
4755
|
+
if not item.IsOk():
|
4756
|
+
return
|
4757
|
+
if tree.IsExpanded(item):
|
4758
|
+
expended_items.append(tree.GetItemData(item))
|
4759
|
+
|
4760
|
+
child = tree.GetFirstChild(item)
|
4761
|
+
while child.IsOk():
|
4762
|
+
traverse_and_store(child)
|
4763
|
+
child = tree.GetNextItem(child)
|
4764
|
+
|
4765
|
+
traverse_and_store(root)
|
4766
|
+
|
4767
|
+
return expended_items
|
4768
|
+
|
4769
|
+
def restore_tree_state(tree:TreeListCtrl, expended_items):
|
4770
|
+
|
4771
|
+
root = tree.GetRootItem()
|
4772
|
+
|
4773
|
+
if root is None:
|
4774
|
+
return
|
4775
|
+
|
4776
|
+
def traverse_and_restore(item):
|
4777
|
+
if not item.IsOk():
|
4778
|
+
return
|
4779
|
+
|
4780
|
+
if tree.GetItemData(item) in expended_items:
|
4781
|
+
tree.Expand(item)
|
4782
|
+
|
4783
|
+
child = tree.GetFirstChild(item)
|
4784
|
+
while child.IsOk():
|
4785
|
+
traverse_and_restore(child)
|
4786
|
+
child = tree.GetNextItem(child)
|
4787
|
+
|
4788
|
+
traverse_and_restore(root)
|
4789
|
+
|
4702
4790
|
if self.wx_exists:
|
4703
4791
|
if self.xls is not None:
|
4792
|
+
|
4793
|
+
expanded = store_tree_state(self.treelist)
|
4794
|
+
|
4704
4795
|
self.treelist.DeleteAllItems()
|
4705
4796
|
|
4706
4797
|
root = self.treelist.GetRootItem()
|
@@ -4712,6 +4803,8 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
4712
4803
|
|
4713
4804
|
self.treelist.Expand(mynode)
|
4714
4805
|
|
4806
|
+
restore_tree_state(self.treelist, expanded)
|
4807
|
+
|
4715
4808
|
def expand_tree(self, objzone=None):
|
4716
4809
|
"""
|
4717
4810
|
Développe la structure pour un objet spécifique stocké dans la self.treelist
|
@@ -5594,17 +5687,54 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
5594
5687
|
else:
|
5595
5688
|
myitemdata.unuse()
|
5596
5689
|
|
5690
|
+
def _callback_destroy_props(self):
|
5691
|
+
|
5692
|
+
self.myprops = None
|
5693
|
+
|
5694
|
+
def _callback_prop(self):
|
5695
|
+
|
5696
|
+
if self._myprops is None:
|
5697
|
+
logging.warning(_('No properties available'))
|
5698
|
+
return
|
5699
|
+
|
5700
|
+
for curzone in self.myzones:
|
5701
|
+
for curvec in curzone.myvectors:
|
5702
|
+
curvec.myprop.fill_property(self._myprops, updateOGL = False)
|
5703
|
+
|
5704
|
+
if self.mapviewer is not None:
|
5705
|
+
self.prep_listogl()
|
5706
|
+
self.mapviewer.Refresh()
|
5707
|
+
|
5708
|
+
|
5709
|
+
def _edit_all_properties(self):
|
5710
|
+
""" Show properties of the zone --> will be applied to all vectors int he zone """
|
5711
|
+
|
5712
|
+
locvec = vector()
|
5713
|
+
locvec.myprop.show()
|
5714
|
+
|
5715
|
+
self._myprops = locvec.myprop.myprops
|
5716
|
+
|
5717
|
+
self._myprops[('Legend','X')] = 99999.
|
5718
|
+
self._myprops[('Legend','Y')] = 99999.
|
5719
|
+
self._myprops[('Legend','Text')] = _('Not used')
|
5720
|
+
self._myprops.Populate()
|
5721
|
+
self._myprops.set_callbacks(self._callback_prop, self._callback_destroy_props)
|
5722
|
+
|
5723
|
+
|
5597
5724
|
def OnRDown(self, event:TreeListEvent):
|
5598
5725
|
"""
|
5599
5726
|
Affiche les propriétés du vecteur courant
|
5600
5727
|
Clicl-droit
|
5601
5728
|
"""
|
5602
5729
|
if self.wx_exists:
|
5603
|
-
if self.
|
5604
|
-
|
5730
|
+
if self.active_zone is None and self.active_zone is None:
|
5731
|
+
|
5732
|
+
logging.info(_('You will edit the properties of the entire instance (all zones and all vectors)'))
|
5733
|
+
self._edit_all_properties()
|
5605
5734
|
|
5606
|
-
|
5735
|
+
elif isinstance(self.last_active, vector):
|
5607
5736
|
self.active_vector.myprop.show()
|
5737
|
+
|
5608
5738
|
elif isinstance(self.last_active, zone):
|
5609
5739
|
self.active_zone.show_properties()
|
5610
5740
|
|
@@ -5620,6 +5750,9 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
5620
5750
|
self.Activate_vector(myitemdata)
|
5621
5751
|
elif isinstance(myitemdata,zone):
|
5622
5752
|
self.Activate_zone(myitemdata)
|
5753
|
+
else:
|
5754
|
+
self.Activate_vector(None)
|
5755
|
+
self.Activate_zone(None)
|
5623
5756
|
|
5624
5757
|
self.last_active = myitemdata
|
5625
5758
|
|
@@ -5631,6 +5764,12 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
5631
5764
|
"""
|
5632
5765
|
if self.wx_exists:
|
5633
5766
|
self.active_vector = object
|
5767
|
+
|
5768
|
+
if self.active_vector is None:
|
5769
|
+
logging.info(_('Active vector is now set to None'))
|
5770
|
+
self.xls.ClearGrid()
|
5771
|
+
return
|
5772
|
+
|
5634
5773
|
self.xls_active_vector()
|
5635
5774
|
|
5636
5775
|
if object.parentzone is not None:
|
@@ -5656,12 +5795,22 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
5656
5795
|
"""
|
5657
5796
|
if self.wx_exists:
|
5658
5797
|
self.active_zone = object
|
5798
|
+
|
5799
|
+
if self.active_zone is None:
|
5800
|
+
logging.info(_('Active zone is now set to None'))
|
5801
|
+
self.xls.ClearGrid()
|
5802
|
+
return
|
5803
|
+
|
5659
5804
|
if object.active_vector is not None:
|
5660
5805
|
self.active_vector = object.active_vector
|
5661
5806
|
elif object.nbvectors>0:
|
5662
5807
|
self.Activate_vector(object.myvectors[0])
|
5663
5808
|
|
5664
|
-
self.
|
5809
|
+
if self.active_vector is None:
|
5810
|
+
logging.warning(_('No vector in the active zone'))
|
5811
|
+
else:
|
5812
|
+
self.labelactvect.SetLabel(self.active_vector.myname)
|
5813
|
+
|
5665
5814
|
self.labelactzone.SetLabel(self.active_zone.myname)
|
5666
5815
|
self.Layout()
|
5667
5816
|
|
wolfhece/Results2DGPU.py
CHANGED
wolfhece/apps/version.py
CHANGED
File without changes
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import numpy as np
|
2
|
+
from math import pi
|
3
|
+
|
4
|
+
class chamber():
|
5
|
+
|
6
|
+
def __init__(self) -> None:
|
7
|
+
|
8
|
+
self.area = 10. # m^2
|
9
|
+
self.elevation = 0. # m
|
10
|
+
self._volume = 100. # m^3
|
11
|
+
self._height = 10. # m
|
12
|
+
|
13
|
+
self.q_in = []
|
14
|
+
self.q_out = []
|
15
|
+
|
16
|
+
self.is_bc = False
|
17
|
+
self.bc_value = 0.
|
18
|
+
|
19
|
+
def reset_q(self):
|
20
|
+
self.q_in = []
|
21
|
+
self.q_out = []
|
22
|
+
|
23
|
+
def add_qin(self, q):
|
24
|
+
self.q_in.append(q)
|
25
|
+
|
26
|
+
def add_qout(self, q):
|
27
|
+
self.q_out.append(q)
|
28
|
+
|
29
|
+
@property
|
30
|
+
def volume(self):
|
31
|
+
return self._volume
|
32
|
+
|
33
|
+
@volume.setter
|
34
|
+
def volume(self, value):
|
35
|
+
self._volume = value
|
36
|
+
self.solve_height()
|
37
|
+
|
38
|
+
@property
|
39
|
+
def height(self):
|
40
|
+
return self._height
|
41
|
+
|
42
|
+
@height.setter
|
43
|
+
def height(self, value):
|
44
|
+
self._height = value
|
45
|
+
self.solve_volume()
|
46
|
+
|
47
|
+
def solve_volume(self):
|
48
|
+
self._volume = self.area * self.height
|
49
|
+
return self._volume
|
50
|
+
|
51
|
+
def solve_height(self):
|
52
|
+
self._height = self.volume / self.area
|
53
|
+
return self._height
|
54
|
+
|
55
|
+
def update(self, dt:float):
|
56
|
+
|
57
|
+
if self.is_bc:
|
58
|
+
self.head = self.bc_value
|
59
|
+
else:
|
60
|
+
self.volume += (np.sum(np.asarray(self.q_in)) - np.sum(np.asarray(self.q_out))) * dt
|
61
|
+
self.solve_height()
|
62
|
+
|
63
|
+
@property
|
64
|
+
def head(self):
|
65
|
+
return self.elevation + self.height
|
66
|
+
|
67
|
+
@head.setter
|
68
|
+
def head(self, value):
|
69
|
+
self.height = value - self.elevation
|
70
|
+
self.solve_volume()
|
71
|
+
|
72
|
+
class junction(chamber):
|
73
|
+
|
74
|
+
def __init__(self) -> None:
|
75
|
+
super().__init__()
|
76
|
+
self.area = 1.e-2
|
77
|
+
self.volume = 0.
|
78
|
+
self.height = 0.
|
79
|
+
self.elevation = 0.
|
80
|
+
|
81
|
+
self._head = 0.
|
82
|
+
|
83
|
+
@property
|
84
|
+
def head(self):
|
85
|
+
return self._head
|
86
|
+
|
87
|
+
@head.setter
|
88
|
+
def head(self, value):
|
89
|
+
self._head = value
|
90
|
+
|
91
|
+
def update(self, dt:float):
|
92
|
+
|
93
|
+
self.head += (np.sum(np.asarray(self.q_in)) - np.sum(np.asarray(self.q_out))) * dt
|
@@ -0,0 +1,100 @@
|
|
1
|
+
import numpy as np
|
2
|
+
from math import pi
|
3
|
+
from scipy.optimize import fsolve, newton, root, root_scalar
|
4
|
+
import matplotlib.pyplot as plt
|
5
|
+
from jax import grad, jit, numpy as jnp
|
6
|
+
import timeit
|
7
|
+
|
8
|
+
@jit
|
9
|
+
def _colebrook_white(f, k, diameter, reynolds):
|
10
|
+
"""
|
11
|
+
Colebrook-White equation for friction factor
|
12
|
+
|
13
|
+
@param f: float, friction factor [-]
|
14
|
+
@param k: float, roughness of the pipe [m]
|
15
|
+
@param diameter: float, diameter of the pipe [m]
|
16
|
+
@param reynolds: float, Reynolds number [-]
|
17
|
+
"""
|
18
|
+
return 1. / jnp.sqrt(f) + 2. * jnp.log10(k / (3.7 * diameter) + 2.51 / (reynolds * jnp.sqrt(f)))
|
19
|
+
|
20
|
+
""" Gradient of the Colebrook-White equation """
|
21
|
+
grad_colebrook_white = jit(grad(_colebrook_white))
|
22
|
+
""" Second derivative of the Colebrook-White equation """
|
23
|
+
grad2_colebrook_white = jit(grad(grad(_colebrook_white)))
|
24
|
+
|
25
|
+
def f_colebrook_white(f, k, diameter, reynolds):
|
26
|
+
"""
|
27
|
+
Solve the Colebrook-White equation using Newton's method
|
28
|
+
|
29
|
+
@param f: float, initial guess for the friction factor [-]
|
30
|
+
@param k: float, roughness of the pipe [m]
|
31
|
+
@param diameter: float, diameter of the pipe [m]
|
32
|
+
@param reynolds: float, Reynolds number [-]
|
33
|
+
"""
|
34
|
+
f_sol = newton(_colebrook_white, f, grad_colebrook_white, args=(k, diameter, reynolds), rtol=1e-6)
|
35
|
+
return f_sol.item()
|
36
|
+
|
37
|
+
|
38
|
+
# Test multiple solvers
|
39
|
+
def test_colebrook_fsolve():
|
40
|
+
""" Test the Colebrook-White equation using Scipy fsolve """
|
41
|
+
|
42
|
+
k= 1.e-4
|
43
|
+
diam = .5
|
44
|
+
viscosity = 1.e-6
|
45
|
+
area = pi * (diam/2.)**2.
|
46
|
+
discharge = 1.
|
47
|
+
velocity = discharge / area
|
48
|
+
reynolds = velocity * diam / viscosity
|
49
|
+
|
50
|
+
f_guess = 0.02 # Initial guess for the friction factor
|
51
|
+
f_sol = fsolve(_colebrook_white, f_guess, args=(k, diam, reynolds), xtol=1e-14)
|
52
|
+
return f_sol[0]
|
53
|
+
|
54
|
+
def test_colebrook_root_scalar():
|
55
|
+
""" Test the Colebrook-White equation using Scipy root_scalar """
|
56
|
+
|
57
|
+
k= 1.e-4
|
58
|
+
diam = .5
|
59
|
+
viscosity = 1.e-6
|
60
|
+
area = pi * (diam/2.)**2.
|
61
|
+
discharge = 1.
|
62
|
+
velocity = discharge / area
|
63
|
+
reynolds = velocity * diam / viscosity
|
64
|
+
|
65
|
+
f_guess = 0.02 # Initial guess for the friction factor
|
66
|
+
f_sol = root_scalar(_colebrook_white, method='brentq', bracket=[0.,10.], x0 = f_guess, args=(k, diam, reynolds)) #, fprime = grad_colebrook_white, fprime2 = grad2_colebrook_white, xtol=1e-6)
|
67
|
+
return f_sol.root
|
68
|
+
|
69
|
+
def test_colebrook_newton():
|
70
|
+
""" Test the Colebrook-White equation using Scipy newton """
|
71
|
+
|
72
|
+
k= 1.e-4
|
73
|
+
diam = .5
|
74
|
+
viscosity = 1.e-6
|
75
|
+
area = pi * (diam/2.)**2.
|
76
|
+
discharge = 1.
|
77
|
+
velocity = discharge / area
|
78
|
+
reynolds = velocity * diam / viscosity
|
79
|
+
|
80
|
+
f_guess = 0.02 # Initial guess for the friction factor
|
81
|
+
|
82
|
+
f_sol = newton(_colebrook_white, f_guess, grad_colebrook_white, args=(k, diam, reynolds), rtol=1e-6)
|
83
|
+
return f_sol.item()
|
84
|
+
|
85
|
+
|
86
|
+
if __name__ == '__main__':
|
87
|
+
|
88
|
+
trootscalar = timeit.timeit(test_colebrook_root_scalar, number = 1000)
|
89
|
+
tfsolve = timeit.timeit(test_colebrook_fsolve, number = 1000)
|
90
|
+
tnewton = timeit.timeit(test_colebrook_newton, number = 1000)
|
91
|
+
|
92
|
+
trootscalar = test_colebrook_root_scalar()
|
93
|
+
tfsolve = test_colebrook_fsolve()
|
94
|
+
tnewton = test_colebrook_newton()
|
95
|
+
|
96
|
+
sol_newton = f_colebrook_white(.02, 1.e-4, .5, 1/(pi*(.5/2.)**2.)*.5/1.e-6)
|
97
|
+
|
98
|
+
assert sol_newton == tnewton
|
99
|
+
|
100
|
+
pass
|