layercake-model 1.0.2a0__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.
Files changed (47) hide show
  1. layercake/__init__.py +16 -0
  2. layercake/arithmetic/equation.py +410 -0
  3. layercake/arithmetic/symbolic/__init__.py +0 -0
  4. layercake/arithmetic/symbolic/expressions.py +73 -0
  5. layercake/arithmetic/symbolic/operators.py +338 -0
  6. layercake/arithmetic/terms/__init__.py +9 -0
  7. layercake/arithmetic/terms/base.py +884 -0
  8. layercake/arithmetic/terms/constant.py +119 -0
  9. layercake/arithmetic/terms/gradient.py +185 -0
  10. layercake/arithmetic/terms/jacobian.py +183 -0
  11. layercake/arithmetic/terms/linear.py +98 -0
  12. layercake/arithmetic/terms/operations.py +262 -0
  13. layercake/arithmetic/terms/operators.py +226 -0
  14. layercake/arithmetic/utils.py +20 -0
  15. layercake/bakery/__init__.py +0 -0
  16. layercake/bakery/cake.py +705 -0
  17. layercake/bakery/layers.py +569 -0
  18. layercake/basis/__init__.py +4 -0
  19. layercake/basis/base.py +244 -0
  20. layercake/basis/planar_fourier.py +418 -0
  21. layercake/basis/spherical_harmonics.py +166 -0
  22. layercake/formatters/__init__.py +0 -0
  23. layercake/formatters/base.py +183 -0
  24. layercake/formatters/fortran.py +85 -0
  25. layercake/formatters/julia.py +93 -0
  26. layercake/formatters/python.py +89 -0
  27. layercake/inner_products/__init__.py +0 -0
  28. layercake/inner_products/definition.py +218 -0
  29. layercake/utils/__init__.py +8 -0
  30. layercake/utils/commutativity.py +45 -0
  31. layercake/utils/integration.py +200 -0
  32. layercake/utils/matrix.py +104 -0
  33. layercake/utils/parallel.py +215 -0
  34. layercake/utils/symbolic_tensor.py +172 -0
  35. layercake/utils/tensor.py +83 -0
  36. layercake/variables/__init__.py +0 -0
  37. layercake/variables/coordinate.py +65 -0
  38. layercake/variables/field.py +535 -0
  39. layercake/variables/parameter.py +664 -0
  40. layercake/variables/systems.py +143 -0
  41. layercake/variables/utils.py +142 -0
  42. layercake/variables/variable.py +314 -0
  43. layercake_model-1.0.2a0.dist-info/METADATA +142 -0
  44. layercake_model-1.0.2a0.dist-info/RECORD +47 -0
  45. layercake_model-1.0.2a0.dist-info/WHEEL +5 -0
  46. layercake_model-1.0.2a0.dist-info/licenses/LICENSE.txt +11 -0
  47. layercake_model-1.0.2a0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,338 @@
