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.
@@ -0,0 +1,128 @@
1
+
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+
5
+ from .pipe import pipe
6
+ from .chamber import chamber, junction
7
+
8
+ class network():
9
+
10
+ def __init__(self) -> None:
11
+
12
+ self.chambers:list[chamber] = []
13
+ self.pipes:list[pipe] = []
14
+ self.links:list[tuple[chamber,chamber,pipe]] = []
15
+
16
+ def add_chamber(self, chamber):
17
+ self.chambers.append(chamber)
18
+
19
+ def add_pipe(self, pipe):
20
+ self.pipes.append(pipe)
21
+
22
+ def link(self, chamber1, chamber2, pipe):
23
+ self.links.append((chamber1, chamber2, pipe))
24
+
25
+ def update(self, dt:float):
26
+
27
+ for chamber in self.chambers:
28
+ chamber.reset_q()
29
+
30
+ for chamber1, chamber2, pipe in self.links:
31
+ pipe.head_up = chamber1.head
32
+ pipe.head_down = chamber2.head
33
+ pipe.solve_flowrate()
34
+
35
+ chamber1.add_qout(pipe.flowrate)
36
+ chamber2.add_qin(pipe.flowrate)
37
+
38
+ for chamber in self.chambers:
39
+ chamber.update(dt)
40
+
41
+ if __name__ == "__main__":
42
+
43
+ def test_simplenetwork():
44
+
45
+ chamber1 = chamber()
46
+ chamber2 = chamber()
47
+ pipe1 = pipe()
48
+
49
+ net = network()
50
+ net.add_chamber(chamber1)
51
+ net.add_chamber(chamber2)
52
+ net.add_pipe(pipe1)
53
+ net.link(chamber1, chamber2, pipe1)
54
+
55
+ chamber1.elevation = 0.
56
+ chamber2.elevation = 0.
57
+ chamber1.area = 1.
58
+ chamber2.area = 1.
59
+
60
+ chamber1.head = 10.
61
+ chamber2.head = 0.
62
+
63
+ pipe1.viscosity = 1.e-6
64
+ pipe1.density = 1000.
65
+ pipe1.gravity = 9.81
66
+
67
+ pipe1.length = 100.
68
+ pipe1.diameter = 0.5
69
+
70
+ pipe1.k = 0.0001
71
+
72
+ net.update(1.)
73
+
74
+ def test_simplenetwork_w_junction(dt:float = 1.):
75
+
76
+ chamber1 = chamber()
77
+ chamber2 = chamber()
78
+ junc = junction()
79
+ pipe1 = pipe()
80
+ pipe2 = pipe()
81
+
82
+ net = network()
83
+ net.add_chamber(chamber1)
84
+ net.add_chamber(chamber2)
85
+ net.add_chamber(junc)
86
+
87
+ net.add_pipe(pipe1)
88
+ net.add_pipe(pipe2)
89
+
90
+ net.link(chamber1, junc, pipe1)
91
+ net.link(junc, chamber2, pipe2)
92
+
93
+ chamber1.elevation = 0.
94
+ chamber2.elevation = 0.
95
+
96
+ chamber1.area = 1.
97
+ chamber2.area = 1.
98
+
99
+ chamber1.is_bc = True
100
+ chamber1.bc_value = 10.
101
+
102
+ chamber2.is_bc = True
103
+ chamber2.bc_value = 0.
104
+
105
+ chamber1.head = 10.
106
+ chamber2.head = 0.
107
+ junc.head = 4.
108
+
109
+ for curpipe in [pipe1, pipe2]:
110
+
111
+ curpipe.viscosity = 1.e-6
112
+ curpipe.density = 1000.
113
+ curpipe.gravity = 9.81
114
+
115
+ curpipe.length = 50.
116
+ curpipe.diameter = 0.5
117
+
118
+ curpipe.k = 0.0001
119
+
120
+ evol = [junc.head]
121
+ old_head = 4.1
122
+ while abs(junc.head - old_head) > 1e-6:
123
+ old_head = junc.head
124
+ net.update(dt)
125
+ evol.append(junc.head)
126
+
127
+ plt.plot(evol)
128
+ plt.show()
@@ -0,0 +1,194 @@
1
+ import numpy as np
2
+ from math import pi
3
+ from scipy.optimize import fsolve
4
+
5
+ from .losses import f_colebrook_white
6
+ from .fluids import Water
7
+
8
+ GRAVITY = 9.81 # m/s^2
9
+ class pipe():
10
+ """ Pipe class for Bernoulli's equation """
11
+
12
+ def __init__(self) -> None:
13
+
14
+ self._head_up:float = 0. # upstream head [m]
15
+ self._head_down:float = 0. # downstream head [m]
16
+ self._flowrate:float = 0. # flowrate [$m^3s^{-1}$]
17
+ self._k:float = 0. # roughness of the pipe [m]
18
+
19
+ self.length:float = 0. # Length of the pipe [m]
20
+ self.diameter:float = 0. # Diameter of the pipe [m]
21
+
22
+ self.fluid = Water()
23
+
24
+ self.f = 0.02 # Initial guess for the friction factor
25
+
26
+ @property
27
+ def head_up(self):
28
+ return self._head_up
29
+
30
+ @head_up.setter
31
+ def head_up(self, value):
32
+ self._head_up = value
33
+
34
+ @property
35
+ def head_down(self):
36
+ return self._head_down
37
+
38
+ @head_down.setter
39
+ def head_down(self, value):
40
+ self._head_down = value
41
+
42
+ @property
43
+ def flowrate(self):
44
+ return self._flowrate
45
+
46
+ @flowrate.setter
47
+ def flowrate(self, value):
48
+ self._flowrate = value
49
+ self._solve_friction_factor()
50
+
51
+ @property
52
+ def k(self):
53
+ return self._k
54
+
55
+ @k.setter
56
+ def k(self, value):
57
+ self._k = value
58
+ self._solve_friction_factor()
59
+
60
+ @property
61
+ def area(self):
62
+ return pi * (self.diameter/2.)**2.
63
+
64
+ @property
65
+ def velocity(self):
66
+ return self.flowrate / self.area
67
+
68
+ @property
69
+ def perimeter(self):
70
+ return pi * self.diameter
71
+
72
+ @property
73
+ def epsilon(self):
74
+ return self.k / self.diameter
75
+
76
+ @property
77
+ def reynolds(self):
78
+ return self.velocity * self.diameter / self.fluid.nu
79
+
80
+ @property
81
+ def head_loss_k(self):
82
+ return self.length / self.diameter * self.friction_factor
83
+
84
+ @property
85
+ def head_loss(self):
86
+ return self.head_loss_k * self.velocity**2. / (2. * GRAVITY)
87
+
88
+ def _solve_friction_factor(self):
89
+ """ Update the friction factor using the Colebrook-White equation """
90
+
91
+ self.f = f_colebrook_white(self.f, self.k, self.diameter, self.reynolds)
92
+
93
+ return self.f
94
+
95
+ @property
96
+ def friction_factor(self):
97
+ return self.f
98
+
99
+ @property
100
+ def bernoulli_error(self):
101
+ return self.head_up - self.head_down - self.head_loss
102
+
103
+ def solve_flowrate(self):
104
+
105
+ def loc_bernoulli(flowrate):
106
+ self.flowrate = flowrate
107
+ return self.bernoulli_error
108
+
109
+ flowrate_solution = fsolve(loc_bernoulli, self.flowrate)
110
+
111
+ self.flowrate = flowrate_solution[0]
112
+
113
+ return self.flowrate
114
+
115
+ def solve_head_up(self):
116
+
117
+ def loc_bernoulli(head_up):
118
+ self.head_up = head_up
119
+ return self.bernoulli_error
120
+
121
+ head_up_solution = fsolve(loc_bernoulli, self.head_up)
122
+
123
+ self.head_up = head_up_solution[0]
124
+
125
+ return self.head_up
126
+
127
+ def solve_head_down(self):
128
+
129
+ def loc_bernoulli(head_down):
130
+ self.head_down = head_down
131
+ return self.bernoulli_error
132
+
133
+ head_down_solution = fsolve(loc_bernoulli, self.head_down)
134
+
135
+ self.head_down = head_down_solution[0]
136
+
137
+ return self.head_down
138
+
139
+ def solve_k(self):
140
+
141
+ def loc_bernoulli(k):
142
+ self.k = k
143
+ return self.bernoulli_error
144
+
145
+ k_solution = fsolve(loc_bernoulli, self.k)
146
+
147
+ self.k = k_solution[0]
148
+
149
+ return self.k
150
+
151
+
152
+ if __name__ == '__main__':
153
+
154
+
155
+ def test_pipe():
156
+ pipe1 = pipe()
157
+
158
+ pipe1.head_up = 10.
159
+ pipe1.head_down = 0.
160
+ pipe1.length = 100.
161
+ pipe1.diameter = 0.5
162
+
163
+ pipe1.k = 0.0001
164
+ pipe1.flowrate = 1.
165
+
166
+ print(pipe1.reynolds)
167
+
168
+ print(pipe1.head_loss)
169
+
170
+ assert abs(pipe1.head_loss - 3.737978364) < 1e-6
171
+
172
+ print(pipe1.solve_flowrate())
173
+ assert abs(pipe1.flowrate - 1.644579263) < 1e-6
174
+
175
+ pipe1.flowrate = 1.
176
+ pipe1.head_up = 10.
177
+ print(pipe1.solve_head_down())
178
+
179
+ assert abs(pipe1.head_down - 6.262021636) < 1e-6
180
+
181
+ pipe1.flowrate = 1.
182
+ pipe1.head_down = 0.
183
+ print(pipe1.solve_head_up())
184
+
185
+ assert abs(pipe1.head_up - 3.737978364) < 1e-6
186
+
187
+ pipe1.flowrate = 1.
188
+ pipe1.head_up = 10.
189
+ pipe1.head_down = 0.
190
+ print(pipe1.solve_k())
191
+
192
+ assert abs(pipe1.k - 4.95827141E-03) < 1e-9
193
+
194
+ pass
@@ -93,7 +93,7 @@ def circle_velocity_field(size:int=201, oxoy:tuple[float]=(0.,0.), dxdy:tuple[fl
93
93
 
94
94
  return ps, t_total
95
95
 
96
- def labyrinth(filename:str=r'doc\examples\labyrinth\lab_uv.npz', nb_particles:int=100, every:float=100.) -> tuple[Particle_system, float]:
96
+ def labyrinth(filename:str=r'docs\source\_static\examples\labyrinth\lab_uv.npz', nb_particles:int=100, every:float=100.) -> tuple[Particle_system, float]:
97
97
  """
98
98
  Load a labyrinth velocity field from file.
99
99
 
@@ -7,7 +7,7 @@ from typing import Union,Literal
7
7
  from os.path import exists
8
8
  from pathlib import Path
9
9
 
10
- from .cst_2D_boundary_conditions import BCType_2D_OO, BCType_2D, ColorsNb, choose_bc_type
10
+ from .cst_2D_boundary_conditions import BCType_2D_OO, BCType_2D, ColorsNb, choose_bc_type, Direction
11
11
  from ..PyTranslate import _
12
12
  from ..wolf_array import WolfArray
13
13
  from .wolf2dprev import prev_boundary_conditions, boundary_condition_2D, prev_parameters_simul
@@ -37,8 +37,11 @@ class BcManager(wx.Frame):
37
37
  DestroyAtClosing=False,
38
38
  Callback=None,
39
39
  mapviewer=None,
40
+ wolfparent=None,
40
41
  *args, **kwargs):
41
42
 
43
+ self.wolfparent = wolfparent
44
+
42
45
  self._filename_cl = ''
43
46
  self._filename_sux = ''
44
47
  self.dx = dx
@@ -95,6 +98,12 @@ class BcManager(wx.Frame):
95
98
  self.Show(True)
96
99
  self._plot_init()
97
100
 
101
+ if wolfparent is not None:
102
+ self.FindBorders()
103
+ self.parse(wolfparent.sim.bc2txt())
104
+ self.update_colors()
105
+
106
+
98
107
  @property
99
108
  def linked_array(self):
100
109
  return self._linked_array
@@ -276,6 +285,7 @@ class BcManager(wx.Frame):
276
285
 
277
286
  def OnClose(self, event:wx.MouseEvent):
278
287
  """ Close the window """
288
+
279
289
  if self._DestroyAtClosing:
280
290
  self._Callback(self)
281
291
  self.Destroy()
@@ -526,10 +536,10 @@ class BcManager(wx.Frame):
526
536
  self._checkBC[tbc].Value=True
527
537
  txt=''
528
538
  if values[tbc]['same']:
529
- for curval in values[tbc]['val']:
539
+ for curval in values[tbc]['val'].values():
530
540
  txt += str(curval)
531
541
  else:
532
- for curval in values[tbc]['val']:
542
+ for curval in values[tbc]['val'].values():
533
543
  txt += str(curval) +' or '
534
544
  txt+='...'
535
545
  self._valueBC[tbc].Value=txt
@@ -546,6 +556,7 @@ class BcManager(wx.Frame):
546
556
  self.bordersY['selected'][:]=False
547
557
  self.update_colors()
548
558
 
559
+
549
560
  def OnClearselection(self,event:wx.MouseEvent):
550
561
  """ Clear selection """
551
562
  self.Clearselection()
@@ -724,10 +735,45 @@ class BcManager(wx.Frame):
724
735
  text+= "simul.add_boundary_condition(i={}, j={},bc_type=BoundaryConditionsTypes.{}, bc_value={}, border=Direction.{})\n".format(i,j,namebc,val,direction)
725
736
  return text
726
737
 
738
+ def send_to_wolfparent(self):
739
+ """
740
+ Send BC to parent
741
+ """
742
+ from ..PyGui import Wolf2DModel
743
+
744
+ if self.wolfparent is not None:
745
+
746
+ if isinstance(self.wolfparent, Wolf2DModel):
747
+
748
+ self.wolfparent.reset_boundary_conditions()
749
+
750
+ for orient in range(1,3):
751
+ if orient==1:
752
+ curlist=self.bordersX['bc']
753
+ direction=Direction.LEFT
754
+ else:
755
+ curlist=self.bordersY['bc']
756
+ direction=Direction.BOTTOM
757
+
758
+ curlist:dict
759
+ ij:str
760
+ allbc:dict
761
+
762
+ for ij, allbc in curlist.items():
763
+ for tbc, val in allbc.items():
764
+ i,j=ij.split('-')
765
+ namebc=self._find_Enum_TypeBC(tbc)
766
+
767
+ if(str(val)!='99999.0'):
768
+ self.wolfparent.add_boundary_condition(int(i), int(j), namebc, float(val), direction)
769
+
770
+ self.wolfparent._show_glob_properties()
771
+
727
772
  def parse(self, text:str):
728
773
  """
729
774
  Parse text and fill bordersX and bordersY
730
775
  """
776
+
731
777
  self._filecontent = text
732
778
 
733
779
  text=text.splitlines()
@@ -755,7 +801,7 @@ class BcManager(wx.Frame):
755
801
  orient=int(float(orient))
756
802
  value=float(value)
757
803
  if orient==1:
758
- texttxt=str(i-1)+'-'+str(j-1)
804
+ texttxt=str(i)+'-'+str(j)
759
805
  try:
760
806
  index=self.bordersX['indicesstr'].index(texttxt)
761
807
  try:
@@ -773,7 +819,7 @@ class BcManager(wx.Frame):
773
819
  except:
774
820
  logging.info('Bad border indices on X ('+str(i)+'-'+str(j)+(')'))
775
821
  elif orient==2:
776
- texttxt=str(i-1)+'-'+str(j-1)
822
+ texttxt=str(i)+'-'+str(j)
777
823
  try:
778
824
  index=self.bordersY['indicesstr'].index(texttxt)
779
825
  try:
@@ -798,6 +844,8 @@ class BcManager(wx.Frame):
798
844
  """ Apply <<< button"""
799
845
  self.parse(self.File.Value)
800
846
 
847
+ self.send_to_wolfparent()
848
+
801
849
  def OnCopyToClipboard(self,event:wx.MouseEvent):
802
850
  """ Copy to clipboard"""
803
851
  if self.wx_exists:
@@ -996,6 +1044,9 @@ class BcManager(wx.Frame):
996
1044
  self._color_bc()
997
1045
  self._update_buffer()
998
1046
 
1047
+ if self.mapviewer is not None:
1048
+ self.mapviewer.Refresh()
1049
+
999
1050
  def _color_bc(self):
1000
1051
  """ Color borders according to number of BC """
1001
1052
  nbmax_colors = len(ColorsNb)
@@ -1043,6 +1094,8 @@ class BcManager(wx.Frame):
1043
1094
 
1044
1095
  def _plot_init(self):
1045
1096
  """ Initialize OpenGL - Program shader"""
1097
+ pass
1098
+
1046
1099
  vertex_shader = glCreateShader(GL_VERTEX_SHADER)
1047
1100
  # glShaderSource(vertex_shader, vertex_shader_source)
1048
1101
 
@@ -1089,6 +1142,7 @@ class BcManager(wx.Frame):
1089
1142
 
1090
1143
  def _update_buffer(self):
1091
1144
  """ Update OpenGL buffer """
1145
+ pass
1092
1146
 
1093
1147
  self.buf_vertices = self._get_coords()
1094
1148
 
@@ -1311,6 +1365,13 @@ class BcManager(wx.Frame):
1311
1365
  if name_bc==name:
1312
1366
  return curbc.name
1313
1367
 
1368
+ def _find_Enum_TypeBC(self,name:str):
1369
+ """Convert nameBC to intBC"""
1370
+ for curbc in self.bc_type:
1371
+ val_bc, name_bc = curbc.value
1372
+ if name_bc==name:
1373
+ return curbc
1374
+
1314
1375
  def get_lists_for_GPU(self) -> tuple[list[boundary_condition_2D], list[boundary_condition_2D]]:
1315
1376
  """
1316
1377
  Return list of BC for GPU computing
@@ -317,7 +317,7 @@ class config_manager_2D:
317
317
  mydata:prev_infiltration
318
318
  txt = _('Number of zones : {} \n'.format(mydata.nb_zones))
319
319
  for i in range(1,mydata.nb_zones+1):
320
- txt += _('Q zone {} : {} \n'.format(i,mydata.my_Q[0][i]))
320
+ txt += _('Q zone {} : {} \n'.format(i,mydata._infiltrations_chronology[0][i]))
321
321
 
322
322
  self.txtctrl.Clear()
323
323
  self.txtctrl.WriteText(txt)
@@ -1,5 +1,6 @@
1
1
  from enum import Enum
2
- from typing import Union
2
+ from typing import Union, Literal
3
+ import logging
3
4
 
4
5
  if not '_' in __builtins__:
5
6
  import gettext
@@ -16,6 +17,8 @@ class Direction(Enum):
16
17
  Y = 2
17
18
 
18
19
  class BCType_2D_GPU(Enum):
20
+ """ Boundary conditions for 2D simulations with wolfgpu """
21
+
19
22
  # The numbers match the numbers in Wolf's simulations parameters.
20
23
  # H = (1,_('Water level [m]'))
21
24
  QX = (2,_('Flow rate along X [m²/s]'))
@@ -25,7 +28,10 @@ class BCType_2D_GPU(Enum):
25
28
  FROUDE_NORMAL = (8,_('Froude normal to the border [-]'))
26
29
 
27
30
  class BCType_2D(Enum):
31
+ """ Boundary conditions for 2D simulations """
32
+
28
33
  # The numbers match the numbers in Wolf's 2D simulations parameters.
34
+ # The values can not be changed freely by the Python user/developer
29
35
  H = (1,_('Water level [m]'))
30
36
  QX = (2,_('Flow rate along X [m²/s]'))
31
37
  QY = (3,_('Flow rate along Y [m²/s]'))
@@ -44,6 +50,10 @@ class BCType_2D(Enum):
44
50
  FROUDE_ABSOLUTE = (16,_('norm of Froude in the cell [-]'))
45
51
 
46
52
  class BCType_2D_OO(Enum):
53
+ """ Boundary conditions for 2D simulations with Object-Oriented approach """
54
+
55
+ # The numbers match the numbers in Wolf's 2D simulations parameters.
56
+ # The values can not be changed freely by the Python user/developer
47
57
  WATER_DEPTH = (1, _('Water depth [m]'))
48
58
  WATER_LEVEL = (2, _('Water level [m]'))
49
59
  FROUDE_NORMAL = (4, _('Froude normal to the border [-]'))
@@ -57,7 +67,54 @@ class BCType_2D_OO(Enum):
57
67
  CLOSE_CONDUIT_QTANGET = (62, _('Close conduit - tangent discharge [m²/s]'))
58
68
  CLOSE_CONDUIT_H_FOR_SPEED = (63, _('Close conduit - h for speed [m]'))
59
69
 
60
- def choose_bc_type(version:Union[int,str] = 1):
70
+
71
+ def BCType_2D_To_BCType_2D_GPU(bc_type:BCType_2D) -> BCType_2D_GPU:
72
+
73
+ if bc_type in [BCType_2D.H, BCType_2D.H.value[0], BCType_2D.HMOD, BCType_2D.HMOD.value[0]]:
74
+ return BCType_2D_GPU.HMOD
75
+ elif bc_type in [BCType_2D.QX, BCType_2D.QX.value[0]]:
76
+ return BCType_2D_GPU.QX
77
+ elif bc_type in [BCType_2D.QY, BCType_2D.QY.value[0]]:
78
+ return BCType_2D_GPU.QY
79
+ elif bc_type in [BCType_2D.NONE, BCType_2D.NONE.value[0]]:
80
+ return BCType_2D_GPU.NONE
81
+ elif bc_type in [BCType_2D.FROUDE_NORMAL, BCType_2D.FROUDE_NORMAL.value[0]]:
82
+ return BCType_2D_GPU.FROUDE_NORMAL
83
+ else:
84
+ logging.error(f"BCType_2D_To_BCType_2D_GPU: {bc_type} not found")
85
+ return None
86
+
87
+
88
+ def revert_bc_type(bc_type:Union[BCType_2D,BCType_2D_OO,BCType_2D_GPU], val:int):
89
+ """
90
+ Return the BCType corresponding to the given value
91
+
92
+ Useful for GUI or scripts
93
+ """
94
+
95
+ if bc_type == BCType_2D:
96
+ for bc in BCType_2D:
97
+ if bc.value[0] == val:
98
+ return bc
99
+ elif bc_type == BCType_2D_OO:
100
+ for bc in BCType_2D_OO:
101
+ if bc.value[0] == val:
102
+ return bc
103
+ elif bc_type == BCType_2D_GPU:
104
+ for bc in BCType_2D_GPU:
105
+ if bc.value[0] == val:
106
+ return bc
107
+
108
+ return None
109
+
110
+
111
+ def choose_bc_type(version:Literal[1,2,3, 'prev', 'oo', 'gpu'] = 1):
112
+ """
113
+ Choose the version of the boundary conditions to use
114
+
115
+ Useful for GUI
116
+ """
117
+
61
118
  if version==1 or version =='prev':
62
119
  return BCType_2D
63
120
  elif version==2 or version =='oo':