wolfhece 2.2.14__py3-none-any.whl → 2.2.16__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,685 @@
1
+ from matplotlib import pyplot as plt
2
+ from matplotlib.axes import Axes
3
+ from matplotlib.figure import Figure
4
+ import numpy as np
5
+
6
+ from ..wolf_array import header_wolf
7
+ from ..wolfresults_2D import q_splitting, u_splitting, splitting_rule
8
+
9
+ class Mesh2D(header_wolf):
10
+
11
+ def __init__(self, src_header:header_wolf):
12
+
13
+ self.set_origin(src_header.origx, src_header.origy)
14
+ self.set_resolution(src_header.dx, src_header.dy)
15
+ self.set_translation(src_header.translx, src_header.transly)
16
+ self.shape = src_header.shape
17
+ self._factor = None
18
+
19
+ def plot_cells(self, ax:Axes=None, color='black', **kwargs):
20
+ """ Plot the grid of the mesh.
21
+ """
22
+
23
+ if ax is None:
24
+ fig, ax = plt.subplots()
25
+ else:
26
+ fig = ax.figure
27
+
28
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
29
+
30
+ for y in np.linspace(ymin, ymax, endpoint=True, num=self.nby + 1):
31
+ ax.plot([xmin, xmax], [y, y], color=color, **kwargs)
32
+
33
+ for x in np.linspace(xmin, xmax, endpoint=True, num=self.nbx + 1):
34
+ ax.plot([x, x], [ymin, ymax], color=color, **kwargs)
35
+
36
+ self.set_aspect_labels(ax=ax, **kwargs)
37
+ return fig, ax
38
+
39
+ def plot_center_cells(self, ax:Axes=None, color='black', linestyle='--', **kwargs):
40
+ """ Plot lines centered to the cells.
41
+ """
42
+
43
+ if ax is None:
44
+ fig, ax = plt.subplots()
45
+ else:
46
+ fig = ax.figure
47
+
48
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
49
+
50
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
51
+ ax.plot([xmin, xmax], [y, y], color=color, linestyle=linestyle, **kwargs)
52
+
53
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
54
+ ax.plot([x, x], [ymin, ymax], color=color, linestyle=linestyle, **kwargs)
55
+
56
+ self.set_aspect_labels(ax=ax, **kwargs)
57
+ return fig, ax
58
+
59
+ def set_ticks_as_dxdy(self, ax:Axes=None, **kwargs):
60
+ """ Set the ticks of the axis as the dx and dy of the mesh.
61
+ """
62
+
63
+ if ax is None:
64
+ fig, ax = plt.subplots()
65
+ else:
66
+ fig = ax.figure
67
+
68
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
69
+
70
+ x_ticks = ['ox + tx', r'+$\Delta x$'] + [f'+{i}$\Delta x$' for i in range(2,self.nbx+1)]
71
+ y_ticks = ['oy + ty', r'+$\Delta y$'] + [f'{+i}$\Delta y$' for i in range(2,self.nby+1)]
72
+
73
+ ax.set_xticks(np.linspace(xmin, xmax, endpoint=True, num=self.nbx + 1))
74
+ ax.set_yticks(np.linspace(ymin, ymax, endpoint=True, num=self.nby + 1))
75
+ ax.set_xticklabels(x_ticks)
76
+ ax.set_yticklabels(y_ticks)
77
+
78
+ return fig, ax
79
+
80
+ def plot_circle_at_centers(self, ax:Axes=None, color='black', radius:float=None, **kwargs):
81
+ """ Plot circles at the center of the cells.
82
+ """
83
+
84
+ if radius is None:
85
+ radius = 0.1 * self.dx
86
+
87
+ if ax is None:
88
+ fig, ax = plt.subplots()
89
+ else:
90
+ fig = ax.figure
91
+
92
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
93
+
94
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
95
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
96
+ circle = plt.Circle((x, y), radius=radius, color=color, **kwargs)
97
+ ax.add_artist(circle)
98
+
99
+ self.set_aspect_labels(ax=ax, **kwargs)
100
+
101
+ return fig, ax
102
+
103
+ def plot_indices_at_centers(self, ax:Axes=None, Fortran_type:bool = True, **kwargs):
104
+ """ Plot the indices of the cells at the center of the cells.
105
+ """
106
+
107
+ if ax is None:
108
+ fig, ax = plt.subplots()
109
+ else:
110
+ fig = ax.figure
111
+
112
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
113
+
114
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
115
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
116
+ i,j = self.xy2ij(x, y)
117
+
118
+ if Fortran_type:
119
+ i+=1
120
+ j+=1
121
+
122
+ ax.text(x, y, f'({i},{j})', horizontalalignment='center', verticalalignment='center', **kwargs)
123
+
124
+ self.set_aspect_labels(ax=ax, **kwargs)
125
+
126
+ return fig, ax
127
+
128
+ def plot_indices_at_bordersX(self, ax:Axes=None, Fortran_type:bool = True, **kwargs):
129
+ """ Plot the indices of the cells at the borders of the cells.
130
+ """
131
+
132
+ if ax is None:
133
+ fig, ax = plt.subplots()
134
+ else:
135
+ fig = ax.figure
136
+
137
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
138
+
139
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
140
+ for x in np.linspace(xmin, xmax, endpoint=True, num=self.nbx + 1):
141
+ i,j = self.xy2ij(x, y)
142
+
143
+ if Fortran_type:
144
+ i+=1
145
+ j+=1
146
+
147
+ ax.text(x, y, f'({i},{j})', horizontalalignment='center', verticalalignment='center', **kwargs)
148
+
149
+ def plot_indices_at_bordersY(self, ax:Axes=None, Fortran_type:bool = True, **kwargs):
150
+ """ Plot the indices of the cells at the borders of the cells.
151
+ """
152
+
153
+ if ax is None:
154
+ fig, ax = plt.subplots()
155
+ else:
156
+ fig = ax.figure
157
+
158
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
159
+
160
+ for y in np.linspace(ymin, ymax, endpoint=True, num=self.nby + 1):
161
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
162
+ i,j = self.xy2ij(x, y)
163
+
164
+ if Fortran_type:
165
+ i+=1
166
+ j+=1
167
+
168
+ ax.text(x, y, f'({i},{j})', horizontalalignment='center', verticalalignment='center', **kwargs)
169
+
170
+ self.set_aspect_labels(ax=ax, **kwargs)
171
+
172
+ return fig, ax
173
+
174
+ def plot_Xarrows_at_center(self, ax:Axes=None,
175
+ randomize:bool=False,
176
+ amplitude:np.ndarray=None,
177
+ color='black', **kwargs):
178
+ """ Plot arrows at the center of the cells.
179
+ """
180
+
181
+ if ax is None:
182
+ fig, ax = plt.subplots()
183
+ else:
184
+ fig = ax.figure
185
+
186
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
187
+
188
+ if amplitude is None:
189
+ amplitude = np.ones((self.nbx, self.nby)) * 0.2 * self.dx
190
+ else:
191
+ amplitude = self.scale_amplitude(amplitude)
192
+
193
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
194
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
195
+
196
+ i,j = self.xy2ij(x, y)
197
+ if randomize:
198
+ dx = np.random.uniform(-0.5, 0.5) * self.dx
199
+ amplitude[i,j] = dx
200
+ else:
201
+ dx = amplitude[i,j]
202
+
203
+ ax.arrow(x - dx/2., y, dx, 0,
204
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
205
+ fc=color, ec=color)
206
+
207
+ self.set_aspect_labels(ax=ax, **kwargs)
208
+
209
+ return fig, ax, amplitude
210
+
211
+ def plot_Yarrows_at_center(self, ax:Axes=None,
212
+ randomize:bool=False,
213
+ amplitude:np.ndarray=None,
214
+ color='black', **kwargs):
215
+ """ Plot arrows at the center of the cells.
216
+ """
217
+
218
+ if ax is None:
219
+ fig, ax = plt.subplots()
220
+ else:
221
+ fig = ax.figure
222
+
223
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
224
+
225
+ if amplitude is None:
226
+ amplitude = np.ones((self.nbx, self.nby)) * 0.2 * self.dy
227
+ else:
228
+ amplitude = self.scale_amplitude(amplitude)
229
+
230
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
231
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
232
+
233
+ i,j = self.xy2ij(x, y)
234
+ if randomize:
235
+ dy = np.random.uniform(-0.5, 0.5) * self.dy
236
+ amplitude[i,j] = dy
237
+ else:
238
+ dy = amplitude[i,j]
239
+
240
+ ax.arrow(x, y - dy/2., 0, dy,
241
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
242
+ fc=color, ec=color)
243
+
244
+ self.set_aspect_labels(ax=ax, **kwargs)
245
+
246
+ return fig, ax, amplitude
247
+
248
+ def plot_Xarrows_at_borders(self, ax:Axes=None,
249
+ randomize:bool=False,
250
+ amplitudeX:np.ndarray=None,
251
+ amplitudeY:np.ndarray=None,
252
+ color='black', **kwargs):
253
+ """ Plot arrows at the borders of the cells.
254
+ """
255
+
256
+ if ax is None:
257
+ fig, ax = plt.subplots()
258
+ else:
259
+ fig = ax.figure
260
+
261
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
262
+
263
+ if amplitudeX is None:
264
+ amplitudeX = np.ones((self.nbx+1, self.nby)) * 0.2 * self.dx
265
+ else:
266
+ if self._factor is not None:
267
+ amplitudeX *= self._factor
268
+
269
+ if amplitudeY is None:
270
+ amplitudeY = np.ones((self.nbx, self.nby+1)) * 0.2 * self.dy
271
+ else:
272
+ if self._factor is not None:
273
+ amplitudeY *= self._factor
274
+
275
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
276
+ for x in np.linspace(xmin, xmax, endpoint=True, num=self.nbx + 1):
277
+
278
+ i,j = self.xy2ij(x, y)
279
+ if randomize:
280
+ dx = np.random.uniform(-0.5, 0.5) * self.dx
281
+ amplitudeX[i,j] = dx
282
+ else:
283
+ dx = amplitudeX[i,j]
284
+
285
+ if dx != 0.:
286
+ ax.arrow(x - dx/2., y, dx, 0,
287
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
288
+ fc=color, ec=color)
289
+
290
+ for y in np.linspace(ymin, ymax, endpoint=True, num=self.nby+1):
291
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
292
+
293
+ i,j = self.xy2ij(x, y)
294
+ if randomize:
295
+ dx = np.random.uniform(-0.5, 0.5) * self.dy
296
+ amplitudeY[i,j] = dx
297
+ else:
298
+ dx = amplitudeY[i,j]
299
+
300
+ if dx != 0.:
301
+ ax.arrow(x - dx, y, dx, 0,
302
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
303
+ fc=color, ec=color)
304
+
305
+ self.set_aspect_labels(ax=ax, **kwargs)
306
+
307
+ return fig, ax, amplitudeX, amplitudeY
308
+
309
+ def plot_Yarrows_at_borders(self, ax:Axes=None,
310
+ randomize:bool=False,
311
+ amplitudeX:np.ndarray=None,
312
+ amplitudeY:np.ndarray=None,
313
+ color='black', **kwargs):
314
+ """ Plot arrows at the borders of the cells.
315
+ """
316
+
317
+ if ax is None:
318
+ fig, ax = plt.subplots()
319
+ else:
320
+ fig = ax.figure
321
+
322
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
323
+
324
+ if amplitudeX is None:
325
+ amplitudeX = np.ones((self.nbx+1, self.nby)) * 0.2 * self.dx
326
+ else:
327
+ if self._factor is not None:
328
+ amplitudeX *= self._factor
329
+
330
+ if amplitudeY is None:
331
+ amplitudeY = np.ones((self.nbx, self.nby+1)) * 0.2 * self.dy
332
+ else:
333
+ if self._factor is not None:
334
+ amplitudeY *= self._factor
335
+
336
+ for y in np.linspace(ymin, ymax, endpoint=True, num=self.nby + 1):
337
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
338
+
339
+ i,j = self.xy2ij(x, y)
340
+ if randomize:
341
+ dy = np.random.uniform(-0.5, 0.5) * self.dy
342
+ amplitudeY[i,j] = dy
343
+ else:
344
+ dy = amplitudeY[i,j]
345
+
346
+ if dy != 0.:
347
+ ax.arrow(x, y - dy/2., 0, dy,
348
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
349
+ fc=color, ec=color)
350
+
351
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
352
+ for x in np.linspace(xmin, xmax, endpoint=True, num=self.nbx + 1):
353
+
354
+ i,j = self.xy2ij(x, y)
355
+ if randomize:
356
+ dy = np.random.uniform(-0.5, 0.5) * self.dx
357
+ amplitudeX[i,j] = dy
358
+ else:
359
+ dy = amplitudeX[i,j]
360
+
361
+ if dy != 0.:
362
+ ax.arrow(x, y - dy/2., 0., dy,
363
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
364
+ fc=color, ec=color)
365
+
366
+ self.set_aspect_labels(ax=ax, **kwargs)
367
+
368
+ return fig, ax, amplitudeX, amplitudeY
369
+
370
+ def plot_normal_arrows_at_borders(self, ax:Axes=None, color='black', **kwargs):
371
+ """ Plot arrows at the borders of the cells.
372
+ """
373
+
374
+ if ax is None:
375
+ fig, ax = plt.subplots()
376
+ else:
377
+ fig = ax.figure
378
+
379
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
380
+
381
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
382
+ for x in np.linspace(xmin, xmax, endpoint=True, num=self.nbx+1):
383
+ ax.arrow(x - 0.1 * self.dx, y, 0.2 * self.dx, 0,
384
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
385
+ fc=color, ec=color)
386
+
387
+ for y in np.linspace(ymin, ymax, endpoint=True, num=self.nby+1):
388
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
389
+ ax.arrow(x, y - 0.1 * self.dy, 0., 0.2 * self.dy,
390
+ head_width=0.1 * self.dx, head_length=0.1 * self.dy,
391
+ fc=color, ec=color)
392
+
393
+ self.set_aspect_labels(ax=ax, **kwargs)
394
+
395
+ return fig, ax
396
+
397
+ def scale_axes(self, ax:Axes=None, factor:float = 0.1, **kwargs):
398
+ """ Scale the axes of the plot to fit the data.
399
+ """
400
+ # augmenter légèrement la taille visible sans
401
+ # ajouter de ticks
402
+ ticksX = ax.get_xticks()
403
+ ticksY = ax.get_yticks()
404
+ ticklabelsX = ax.get_xticklabels()
405
+ ticklabelsY = ax.get_yticklabels()
406
+
407
+ deltaX = ticksX[-1] - ticksX[0]
408
+ deltaY = ticksY[-1] - ticksY[0]
409
+ ax.set_xlim(ticksX[0] - factor * deltaX, ticksX[-1] + factor * deltaX)
410
+ ax.set_ylim(ticksY[0] - factor * deltaY, ticksY[-1] + factor * deltaY)
411
+
412
+ ax.set_xticks(ticksX)
413
+ ax.set_yticks(ticksY)
414
+ ax.set_xticklabels(ticklabelsX) #, rotation=45)
415
+ ax.set_yticklabels(ticklabelsY) #, rotation=45)
416
+
417
+ # remove up border and right border
418
+ ax.spines['top'].set_visible(False)
419
+ ax.spines['right'].set_visible(False)
420
+
421
+ return ax.figure, ax
422
+
423
+ def plot_reconstructed_values_at_borders(self, ax:Axes=None,
424
+ colors=['green', 'blue', 'red', 'brown'],
425
+ radius:float = None, **kwargs):
426
+ """ Plot 4 small circles on each side of the border.
427
+ """
428
+
429
+ if radius is None:
430
+ radius = 0.02 * self.dx
431
+
432
+ if ax is None:
433
+ fig, ax = plt.subplots()
434
+ else:
435
+ fig = ax.figure
436
+
437
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
438
+
439
+ deltay = self.dy / 6.
440
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
441
+ x = xmin
442
+ for i in range(4):
443
+ ax.add_artist(plt.Circle((x+.1*self.dx, y - 1.5*deltay + i*deltay),
444
+ radius=radius, color=colors[-i-1], **kwargs))
445
+ x = xmax
446
+ for i in range(4):
447
+ ax.add_artist(plt.Circle((x-.1*self.dx, y - 1.5*deltay + i*deltay),
448
+ radius=radius, color=colors[-i-1], **kwargs))
449
+
450
+ for x in np.linspace(xmin + self.dx, xmax - self.dx, endpoint=True, num=self.nbx-1):
451
+ for i in range(4):
452
+ ax.add_artist(plt.Circle((x+.1*self.dx, y - 1.5*deltay + i*deltay),
453
+ radius=radius, color=colors[-i-1], **kwargs))
454
+ ax.add_artist(plt.Circle((x-.1*self.dx, y - 1.5*deltay + i*deltay),
455
+ radius=radius, color=colors[-i-1], **kwargs))
456
+
457
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
458
+ y = ymin
459
+ for i in range(4):
460
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i*deltay, y+.1*self.dy),
461
+ radius=radius, color=colors[i], **kwargs))
462
+ y = ymax
463
+ for i in range(4):
464
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i*deltay, y-.1*self.dy),
465
+ radius=radius, color=colors[i], **kwargs))
466
+
467
+ for y in np.linspace(ymin + self.dy, ymax - self.dy, endpoint=True, num=self.nby-1):
468
+ for i in range(4):
469
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i*deltay, y+.1*self.dy),
470
+ radius=radius, color=colors[i], **kwargs))
471
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i*deltay, y-.1*self.dy),
472
+ radius=radius, color=colors[i], **kwargs))
473
+
474
+ self.set_aspect_labels(ax=ax, **kwargs)
475
+
476
+ def plot_splitted_values_at_borders(self, ax:Axes=None,
477
+ qx:np.ndarray=None,
478
+ qy:np.ndarray=None,
479
+ colors=['green', 'blue', 'red', 'brown'],
480
+ radius:float = None, **kwargs):
481
+ """ Plot 4 small circles on each side of the border.
482
+ """
483
+
484
+ split_x = self.zeros_bordersX()
485
+ split_y = self.zeros_bordersY()
486
+
487
+ for i in range(1, self.nbx):
488
+ for j in range(self.nby):
489
+ split_x[i,j] = splitting_rule(qx[i-1,j], qx[i,j])
490
+ for i in range(self.nbx):
491
+ for j in range(1, self.nby):
492
+ split_y[i,j] = splitting_rule(qy[i,j-1], qy[i,j])
493
+
494
+ if radius is None:
495
+ radius = 0.02 * self.dx
496
+
497
+ if ax is None:
498
+ fig, ax = plt.subplots()
499
+ else:
500
+ fig = ax.figure
501
+
502
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
503
+
504
+ deltay = self.dy / 6.
505
+
506
+ # X borders
507
+ for y in np.linspace(ymin + self.dy/2., ymax - self.dy/2., endpoint=True, num=self.nby):
508
+ x = xmin
509
+ i,j = self.xy2ij(x, y)
510
+ for i_unk in range(4):
511
+ ax.add_artist(plt.Circle((x+.1*self.dx, y - 1.5*deltay + i_unk*deltay),
512
+ radius=radius, color=colors[-i_unk-1], **kwargs))
513
+ x = xmax
514
+ i,j = self.xy2ij(x, y)
515
+ for i_unk in range(4):
516
+ ax.add_artist(plt.Circle((x-.1*self.dx, y - 1.5*deltay + i_unk*deltay),
517
+ radius=radius, color=colors[-i_unk-1], **kwargs))
518
+
519
+ for x in np.linspace(xmin + self.dx, xmax - self.dx, endpoint=True, num=self.nbx-1):
520
+ i,j = self.xy2ij(x, y)
521
+
522
+ pond = split_x[i,j]
523
+ if pond == 0.5:
524
+ for i_unk in range(4):
525
+ ax.add_artist(plt.Circle((x+.1*self.dx, y - 1.5*deltay + i_unk*deltay),
526
+ radius=radius, color=colors[-i_unk-1], **kwargs))
527
+ ax.add_artist(plt.Circle((x-.1*self.dx, y - 1.5*deltay + i_unk*deltay),
528
+ radius=radius, color=colors[-i_unk-1], **kwargs))
529
+ elif pond == 1.0:
530
+ # left is upstream
531
+ for i_unk in [1,2]:
532
+ ax.add_artist(plt.Circle((x-.1*self.dx, y - 1.5*deltay + i_unk*deltay),
533
+ radius=radius, color=colors[-i_unk-1], **kwargs))
534
+ for i_unk in [0,3]:
535
+ ax.add_artist(plt.Circle((x+.1*self.dx, y - 1.5*deltay + i_unk*deltay),
536
+ radius=radius, color=colors[-i_unk-1], **kwargs))
537
+ elif pond == 0.0:
538
+ # right is upstream
539
+ for i_unk in [0,3]:
540
+ ax.add_artist(plt.Circle((x-.1*self.dx, y - 1.5*deltay + i_unk*deltay),
541
+ radius=radius, color=colors[-i_unk-1], **kwargs))
542
+ for i_unk in [1,2]:
543
+ ax.add_artist(plt.Circle((x+.1*self.dx, y - 1.5*deltay + i_unk*deltay),
544
+ radius=radius, color=colors[-i_unk-1], **kwargs))
545
+
546
+ # Y borders
547
+ for x in np.linspace(xmin + self.dx/2., xmax - self.dx/2., endpoint=True, num=self.nbx):
548
+ y = ymin
549
+ i,j = self.xy2ij(x, y)
550
+ for i_unk in range(4):
551
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y+.1*self.dy),
552
+ radius=radius, color=colors[i_unk], **kwargs))
553
+ y = ymax
554
+ i,j = self.xy2ij(x, y)
555
+ for i_unk in range(4):
556
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y-.1*self.dy),
557
+ radius=radius, color=colors[i_unk], **kwargs))
558
+
559
+ for y in np.linspace(ymin + self.dy, ymax - self.dy, endpoint=True, num=self.nby-1):
560
+ i,j = self.xy2ij(x, y)
561
+ pond = split_y[i,j]
562
+ if pond == 0.5:
563
+ for i_unk in range(4):
564
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y+.1*self.dy),
565
+ radius=radius, color=colors[i_unk], **kwargs))
566
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y-.1*self.dy),
567
+ radius=radius, color=colors[i_unk], **kwargs))
568
+ elif pond == 1.0:
569
+ for i_unk in [1,2]:
570
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y-.1*self.dy),
571
+ radius=radius, color=colors[i_unk], **kwargs))
572
+ for i_unk in [0,3]:
573
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y+.1*self.dy),
574
+ radius=radius, color=colors[i_unk], **kwargs))
575
+ elif pond == 0.0:
576
+ for i_unk in [0,3]:
577
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y-.1*self.dy),
578
+ radius=radius, color=colors[i_unk], **kwargs))
579
+ for i_unk in [1,2]:
580
+ ax.add_artist(plt.Circle((x - 1.5*deltay + i_unk*deltay, y+.1*self.dy),
581
+ radius=radius, color=colors[i_unk], **kwargs))
582
+
583
+
584
+ self.set_aspect_labels(ax=ax, **kwargs)
585
+
586
+ def set_aspect_labels(self, ax:Axes=None, **kwargs):
587
+ """ Set the aspect of the plot to be equal.
588
+ """
589
+ if ax is None:
590
+ fig, ax = plt.subplots()
591
+ else:
592
+ fig = ax.figure
593
+
594
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
595
+
596
+ ax.set_aspect('equal')
597
+ ax.set_xlim(xmin, xmax)
598
+ ax.set_ylim(ymin, ymax)
599
+ ax.set_xlabel('X (m)')
600
+ ax.set_ylabel('Y (m)')
601
+ return fig, ax
602
+
603
+ def zeros(self):
604
+ """ Return a 2D array of zeros with the shape of the mesh.
605
+ """
606
+ return np.zeros((self.nbx, self.nby))
607
+
608
+ def ones(self):
609
+ """ Return a 2D array of ones with the shape of the mesh.
610
+ """
611
+ return np.ones((self.nbx, self.nby))
612
+
613
+ def zeros_bordersX(self):
614
+ """ Return a 2D array of zeros with the shape of the mesh + 1 in x direction.
615
+ """
616
+ return np.zeros((self.nbx+1, self.nby))
617
+
618
+ def zeros_bordersY(self):
619
+ """ Return a 2D array of zeros with the shape of the mesh + 1 in y direction.
620
+ """
621
+ return np.zeros((self.nbx, self.nby+1))
622
+
623
+ def ones_bordersX(self):
624
+ """ Return a 2D array of ones with the shape of the mesh + 1 in x direction.
625
+ """
626
+ return np.ones((self.nbx+1, self.nby))
627
+
628
+ def ones_bordersY(self):
629
+ """ Return a 2D array of ones with the shape of the mesh + 1 in y direction.
630
+ """
631
+ return np.ones((self.nbx, self.nby+1))
632
+
633
+ def apply_splitting_X(self, q:np.ndarray):
634
+ """ Apply the splitting rule to the X direction.
635
+ """
636
+ q_borderX = self.zeros_bordersX()
637
+ for i in range(1,self.nbx):
638
+ for j in range(self.nby):
639
+ q_borderX[i,j] = q_splitting(q[i-1,j], q[i,j])
640
+ return q_borderX
641
+
642
+ def apply_splitting_Y(self, q:np.ndarray):
643
+ """ Apply the splitting rule to the Y direction.
644
+ """
645
+ q_borderY = self.zeros_bordersY()
646
+ for i in range(self.nbx):
647
+ for j in range(1,self.nby):
648
+ q_borderY[i,j] = q_splitting(q[i,j-1], q[i,j])
649
+ return q_borderY
650
+
651
+ def scale_amplitude(self, amplitude:np.ndarray, factor:float = None):
652
+ """ Scale the amplitude of the arrows.
653
+ """
654
+
655
+ if self._factor is not None:
656
+ return amplitude * self._factor
657
+
658
+ if factor is not None:
659
+ return amplitude * factor
660
+
661
+ factor = min(self.dx, self.dy) * .5 / np.max(amplitude)
662
+ self._factor = factor
663
+
664
+ return amplitude * factor
665
+
666
+ def plot_outside_domain(self, ax:Axes=None, color='black', **kwargs):
667
+ """ Plot a hashed zone outside of the domain.
668
+ """
669
+ if ax is None:
670
+ fig, ax = plt.subplots()
671
+ else:
672
+ fig = ax.figure
673
+
674
+ [xmin, xmax], [ymin, ymax] = self.get_bounds()
675
+
676
+ # Create a rectangle outside the domain
677
+ rect = plt.Rectangle((xmin-self.dx, ymin-self.dy), xmax - xmin + 2.*self.dx, ymax - ymin + 2.*self.dy,
678
+ color=color, alpha=0.2, hatch='//', **kwargs)
679
+ ax.add_patch(rect)
680
+
681
+ rect2 = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin,
682
+ color='white', alpha=1., hatch='', **kwargs)
683
+ ax.add_patch(rect2)
684
+
685
+ return fig, ax