runge-kutta 0.1.0__tar.gz

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,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: runge-kutta
3
+ Version: 0.1.0
4
+ Summary: Runge-Kutta ODE solvers
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: numpy
8
+
9
+ # Runge-Kutta ODE Solvers
10
+
11
+ Small Python implementations of classical fourth-order Runge-Kutta (RK4) and
12
+ Runge-Kutta-Fehlberg (RK45) methods for numerically solving ordinary
13
+ differential equations (ODEs).
14
+
15
+ ## Requirements
16
+
17
+ - Python 3
18
+ - NumPy
19
+ - Matplotlib (for the example scripts)
20
+
21
+ Install the module and its dependencies:
22
+
23
+ ```bash
24
+ python -m pip install .
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ Import a solver from `runge_kutta`. Each function advances the solution by
30
+ one integration step for an equation of the form `dy/dt = f(t, y)`.
31
+
32
+ ```python
33
+ import numpy as np
34
+ from runge_kutta import rk4
35
+
36
+ def rhs(t, y):
37
+ return -y
38
+
39
+ t, y = rk4(rhs, t0=0.0, y0=np.array([1.0]), h=0.1)
40
+ ```
41
+
42
+ ### Solvers
43
+
44
+ | Function | Description | Returns |
45
+ | --- | --- | --- |
46
+ | `rk4(f, t0, y0, h)` | Performs one fixed-size classical fourth-order Runge-Kutta step. | `(t, y)` |
47
+ | `rk45(f, t0, y0, h)` | Performs one fixed-size Runge-Kutta-Fehlberg step using the fourth-order estimate. | `(t, y, error)` |
48
+ | `rk45_h_adj(f, t0, y0, h, epsilon)` | Performs an RK45 step and proposes a next step size from the embedded error estimate. | `(t, y, error, h_adj)` |
49
+
50
+ `f` must accept `(t, y)` and return the derivative at that point. `y` may be a
51
+ scalar or a NumPy array.
52
+
53
+ ## Examples
54
+
55
+ The included scripts compare RK4 and RK45 while plotting solution trajectories
56
+ and RK45 error estimates:
57
+
58
+ ```bash
59
+ python test1.py # Lorenz system
60
+ python test2.py # damped second-order system
61
+ ```
62
+
63
+ Both scripts open Matplotlib windows. `test1.py` integrates the Lorenz system
64
+ for 500,000 steps and can take noticeably longer to run.
@@ -0,0 +1,56 @@
1
+ # Runge-Kutta ODE Solvers
2
+
3
+ Small Python implementations of classical fourth-order Runge-Kutta (RK4) and
4
+ Runge-Kutta-Fehlberg (RK45) methods for numerically solving ordinary
5
+ differential equations (ODEs).
6
+
7
+ ## Requirements
8
+
9
+ - Python 3
10
+ - NumPy
11
+ - Matplotlib (for the example scripts)
12
+
13
+ Install the module and its dependencies:
14
+
15
+ ```bash
16
+ python -m pip install .
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Import a solver from `runge_kutta`. Each function advances the solution by
22
+ one integration step for an equation of the form `dy/dt = f(t, y)`.
23
+
24
+ ```python
25
+ import numpy as np
26
+ from runge_kutta import rk4
27
+
28
+ def rhs(t, y):
29
+ return -y
30
+
31
+ t, y = rk4(rhs, t0=0.0, y0=np.array([1.0]), h=0.1)
32
+ ```
33
+
34
+ ### Solvers
35
+
36
+ | Function | Description | Returns |
37
+ | --- | --- | --- |
38
+ | `rk4(f, t0, y0, h)` | Performs one fixed-size classical fourth-order Runge-Kutta step. | `(t, y)` |
39
+ | `rk45(f, t0, y0, h)` | Performs one fixed-size Runge-Kutta-Fehlberg step using the fourth-order estimate. | `(t, y, error)` |
40
+ | `rk45_h_adj(f, t0, y0, h, epsilon)` | Performs an RK45 step and proposes a next step size from the embedded error estimate. | `(t, y, error, h_adj)` |
41
+
42
+ `f` must accept `(t, y)` and return the derivative at that point. `y` may be a
43
+ scalar or a NumPy array.
44
+
45
+ ## Examples
46
+
47
+ The included scripts compare RK4 and RK45 while plotting solution trajectories
48
+ and RK45 error estimates:
49
+
50
+ ```bash
51
+ python test1.py # Lorenz system
52
+ python test2.py # damped second-order system
53
+ ```
54
+
55
+ Both scripts open Matplotlib windows. `test1.py` integrates the Lorenz system
56
+ for 500,000 steps and can take noticeably longer to run.
@@ -0,0 +1,14 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "runge-kutta"
7
+ version = "0.1.0"
8
+ description = "Runge-Kutta ODE solvers"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ dependencies = ["numpy"]
12
+
13
+ [tool.setuptools]
14
+ py-modules = ["runge_kutta"]
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: runge-kutta
3
+ Version: 0.1.0
4
+ Summary: Runge-Kutta ODE solvers
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: numpy
8
+
9
+ # Runge-Kutta ODE Solvers
10
+
11
+ Small Python implementations of classical fourth-order Runge-Kutta (RK4) and
12
+ Runge-Kutta-Fehlberg (RK45) methods for numerically solving ordinary
13
+ differential equations (ODEs).
14
+
15
+ ## Requirements
16
+
17
+ - Python 3
18
+ - NumPy
19
+ - Matplotlib (for the example scripts)
20
+
21
+ Install the module and its dependencies:
22
+
23
+ ```bash
24
+ python -m pip install .
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ Import a solver from `runge_kutta`. Each function advances the solution by
30
+ one integration step for an equation of the form `dy/dt = f(t, y)`.
31
+
32
+ ```python
33
+ import numpy as np
34
+ from runge_kutta import rk4
35
+
36
+ def rhs(t, y):
37
+ return -y
38
+
39
+ t, y = rk4(rhs, t0=0.0, y0=np.array([1.0]), h=0.1)
40
+ ```
41
+
42
+ ### Solvers
43
+
44
+ | Function | Description | Returns |
45
+ | --- | --- | --- |
46
+ | `rk4(f, t0, y0, h)` | Performs one fixed-size classical fourth-order Runge-Kutta step. | `(t, y)` |
47
+ | `rk45(f, t0, y0, h)` | Performs one fixed-size Runge-Kutta-Fehlberg step using the fourth-order estimate. | `(t, y, error)` |
48
+ | `rk45_h_adj(f, t0, y0, h, epsilon)` | Performs an RK45 step and proposes a next step size from the embedded error estimate. | `(t, y, error, h_adj)` |
49
+
50
+ `f` must accept `(t, y)` and return the derivative at that point. `y` may be a
51
+ scalar or a NumPy array.
52
+
53
+ ## Examples
54
+
55
+ The included scripts compare RK4 and RK45 while plotting solution trajectories
56
+ and RK45 error estimates:
57
+
58
+ ```bash
59
+ python test1.py # Lorenz system
60
+ python test2.py # damped second-order system
61
+ ```
62
+
63
+ Both scripts open Matplotlib windows. `test1.py` integrates the Lorenz system
64
+ for 500,000 steps and can take noticeably longer to run.
@@ -0,0 +1,8 @@
1
+ README.md
2
+ pyproject.toml
3
+ runge_kutta.py
4
+ runge_kutta.egg-info/PKG-INFO
5
+ runge_kutta.egg-info/SOURCES.txt
6
+ runge_kutta.egg-info/dependency_links.txt
7
+ runge_kutta.egg-info/requires.txt
8
+ runge_kutta.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ numpy
@@ -0,0 +1 @@
1
+ runge_kutta
@@ -0,0 +1,116 @@
1
+
2
+ from numpy.linalg import norm
3
+ from numpy import inf
4
+
5
+ __all__ = ["rk4", "rk45", "rk45_h_adj"]
6
+
7
+ def rk4(f, t0, y0, h):
8
+ """Advance an ordinary differential equation by one fourth-order RK step.
9
+
10
+ Solves ``dy/dt = f(t, y)`` from ``(t0, y0)`` using the classical
11
+ four-stage Runge-Kutta method and a fixed step size.
12
+
13
+ Parameters:
14
+ f : callable
15
+ Function defining the differential equation ``dy/dt = f(t, y)``.
16
+ t0 : float
17
+ The initial time.
18
+ y0 : float or numpy.ndarray
19
+ State at ``t0``.
20
+ h : float
21
+ Fixed integration step size.
22
+
23
+ Returns:
24
+ tuple[float, float or numpy.ndarray]
25
+ The time and state after one step.
26
+ """
27
+ k1 = f(t0, y0)
28
+ k2 = f(t0 + (h/2), y0 + (h*k1/2))
29
+ k3 = f(t0 + (h/2), y0 + (h*k2/2))
30
+ k4 = f(t0 + h, y0 + (h*k3))
31
+
32
+ t = t0 + h
33
+ y = y0 + (h/6)*(k1 + 2*k2 + 2*k3 + k4)
34
+
35
+ return t, y
36
+
37
+ def rk45(f, t0, y0, h):
38
+ """Advance an ODE by one fixed Runge-Kutta-Fehlberg (RK45) step.
39
+
40
+ Computes the fourth-order state estimate and the difference between the
41
+ embedded fourth- and fifth-order estimates, which callers can use for
42
+ local-error control.
43
+
44
+ Parameters:
45
+ f : callable
46
+ Function defining the differential equation ``dy/dt = f(t, y)``.
47
+ t0 : float
48
+ The initial time.
49
+ y0 : float or numpy.ndarray
50
+ State at ``t0``.
51
+ h : float
52
+ Fixed integration step size.
53
+
54
+ Returns:
55
+ tuple[float, float or numpy.ndarray, float or numpy.ndarray]
56
+ The time and fourth-order state estimate after one step, followed by
57
+ the embedded local-error estimate.
58
+ """
59
+ k1 = f(t0, y0)
60
+ k2 = f(t0 + (h/4), y0 + (h*k1/4))
61
+ k3 = f(t0 + (3*h/8), y0 + (3*h*k1/32) + (9*h*k2/32))
62
+ k4 = f(t0 + (12*h/13), y0 + (1932*h*k1/2197) - (7200*h*k2/2197) + (7296*h*k3/2197))
63
+ k5 = f(t0 + h, y0 + (439*h*k1/216) - (8*h*k2) + (3680*h*k3/513) - (845*h*k4/4104))
64
+ k6 = f(t0 + (h/2), y0 - (8*h*k1/27) + (2*h*k2) - (3544*h*k3/2565) + (1859*h*k4/4104) - (11*h*k5/40))
65
+
66
+ t = t0 + h
67
+ y = y0 + h*((25*k1/216) + (1408*k3/2565) + (2197*k4/4104) - (1*k5/5))
68
+ error = h*((1*k1/360) - (128*k3/4275) - (2197*k4/75240) + (1*k5/50) + (2*k6/55))
69
+
70
+ return t, y, error
71
+
72
+ def rk45_h_adj(f, t0, y0, h, epsilon):
73
+ """Perform an RK45 step and calculate an adjusted next step size.
74
+
75
+ The returned state is the fourth-order Runge-Kutta-Fehlberg estimate.
76
+ The proposed next step uses the infinity norm of the difference between
77
+ the embedded fourth- and fifth-order estimates and a safety factor of
78
+ 0.84.
79
+
80
+ Parameters:
81
+ f : callable
82
+ Function defining the differential equation ``dy/dt = f(t, y)``.
83
+ t0 : float
84
+ The initial time.
85
+ y0 : float or numpy.ndarray
86
+ State at ``t0``.
87
+ h : float
88
+ Step size used for this integration step.
89
+ epsilon : float
90
+ Desired local-error tolerance used to calculate the next step size.
91
+
92
+ Returns:
93
+ tuple[float, float or numpy.ndarray, float or numpy.ndarray, float]
94
+ The time and fourth-order state estimate after one step, the embedded
95
+ local-error estimate, and the proposed step size for the next step.
96
+ """
97
+ k1 = f( t0, y0 );
98
+ k2 = f( t0 + h/4, y0 + k1*h/4 );
99
+ k3 = f( t0 + 3*h/8, y0 + 3*k1*h/32 + 9*k2*h/32 );
100
+ k4 = f( t0 + 12*h/13, y0 + 1932*k1*h/2197 - 7200*k2*h/2197 + 7296*k3*h/2197 );
101
+ k5 = f( t0 + h, y0 + 439*k1*h/216 - 8*k2*h + 3680*k3*h/513 - 845*k4*h/4104 );
102
+ k6 = f( t0 + h/2, y0 - 8*k1*h/27 + 2*k2*h - 3544*k3*h/2565 + 1859*k4*h/4104 - 11*k5*h/40 );
103
+
104
+ # RK4
105
+ y_rk4 = y0 + h*( 25*k1/216 + 1408*k3/2565 + 2197*k4/4104 - k5/5 );
106
+ y_rk5 = y0 + h*( 16*k1/135 + 6656*k3/12825 + 28561*k4/56430 - 9*k5/50 + 2*k6/55 );
107
+ y = y_rk4;
108
+ t = t0 + h;
109
+ # estimativa do erro
110
+ error = h*( k1/360 - 128*k3/4275 - 2197*k4/75240 + k5/50 + 2*k6/55 );
111
+ # h ajustado
112
+ alpha = 0.84; # Segundo a ref.
113
+ p = 4; # RK order
114
+ h_adj = alpha*h*(epsilon*h/norm(y_rk5 - y_rk4, inf))**(1/p);
115
+ #
116
+ return t, y, error, h_adj
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+