diffenix 0.0.0.1__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,230 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Callable, Any
4
+
5
+ import numpy as np
6
+ from scipy.linalg import solve
7
+
8
+
9
+ def grid_refine_inner_edge(x_orig: np.ndarray[np.float64],
10
+ nlev: int, nspan: int) -> np.ndarray[np.float64]:
11
+ """
12
+ A simple grid refinement function
13
+
14
+ Parameters
15
+ ----------
16
+ x_orig: np.ndarray[np.float64]
17
+ The origi,al grid to be refined
18
+ nlev: int
19
+ nspan: int
20
+
21
+ Returns
22
+ -------
23
+ np.ndarray[np.float64]
24
+ The refined grid
25
+
26
+ """
27
+
28
+ x: np.ndarray[np.float64] = x_orig.copy()
29
+ rev: bool = x[0] > x[1]
30
+
31
+ for ilev in range(nlev):
32
+ x_new = 0.5 * (x[1:nspan+1] + x[:nspan])
33
+ x_ref = np.hstack((x, x_new))
34
+ x_ref.sort()
35
+ x = x_ref
36
+ if rev:
37
+ x = x[::-1]
38
+
39
+ return x
40
+
41
+
42
+ def gradient_weno5(y: np.ndarray, dx: np.float64 = 1.0, axis: int = -1) -> np.ndarray:
43
+ """
44
+ Compute the spatial derivative of y following the WENO discretization scheme, robust to discontinuity,
45
+ along a specified axis.
46
+
47
+ Parameters
48
+ ----------
49
+ y : np.ndarray
50
+ The array to be derived
51
+ dx : np.float64, optional, default: 1.0
52
+ The space step, the space domain should be evenly spaced with dx
53
+ axis : int, optional, default: -1
54
+ The axis along which to compute the derivative
55
+
56
+ Returns
57
+ -------
58
+ np.ndarray
59
+ The order 1 spatial derivative of y at each point along the specified axis
60
+ """
61
+ eps: np.float64 = np.double(1e-200)
62
+
63
+ # Move the specified axis to the last position for easier manipulation
64
+ y = np.moveaxis(y, axis, -1)
65
+
66
+ # Initialize arrays for alpha0, alpha1, alpha2
67
+ alpha0 = ((13. / 12.) * (y[..., :-4] - 2. * y[..., 1:-3] + y[..., 2:-2]) ** 2
68
+ + (1. / 4.) * (y[..., :-4] - 4. * y[..., 1:-3] + 3. * y[..., 2:-2]) ** 2)
69
+ alpha1 = ((13. / 12.) * (y[..., 2:-2] - 2. * y[..., 3:-1] + y[..., 4:]) ** 2
70
+ + (1. / 4.) * (y[..., 2:-2] - y[..., 4:]) ** 2)
71
+ alpha2 = ((13. / 12.) * (y[..., 1:-3] - 2. * y[..., 2:-2] + y[..., 3:-1]) ** 2
72
+ + (1. / 4.) * (y[..., 1:-3] - 4. * y[..., 2:-2] + 3. * y[..., 3:-1]) ** 2)
73
+ # alpha0 = ((13. / 12.) * (y[..., 2:-2] - 2. * y[..., 3:-1] + y[..., 4:]) ** 2
74
+ # + (1. / 4.) * (3. * y[..., 2:-2] - 4. * y[..., 3:-1] + y[..., 4:]) ** 2)
75
+ # alpha1 = ((13. / 12.) * (y[..., 1:-3] - 2. * y[..., 2:-2] + y[..., 3:-1]) ** 2
76
+ # + (1. / 4.) * (y[..., 1:-3] - y[..., 3:-1]) ** 2)
77
+ # alpha2 = ((13. / 12.) * (y[..., :-4] - 2. * y[..., 1:-3] + y[..., 2:-2]) ** 2
78
+ # + (1. / 4.) * (y[..., :-4] - 4. * y[..., 1:-3] + 3. * y[..., 2:-2]) ** 2)
79
+ eps = 1e-6 * np.min([abs(alpha0), abs(alpha1), abs(alpha2)]) + 1e-150
80
+ # eps = 1e200
81
+ # print(eps, np.argwhere(np.isnan(alpha0)), np.argwhere(np.isnan(alpha1)), np.argwhere(np.isnan(alpha2)))
82
+ # Compute alpha0, alpha1, alpha2 along the last axis
83
+
84
+ alpha0 = 0.1 / ((eps + alpha0) * (eps + alpha0))
85
+
86
+ alpha1 = 0.6 / ((eps + alpha1) * (eps + alpha1))
87
+
88
+ alpha2 = 0.3 / ((eps + alpha2) * (eps + alpha2))
89
+
90
+ # print(alpha0, alpha1, alpha2)
91
+
92
+ # Compute fp
93
+ fp = (alpha0 * ((2. / 6.) * y[..., :-4] - (7. / 6.) * y[..., 1:-3] + (11. / 6.) * y[..., 2:-2])
94
+ + alpha1 * (-(1. / 6.) * y[..., 1:-3] + (5. / 6.) * y[..., 2:-2] + (2. / 6.) * y[..., 3:-1])
95
+ + alpha2 * ((2. / 6.) * y[..., 2:-2] + (5. / 6.) * y[..., 3:-1] - (1. / 6.) * y[..., 4:])) / (
96
+ alpha0 + alpha1 + alpha2)
97
+ # fp = (alpha0 * ((-1. / 6.) * y[..., :-4] + (5. / 6.) * y[..., 1:-3] + (2. / 6.) * y[..., 2:-2])
98
+ # + alpha1 * ((2. / 6.) * y[..., 1:-3] + (5. / 6.) * y[..., 2:-2] - (1. / 6.) * y[..., 3:-1])
99
+ # + alpha2 * ((11. / 6.) * y[..., 2:-2] - (7. / 6.) * y[..., 3:-1] + (2. / 6.) * y[..., 4:])) / (
100
+ # alpha0 + alpha1 + alpha2)
101
+ # Initialize result array
102
+ res = np.zeros_like(y)
103
+
104
+ # Compute the derivative along the last axis
105
+ res[..., 3:-2] = (fp[..., 1:] - fp[..., :-1]) / dx
106
+ # res[..., :3] = (y[..., 1:4] - y[..., :3]) / dx
107
+ res[..., 1:3] = (res[..., 2:4] - res[..., :2]) * 2 / dx
108
+ res[..., 0] = (y[..., 1] - y[..., 0]) / dx
109
+ res[..., -2:] = (y[..., -2:] - y[..., -3:-1]) / dx
110
+
111
+ # Move the axis back to its original position
112
+ res = np.moveaxis(res, -1, axis)
113
+ # return np.gradient(y, axis=axis) / dx
114
+ # return fp
115
+ return res
116
+
117
+
118
+ def gradient_g(y: np.ndarray[np.float64], dx: np.float64 = np.double(1), axis: int = -1) -> np.ndarray[np.float64]:
119
+ y = np.moveaxis(y, axis, -1)
120
+ res = np.zeros_like(y)
121
+ res[..., 1:] = (y[..., 1:] - y[..., :-1]) / dx
122
+ res[..., 0] = (y[..., 1] - y[..., 0]) / dx
123
+ res = np.moveaxis(res, -1, axis)
124
+ return res
125
+
126
+
127
+ def gradient_d(y: np.ndarray[np.float64], dx: np.float64 = np.double(1), axis: int = -1) -> np.ndarray[np.float64]:
128
+ y = np.moveaxis(y, axis, -1)
129
+ res = np.zeros_like(y)
130
+ res[..., :-1] = (y[..., 1:] - y[..., :-1]) / dx
131
+ res[..., -1] = (y[..., -1] - y[..., -2]) / dx
132
+ res = np.moveaxis(res, -1, axis)
133
+ return res
134
+
135
+
136
+ def gradient(y: np.ndarray[np.float64], dx: np.float64 = np.double(1), axis: int = -1,
137
+ radial_speed: np.ndarray[np.float64] = None) -> np.ndarray[np.float64]:
138
+ y = np.moveaxis(y, axis, -1)
139
+ dg = gradient_g(y, dx, axis)
140
+ dd = gradient_d(y, dx, axis)
141
+ if radial_speed is None:
142
+ res = (dg + dd) / 2
143
+ else:
144
+ res = dd
145
+ if np.any(radial_speed < 0):
146
+ idx_negs: np.ndarray[int] = np.argwhere(radial_speed < 0)[:, 0]
147
+ res[..., idx_negs] = dg[..., idx_negs]
148
+ res = np.moveaxis(res, -1, axis)
149
+ return res
150
+
151
+
152
+ def gradient2(y: np.ndarray[np.float64], dx: np.float64 = np.double(1), axis: int = -1) -> np.ndarray[np.float64]:
153
+ y = np.moveaxis(y, axis, -1)
154
+ res = np.zeros_like(y)
155
+ res[..., 1:-1] = (y[..., 2:] + y[..., :-2] - 2. * y[..., 1:-1]) / (dx * dx)
156
+ # res[..., 0] = (y[..., 0] - 2 * y[..., 1] + y[..., 2]) / (dx * dx)
157
+ # res[..., -1] = (y[..., -3] - 2 * y[..., -2] + y[..., -1]) / (dx * dx)
158
+ # res[wleft * wright == 0] = 0.
159
+ res = np.moveaxis(res, -1, axis)
160
+ return res
161
+
162
+
163
+ def linear_interpolation(x: np.ndarray[np.float64] | np.float64, y: np.ndarray[np.float64] | np.float64, ):
164
+ """
165
+ Linear interpolation
166
+
167
+ Parameters
168
+ ----------
169
+ x : np.float64 | np.ndarray[np.float64]
170
+ The variable
171
+ y : np.float64 | np.ndarray[np.float64]
172
+ The datapoints asssociated with the variable x to be interpolated. Both x and y can be multisimensionals vectors
173
+
174
+ Returns
175
+ -------
176
+ A function that returns the interpolated value
177
+ """
178
+
179
+ def result(x_new: np.float64) -> np.float64 | np.ndarray:
180
+ # i = np.searchsorted(x, x_new)
181
+ # i = np.clip(i, 0, len(x) - 2)
182
+ i = np.argmin(np.abs(x_new - x))
183
+ x1 = x[i]
184
+ x2 = x[i + 1]
185
+ alpha = (x_new - x1) / (x2 - x1)
186
+ y_new = (1 - alpha) * y[i] + alpha * y[i + 1]
187
+ return y_new
188
+
189
+ return result
190
+
191
+
192
+ # Intégration d'équations différentielles
193
+ class SolutionED:
194
+ def __init__(self, x, y: list | np.ndarray, itérations: int = -1):
195
+ self.t: np.ndarray = np.array(x)
196
+ self.y: np.ndarray = np.array(y).T
197
+ self.status: int = 0
198
+ self.iteration: int = itérations
199
+
200
+
201
+ def rk4(
202
+ f: Callable,
203
+ x0: np.float64 | np.ndarray = None, y0: np.float64 | np.ndarray = None,
204
+ xf: np.float64 = np.double(-1), dx_max: np.float64 = None,
205
+ args: list | tuple = None, IT_s_max: int = 1000,
206
+ f_dx: Callable = None,
207
+ ) -> SolutionED:
208
+ if args is None:
209
+ args = []
210
+ if dx_max is None:
211
+ dx_max: np.float64 = (xf - x0) / IT_s_max
212
+ Y = [y0]
213
+ Xf: list = [x0]
214
+ if f_dx is not None:
215
+ dx: np.float64 = np.sign(dx_max) * min(abs(dx_max), abs(f_dx(x0, y0, *args)))
216
+ else:
217
+ dx: np.float64 = dx_max
218
+ k1 = f(Xf[-1], Y[-1], *args)
219
+ while Xf[-1] < xf:
220
+ k2 = f(Xf[-1] + dx / 2, Y[-1] + (dx / 2) * k1, *args)
221
+ k3 = f(Xf[-1] + dx / 2, Y[-1] + (dx / 2) * k2, *args)
222
+ k4 = f(Xf[-1] + dx, Y[-1] + dx * k3, *args)
223
+ y = Y[-1] + (dx / 6) * (k1 + 2 * k2 + 2 * k3 + k4)
224
+ if f_dx is not None :
225
+ dx: np.float64 = np.sign(dx_max) * min(abs(dx_max), abs(f_dx(Xf[-1] + dx, y, *args)))
226
+ Xf.append(Xf[-1] + dx)
227
+ Y.append(y)
228
+
229
+ résultat: SolutionED = SolutionED(np.array(Xf), Y)
230
+ return résultat