zoomy-core 0.1.0__py3-none-any.whl → 0.1.2__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.

Potentially problematic release.


This version of zoomy-core might be problematic. Click here for more details.

Files changed (57) hide show
  1. zoomy_core/decorators/decorators.py +25 -0
  2. zoomy_core/fvm/flux.py +97 -0
  3. zoomy_core/fvm/nonconservative_flux.py +97 -0
  4. zoomy_core/fvm/ode.py +55 -0
  5. zoomy_core/fvm/solver_numpy.py +305 -0
  6. zoomy_core/fvm/timestepping.py +13 -0
  7. zoomy_core/mesh/gmsh_loader.py +301 -0
  8. zoomy_core/mesh/mesh.py +1192 -0
  9. zoomy_core/mesh/mesh_extrude.py +168 -0
  10. zoomy_core/mesh/mesh_util.py +487 -0
  11. zoomy_core/misc/custom_types.py +6 -0
  12. zoomy_core/misc/gui.py +61 -0
  13. zoomy_core/misc/interpolation.py +140 -0
  14. zoomy_core/misc/io.py +401 -0
  15. zoomy_core/misc/logger_config.py +18 -0
  16. zoomy_core/misc/misc.py +216 -0
  17. zoomy_core/misc/static_class.py +94 -0
  18. zoomy_core/model/analysis.py +147 -0
  19. zoomy_core/model/basefunction.py +113 -0
  20. zoomy_core/model/basemodel.py +512 -0
  21. zoomy_core/model/boundary_conditions.py +193 -0
  22. zoomy_core/model/initial_conditions.py +171 -0
  23. zoomy_core/model/model.py +63 -0
  24. zoomy_core/model/models/GN.py +70 -0
  25. zoomy_core/model/models/advection.py +53 -0
  26. zoomy_core/model/models/basisfunctions.py +181 -0
  27. zoomy_core/model/models/basismatrices.py +377 -0
  28. zoomy_core/model/models/core.py +564 -0
  29. zoomy_core/model/models/coupled_constrained.py +60 -0
  30. zoomy_core/model/models/old_smm copy.py +867 -0
  31. zoomy_core/model/models/poisson.py +41 -0
  32. zoomy_core/model/models/shallow_moments.py +757 -0
  33. zoomy_core/model/models/shallow_moments_sediment.py +378 -0
  34. zoomy_core/model/models/shallow_moments_topo.py +423 -0
  35. zoomy_core/model/models/shallow_moments_variants.py +1509 -0
  36. zoomy_core/model/models/shallow_water.py +266 -0
  37. zoomy_core/model/models/shallow_water_topo.py +111 -0
  38. zoomy_core/model/models/shear_shallow_flow.py +594 -0
  39. zoomy_core/model/models/sme_turbulent.py +613 -0
  40. zoomy_core/model/models/swe_old.py +1018 -0
  41. zoomy_core/model/models/vam.py +455 -0
  42. zoomy_core/postprocessing/postprocessing.py +72 -0
  43. zoomy_core/preprocessing/openfoam_moments.py +452 -0
  44. zoomy_core/transformation/helpers.py +25 -0
  45. zoomy_core/transformation/to_amrex.py +238 -0
  46. zoomy_core/transformation/to_c.py +181 -0
  47. zoomy_core/transformation/to_jax.py +14 -0
  48. zoomy_core/transformation/to_numpy.py +115 -0
  49. zoomy_core/transformation/to_openfoam.py +254 -0
  50. zoomy_core/transformation/to_ufl.py +67 -0
  51. {zoomy_core-0.1.0.dist-info → zoomy_core-0.1.2.dist-info}/METADATA +1 -1
  52. zoomy_core-0.1.2.dist-info/RECORD +55 -0
  53. zoomy_core-0.1.2.dist-info/top_level.txt +1 -0
  54. zoomy_core-0.1.0.dist-info/RECORD +0 -5
  55. zoomy_core-0.1.0.dist-info/top_level.txt +0 -1
  56. {zoomy_core-0.1.0.dist-info → zoomy_core-0.1.2.dist-info}/WHEEL +0 -0
  57. {zoomy_core-0.1.0.dist-info → zoomy_core-0.1.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,757 @@
1
+ import numpy as np
2
+ import numpy.polynomial.legendre as L
3
+ import numpy.polynomial.chebyshev as C
4
+ from scipy.optimize import least_squares as lsq
5
+ import sympy
6
+ from sympy import Matrix, Piecewise, sqrt
7
+ from sympy.abc import x
8
+
9
+ from sympy import integrate, diff
10
+ from sympy import legendre
11
+ from sympy import lambdify
12
+
13
+ from attrs import define, field
14
+ from typing import Union
15
+
16
+
17
+
18
+ from library.zoomy_core.model.basemodel import (
19
+ register_sympy_attribute,
20
+ eigenvalue_dict_to_matrix,
21
+ )
22
+ from library.zoomy_core.model.basemodel import Model
23
+ import library.zoomy_core.model.initial_conditions as IC
24
+ from library.zoomy_core.model.models.basismatrices import Basismatrices
25
+ from library.zoomy_core.model.models.basisfunctions import Legendre_shifted, Basisfunction
26
+
27
+
28
+
29
+ @define(frozen=True, slots=True, kw_only=True)
30
+ class ShallowMoments2d(Model):
31
+ dimension: int = 2
32
+ level: int
33
+ variables: Union[list, int] = field(init=False)
34
+ aux_variables: Union[list, int] = field(default=2)
35
+ basisfunctions: Union[Basisfunction, type[Basisfunction]] = field(default=Legendre_shifted)
36
+ basismatrices: Basismatrices = field(init=False)
37
+
38
+ _default_parameters: dict = field(
39
+ init=False,
40
+ factory=lambda: {"g": 9.81, "ex": 0.0, "ey": 0.0, "ez": 1.0}
41
+ )
42
+
43
+ def __attrs_post_init__(self):
44
+ object.__setattr__(self, "variables", ((self.level+1)*self.dimension)+1)
45
+ super().__attrs_post_init__()
46
+ aux_variables = self.aux_variables
47
+ aux_var_list = aux_variables.keys()
48
+ if not aux_variables.contains("dudx"):
49
+ aux_var_list += ["dudx"]
50
+ if self.dimension == 2 and not aux_variables.contains("dvdy"):
51
+ aux_var_list += ["dvdy"]
52
+ object.__setattr__(self, "aux_variables", register_sympy_attribute(aux_var_list, "qaux_"))
53
+
54
+ # Recompute basis matrices
55
+ object.__setattr__(self, "basisfunctions", self.basisfunctions(level=self.level))
56
+ basismatrices = Basismatrices(self.basisfunctions)
57
+ basismatrices.compute_matrices(self.level)
58
+ object.__setattr__(self, "basismatrices", basismatrices)
59
+
60
+
61
+
62
+
63
+ def project_2d_to_3d(self):
64
+ out = Matrix([0 for i in range(6)])
65
+ level = self.level
66
+ offset = level+1
67
+ x = self.position[0]
68
+ y = self.position[1]
69
+ z = self.position[2]
70
+ h = self.variables[0]
71
+ a = [self.variables[1+i]/h for i in range(offset)]
72
+ dhdx = self.aux_variables[0]
73
+ dadx = [self.aux_variables[1+i] for i in range(offset)]
74
+
75
+ psi = [self.basisfunctions.eval_psi(k, z) for k in range(level+1)]
76
+ phi = [self.basisfunctions.eval(k, z) for k in range(level+1)]
77
+
78
+ rho_w = 1000.
79
+ g = 9.81
80
+ u_3d = self.basismatrices.basisfunctions.reconstruct_velocity_profile_at(a, z)
81
+ v_3d = 0
82
+ b = 0
83
+ dbdx = 0
84
+ def dot(a, b):
85
+ s = 0
86
+ for i in range(len(a)):
87
+ s += a[i] * b[i]
88
+ return s
89
+ w_3d = - dhdx * dot(a,psi) - h * dot(dadx,psi) + dot(a, phi) * (z * dhdx + dbdx)
90
+ if self.dimension == 2:
91
+ beta = [self.variables[1+offset+i]/h for i in range(offset)]
92
+ v_3d = self.basismatrices.basisfunctions.reconstruct_velocity_profile_at(beta, z)
93
+
94
+ b = 0
95
+ out[0] = b
96
+ out[1] = h
97
+ out[2] = u_3d
98
+ out[3] = v_3d
99
+ out[4] = w_3d
100
+ out[5] = rho_w * g * h * (1-z)
101
+
102
+ return out
103
+
104
+ def flux(self):
105
+ offset = self.level + 1
106
+ flux_x = Matrix([0 for i in range(self.n_variables)])
107
+ flux_y = Matrix([0 for i in range(self.n_variables)])
108
+ h = self.variables[0]
109
+ ha = self.variables[1 : 1 + self.level + 1]
110
+ p = self.parameters
111
+ flux_x[0] = ha[0]
112
+ flux_x[1] = p.g * p.ez * h * h / 2
113
+ for k in range(self.level + 1):
114
+ for i in range(self.level + 1):
115
+ for j in range(self.level + 1):
116
+ # TODO avoid devision by zero
117
+ flux_x[k + 1] += (
118
+ ha[i]
119
+ * ha[j]
120
+ / h
121
+ * self.basismatrices.A[k, i, j] / self.basismatrices.M[k, k]
122
+ )
123
+ if self.dimension == 2:
124
+ hb = self.variables[1 + self.level + 1 : 1 + 2 * (self.level + 1)]
125
+
126
+ for k in range(self.level + 1):
127
+ for i in range(self.level + 1):
128
+ for j in range(self.level + 1):
129
+ # TODO avoid devision by zero
130
+ flux_x[k + 1 + offset] += (
131
+ hb[i]
132
+ * ha[j]
133
+ / h
134
+ * self.basismatrices.A[k, i, j]/ self.basismatrices.M[k, k]
135
+ )
136
+
137
+ flux_y[0] = hb[0]
138
+ flux_y[1 + offset] = p.g * p.ez * h * h / 2
139
+ for k in range(self.level + 1):
140
+ for i in range(self.level + 1):
141
+ for j in range(self.level + 1):
142
+ # TODO avoid devision by zero
143
+ flux_y[k + 1] += (
144
+ hb[i]
145
+ * ha[j]
146
+ / h
147
+ * self.basismatrices.A[k, i, j]/ self.basismatrices.M[k, k]
148
+ )
149
+ for k in range(self.level + 1):
150
+ for i in range(self.level + 1):
151
+ for j in range(self.level + 1):
152
+ # TODO avoid devision by zero
153
+ flux_y[k + 1 + offset] += (
154
+ hb[i]
155
+ * hb[j]
156
+ / h
157
+ * self.basismatrices.A[k, i, j]/ self.basismatrices.M[k, k]
158
+ )
159
+ return [flux_x, flux_y]
160
+
161
+ def nonconservative_matrix(self):
162
+ offset = self.level + 1
163
+ nc_x = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
164
+ nc_y = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
165
+ h = self.variables[0]
166
+ ha = self.variables[1 : 1 + self.level + 1]
167
+ p = self.parameters
168
+ um = ha[0] / h
169
+
170
+ for k in range(1, self.level + 1):
171
+ nc_x[k + 1, k + 1] += um
172
+ for k in range(self.level + 1):
173
+ for i in range(1, self.level + 1):
174
+ for j in range(1, self.level + 1):
175
+ nc_x[k + 1, i + 1] -= (
176
+ ha[j]
177
+ / h
178
+ * self.basismatrices.B[k, i, j]/ self.basismatrices.M[k, k]
179
+ )
180
+
181
+
182
+ if self.dimension == 2:
183
+ hb = self.variables[1 + offset : 1 + offset + self.level + 1]
184
+ vm = hb[0] / h
185
+ for k in range(1, self.level + 1):
186
+ nc_y[k + 1, k + 1 + offset] += um
187
+ for k in range(self.level + 1):
188
+ for i in range(1, self.level + 1):
189
+ for j in range(1, self.level + 1):
190
+ nc_y[k + 1, i + 1 + offset] -= (
191
+ ha[j]
192
+ / h
193
+ * self.basismatrices.B[k, i, j]/ self.basismatrices.M[k, k]
194
+ )
195
+
196
+ for k in range(1, self.level + 1):
197
+ nc_x[k + 1 + offset, k + 1] += vm
198
+ nc_y[k + 1 + offset, k + 1 + offset] += vm
199
+ for k in range(self.level + 1):
200
+ for i in range(1, self.level + 1):
201
+ for j in range(1, self.level + 1):
202
+ nc_x[k + 1 + offset, i + 1] -= (
203
+ hb[j]
204
+ / h
205
+ * self.basismatrices.B[k, i, j]
206
+ )
207
+ nc_y[k + 1 + offset, i + 1 + offset] -= (
208
+ hb[j]
209
+ / h
210
+ * self.basismatrices.B[k, i, j]/ self.basismatrices.M[k, k]
211
+ )
212
+ return [-nc_x, -nc_y]
213
+
214
+ def eigenvalues(self):
215
+ # we delete heigher order moments (level >= 2) for analytical eigenvalues
216
+ offset = self.level + 1
217
+ A = self.normal[0] * self.quasilinear_matrix()[0]
218
+ for d in range(1, self.dimension):
219
+ A += self.normal[d] * self.quasilinear_matrix()[d]
220
+ alpha_erase = self.variables[2 : 2 + self.level]
221
+ beta_erase = self.variables[2 + offset : 2 + offset + self.level]
222
+ for alpha_i in alpha_erase:
223
+ A = A.subs(alpha_i, 0)
224
+ for beta_i in beta_erase:
225
+ A = A.subs(beta_i, 0)
226
+ return eigenvalue_dict_to_matrix(A.eigenvals())
227
+
228
+
229
+ def source(self):
230
+ out = Matrix([0 for i in range(self.n_variables)])
231
+ return out
232
+
233
+ def gravity(self):
234
+ out = Matrix([0 for i in range(self.n_variables)])
235
+ out[1] = -self.parameters.g * self.parameters.ex * self.variables[0]
236
+ if self.dimension == 2:
237
+ offset = self.level + 1
238
+ out[1 + offset] = -self.parameters.g * self.parameters.ey * self.variables[0]
239
+ return out
240
+
241
+ def newtonian_turbulent(self):
242
+ p = self.parameters
243
+ nut1 = [
244
+ 1.06245397e-05,
245
+ -8.64966128e-06,
246
+ -4.24655215e-06,
247
+ 1.51861028e-06,
248
+ 2.25140517e-06,
249
+ 1.81867029e-06,
250
+ -1.02154323e-06,
251
+ -1.78795289e-06,
252
+ -5.07515843e-07,
253
+ ]
254
+ nut2 = np.array(
255
+ [
256
+ 0.21923893,
257
+ -0.04171894,
258
+ -0.05129916,
259
+ -0.04913612,
260
+ -0.03863209,
261
+ -0.02533469,
262
+ -0.0144186,
263
+ -0.00746847,
264
+ -0.0031811,
265
+ -0.00067986,
266
+ 0.0021782,
267
+ ]
268
+ )
269
+ nut2 = nut2 / nut2[0] * 1.06245397 * 10 ** (-5)
270
+ nut3 = [
271
+ 1.45934315e-05,
272
+ -1.91969629e-05,
273
+ 5.80456268e-06,
274
+ -5.13207491e-07,
275
+ 2.29489571e-06,
276
+ -1.24361978e-06,
277
+ -2.78720732e-06,
278
+ -2.01469118e-07,
279
+ 1.24957663e-06,
280
+ ]
281
+ nut4 = [
282
+ 1.45934315e-05,
283
+ -1.45934315e-05 * 3 / 4,
284
+ -1.45934315e-05 * 1 / 4,
285
+ 0,
286
+ 0,
287
+ 0,
288
+ 0,
289
+ 0,
290
+ 0,
291
+ 0,
292
+ 0,
293
+ 0,
294
+ ]
295
+ nut5 = [p.nut, -p.nut * 3 / 4, -p.nut * 1 / 4, 0, 0, 0, 0, 0, 0, 0, 0, 0]
296
+ nut = nut5
297
+ out = Matrix([0 for i in range(self.n_variables)])
298
+ h = self.variables[0]
299
+ ha = self.variables[1 : 1 + self.level + 1]
300
+ p = self.parameters
301
+ for k in range(1 + self.level):
302
+ for i in range(1 + self.level):
303
+ for j in range(1 + self.level):
304
+ out[1 + k] += (
305
+ -p.c_nut
306
+ * nut[j]
307
+ / h
308
+ * ha[i]
309
+ / h
310
+ * self.basismatrices.DT[k, i, j]/ self.basismatrices.M[k, k]
311
+ )
312
+ return out
313
+
314
+ def newtonian_boundary_layer_classic(self):
315
+ assert "nu" in vars(self.parameters)
316
+ assert "eta" in vars(self.parameters)
317
+ out = Matrix([0 for i in range(self.n_variables)])
318
+ h = self.variables[0]
319
+ ha = self.variables[1 : 1 + self.level + 1]
320
+ p = self.parameters
321
+ phi_0 = [
322
+ self.basismatrices.basisfunctions.eval(i, 0.0)
323
+ for i in range(self.level + 1)
324
+ ]
325
+ dphidx_0 = [
326
+ (diff(self.basismatrices.basisfunctions.eval(i, x), x)).subs(x, 0.0)
327
+ for i in range(self.level + 1)
328
+ ]
329
+ tau_bot = 0
330
+ for i in range(1 + self.level):
331
+ tau_bot += ha[i] / h * dphidx_0[i]
332
+ for k in range(1 + self.level):
333
+ out[k + 1] = (
334
+ -p.c_bl
335
+ * p.eta
336
+ * (p.nu + p.nut_bl)
337
+ / h
338
+ * tau_bot
339
+ * phi_0[k]/ self.basismatrices.M[k, k]
340
+ )
341
+ return out
342
+
343
+ def newtonian(self):
344
+ assert "nu" in vars(self.parameters)
345
+ out = Matrix([0 for i in range(self.n_variables)])
346
+ offset = self.level + 1
347
+ h = self.variables[0]
348
+ ha = self.variables[1 : 1 + self.level + 1]
349
+ p = self.parameters
350
+ for k in range(1 + self.level):
351
+ for i in range(1 + self.level):
352
+ out[1 + k] += (
353
+ -p.nu
354
+ / h
355
+ * ha[i]
356
+ / h
357
+ * self.basismatrices.D[i, k]/ self.basismatrices.M[k, k]
358
+ )
359
+ if self.dimension == 2:
360
+ hb = self.variables[1 + offset : 1 + self.level + 1 + offset]
361
+ for k in range(1 + self.level):
362
+ for i in range(1 + self.level):
363
+ out[1 + k + offset] += (
364
+ -p.nu
365
+ / h
366
+ * hb[i]
367
+ / h
368
+ * self.basismatrices.D[i, k]/ self.basismatrices.M[k, k]
369
+ )
370
+
371
+ return out
372
+
373
+ def newtonian_turbulent_algebraic(self):
374
+ assert "nu" in vars(self.parameters)
375
+ assert "l_bl" in vars(self.parameters)
376
+ assert "l_turb" in vars(self.parameters)
377
+ assert "kappa" in vars(self.parameters)
378
+ out = Matrix([0 for i in range(self.n_variables)])
379
+ offset = self.level + 1
380
+ h = self.variables[0]
381
+ a = [_ha / h for _ha in self.variables[1 : 1 + self.level + 1]]
382
+ p = self.parameters
383
+ dU_dx = a[0] / (p.l_turb * h)
384
+ abs_dU_dx = sympy.Piecewise((dU_dx, dU_dx >=0), (-dU_dx, True))
385
+ for k in range(1 + self.level):
386
+ out[1 + k] += (
387
+ -(p.nu + p.kappa * sympy.sqrt(p.nu * abs_dU_dx) * p.l_bl * ( 1-p.l_bl)) * dU_dx * self.basismatrices.phib[k] / h/ self.basismatrices.M[k, k]
388
+ )
389
+ for i in range(1 + self.level):
390
+ out[1 + k] += (
391
+ -p.nu
392
+ / h
393
+ * a[i]
394
+ * self.basismatrices.D[i, k]/ self.basismatrices.M[k, k]
395
+ )
396
+ out[1 + k] += (
397
+ -p.kappa * sympy.sqrt(p.nu * abs_dU_dx)
398
+ / h
399
+ * a[i]
400
+ * (self.basismatrices.Dxi[i, k] - self.basismatrices.Dxi2[i, k])/ self.basismatrices.M[k, k]
401
+ )
402
+ if self.dimension == 2:
403
+ b = [_hb / h for _hb in self.variables[1 + offset : 1 + self.level + 1 + offset] ]
404
+ dV_dy = b[0] / (p.l_turb * h)
405
+ abs_dV_dy = sympy.Piecewise((dV_dy, dV_dy >=0), (-dV_dy, True))
406
+ for k in range(1 + self.level):
407
+ out[1 + k + offset] += (
408
+ -(p.nu + p.kappa * sympy.sqrt(p.nu * abs_dV_dy) * p.l_bl * ( 1-p.l_bl)) * dV_dy * self.basismatrices.phib[k] / h/ self.basismatrices.M[k, k]
409
+ )
410
+ for i in range(1 + self.level):
411
+ out[1 + k + offset] += (
412
+ -p.nu
413
+ / h
414
+ * b[i]
415
+ * self.basismatrices.D[i, k]/ self.basismatrices.M[k, k]
416
+ )
417
+ out[1 + k + offset] += (
418
+ -p.kappa * sympy.sqrt(p.nu * abs_dV_dy)
419
+ / h
420
+ * b[i]
421
+ * (self.basismatrices.Dxi[i, k] - self.basismatrices.Dxi2[i, k])/ self.basismatrices.M[k, k]
422
+ )
423
+
424
+ return out
425
+
426
+ def regress_against_power_profile(self):
427
+ """
428
+ :gui:
429
+ - requires_parameter: ('lamda', 0.0)
430
+ - requires_parameter: ('rho', 1.0)
431
+ """
432
+ assert "r_pp" in vars(self.parameters)
433
+ out = Matrix([0 for i in range(self.n_variables)])
434
+ offset = self.level+1
435
+ h = self.variables[0]
436
+ ha = self.variables[1 : 1 + self.level + 1]
437
+ p = self.parameters
438
+ ub = 0
439
+ Z = np.linspace(0,1,100)
440
+ U = 1-(1-Z)**8
441
+ power_profile_coefs = self.basisfunctions.project_onto_basis(U)
442
+ for i in range(1 + self.level):
443
+ ub += ha[i] / h
444
+ for k in range(1, 1 + self.level):
445
+ out[1 + k] += (
446
+ -p.r_pp * sympy.Piecewise((ub, ub >=0), (-ub, True)) * (ha[i] - ha[0]*power_profile_coefs[i])/ self.basismatrices.M[k, k]
447
+ )
448
+ return out
449
+
450
+ def slip_mod(self):
451
+ """
452
+ :gui:
453
+ - requires_parameter: ('lamda', 0.0)
454
+ - requires_parameter: ('rho', 1.0)
455
+ """
456
+ assert "lamda" in vars(self.parameters)
457
+ assert "rho" in vars(self.parameters)
458
+ out = Matrix([0 for i in range(self.n_variables)])
459
+ offset = self.level+1
460
+ h = self.variables[0]
461
+ ha = self.variables[1 : 1 + self.level + 1]
462
+ p = self.parameters
463
+ ub = 0
464
+ for i in range(1 + self.level):
465
+ ub += ha[i] / h
466
+ for k in range(1, 1 + self.level):
467
+ out[1 + k] += (
468
+ -p.c_slipmod / p.lamda / p.rho * ub / self.basismatrices.M[k, k]
469
+ )
470
+ if self.dimension == 2:
471
+ hb = self.variables[1+offset : 1+offset + self.level + 1]
472
+ vb = 0
473
+ for i in range(1 + self.level):
474
+ vb += hb[i] / h
475
+ for k in range(1, 1 + self.level):
476
+ out[1+offset+k] += (
477
+ -1.0 * p.c_slipmod / p.lamda / p.rho * vb/ self.basismatrices.M[k, k]
478
+ )
479
+ return out
480
+
481
+ def newtonian_boundary_layer(self):
482
+ assert "nu" in vars(self.parameters)
483
+ out = Matrix([0 for i in range(self.n_variables)])
484
+ offset = self.level + 1
485
+ h = self.variables[0]
486
+ ha = self.variables[1 : 1 + self.level + 1]
487
+ p = self.parameters
488
+ phi_0 = [self.basismatrices.eval(i, 0.0) for i in range(self.level + 1)]
489
+ dphidx_0 = [
490
+ (diff(self.basismatrices.eval(i, x), x)).subs(x, 0.0)
491
+ for i in range(self.level + 1)
492
+ ]
493
+ for k in range(1 + self.level):
494
+ for i in range(1 + self.level):
495
+ out[1 + k] += (
496
+ -p.nu
497
+ / h
498
+ * ha[i]
499
+ / h
500
+ * phi_0[k]
501
+ * dphidx_0[i]/ self.basismatrices.M[k, k]
502
+ )
503
+ if self.dimension==2:
504
+ hb = self.variables[1 + offset : 1 + self.level + 1 + offset]
505
+ for k in range(1 + self.level):
506
+ for i in range(1 + self.level):
507
+ out[1 + k + offset] += (
508
+ -p.nu
509
+ / h
510
+ * hb[i]
511
+ / h
512
+ * phi_0[k]
513
+ * dphidx_0[i]/ self.basismatrices.M[k, k]
514
+ )
515
+ return out
516
+
517
+ def sindy(self):
518
+ assert "nu" in vars(self.parameters)
519
+ out = Matrix([0 for i in range(self.n_variables)])
520
+ offset = self.level + 1
521
+ h = self.variables[0]
522
+ ha = self.variables[1 : 1 + self.level + 1]
523
+ hb = self.variables[1 + offset : 1 + self.level + 1 + offset]
524
+ p = self.parameters
525
+ out[1] += (
526
+ p.C1 * sympy.Abs(ha[0] / h)
527
+ + p.C2 * sympy.Abs(ha[1] / h)
528
+ + p.C3 * sympy.Abs(ha[0] / h) ** (7 / 3)
529
+ + p.C4 * sympy.Abs(ha[1] / h) ** (7 / 3)
530
+ )
531
+ out[2] += (
532
+ p.C5 * sympy.Abs(ha[0] / h)
533
+ + p.C6 * sympy.Abs(ha[1] / h)
534
+ + p.C7 * sympy.Abs(ha[0] / h) ** (7 / 3)
535
+ + p.C8 * sympy.Abs(ha[1] / h) ** (7 / 3)
536
+ )
537
+ out[3] += (
538
+ p.C1 * sympy.Abs(ha[0] / h)
539
+ + p.C2 * sympy.Abs(ha[1] / h)
540
+ + p.C3 * sympy.Abs(ha[0] / h) ** (7 / 3)
541
+ + p.C4 * sympy.Abs(ha[1] / h) ** (7 / 3)
542
+ )
543
+ out[4] += (
544
+ p.C5 * sympy.Abs(ha[0] / h)
545
+ + p.C6 * sympy.Abs(ha[1] / h)
546
+ + p.C7 * sympy.Abs(ha[0] / h) ** (7 / 3)
547
+ + p.C8 * sympy.Abs(ha[1] / h) ** (7 / 3)
548
+ )
549
+ return out
550
+
551
+ def slip(self):
552
+ assert "lamda" in vars(self.parameters)
553
+ assert "rho" in vars(self.parameters)
554
+ out = Matrix([0 for i in range(self.n_variables)])
555
+ offset = self.level + 1
556
+ h = self.variables[0]
557
+ h = self.variables[0]
558
+ ha = self.variables[1 : 1 + self.level + 1]
559
+ p = self.parameters
560
+ for k in range(1 + self.level):
561
+ for i in range(1 + self.level):
562
+ out[1 + k] += (
563
+ -1.0 / p.lamda / p.rho * ha[i] / h / self.basismatrices.M[k, k]
564
+ )
565
+
566
+ if self.dimension == 2:
567
+ hb = self.variables[1 + offset : 1 + self.level + 1 + offset]
568
+ for k in range(1 + self.level):
569
+ for i in range(1 + self.level):
570
+ out[1 + k + offset] += (
571
+ -1.0 / p.lamda / p.rho/ self.basismatrices.M[k, k]
572
+ )
573
+ return out
574
+
575
+ def chezy(self):
576
+ assert "C" in vars(self.parameters)
577
+ out = Matrix([0 for i in range(self.n_variables)])
578
+ h = self.variables[0]
579
+ ha = self.variables[1 : 1 + self.level + 1]
580
+ p = self.parameters
581
+ tmp = 0
582
+ if self.dimension == 1:
583
+ for i in range(1 + self.level):
584
+ for j in range(1 + self.level):
585
+ tmp += ha[i] * ha[j] / h / h
586
+ sqrt = sympy.sqrt(tmp)
587
+ for k in range(1 + self.level):
588
+ for l in range(1 + self.level):
589
+ out[1 + k] += (
590
+ -1.0 / (p.C**2) * ha[l] * sqrt / h/ self.basismatrices.M[k, k]
591
+ )
592
+ if self.dimension == 2:
593
+ offset = self.level + 1
594
+ hb = self.variables[1 + offset : 1 + self.level + 1 + offset]
595
+ for i in range(1 + self.level):
596
+ for j in range(1 + self.level):
597
+ tmp += ha[i] * ha[j] / h / h + hb[i] * hb[j] / h / h
598
+ sqrt = sympy.sqrt(tmp)
599
+ for k in range(1 + self.level):
600
+ for l in range(1 + self.level):
601
+ out[1 + k] += (
602
+ -1.0 / (p.C**2) * ha[l] * sqrt / h/ self.basismatrices.M[k, k]
603
+ )
604
+ out[1 + k + offset] += (
605
+ -1.0 / (p.C**2) * hb[l] * sqrt / h/ self.basismatrices.M[k, k]
606
+ )
607
+
608
+ return out
609
+
610
+
611
+ def reconstruct_uvw(Q, grad, lvl, phi, psi):
612
+ """
613
+ returns functions u(z), v(z), w(z)
614
+ """
615
+ offset = lvl + 1
616
+ h = Q[0]
617
+ alpha = Q[1 : 1 + offset] / h
618
+ beta = Q[1 + offset : 1 + 2 * offset] / h
619
+ dhalpha_dx = grad[1 : 1 + offset, 0]
620
+ dhbeta_dy = grad[1 + offset : 1 + 2 * offset, 1]
621
+
622
+ def u(z):
623
+ u_z = 0
624
+ for i in range(lvl + 1):
625
+ u_z += alpha[i] * phi(z)[i]
626
+ return u_z
627
+
628
+ def v(z):
629
+ v_z = 0
630
+ for i in range(lvl + 1):
631
+ v_z += beta[i] * phi(z)[i]
632
+ return v_z
633
+
634
+ def w(z):
635
+ basis_0 = psi(0)
636
+ basis_z = psi(z)
637
+ u_z = 0
638
+ v_z = 0
639
+ grad_h = grad[0, :]
640
+ # grad_hb = grad[-1, :]
641
+ grad_hb = np.zeros(grad[0, :].shape)
642
+ result = 0
643
+ for i in range(lvl + 1):
644
+ u_z += alpha[i] * basis_z[i]
645
+ v_z += beta[i] * basis_z[i]
646
+ for i in range(lvl + 1):
647
+ result -= dhalpha_dx[i] * (basis_z[i] - basis_0[i])
648
+ result -= dhbeta_dy[i] * (basis_z[i] - basis_0[i])
649
+
650
+ result += u_z * (z * grad_h[0] + grad_hb[0])
651
+ result += v_z * (z * grad_h[1] + grad_hb[1])
652
+ return result
653
+
654
+ return u, v, w
655
+
656
+
657
+ def generate_velocity_profiles(
658
+ Q,
659
+ centers,
660
+ model: Model,
661
+ list_of_positions: list[np.ndarray],
662
+ ):
663
+ def find_closest_element(centers, pos):
664
+ assert centers.shape[1] == np.array(pos).shape[0]
665
+ return np.argmin(np.linalg.norm(centers - pos, axis=1))
666
+
667
+ # find the closest element to the given position
668
+ vertices = []
669
+ for pos in list_of_positions:
670
+ vertex = find_closest_element(centers, pos)
671
+ vertices.append(vertex)
672
+
673
+ Z = np.linspace(0, 1, 100)
674
+ list_profiles = []
675
+ list_means = []
676
+ level = int((model.n_variables - 1) / model.dimension) - 1
677
+ offset = level + 1
678
+ list_h = []
679
+ for vertex in vertices:
680
+ profiles = []
681
+ means = []
682
+ for d in range(model.dimension):
683
+ q = Q[vertex, :]
684
+ h = q[0]
685
+ coefs = q[1 + d * offset : 1 + (d + 1) * offset] / h
686
+ profile = model.basis.basis.reconstruct_velocity_profile(coefs, Z=Z)
687
+ mean = coefs[0]
688
+ profiles.append(profile)
689
+ means.append(mean)
690
+ list_profiles.append(profiles)
691
+ list_means.append(means)
692
+ list_h.append(h)
693
+ return list_profiles, list_means, list_of_positions, Z, list_h
694
+
695
+
696
+ if __name__ == "__main__":
697
+ # basis = Legendre_shifted(1)
698
+ # basis = Spline()
699
+ # basis = OrthogonalSplineWithConstant(degree=2, knots=[0, 0.1, 0.3,0.5, 1,1])
700
+ # basis=OrthogonalSplineWithConstant(degree=1, knots=[0,0, 0.02, 0.04, 0.06, 0.08, 0.1, 1])
701
+ # basis=OrthogonalSplineWithConstant(degree=1, knots=[0,0, 0.1, 1])
702
+ # basis.plot()
703
+
704
+ # basis = Legendre_shifted(basis=Legendre_shifted(order=8))
705
+ # f = basis.enforce_boundary_conditions()
706
+ # q = np.array([[1., 0.1, 0., 0., 0., 0.], [1., 0.1, 0., 0., 3., 0.]])
707
+ # print(f(q))
708
+
709
+ # basis =Legendre_shifted(order=8)
710
+ # basis.plot()
711
+ # z = np.linspace(0,1,100)
712
+ # f = basis.get_lambda(1)
713
+ # print(f(z), f(1.0))
714
+ # f = basis.get_lambda(1)
715
+ # print(f(z))
716
+
717
+ # X = np.linspace(0,1,100)
718
+ # coef = np.array([0.2, -0.01, -0.1, -0.05, -0.04])
719
+ # U = basis.basis.reconstruct_velocity_profile(coef, Z=X)
720
+ # coef2 = coef*2
721
+ # factor = 1.0 / 0.2
722
+ # coef3 = coef * factor
723
+ # U2 = basis.basis.reconstruct_velocity_profile(coef2, Z=X)
724
+ # U3 = basis.basis.reconstruct_velocity_profile(coef3, Z=X)
725
+ # fig, ax = plt.subplots()
726
+ # ax.plot(U, X)
727
+ # ax.plot(U2, X)
728
+ # ax.plot(U3, X)
729
+ # plt.show()
730
+
731
+ # X = np.linspace(0,1,100)
732
+ # nut = 10**(-5)
733
+ # coef = np.array([nut, -nut, 0, 0, 0, 0, 0 ])
734
+ # U = basis.basis.reconstruct_velocity_profile(coef, Z=X)
735
+ # fig, ax = plt.subplots()
736
+ # ax.plot(U, X)
737
+ # plt.show()
738
+
739
+ # nut = np.load('/home/ingo/Git/sms/nut_nut2.npy')
740
+ # y = np.load('/home/ingo/Git/sms/nut_y2.npy')
741
+ # coef = basis.basis.reconstruct_alpha(nut, y)
742
+ # coef_offset = np.sum(coef)
743
+ # coef[0] -= coef_offset
744
+ # print(coef)
745
+ # X = np.linspace(0,1,100)
746
+ # _nut = basis.basis.reconstruct_velocity_profile(coef, Z=X)
747
+ # fig, ax = plt.subplots()
748
+ # ax.plot(_nut, X)
749
+ # plt.show()
750
+
751
+ basis = Legendre_shifted(basis=Legendre_shifted(level=2))
752
+ basis.compute_matrices(2)
753
+ print(basis.D)
754
+
755
+ @define(frozen=True, slots=True, kw_only=True)
756
+ class ShallowMoments(ShallowMoments2d):
757
+ dimension: int = 1