1
+
2
+ """
3
+
4
+ Operators definition module
5
+ ===========================
6
+
7
+ This module defines various symbolic operators (mainly differential ones)
8
+ acting on the fields of the partial differential equations in |Sympy| expression.
9
+
10
+ """
11
+
12
+
13
+ from sympy.core.decorators import call_highest_priority
14
+ from sympy import Expr, Matrix, Mul, Add, diff
15
+ from sympy.core.numbers import Zero
16
+ from sympy import Derivative
17
+
18
+ from layercake.utils.commutativity import enable_commutativity, disable_commutativity
19
+ from layercake.variables.systems import CoordinateSystem
20
+
21
+ # courtesy of https://stackoverflow.com/questions/15463412/differential-operator-usable-in-matrix-form-in-python-module-sympy
22
+
23
+
24
+ class D(Expr):
25
+ """Symbolic differential operator acting on |Sympy| expression.
26
+ Inspired by `this post <https://stackoverflow.com/questions/15463412/differential-operator-usable-in-matrix-form-in-python-module-sympy>`_.
27
+
28
+ Parameters
29
+ ----------
30
+ *variables: ~sympy.core.symbol.Symbol
31
+ Variables with respect to which the operator differentiates.
32
+ The number of variables indicate the order of the derivative.
33
+
34
+ Attributes
35
+ ----------
36
+ variables: list(~sympy.core.symbol.Symbol)
37
+ Variables with respect to which the operator differentiates.
38
+ The number of variables indicate the order of the derivative.
39
+ evaluate: bool
40
+ Whether the expression resulting from the action of the operator is
41
+ evaluated.
42
+ Default to `False`.
43
+ latex: str
44
+ LaTeX representation of the operator.
45
+
46
+ """
47
+
48
+ _op_priority = 11.
49
+ is_commutative = False
50
+
51
+ def __new__(cls, *variables, **kwargs):
52
+ derivatives = Expr.__new__(cls, *variables, **kwargs)
53
+ derivatives.evaluate = False
54
+ nc_variables = [disable_commutativity(var) for var in variables]
55
+ derivatives.variables = nc_variables
56
+ latexes = list()
57
+ for var in variables:
58
+ if hasattr(var, 'latex'):
59
+ if var.latex is not None:
60
+ latexes.append(var.latex)
61
+ continue
62
+ if hasattr(var, 'symbol'):
63
+ if var.symbol is not None:
64
+ latexes.append(str(var.symbol))
65
+ continue
66
+ latexes.append(str(var))
67
+
68
+ if len(variables) > 1:
69
+ derivatives.latex = r'\frac{\partial^' + str(len(variables)) + r'}{'
70
+ else:
71
+ derivatives.latex = r'\frac{\partial}{'
72
+
73
+ for var in latexes[:-1]:
74
+ derivatives.latex += r'\partial ' + var + ' '
75
+ derivatives.latex += r'\partial ' + latexes[-1] + r'}'
76
+
77
+ return derivatives
78
+
79
+ def __repr__(self):
80
+ return 'D%s' % str(tuple(self.variables))
81
+
82
+ def __str__(self):
83
+ return self.__repr__()
84
+
85
+ @call_highest_priority('__mul__')
86
+ def __rmul__(self, other):
87
+ return Mul(other, self)
88
+
89
+ @call_highest_priority('__rmul__')
90
+ def __mul__(self, other):
91
+ if isinstance(other, D):
92
+ variables = self.variables + other.variables
93
+ return D(*variables)
94
+ if isinstance(other, Matrix):
95
+ other_copy = other.copy()
96
+ for i, elem in enumerate(other):
97
+ other_copy[i] = self * elem
98
+ return other_copy
99
+
100
+ if self.evaluate:
101
+ return diff(other, *self.variables)
102
+ else:
103
+ return Mul(self, other)
104
+
105
+ def __pow__(self, power, modulo=None):
106
+
107
+ if modulo is not None:
108
+ raise NotImplemented('D class: Modular exponentiation not implemented for derivatives')
109
+
110
+ variables = self.variables
111
+ for i in range(power - 1):
112
+ variables += self.variables
113
+ return D(*variables)
114
+
115
+
116
+ def _diff(expr, *variables):
117
+ if isinstance(expr, D):
118
+ expr.variables += variables
119
+ return D(*expr.variables)
120
+ if isinstance(expr, Matrix):
121
+ expr_copy = expr.copy()
122
+ for i, elem in enumerate(expr):
123
+ expr_copy[i] = diff(elem, *variables)
124
+ return expr_copy
125
+ return diff(expr, *variables)
126
+
127
+
128
+ def _evaluate_mul(expr):
129
+ end = 0
130
+ if expr.args:
131
+ if isinstance(expr.args[-1], D):
132
+ if len(expr.args[:-1]) == 1:
133
+ cte = expr.args[0]
134
+ return Zero()
135
+ end = -1
136
+ for i in range(len(expr.args)-1+end, -1, -1):
137
+ arg = expr.args[i]
138
+ if isinstance(arg, Add):
139
+ arg = _evaluate_add(arg)
140
+ if isinstance(arg, Mul):
141
+ arg = _evaluate_mul(arg)
142
+ if isinstance(arg, D):
143
+ left = Mul(*expr.args[:i])
144
+ right = Mul(*expr.args[i+1:])
145
+ right = _diff(right, *arg.variables)
146
+ ans = left * right
147
+ return _evaluate_mul(ans)
148
+ return expr
149
+
150
+
151
+ def _evaluate_add(expr):
152
+ newargs = []
153
+ for arg in expr.args:
154
+ if isinstance(arg, Mul):
155
+ arg = _evaluate_mul(arg)
156
+ if isinstance(arg, Add):
157
+ arg = _evaluate_add(arg)
158
+ if isinstance(arg, D):
159
+ arg = Zero()
160
+ newargs.append(arg)
161
+ return Add(*newargs)
162
+
163
+
164
+ def _test_if_derivative_in_expr(expr, subs):
165
+
166
+ status = False
167
+ for arg in expr.args:
168
+
169
+ if isinstance(arg, Derivative) or isinstance(arg, D):
170
+ if arg not in subs:
171
+ subs.append(arg)
172
+ status = True
173
+ if hasattr(arg, 'args'):
174
+ res = _test_if_derivative_in_expr(arg, subs)
175
+ if res:
176
+ status = True
177
+
178
+ return status
179
+
180
+
181
+ def evaluate_expr(expr):
182
+ """Evaluate a given |Sympy| expression.
183
+
184
+ Parameters
185
+ ----------
186
+ expr: ~sympy.core.expr.Expr
187
+ The expression to evaluate.
188
+
189
+ Returns
190
+ -------
191
+ ~sympy.core.expr.Expr
192
+ The evaluated expression.
193
+
194
+ """
195
+ if isinstance(expr, Matrix):
196
+ for i, elem in enumerate(expr):
197
+ elem = elem.expand()
198
+ expr[i] = evaluate_expr(elem)
199
+ return enable_commutativity(expr)
200
+ expr = expr.expand()
201
+ if isinstance(expr, Mul):
202
+ expr = _evaluate_mul(expr)
203
+ elif isinstance(expr, Add):
204
+ expr = _evaluate_add(expr)
205
+ elif isinstance(expr, D):
206
+ expr = Zero()
207
+
208
+ constant = True
209
+ while constant:
210
+ repl = list()
211
+ constant = _test_if_derivative_in_expr(expr, repl)
212
+ if constant:
213
+ new_expr = expr.replace(repl[0], Zero())
214
+ for rep in repl[1:]:
215
+ new_expr = new_expr.replace(rep, Zero())
216
+ else:
217
+ new_expr = expr
218
+
219
+ expr = new_expr
220
+
221
+ return expr
222
+
223
+
224
+ def _latex_repr(r):
225
+ def wrapper(f):
226
+ f.latex = r
227
+ return f
228
+ return wrapper
229
+
230
+
231
+ @_latex_repr(r'\nabla')
232
+ def Nabla(coordinate_system):
233
+ """Function returning the Nabla (Del - :math:`\\nabla`) operator associated with a given
234
+ coordinate system.
235
+
236
+ Notes
237
+ -----
238
+ The returned expression has an additional `latex` attribute.
239
+
240
+ Parameters
241
+ ----------
242
+ coordinate_system: ~systems.CoordinateSystem
243
+ Coordinate system for which the :math:`\\nabla` operator must be returned.
244
+
245
+ Returns
246
+ -------
247
+ ~sympy.core.expr.Expr
248
+ The :math:`\\nabla` operator associated with the coordinate system.
249
+
250
+ """
251
+ if not isinstance(coordinate_system, CoordinateSystem):
252
+ raise ValueError('Nabla only take coordinates systems as input.')
253
+
254
+ derivative_list = list()
255
+ for coord in coordinate_system.coordinates:
256
+ derivative_list.append(Mul(coord.infinitesimal_length**(-1), D(coord.symbol), evaluate=False))
257
+
258
+ mat = Matrix([derivative_list])
259
+ mat.latex = r'\nabla'
260
+ return mat
261
+
262
+
263
+ @_latex_repr(r'\nabla \cdot')
264
+ def Divergence(coordinate_system):
265
+ """Function returning the divergence (:math:`\\nabla \\cdot`) operator associated with a given
266
+ coordinate system.
267
+
268
+ Notes
269
+ -----
270
+ The returned expression has an additional `latex` attribute.
271
+
272
+ Parameters
273
+ ----------
274
+ coordinate_system: ~systems.CoordinateSystem
275
+ Coordinate system for which the divergence operator must be returned.
276
+
277
+ Returns
278
+ -------
279
+ ~sympy.core.expr.Expr
280
+ The divergence operator associated with the coordinate system.
281
+
282
+ """
283
+
284
+ if not isinstance(coordinate_system, CoordinateSystem):
285
+ raise ValueError('Divergence only take coordinates systems as input.')
286
+
287
+ derivative_list = list()
288
+ volume = coordinate_system.infinitesimal_volume
289
+ for coord in coordinate_system.coordinates:
290
+ derivative_list.append(Mul(volume**(-1), Mul(D(coord.symbol), volume / coord.infinitesimal_length,
291
+ evaluate=False), evaluate=False))
292
+
293
+ mat = Matrix([derivative_list])
294
+ mat.latex = r'\nabla \cdot'
295
+ return mat
296
+
297
+
298
+ class _Add_Laplacian(Add):
299
+
300
+ def __new__(cls, *args, **kwargs):
301
+ a = Add.__new__(cls, *args, **kwargs)
302
+ a._latex = r'\nabla^2'
303
+
304
+ return a
305
+
306
+ @property
307
+ def latex(self):
308
+ return self._latex
309
+
310
+
311
+ @_latex_repr(r'\nabla^2')
312
+ def Laplacian(coordinate_system):
313
+ """Function returning the Laplacian (:math:`\\nabla^2`) operator associated with a given
314
+ coordinate system.
315
+
316
+ Notes
317
+ -----
318
+ The returned expression has an additional `latex` attribute.
319
+
320
+ Parameters
321
+ ----------
322
+ coordinate_system: ~systems.CoordinateSystem
323
+ Coordinate system for which the Laplacian operator must be returned.
324
+
325
+ Returns
326
+ -------
327
+ ~sympy.core.expr.Expr
328
+ The Laplacian operator associated with the coordinate system.
329
+
330
+ """
331
+ if not isinstance(coordinate_system, CoordinateSystem):
332
+ raise ValueError('Laplacian only take coordinates systems as input.')
333
+ nabla = Nabla(coordinate_system)
334
+ divergence = Divergence(coordinate_system)
335
+ laplacian = Mul(divergence[0] * nabla[0], evaluate=False)
336
+ for i in range(1, len(nabla)):
337
+ laplacian = _Add_Laplacian(laplacian, Mul(divergence[i] * nabla[i], evaluate=False))
338
+ return laplacian
@@ -0,0 +1,9 @@
1
+
2
+ from .jacobian import vorticity_advection, Jacobian
3
+ from .operators import OperatorTerm
4
+ from .operations import AdditionOfTerms, ProductOfTerms
5
+ from .linear import LinearTerm
6
+ from .constant import ConstantTerm
7
+
8
+ __all__ = ['vorticity_advection', 'Jacobian', 'ProductOfTerms',
9
+ 'OperatorTerm', 'AdditionOfTerms', 'LinearTerm', 'ConstantTerm']