wolfhece 2.0.54__py3-none-any.whl → 2.1.0__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/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,
@@ -911,11 +911,14 @@ class vector:
911
911
 
912
912
  def __init__(self, lines:list=[], is2D=True, name='NoName', parentzone:"zone"=None, fromshapely=None) -> None:
913
913
  """
914
- lines : utile pour lecture de fichier
915
- is2D : on interprète les 'vertices' comme 2D même si chaque 'wolfvertex' contient toujours x, y et z
916
- name : nom du vecteur
917
- parentzone : instance de type 'zone' qui contient le 'vector'
914
+
915
+ :param lines: utile pour lecture de fichier
916
+ :param is2D: on interprète les 'vertices' comme 2D même si chaque 'wolfvertex' contient toujours x, y et z
917
+ :param name: nom du vecteur
918
+ :param parentzone: instance de type 'zone' qui contient le 'vector'
919
+
918
920
  """
921
+
919
922
  self.myname=''
920
923
  self.is2D = is2D
921
924
  self.closed=False
@@ -1367,12 +1370,12 @@ class vector:
1367
1370
  # again checks that the vector is not closed; in the case where
1368
1371
  # two vertices are not the same one but have the same coordinates)
1369
1372
 
1370
- is_open = self.myvertices[-1] is not self.myvertices[0] or \
1371
- (self.myvertices[-1].x!=self.myvertices[0].x or \
1372
- self.myvertices[-1].y!=self.myvertices[0].y)
1373
+ is_open = not((self.myvertices[-1] is self.myvertices[0]) or \
1374
+ (self.myvertices[-1].x==self.myvertices[0].x and \
1375
+ self.myvertices[-1].y==self.myvertices[0].y))
1373
1376
 
1374
1377
  if not self.is2D :
1375
- is_open = is_open and self.myvertices[-1].z!=self.myvertices[0].z
1378
+ is_open = is_open or self.myvertices[-1].z!=self.myvertices[0].z
1376
1379
 
1377
1380
  if is_open:
1378
1381
  self.add_vertex(self.myvertices[0])
@@ -1800,10 +1803,10 @@ class vector:
1800
1803
 
1801
1804
  if length<1:
1802
1805
  length*=1000.
1803
- alls = np.linspace(0,int(length),nb)
1806
+ alls = np.linspace(0, length, nb)
1804
1807
  alls/=1000.
1805
1808
  else:
1806
- alls = np.linspace(0,int(length),nb,endpoint=True)
1809
+ alls = np.linspace(0, length, nb, endpoint=True)
1807
1810
 
1808
1811
  pts = [myls.interpolate(curs) for curs in alls]
1809
1812
  # pts = [(curpt.x, curpt.y) for curpt in pts]
@@ -2147,16 +2150,28 @@ class vector:
2147
2150
 
2148
2151
  if name is None:
2149
2152
  name = self.myname + "_copy"
2150
- if parentzone:
2151
- copied_vector = vector(name=name,parentzone=parentzone)
2152
- else:
2153
- copied_vector = vector(name=name)
2154
2153
 
2155
- copied_vector.myvertices = copy.deepcopy(self.myvertices)
2156
- # copied_vector.nbvertices = copy.deepcopy(self.nbvertices)
2154
+ if parentzone:
2155
+ copied_vector = vector(name=name,parentzone=parentzone)
2156
+ else:
2157
+ copied_vector = vector(name=name)
2158
+
2159
+ copied_vector.myvertices = copy.deepcopy(self.myvertices)
2160
+
2161
+ return copied_vector
2162
+
2163
+ def set_legend_to_centroid(self, text:str='', visible:bool=True):
2164
+ """
2165
+ Positionne la légende au centre du vecteur
2166
+ """
2167
+ self.myprop.legendvisible = visible
2157
2168
 
2158
- return copied_vector
2169
+ ls = self.asshapely_pol()
2170
+ centroid = ls.centroid
2159
2171
 
2172
+ self.myprop.legendx = centroid.x
2173
+ self.myprop.legendy = centroid.y
2174
+ self.myprop.legendtext = text if text else self.myname
2160
2175
 
2161
2176
  class zone:
2162
2177
  """
@@ -3657,6 +3672,14 @@ class zone:
3657
3672
  if self.parent.mapviewer is not None:
3658
3673
  self.prep_listogl()
3659
3674
  self.parent.mapviewer.Refresh()
3675
+
3676
+ def set_legend_to_centroid(self):
3677
+ """
3678
+ Set the legend to the centroid of the zone
3679
+ """
3680
+ for curvec in self.myvectors:
3681
+ curvec.set_legend_to_centroid()
3682
+
3660
3683
  class Zones(wx.Frame, Element_To_Draw):
3661
3684
  """
3662
3685
  Objet de gestion d'informations vectorielles
@@ -5661,7 +5684,11 @@ class Zones(wx.Frame, Element_To_Draw):
5661
5684
  elif object.nbvectors>0:
5662
5685
  self.Activate_vector(object.myvectors[0])
5663
5686
 
5664
- self.labelactvect.SetLabel(self.active_vector.myname)
5687
+ if self.active_vector is None:
5688
+ logging.warning(_('No vector in the active zone'))
5689
+ else:
5690
+ self.labelactvect.SetLabel(self.active_vector.myname)
5691
+
5665
5692
  self.labelactzone.SetLabel(self.active_zone.myname)
5666
5693
  self.Layout()
5667
5694
 
wolfhece/Results2DGPU.py CHANGED
@@ -500,8 +500,7 @@ class Sim_2D_GPU():
500
500
  self.loaded = False
501
501
 
502
502
  if self.filename.exists():
503
- self.sim = SimpleSimulation()
504
- self.sim.load(self.filename)
503
+ self.sim = SimpleSimulation.load(self.filename)
505
504
  self.loaded = True
506
505
 
507
506
  pass
wolfhece/apps/version.py CHANGED
@@ -4,8 +4,8 @@ class WolfVersion():
4
4
  def __init__(self):
5
5
 
6
6
  self.major = 2
7
- self.minor = 0
8
- self.patch = 54
7
+ self.minor = 1
8
+ self.patch = 0
9
9
 
10
10
  def __str__(self):
11
11
 
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,10 @@
1
+ from enum import Enum
2
+
3
+ class Water():
4
+
5
+ rho:float = 1000.
6
+ mu:float = 1e-3
7
+
8
+ @property
9
+ def nu(self) -> float:
10
+ return self.mu / self.rho
@@ -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
@@ -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