zoomy-core 0.1.11__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 (51) hide show
  1. zoomy_core/__init__.py +7 -0
  2. zoomy_core/decorators/decorators.py +25 -0
  3. zoomy_core/fvm/flux.py +52 -0
  4. zoomy_core/fvm/nonconservative_flux.py +97 -0
  5. zoomy_core/fvm/ode.py +55 -0
  6. zoomy_core/fvm/solver_numpy.py +297 -0
  7. zoomy_core/fvm/timestepping.py +13 -0
  8. zoomy_core/mesh/mesh.py +1236 -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/interpolation.py +140 -0
  13. zoomy_core/misc/io.py +439 -0
  14. zoomy_core/misc/logger_config.py +18 -0
  15. zoomy_core/misc/misc.py +213 -0
  16. zoomy_core/model/analysis.py +147 -0
  17. zoomy_core/model/basefunction.py +113 -0
  18. zoomy_core/model/basemodel.py +512 -0
  19. zoomy_core/model/boundary_conditions.py +193 -0
  20. zoomy_core/model/initial_conditions.py +171 -0
  21. zoomy_core/model/model.py +63 -0
  22. zoomy_core/model/models/GN.py +70 -0
  23. zoomy_core/model/models/advection.py +53 -0
  24. zoomy_core/model/models/basisfunctions.py +181 -0
  25. zoomy_core/model/models/basismatrices.py +377 -0
  26. zoomy_core/model/models/core.py +564 -0
  27. zoomy_core/model/models/coupled_constrained.py +60 -0
  28. zoomy_core/model/models/poisson.py +41 -0
  29. zoomy_core/model/models/shallow_moments.py +757 -0
  30. zoomy_core/model/models/shallow_moments_sediment.py +378 -0
  31. zoomy_core/model/models/shallow_moments_topo.py +423 -0
  32. zoomy_core/model/models/shallow_moments_variants.py +1509 -0
  33. zoomy_core/model/models/shallow_water.py +266 -0
  34. zoomy_core/model/models/shallow_water_topo.py +111 -0
  35. zoomy_core/model/models/shear_shallow_flow.py +594 -0
  36. zoomy_core/model/models/sme_turbulent.py +613 -0
  37. zoomy_core/model/models/vam.py +455 -0
  38. zoomy_core/postprocessing/postprocessing.py +72 -0
  39. zoomy_core/preprocessing/openfoam_moments.py +452 -0
  40. zoomy_core/transformation/helpers.py +25 -0
  41. zoomy_core/transformation/to_amrex.py +238 -0
  42. zoomy_core/transformation/to_c.py +181 -0
  43. zoomy_core/transformation/to_jax.py +14 -0
  44. zoomy_core/transformation/to_numpy.py +115 -0
  45. zoomy_core/transformation/to_openfoam.py +254 -0
  46. zoomy_core/transformation/to_ufl.py +67 -0
  47. zoomy_core-0.1.11.dist-info/METADATA +225 -0
  48. zoomy_core-0.1.11.dist-info/RECORD +51 -0
  49. zoomy_core-0.1.11.dist-info/WHEEL +5 -0
  50. zoomy_core-0.1.11.dist-info/licenses/LICENSE +674 -0
  51. zoomy_core-0.1.11.dist-info/top_level.txt +1 -0
