pynamicalsys 1.2.2__py3-none-any.whl → 1.3.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.
- pynamicalsys/__version__.py +16 -3
- pynamicalsys/common/recurrence_quantification_analysis.py +1 -1
- pynamicalsys/common/utils.py +23 -24
- pynamicalsys/continuous_time/chaotic_indicators.py +176 -80
- pynamicalsys/continuous_time/numerical_integrators.py +8 -8
- pynamicalsys/continuous_time/trajectory_analysis.py +60 -24
- pynamicalsys/core/continuous_dynamical_systems.py +184 -11
- pynamicalsys/core/discrete_dynamical_systems.py +264 -16
- pynamicalsys/discrete_time/dynamical_indicators.py +415 -171
- pynamicalsys/discrete_time/models.py +2 -2
- pynamicalsys/discrete_time/trajectory_analysis.py +10 -10
- pynamicalsys/discrete_time/transport.py +74 -112
- pynamicalsys/discrete_time/validators.py +1 -1
- {pynamicalsys-1.2.2.dist-info → pynamicalsys-1.3.1.dist-info}/METADATA +3 -3
- pynamicalsys-1.3.1.dist-info/RECORD +28 -0
- pynamicalsys-1.2.2.dist-info/RECORD +0 -28
- {pynamicalsys-1.2.2.dist-info → pynamicalsys-1.3.1.dist-info}/WHEEL +0 -0
- {pynamicalsys-1.2.2.dist-info → pynamicalsys-1.3.1.dist-info}/top_level.txt +0 -0
pynamicalsys/__version__.py
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
# file generated by setuptools-scm
|
2
2
|
# don't change, don't track in version control
|
3
3
|
|
4
|
-
__all__ = [
|
4
|
+
__all__ = [
|
5
|
+
"__version__",
|
6
|
+
"__version_tuple__",
|
7
|
+
"version",
|
8
|
+
"version_tuple",
|
9
|
+
"__commit_id__",
|
10
|
+
"commit_id",
|
11
|
+
]
|
5
12
|
|
6
13
|
TYPE_CHECKING = False
|
7
14
|
if TYPE_CHECKING:
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
9
16
|
from typing import Union
|
10
17
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
19
|
+
COMMIT_ID = Union[str, None]
|
12
20
|
else:
|
13
21
|
VERSION_TUPLE = object
|
22
|
+
COMMIT_ID = object
|
14
23
|
|
15
24
|
version: str
|
16
25
|
__version__: str
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
18
27
|
version_tuple: VERSION_TUPLE
|
28
|
+
commit_id: COMMIT_ID
|
29
|
+
__commit_id__: COMMIT_ID
|
19
30
|
|
20
|
-
__version__ = version = '1.
|
21
|
-
__version_tuple__ = version_tuple = (1,
|
31
|
+
__version__ = version = '1.3.1'
|
32
|
+
__version_tuple__ = version_tuple = (1, 3, 1)
|
33
|
+
|
34
|
+
__commit_id__ = commit_id = None
|
pynamicalsys/common/utils.py
CHANGED
@@ -21,7 +21,7 @@ from numpy.typing import NDArray
|
|
21
21
|
from numba import njit
|
22
22
|
|
23
23
|
|
24
|
-
@njit
|
24
|
+
@njit
|
25
25
|
def qr(M: NDArray[np.float64]) -> Tuple[NDArray[np.float64], NDArray[np.float64]]:
|
26
26
|
"""
|
27
27
|
Perform numerically stable QR decomposition using modified Gram-Schmidt with reorthogonalization.
|
@@ -92,7 +92,7 @@ def qr(M: NDArray[np.float64]) -> Tuple[NDArray[np.float64], NDArray[np.float64]
|
|
92
92
|
return Q, R
|
93
93
|
|
94
94
|
|
95
|
-
@njit
|
95
|
+
@njit
|
96
96
|
def householder_qr(
|
97
97
|
M: NDArray[np.float64],
|
98
98
|
) -> Tuple[NDArray[np.float64], NDArray[np.float64]]:
|
@@ -184,7 +184,7 @@ def householder_qr(
|
|
184
184
|
return Q, R
|
185
185
|
|
186
186
|
|
187
|
-
@njit
|
187
|
+
@njit
|
188
188
|
def finite_difference_jacobian(
|
189
189
|
u: NDArray[np.float64],
|
190
190
|
parameters: NDArray[np.float64],
|
@@ -257,7 +257,7 @@ def finite_difference_jacobian(
|
|
257
257
|
|
258
258
|
|
259
259
|
@njit
|
260
|
-
def
|
260
|
+
def wedge_norm_2(vectors: NDArray[np.float64]) -> float:
|
261
261
|
"""
|
262
262
|
Computes the norm of the wedge product of n m-dimensional vectors using the Gram determinant.
|
263
263
|
|
@@ -295,6 +295,25 @@ def wedge_product_norm(vectors: NDArray[np.float64]) -> float:
|
|
295
295
|
return norm
|
296
296
|
|
297
297
|
|
298
|
+
def wedge_norm(V: NDArray[np.float64]) -> float:
|
299
|
+
"""
|
300
|
+
Computes the norm of the wedge product of k d-dimensional vectors using the Gram determinant.
|
301
|
+
|
302
|
+
Parameters:
|
303
|
+
vectors : NDArray[np.float64]
|
304
|
+
A (d, k) array where d is the dimension and k is the number of vectors.
|
305
|
+
|
306
|
+
Returns:
|
307
|
+
norm : float
|
308
|
+
The norm (magnitude) of the wedge product.
|
309
|
+
"""
|
310
|
+
G = V.T @ V # Gram matrix, shape (k, k)
|
311
|
+
|
312
|
+
det = np.linalg.det(G)
|
313
|
+
|
314
|
+
return 0 if det < 0 else np.sqrt(det)
|
315
|
+
|
316
|
+
|
298
317
|
@njit
|
299
318
|
def _coeff_mat(x: NDArray[np.float64], deg: int) -> NDArray[np.float64]:
|
300
319
|
mat_ = np.zeros(shape=(x.shape[0], deg + 1))
|
@@ -322,23 +341,3 @@ def fit_poly(
|
|
322
341
|
p = _fit_x(a, y)
|
323
342
|
# Reverse order so p[0] is coefficient of highest order
|
324
343
|
return p[::-1]
|
325
|
-
|
326
|
-
|
327
|
-
if __name__ == "__main__":
|
328
|
-
|
329
|
-
v = np.random.rand(2, 2)
|
330
|
-
w = v.copy()
|
331
|
-
|
332
|
-
q, r = qr(v)
|
333
|
-
print("Q:\n", q)
|
334
|
-
print("R:\n", r)
|
335
|
-
print("QR Product:\n", np.dot(q, r))
|
336
|
-
print("Original Matrix:\n", v)
|
337
|
-
|
338
|
-
print()
|
339
|
-
|
340
|
-
q, r = householder_qr(v)
|
341
|
-
print("Q:\n", q)
|
342
|
-
print("R:\n", r)
|
343
|
-
print("QR Product:\n", np.dot(q, r))
|
344
|
-
print("Original Matrix:\n", v)
|
@@ -18,14 +18,14 @@
|
|
18
18
|
from typing import Optional, Callable, Union, Tuple, Dict, List, Any, Sequence
|
19
19
|
from numpy.typing import NDArray
|
20
20
|
import numpy as np
|
21
|
-
from numba import njit
|
21
|
+
from numba import njit
|
22
22
|
|
23
|
-
from pynamicalsys.common.utils import qr
|
24
|
-
from pynamicalsys.continuous_time.trajectory_analysis import evolve_system
|
23
|
+
from pynamicalsys.common.utils import qr, wedge_norm
|
24
|
+
from pynamicalsys.continuous_time.trajectory_analysis import step, evolve_system
|
25
25
|
from pynamicalsys.continuous_time.numerical_integrators import rk4_step_wrapped
|
26
26
|
|
27
27
|
|
28
|
-
@njit
|
28
|
+
# @njit
|
29
29
|
def lyapunov_exponents(
|
30
30
|
u: NDArray[np.float64],
|
31
31
|
parameters: NDArray[np.float64],
|
@@ -36,6 +36,7 @@ def lyapunov_exponents(
|
|
36
36
|
jacobian: Callable[
|
37
37
|
[np.float64, NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]
|
38
38
|
],
|
39
|
+
num_exponents: int,
|
39
40
|
transient_time: Optional[float] = None,
|
40
41
|
time_step: float = 0.01,
|
41
42
|
atol: float = 1e-6,
|
@@ -50,7 +51,7 @@ def lyapunov_exponents(
|
|
50
51
|
) -> NDArray[np.float64]:
|
51
52
|
|
52
53
|
neq = len(u) # Number of equations of the system
|
53
|
-
nt = neq + neq
|
54
|
+
nt = neq + neq * num_exponents # system + variational equations
|
54
55
|
|
55
56
|
u = u.copy()
|
56
57
|
|
@@ -79,57 +80,55 @@ def lyapunov_exponents(
|
|
79
80
|
# Randomly define the deviation vectors and orthonormalize them
|
80
81
|
np.random.seed(seed)
|
81
82
|
uv[neq:] = -1 + 2 * np.random.rand(nt - neq)
|
82
|
-
v = uv[neq:].reshape(neq,
|
83
|
+
v = uv[neq:].reshape(neq, num_exponents)
|
83
84
|
v, _ = QR(v)
|
84
|
-
uv[neq:] = v.reshape(neq
|
85
|
+
uv[neq:] = v.reshape(neq * num_exponents)
|
85
86
|
|
86
|
-
exponents = np.zeros(
|
87
|
+
exponents = np.zeros(num_exponents, dtype=np.float64)
|
87
88
|
history = []
|
88
89
|
|
89
90
|
while time < total_time:
|
90
91
|
if time + time_step > total_time:
|
91
92
|
time_step = total_time - time
|
92
93
|
|
93
|
-
|
94
|
+
uv, time, time_step = step(
|
94
95
|
time,
|
95
96
|
uv,
|
96
97
|
parameters,
|
97
98
|
equations_of_motion,
|
98
99
|
jacobian=jacobian,
|
99
100
|
time_step=time_step,
|
101
|
+
atol=atol,
|
102
|
+
rtol=rtol,
|
103
|
+
integrator=integrator,
|
104
|
+
number_of_deviation_vectors=num_exponents,
|
100
105
|
)
|
101
106
|
|
102
|
-
|
103
|
-
|
104
|
-
uv = uv_new.copy()
|
105
|
-
# Reshape the deviation vectors into a neq x neq matrix
|
106
|
-
v = uv[neq:].reshape(neq, neq).copy()
|
107
|
+
# Reshape the deviation vectors into a neq x neq matrix
|
108
|
+
v = uv[neq:].reshape(neq, num_exponents).copy()
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
+
# Perform the QR decomposition
|
111
|
+
v, R = QR(v)
|
112
|
+
# Accumulate the log
|
113
|
+
exponents += np.log(np.abs(np.diag(R))) / np.log(log_base)
|
110
114
|
|
111
|
-
|
112
|
-
|
115
|
+
if return_history:
|
116
|
+
result = [time]
|
117
|
+
for i in range(num_exponents):
|
118
|
+
result.append(
|
119
|
+
exponents[i]
|
120
|
+
/ (time - (transient_time if transient_time is not None else 0))
|
121
|
+
)
|
122
|
+
history.append(result)
|
113
123
|
|
114
|
-
|
115
|
-
|
116
|
-
for i in range(neq):
|
117
|
-
result.append(
|
118
|
-
exponents[i]
|
119
|
-
/ (time - (transient_time if transient_time is not None else 0))
|
120
|
-
)
|
121
|
-
history.append(result)
|
122
|
-
|
123
|
-
# Reshape v back to uv
|
124
|
-
uv[neq:] = v.reshape(neq**2)
|
125
|
-
|
126
|
-
time_step = time_step_new
|
124
|
+
# Reshape v back to uv
|
125
|
+
uv[neq:] = v.reshape(neq * num_exponents)
|
127
126
|
|
128
127
|
if return_history:
|
129
128
|
return history
|
130
129
|
else:
|
131
130
|
result = []
|
132
|
-
for i in range(
|
131
|
+
for i in range(num_exponents):
|
133
132
|
result.append(
|
134
133
|
exponents[i]
|
135
134
|
/ (time - (transient_time if transient_time is not None else 0))
|
@@ -137,7 +136,7 @@ def lyapunov_exponents(
|
|
137
136
|
return [result]
|
138
137
|
|
139
138
|
|
140
|
-
@njit
|
139
|
+
@njit
|
141
140
|
def SALI(
|
142
141
|
u: NDArray[np.float64],
|
143
142
|
parameters: NDArray[np.float64],
|
@@ -197,44 +196,41 @@ def SALI(
|
|
197
196
|
if time + time_step > total_time:
|
198
197
|
time_step = total_time - time
|
199
198
|
|
200
|
-
|
199
|
+
uv, time, time_step = step(
|
201
200
|
time,
|
202
201
|
uv,
|
203
202
|
parameters,
|
204
203
|
equations_of_motion,
|
205
204
|
jacobian=jacobian,
|
206
205
|
time_step=time_step,
|
206
|
+
atol=atol,
|
207
|
+
rtol=rtol,
|
208
|
+
integrator=integrator,
|
207
209
|
number_of_deviation_vectors=ndv,
|
208
210
|
)
|
209
211
|
|
210
|
-
|
211
|
-
|
212
|
-
uv = uv_new.copy()
|
213
|
-
|
214
|
-
# Reshape the deviation vectors into a neq x ndv matrix
|
215
|
-
v = uv[neq:].reshape(neq, ndv)
|
212
|
+
# Reshape the deviation vectors into a neq x ndv matrix
|
213
|
+
v = uv[neq:].reshape(neq, ndv)
|
216
214
|
|
217
|
-
|
218
|
-
|
219
|
-
|
215
|
+
# Normalize the deviation vectors
|
216
|
+
v[:, 0] /= np.linalg.norm(v[:, 0])
|
217
|
+
v[:, 1] /= np.linalg.norm(v[:, 1])
|
220
218
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
219
|
+
# Calculate the aligment indexes and SALI
|
220
|
+
PAI = np.linalg.norm(v[:, 0] + v[:, 1])
|
221
|
+
AAI = np.linalg.norm(v[:, 0] - v[:, 1])
|
222
|
+
sali = min(PAI, AAI)
|
225
223
|
|
226
|
-
|
227
|
-
|
228
|
-
|
224
|
+
if return_history:
|
225
|
+
result = [time, sali]
|
226
|
+
history.append(result)
|
229
227
|
|
230
|
-
|
231
|
-
|
232
|
-
|
228
|
+
# Early termination
|
229
|
+
if sali <= threshold:
|
230
|
+
break
|
233
231
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
time_step = time_step_new
|
232
|
+
# Reshape v back to uv
|
233
|
+
uv[neq:] = v.reshape(neq * ndv)
|
238
234
|
|
239
235
|
if return_history:
|
240
236
|
return history
|
@@ -242,7 +238,7 @@ def SALI(
|
|
242
238
|
return [[time, sali]]
|
243
239
|
|
244
240
|
|
245
|
-
# @njit
|
241
|
+
# @njit
|
246
242
|
def LDI(
|
247
243
|
u: NDArray[np.float64],
|
248
244
|
parameters: NDArray[np.float64],
|
@@ -303,45 +299,145 @@ def LDI(
|
|
303
299
|
if time + time_step > total_time:
|
304
300
|
time_step = total_time - time
|
305
301
|
|
306
|
-
|
302
|
+
uv, time, time_step = step(
|
307
303
|
time,
|
308
304
|
uv,
|
309
305
|
parameters,
|
310
306
|
equations_of_motion,
|
311
307
|
jacobian=jacobian,
|
312
308
|
time_step=time_step,
|
309
|
+
atol=atol,
|
310
|
+
rtol=rtol,
|
311
|
+
integrator=integrator,
|
313
312
|
number_of_deviation_vectors=ndv,
|
314
313
|
)
|
315
314
|
|
316
|
-
|
317
|
-
|
318
|
-
|
315
|
+
# Reshape the deviation vectors into a neq x ndv matrix
|
316
|
+
v = uv[neq:].reshape(neq, ndv)
|
317
|
+
|
318
|
+
# Normalize the deviation vectors
|
319
|
+
for i in range(ndv):
|
320
|
+
v[:, i] /= np.linalg.norm(v[:, i])
|
321
|
+
|
322
|
+
# Calculate the singular values
|
323
|
+
S = np.linalg.svd(v, full_matrices=False, compute_uv=False)
|
324
|
+
ldi = np.exp(np.sum(np.log(S))) # LDI is the product of all singular values
|
325
|
+
# Instead of computing prod(S) directly, which could lead to underflows
|
326
|
+
# or overflows, we compute the sum_{i=1}^k log(S_i) and then take the
|
327
|
+
# exponential of this sum.
|
319
328
|
|
320
|
-
|
321
|
-
|
329
|
+
if return_history:
|
330
|
+
result = [time, ldi]
|
331
|
+
history.append(result)
|
322
332
|
|
323
|
-
|
324
|
-
|
325
|
-
|
333
|
+
# Early termination
|
334
|
+
if ldi <= threshold:
|
335
|
+
break
|
326
336
|
|
327
|
-
|
328
|
-
|
329
|
-
|
337
|
+
# Reshape v back to uv
|
338
|
+
uv[neq:] = v.reshape(neq * ndv)
|
339
|
+
|
340
|
+
if return_history:
|
341
|
+
return history
|
342
|
+
else:
|
343
|
+
return [[time, ldi]]
|
330
344
|
|
331
|
-
if return_history:
|
332
|
-
result = [time, ldi]
|
333
|
-
history.append(result)
|
334
345
|
|
335
|
-
|
336
|
-
|
337
|
-
|
346
|
+
def GALI(
|
347
|
+
u: NDArray[np.float64],
|
348
|
+
parameters: NDArray[np.float64],
|
349
|
+
total_time: float,
|
350
|
+
equations_of_motion: Callable[
|
351
|
+
[np.float64, NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]
|
352
|
+
],
|
353
|
+
jacobian: Callable[
|
354
|
+
[np.float64, NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]
|
355
|
+
],
|
356
|
+
number_deviation_vectors: int,
|
357
|
+
transient_time: Optional[float] = None,
|
358
|
+
time_step: float = 0.01,
|
359
|
+
atol: float = 1e-6,
|
360
|
+
rtol: float = 1e-3,
|
361
|
+
integrator=rk4_step_wrapped,
|
362
|
+
return_history: bool = False,
|
363
|
+
seed: int = 13,
|
364
|
+
threshold: float = 1e-16,
|
365
|
+
) -> NDArray[np.float64]:
|
338
366
|
|
339
|
-
|
340
|
-
|
367
|
+
neq = len(u) # Number of equations of the system
|
368
|
+
ndv = number_deviation_vectors # Number of deviation vectors
|
369
|
+
nt = neq + neq * ndv # Total number of equations including variational equations
|
341
370
|
|
342
|
-
|
371
|
+
u = u.copy()
|
372
|
+
|
373
|
+
# Handle transient time
|
374
|
+
if transient_time is not None:
|
375
|
+
u = evolve_system(
|
376
|
+
u,
|
377
|
+
parameters,
|
378
|
+
transient_time,
|
379
|
+
equations_of_motion,
|
380
|
+
time_step=time_step,
|
381
|
+
atol=atol,
|
382
|
+
rtol=rtol,
|
383
|
+
integrator=integrator,
|
384
|
+
)
|
385
|
+
time = transient_time
|
386
|
+
else:
|
387
|
+
time = 0
|
388
|
+
|
389
|
+
# State + deviation vectors
|
390
|
+
uv = np.zeros(nt)
|
391
|
+
uv[:neq] = u.copy()
|
392
|
+
|
393
|
+
# Randomly define the deviation vectors and orthonormalize them
|
394
|
+
np.random.seed(seed)
|
395
|
+
uv[neq:] = -1 + 2 * np.random.rand(nt - neq)
|
396
|
+
v = uv[neq:].reshape(neq, ndv)
|
397
|
+
v, _ = qr(v)
|
398
|
+
uv[neq:] = v.reshape(neq * ndv)
|
399
|
+
|
400
|
+
history = []
|
401
|
+
|
402
|
+
while time < total_time:
|
403
|
+
if time + time_step > total_time:
|
404
|
+
time_step = total_time - time
|
405
|
+
|
406
|
+
uv, time, time_step = step(
|
407
|
+
time,
|
408
|
+
uv,
|
409
|
+
parameters,
|
410
|
+
equations_of_motion,
|
411
|
+
jacobian=jacobian,
|
412
|
+
time_step=time_step,
|
413
|
+
atol=atol,
|
414
|
+
rtol=rtol,
|
415
|
+
integrator=integrator,
|
416
|
+
number_of_deviation_vectors=ndv,
|
417
|
+
)
|
418
|
+
|
419
|
+
# Reshape the deviation vectors into a neq x ndv matrix
|
420
|
+
v = uv[neq:].reshape(neq, ndv)
|
421
|
+
|
422
|
+
# Normalize the deviation vectors
|
423
|
+
for i in range(ndv):
|
424
|
+
v[:, i] /= np.linalg.norm(v[:, i])
|
425
|
+
|
426
|
+
# Calculate GALI
|
427
|
+
gali = wedge_norm(v)
|
428
|
+
|
429
|
+
if return_history:
|
430
|
+
result = [time, gali]
|
431
|
+
history.append(result)
|
432
|
+
|
433
|
+
# Early termination
|
434
|
+
if gali <= threshold:
|
435
|
+
break
|
436
|
+
|
437
|
+
# Reshape v back to uv
|
438
|
+
uv[neq:] = v.reshape(neq * ndv)
|
343
439
|
|
344
440
|
if return_history:
|
345
441
|
return history
|
346
442
|
else:
|
347
|
-
return [[time,
|
443
|
+
return [[time, gali]]
|
@@ -23,7 +23,7 @@ from numba import njit, prange
|
|
23
23
|
from pynamicalsys.continuous_time.models import variational_equations
|
24
24
|
|
25
25
|
|
26
|
-
@njit
|
26
|
+
@njit
|
27
27
|
def rk4_step(
|
28
28
|
t: float,
|
29
29
|
u: NDArray[np.float64],
|
@@ -43,7 +43,7 @@ def rk4_step(
|
|
43
43
|
return u_next
|
44
44
|
|
45
45
|
|
46
|
-
@njit
|
46
|
+
@njit
|
47
47
|
def variational_rk4_step(
|
48
48
|
t: float,
|
49
49
|
u: NDArray[np.float64],
|
@@ -115,7 +115,7 @@ RK45_B4 = np.array(
|
|
115
115
|
)
|
116
116
|
|
117
117
|
|
118
|
-
@njit
|
118
|
+
@njit
|
119
119
|
def rk45_step(t, u, parameters, equations_of_motion, time_step, atol=1e-6, rtol=1e-3):
|
120
120
|
"""Single adaptive step of RK45 (Dormand-Prince).
|
121
121
|
|
@@ -163,7 +163,7 @@ def rk45_step(t, u, parameters, equations_of_motion, time_step, atol=1e-6, rtol=
|
|
163
163
|
return u5, t + time_step, time_step_new, accept
|
164
164
|
|
165
165
|
|
166
|
-
@njit
|
166
|
+
@njit
|
167
167
|
def variational_rk45_step(
|
168
168
|
t,
|
169
169
|
u,
|
@@ -227,7 +227,7 @@ def variational_rk45_step(
|
|
227
227
|
return u5, t + time_step, time_step_new, accept
|
228
228
|
|
229
229
|
|
230
|
-
@njit
|
230
|
+
@njit
|
231
231
|
def rk4_step_wrapped(
|
232
232
|
t: float,
|
233
233
|
u: NDArray[np.float64],
|
@@ -237,7 +237,7 @@ def rk4_step_wrapped(
|
|
237
237
|
],
|
238
238
|
jacobian=None,
|
239
239
|
time_step: float = 0.01,
|
240
|
-
number_of_deviation_vectors=None,
|
240
|
+
number_of_deviation_vectors: Optional[int] = None,
|
241
241
|
atol: float = 1e-6, # unused, just to match signature
|
242
242
|
rtol: float = 1e-3, # unused, just to match signature
|
243
243
|
) -> tuple[NDArray[np.float64], float, float, bool]:
|
@@ -265,7 +265,7 @@ def rk4_step_wrapped(
|
|
265
265
|
return u_next, t_next, h_next, accept
|
266
266
|
|
267
267
|
|
268
|
-
@njit
|
268
|
+
@njit
|
269
269
|
def rk45_step_wrapped(
|
270
270
|
t: float,
|
271
271
|
u: NDArray[np.float64],
|
@@ -302,7 +302,7 @@ def rk45_step_wrapped(
|
|
302
302
|
)
|
303
303
|
|
304
304
|
|
305
|
-
@njit
|
305
|
+
@njit
|
306
306
|
def estimate_initial_step(
|
307
307
|
t0: float,
|
308
308
|
u0: np.ndarray,
|