@@ -0,0 +1,594 @@
1
+ import sympy
2
+ from sympy import Matrix
3
+
4
+ # from sympy import *
5
+
6
+ from zoomy_core.model.basemodel import (
7
+ register_sympy_attribute,
8
+ )
9
+ from zoomy_core.model.basemodel import Model
10
+
11
+
12
+
13
+
14
+
15
+
16
+ class ShearShallowFlow(Model):
17
+ """
18
+ Shallow Moments
19
+
20
+ :gui:
21
+ - tab: model
22
+ - requires: [ 'mesh.dimension': 1 ]
23
+
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ boundary_conditions,
29
+ initial_conditions,
30
+ dimension=1,
31
+ fields=3,
32
+ aux_variables=0,
33
+ parameters={},
34
+ _default_parameters={"g": 1.0, "ex": 0.0, "ez": 1.0},
35
+ settings={},
36
+ settings_default={"topography": False, "friction": []},
37
+ ):
38
+ self.variables = register_sympy_attribute(fields, "q")
39
+ self.n_variables = self.variables.length()
40
+ super().__init__(
41
+ dimension=dimension,
42
+ fields=fields,
43
+ aux_variables=aux_variables,
44
+ parameters=parameters,
45
+ _default_parameters=_default_parameters,
46
+ boundary_conditions=boundary_conditions,
47
+ initial_conditions=initial_conditions,
48
+ settings={**settings_default, **settings},
49
+ )
50
+
51
+ def flux(self):
52
+ flux_x = Matrix([0 for i in range(self.n_variables)])
53
+ h = self.variables[0]
54
+ hu = self.variables[1]
55
+ u = hu / h
56
+ P11 = self.variables[2]
57
+ p = self.parameters
58
+ flux_x[0] = hu
59
+ flux_x[1] = hu * u + p.g * h**2 / 2 + h * P11
60
+ # flux_x[1] = hu * u + h*P11
61
+ # flux_x[2] = 0.
62
+ flux_x[2] = 2 * P11 * u
63
+
64
+ return [flux_x]
65
+
66
+ def nonconservative_matrix(self):
67
+ nc_x = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
68
+ h = self.variables[0]
69
+ hu = self.variables[1]
70
+ u = hu / h
71
+ P11 = self.variables[2]
72
+ p = self.parameters
73
+
74
+ # nc_x[2, 0] = - p.g * h
75
+ nc_x[2, 0] = 0
76
+ nc_x[2, 1] = 0
77
+ nc_x[2, 2] = u
78
+ return [nc_x]
79
+
80
+ def source(self):
81
+ out = Matrix([0 for i in range(self.n_variables)])
82
+ return out
83
+
84
+ def topography(self):
85
+ assert "dhdx" in vars(self.aux_variables)
86
+ out = Matrix([0 for i in range(self.n_variables)])
87
+ h = self.variables[0]
88
+ p = self.parameters
89
+ dhdx = self.aux_variables.dhdx
90
+ # out[1] = h * p.g * (p.ex - p.ez * dhdx)
91
+ return out
92
+
93
+ def eigenvalues(self):
94
+ evs = Matrix([0 for i in range(self.n_variables)])
95
+ h = self.variables[0]
96
+ hu = self.variables[1]
97
+ u = hu / h
98
+ P11 = self.variables[2]
99
+ p = self.parameters
100
+
101
+ b = sympy.sqrt(P11)
102
+ a = sympy.sqrt(p.g * h + 3 * P11)
103
+
104
+ evs[0] = u
105
+ evs[1] = u + a
106
+ evs[2] = u - a
107
+
108
+ return evs
109
+
110
+ def friction_paper(self):
111
+ assert "phi" in vars(self.parameters)
112
+ out = Matrix([0 for i in range(self.n_variables)])
113
+ h = self.variables[0]
114
+ hu = self.variables[1]
115
+ u = hu / h
116
+ P11 = self.variables[2]
117
+ p = self.parameters
118
+
119
+ abs_u = sympy.sqrt(u**2)
120
+ trace_P = P11
121
+ grad_b = [-sympy.tan(p.theta)]
122
+ # alpha = max(0, p.Cr * (trace_P/h**2 - p.phi)/(trace_P**2/h**2))
123
+ alpha = sympy.Piecewise(
124
+ (
125
+ p.Cr * (trace_P / h**2 - p.phi) / (trace_P**2 / h**2),
126
+ p.Cr * (trace_P / h**2 - p.phi) / (trace_P**2 / h**2) > 0,
127
+ ),
128
+ (0, p.Cr * (trace_P / h**2 - p.phi) / (trace_P**2 / h**2) <= 0),
129
+ )
130
+ D11 = -2 * alpha / h * abs_u**3 * P11
131
+ Q = alpha * trace_P * abs_u**3
132
+
133
+ out[1] = -h * p.g * grad_b[0] - p.Cr * u * abs_u
134
+ out[2] = Q
135
+ return out
136
+
137
+ def chezy(self):
138
+ assert "Cf" in vars(self.parameters)
139
+ out = Matrix([0 for i in range(self.n_variables)])
140
+ Q = self.variables
141
+
142
+ u = Q[1] / Q[0]
143
+
144
+ p = self.parameters
145
+ abs_u = sympy.sqrt(u**2)
146
+ out[1] = -p.Cf * abs_u * u
147
+ # out[2] = - p.Cf * abs_u**3
148
+ return out
149
+
150
+
151
+ class ShearShallowFlowEnergy(Model):
152
+ """
153
+ Shallow Moments
154
+
155
+ :gui:
156
+ - tab: model
157
+ - requires: [ 'mesh.dimension': 1 ]
158
+
159
+ """
160
+
161
+ def __init__(
162
+ self,
163
+ boundary_conditions,
164
+ initial_conditions,
165
+ dimension=1,
166
+ fields=3,
167
+ aux_variables=0,
168
+ parameters={},
169
+ _default_parameters={"g": 1.0, "ex": 0.0, "ez": 1.0},
170
+ settings={},
171
+ settings_default={"topography": False, "friction": []},
172
+ ):
173
+ self.variables = register_sympy_attribute(fields, "q")
174
+ self.n_variables = self.variables.length()
175
+ super().__init__(
176
+ dimension=dimension,
177
+ fields=fields,
178
+ aux_variables=aux_variables,
179
+ parameters=parameters,
180
+ _default_parameters=_default_parameters,
181
+ boundary_conditions=boundary_conditions,
182
+ initial_conditions=initial_conditions,
183
+ settings={**settings_default, **settings},
184
+ )
185
+
186
+ def flux(self):
187
+ flux_x = Matrix([0 for i in range(self.n_variables)])
188
+
189
+ p = self.parameters
190
+ h = self.variables[0]
191
+ hu = self.variables[1]
192
+ u = hu / h
193
+ E = self.variables[2]
194
+ R = 2 * E - h * u**2
195
+ flux_x[0] = hu
196
+ flux_x[1] = hu * u + p.g * h**2 / 2 + R
197
+ flux_x[2] = (E + R) * u
198
+ return [flux_x]
199
+
200
+ def nonconservative_matrix(self):
201
+ nc_x = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
202
+ p = self.parameters
203
+ Q = self.variables
204
+ h = Q[0]
205
+ u = Q[1] / h
206
+ nc_x[2, 0] = -p.g * h * u
207
+ return [nc_x]
208
+
209
+ def chezy(self):
210
+ assert "Cf" in vars(self.parameters)
211
+ out = Matrix([0 for i in range(self.n_variables)])
212
+ Q = self.variables
213
+
214
+ u = Q[1] / Q[0]
215
+
216
+ p = self.parameters
217
+ abs_u = sympy.sqrt(u**2)
218
+ out[1] = -p.Cf * abs_u * u
219
+ out[2] = -p.Cf * abs_u**3
220
+ return out
221
+
222
+
223
+ class ShearShallowFlowPathconservative(Model):
224
+ """
225
+ Shallow Moments
226
+
227
+ :gui:
228
+ - tab: model
229
+ - requires: [ 'mesh.dimension': 1 ]
230
+
231
+ """
232
+
233
+ def __init__(
234
+ self,
235
+ boundary_conditions,
236
+ initial_conditions,
237
+ dimension=1,
238
+ fields=6,
239
+ aux_variables=0,
240
+ parameters={},
241
+ _default_parameters={"g": 1.0, "ex": 0.0, "ez": 1.0},
242
+ settings={},
243
+ settings_default={"topography": False, "friction": []},
244
+ ):
245
+ self.variables = register_sympy_attribute(fields, "q")
246
+ self.n_variables = self.variables.length()
247
+ super().__init__(
248
+ dimension=dimension,
249
+ fields=fields,
250
+ aux_variables=aux_variables,
251
+ parameters=parameters,
252
+ _default_parameters=_default_parameters,
253
+ boundary_conditions=boundary_conditions,
254
+ initial_conditions=initial_conditions,
255
+ settings={**settings_default, **settings},
256
+ )
257
+
258
+ def get_primitives(self, Q):
259
+ h = Q[0]
260
+ u = Q[1] / Q[0]
261
+ v = Q[2] / Q[0]
262
+ E11 = Q[3]
263
+ E12 = Q[4]
264
+ E22 = Q[5]
265
+ R11 = 2 * E11 - Q[1] ** 2 / Q[0]
266
+ R12 = 2 * E12 - Q[1] * Q[2] / Q[0]
267
+ R22 = 2 * E22 - Q[2] ** 2 / Q[0]
268
+ P11 = R11 / h
269
+ P12 = R12 / h
270
+ P22 = R22 / h
271
+ return h, u, v, R11, R12, R22, E11, E12, E22, P11, P12, P22
272
+
273
+ def flux(self):
274
+ flux_x = Matrix([0 for i in range(self.n_variables)])
275
+
276
+ h, u, v, R11, R12, R22, E11, E12, E22, P11, P12, P22 = self.get_primitives(
277
+ self.variables.get_list()
278
+ )
279
+ p = self.parameters
280
+
281
+ flux_x[0] = h * u
282
+ flux_x[1] = R11 + h * u**2 + 1 / 2 * p.g * h**2
283
+ flux_x[2] = R12 + h * u * v
284
+ flux_x[3] = (E11 + R11) * u
285
+ flux_x[4] = E12 * u + 1 / 2 * (R11 * v + R12 * u)
286
+ flux_x[5] = E22 * u + R12 * v
287
+ return [flux_x]
288
+
289
+ def nonconservative_matrix(self):
290
+ nc_x = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
291
+
292
+ h, u, v, R11, R12, R22, E11, E12, E22, P11, P12, P22 = self.get_primitives(
293
+ self.variables.get_list()
294
+ )
295
+ p = self.parameters
296
+
297
+ nc_x[3, 0] = -p.g * h * u
298
+ nc_x[4, 0] = -1 / 2 * p.g * h * v
299
+ return [nc_x]
300
+
301
+ def source(self):
302
+ out = Matrix([0 for i in range(self.n_variables)])
303
+ return out
304
+
305
+ def topography(self):
306
+ assert "dhdx" in vars(self.aux_variables)
307
+ out = Matrix([0 for i in range(self.n_variables)])
308
+ h = self.variables[0]
309
+ p = self.parameters
310
+ dhdx = self.aux_variables.dhdx
311
+ # out[1] = h * p.g * (p.ex - p.ez * dhdx)
312
+ return out
313
+
314
+ def eigenvalues(self):
315
+ evs = Matrix([0 for i in range(self.n_variables)])
316
+
317
+ h, u, v, R11, R12, R22, E11, E12, E22, P11, P12, P22 = self.get_primitives(
318
+ self.variables.get_list()
319
+ )
320
+ p = self.parameters
321
+
322
+ b = sympy.sqrt(P11)
323
+ a = sympy.sqrt(p.g * h + 3 * P11)
324
+
325
+ evs[0] = u - a
326
+ evs[1] = u - b
327
+ evs[2] = u
328
+ evs[3] = u
329
+ evs[4] = u + b
330
+ evs[5] = u + a
331
+
332
+ return evs
333
+
334
+ def chezy(self):
335
+ assert "Cf" in vars(self.parameters)
336
+ out = Matrix([0 for i in range(self.n_variables)])
337
+
338
+ h, u, v, R11, R12, R22, E11, E12, E22, P11, P12, P22 = self.get_primitives(
339
+ self.variables.get_list()
340
+ )
341
+ p = self.parameters
342
+
343
+ abs_u = sympy.sqrt(u**2 + v**2)
344
+ out[1] = p.Cf * abs_u * u
345
+ out[2] = -p.Cf * abs_u * v
346
+ out[3] = p.Cf * abs_u * u**2
347
+ out[4] = p.Cf * abs_u * u * v
348
+ out[5] = p.Cf * abs_u * v
349
+ return out
350
+
351
+ def friction_paper(self):
352
+ assert "Cf" in vars(self.parameters)
353
+ assert "Cr" in vars(self.parameters)
354
+ assert "g" in vars(self.parameters)
355
+ assert "theta" in vars(self.parameters)
356
+ out = Matrix([0 for i in range(self.n_variables)])
357
+
358
+ h, u, v, R11, R12, R22, E11, E12, E22, P11, P12, P22 = self.get_primitives(
359
+ self.variables.get_list()
360
+ )
361
+ p = self.parameters
362
+
363
+ abs_u = sympy.sqrt(u**2 + v**2)
364
+ grad_b = [-sympy.tan(p.theta)]
365
+ trace_P = P11 + P22
366
+ expr = p.Cr * (trace_P / h**2 - p.phi) / (trace_P**2 / h**2)
367
+ alpha = sympy.Piecewise((0, expr < 0), (expr, True))
368
+
369
+ out[1] = -h * p.g * grad_b[0] - p.Cf * abs_u * u
370
+ out[2] = -p.Cf * abs_u * v
371
+ out[3] = -alpha * abs_u**3 * P11 - p.g * h * u * grad_b[0] - p.Cf * abs_u * u**2
372
+ out[4] = (
373
+ -alpha * abs_u**3 * P12 - p.g * h * v * grad_b[0] - p.Cf * abs_u * u * v
374
+ )
375
+ out[5] = -alpha * abs_u**3 * P12 - p.Cf * abs_u * v
376
+ return out
377
+
378
+
379
+ class ShearShallowFlowPathconservative2(ShearShallowFlowPathconservative):
380
+ """
381
+ Shallow Moments
382
+
383
+ :gui:
384
+ - tab: model
385
+ - requires: [ 'mesh.dimension': 1 ]
386
+
387
+ """
388
+
389
+ def __init__(
390
+ self,
391
+ boundary_conditions,
392
+ initial_conditions,
393
+ dimension=1,
394
+ fields=6,
395
+ aux_variables=0,
396
+ parameters={},
397
+ _default_parameters={"g": 1.0, "ex": 0.0, "ez": 1.0},
398
+ settings={},
399
+ settings_default={"topography": False, "friction": []},
400
+ ):
401
+ self.variables = register_sympy_attribute(fields, "q")
402
+ self.n_variables = self.variables.length()
403
+ super().__init__(
404
+ dimension=dimension,
405
+ fields=fields,
406
+ aux_variables=aux_variables,
407
+ parameters=parameters,
408
+ _default_parameters=_default_parameters,
409
+ boundary_conditions=boundary_conditions,
410
+ initial_conditions=initial_conditions,
411
+ settings={**settings_default, **settings},
412
+ )
413
+
414
+ def flux(self):
415
+ SSF = ShearShallowFlowPathconservative(
416
+ boundary_conditions=self.boundary_conditions,
417
+ initial_conditions=self.initial_conditions,
418
+ parameters=self._default_parameters,
419
+ )
420
+ SSF.init_derived_sympy_functions()
421
+ flux_x = 0.0 * SSF.sympy_flux[0]
422
+ return [flux_x]
423
+
424
+ def nonconservative_matrix(self):
425
+ SSF = ShearShallowFlowPathconservative(
426
+ boundary_conditions=self.boundary_conditions,
427
+ initial_conditions=self.initial_conditions,
428
+ parameters=self._default_parameters,
429
+ )
430
+ SSF.init_derived_sympy_functions()
431
+ nc_x = SSF.sympy_nonconservative_matrix[0] - 1.0 * SSF.sympy_flux_jacobian[0]
432
+ return [nc_x]
433
+
434
+
435
+ class ShearShallowFlow2d(Model):
436
+ """
437
+ Shallow Moments 2d
438
+
439
+ :gui:
440
+ - tab: model
441
+ - requires: [ 'mesh.dimension': 1 ]
442
+
443
+ """
444
+
445
+ def __init__(
446
+ self,
447
+ boundary_conditions,
448
+ initial_conditions,
449
+ dimension=2,
450
+ fields=6,
451
+ aux_variables=0,
452
+ parameters={},
453
+ _default_parameters={"g": 1.0, "ex": 0.0, "ez": 1.0},
454
+ settings={},
455
+ settings_default={"topography": False, "friction": []},
456
+ ):
457
+ self.variables = register_sympy_attribute(fields, "q")
458
+ self.n_variables = self.variables.length()
459
+ super().__init__(
460
+ dimension=dimension,
461
+ fields=fields,
462
+ aux_variables=aux_variables,
463
+ parameters=parameters,
464
+ _default_parameters=_default_parameters,
465
+ boundary_conditions=boundary_conditions,
466
+ initial_conditions=initial_conditions,
467
+ settings={**settings_default, **settings},
468
+ )
469
+
470
+ def flux(self):
471
+ flux_x = Matrix([0 for i in range(self.n_variables)])
472
+ flux_y = Matrix([0 for i in range(self.n_variables)])
473
+ h = self.variables[0]
474
+ hu = self.variables[1]
475
+ hv = self.variables[2]
476
+ u = hu / h
477
+ v = hv / h
478
+ P11 = self.variables[3]
479
+ P12 = self.variables[4]
480
+ P22 = self.variables[5]
481
+ p = self.parameters
482
+ flux_x[0] = hu
483
+ flux_x[1] = hu * u + p.g * h**2 / 2 + P11
484
+ flux_x[2] = hu * v + h * P12
485
+ flux_x[3] = u * P11
486
+ flux_x[4] = u * P12
487
+ flux_x[5] = 0
488
+
489
+ flux_y[0] = hv
490
+ flux_y[1] = hu * v + P12
491
+ flux_y[2] = hv * v + p.g * h**2 / 2 + P22
492
+ flux_y[3] = 0
493
+ flux_y[4] = v * P12
494
+ flux_y[5] = v * P22
495
+ return [flux_x, flux_y]
496
+
497
+ def nonconservative_matrix(self):
498
+ nc_x = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
499
+ nc_y = Matrix([[0 for i in range(self.n_variables)] for j in range(self.n_variables)])
500
+ h = self.variables[0]
501
+ hu = self.variables[1]
502
+ hv = self.variables[2]
503
+ u = hu / h
504
+ v = hv / h
505
+ P11 = self.variables[3]
506
+ P12 = self.variables[4]
507
+ P22 = self.variables[5]
508
+
509
+ nc_x[3, 0] = -P11 / h
510
+ nc_x[3, 1] = +P11 / h
511
+ nc_y[3, 0] = -2 * P11 / h
512
+ nc_y[3, 1] = +2 * P11 / h
513
+ nc_y[3, 3] = +v
514
+
515
+ nc_x[4, 0] = -P11 / h
516
+ nc_x[4, 2] = +P11 / h
517
+ nc_y[4, 0] = -P22 / h
518
+ nc_y[4, 1] = +P22 / h
519
+
520
+ nc_x[5, 0] = -2 * P12 / h
521
+ nc_x[5, 2] = +2 * P12 / h
522
+ nc_y[5, 0] = -P22 / h
523
+ nc_y[5, 2] = +P22 / h
524
+ nc_x[5, 5] = u
525
+ return [nc_x, nc_y]
526
+
527
+ def source(self):
528
+ out = Matrix([0 for i in range(self.n_variables)])
529
+ return out
530
+
531
+ def topography(self):
532
+ assert "dhdx" in vars(self.aux_variables)
533
+ out = Matrix([0 for i in range(self.n_variables)])
534
+ h = self.variables[0]
535
+ p = self.parameters
536
+ dhdx = self.aux_variables.dhdx
537
+ # out[1] = h * p.g * (p.ex - p.ez * dhdx)
538
+ return out
539
+
540
+ def eigenvalues(self):
541
+ evs = Matrix([0 for i in range(self.n_variables)])
542
+ h = self.variables[0]
543
+ hu = self.variables[1]
544
+ hv = self.variables[2]
545
+ u = hu / h
546
+ v = hv / h
547
+ P11 = self.variables[3]
548
+ P12 = self.variables[4]
549
+ P22 = self.variables[5]
550
+ p = self.parameters
551
+
552
+ b = sympy.sqrt(P11)
553
+ a = sympy.sqrt(p.g * h + 3 * P11)
554
+
555
+ evs[0] = u
556
+ evs[1] = u
557
+ evs[2] = u + b
558
+ evs[3] = u - b
559
+ evs[4] = u + a
560
+ evs[5] = u - a
561
+
562
+ return evs
563
+
564
+ def friction_paper(self):
565
+ assert "phi" in vars(self.parameters)
566
+ assert "theta" in vars(self.parameters)
567
+ assert "Cr" in vars(self.parameters)
568
+ assert "g" in vars(self.parameters)
569
+ out = Matrix([0 for i in range(self.n_variables)])
570
+ h = self.variables[0]
571
+ hu = self.variables[1]
572
+ hv = self.variables[2]
573
+ u = hu / h
574
+ v = hv / h
575
+ P11 = self.variables[3]
576
+ P12 = self.variables[4]
577
+ P22 = self.variables[5]
578
+ p = self.parameters
579
+
580
+ abs_u = sympy.sqrt(u**2 + v**2)
581
+ trace_P = P11 + P22
582
+ grad_b = [-sympy.tan(p.theta), 0]
583
+ alpha = max(0, p.Cr * (trace_P / h**2 - p.phi) / (trace_P**2 / h**2))
584
+ D11 = -2 * alpha / h * abs_u**3 * P11
585
+ D12 = -2 * alpha / h * abs_u**3 * P12
586
+ D22 = -2 * alpha / h * abs_u**3 * P22
587
+ Q = alpha * trace_P * abs_u**3
588
+
589
+ out[1] = -h * p.g * grad_b[0] - p.Cr * u * abs_u
590
+ out[2] = -h * p.g * grad_b[1] - p.Cr * v * abs_u
591
+ out[3] = h * D11
592
+ out[4] = h * D12
593
+ out[5] = h * D22
594
+ return out