physpyx 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.
physpyx-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.3
2
+ Name: physpyx
3
+ Version: 0.1.0
4
+ Summary: Provides a way to use python code in LaTeX
5
+ Author: Jérôme Dufour
6
+ Author-email: Jérôme Dufour <jerome.dufour@eduvaud.ch>
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
9
+ Classifier: Operating System :: Unix
10
+ Classifier: Environment :: X11 Applications :: Qt
11
+ Classifier: Topic :: Education
12
+ Classifier: Topic :: Scientific/Engineering :: Physics
13
+ Requires-Dist: numpy>=2.3.4
14
+ Requires-Dist: pint>=0.25.1
15
+ Requires-Dist: scipy>=1.17.0
16
+ Requires-Python: >=3.13
17
+ Project-URL: Repository, https://bitbucket.org/jdufour/physpyx/src/master/
18
+ Project-URL: Changelog, https://bitbucket.org/jdufour/physpyx/src/master/CHANGELOG.md
19
+ Description-Content-Type: text/markdown
20
+
21
+ # PhysPyX
22
+
@@ -0,0 +1,2 @@
1
+ # PhysPyX
2
+
@@ -0,0 +1,45 @@
1
+ [project]
2
+ name = "physpyx"
3
+ version = "0.1.0"
4
+ authors = [
5
+ { name="Jérôme Dufour", email="jerome.dufour@eduvaud.ch" },
6
+ ]
7
+ description = "Provides a way to use python code in LaTeX"
8
+ classifiers = [
9
+ "Programming Language :: Python :: 3",
10
+ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
11
+ "Operating System :: Unix",
12
+ "Environment :: X11 Applications :: Qt",
13
+ "Topic :: Education",
14
+ "Topic :: Scientific/Engineering :: Physics"
15
+ ]
16
+ readme = "README.md"
17
+ requires-python = ">=3.13"
18
+ dependencies = [
19
+ "numpy>=2.3.4",
20
+ "pint>=0.25.1",
21
+ "scipy>=1.17.0",
22
+ ]
23
+
24
+ [dependency-groups]
25
+ dev = [
26
+ "mypy>=1.18.1",
27
+ "ipdb>=0.13.13",
28
+ ]
29
+ docs = [
30
+ "sphinx>=7.1.2",
31
+ "sphinx-rtd-theme>=3.0.2",
32
+ "sphinx-argparse>=0.5.2",
33
+ "myst-parser>=4.0.1",
34
+ "sphinx-autodoc2>=0.5.0",
35
+ "sphinx-autobuild>=2025.8.25",
36
+ ]
37
+
38
+ [build-system]
39
+ requires = [ "uv-build" ]
40
+ build-backend = "uv_build"
41
+
42
+ [project.urls]
43
+ Repository = "https://bitbucket.org/jdufour/physpyx/src/master/"
44
+ Changelog = "https://bitbucket.org/jdufour/physpyx/src/master/CHANGELOG.md"
45
+
@@ -0,0 +1,5 @@
1
+ from .nuclide import NuclideTable
2
+ from .physpyx import PhysPyX
3
+ from .qty import Qty
4
+
5
+ __all__ = ["NuclideTable", "PhysPyX", "Qty"]
@@ -0,0 +1,120 @@
1
+ from typing import Iterator
2
+ import numpy as np
3
+ from numpy.typing import NDArray
4
+ from scipy.special import ellipk, ellipkinc
5
+ from scipy.optimize import newton
6
+
7
+
8
+ class Orbit:
9
+ # https://en.wikipedia.org/wiki/Kepler_orbit
10
+ def __init__(
11
+ self,
12
+ *,
13
+ a: float, # demi-grand axe
14
+ mu: float, # gravitationnal constant x total mass, named alpha in the wiki page
15
+ e: float | None = None, # eccentricite (e=0 -> cercle, e=1 -> parabola)
16
+ b: float | None = None, # demi-petit axe
17
+ ):
18
+ self.a = a
19
+ self.mu = mu
20
+ if (e is None and b is None) or (e is not None and b is not None):
21
+ raise ValueError("Need to provide either 'e' or 'b'")
22
+ elif e is None and b is not None:
23
+ self.e = np.sqrt(1 - b * b / a / a)
24
+ self.b = b
25
+ elif b is None and e is not None:
26
+ self.e = e
27
+ self.b = self.a * np.sqrt(1.0 - self.e * self.e)
28
+ else:
29
+ raise ValueError
30
+
31
+ self.c = self.a * self.e # linear eccentricity
32
+ self.p = self.a * (1.0 - self.e * self.e) # semi-latus
33
+ self.T = 2 * np.pi * self.a * np.sqrt(self.a / self.mu) # period
34
+
35
+ self.v0 = np.sqrt(self.mu / self.p)
36
+ self.F = np.sqrt(self.a * self.a - self.b * self.b) # foyer
37
+
38
+ self.theta = 0
39
+ self.x = np.array([self.p / (1 + self.e), 0])
40
+ self.v = self.v0 * np.array([0, self.e + 1])
41
+
42
+ def __str__(self):
43
+ return (
44
+ f"T={self.T}, "
45
+ f"a={self.a}, "
46
+ f"b={self.b}, "
47
+ f"c={self.c}, "
48
+ f"e={self.e}, "
49
+ f"mu={self.mu}, "
50
+ f"F={self.F}, "
51
+ f"T^2/a^3={4 * np.pi * np.pi / self.mu}"
52
+ )
53
+
54
+ def step(self, dt: float) -> None:
55
+ self.theta = np.arctan2(self.x[1], self.x[0])
56
+ self.v = self.v0 * np.array([-np.sin(self.theta), self.e + np.cos(self.theta)])
57
+ r = self.p / (1 + self.e * np.cos(self.theta))
58
+ self.x = r * np.array([np.cos(self.theta), np.sin(self.theta)]) + self.v * dt
59
+
60
+ def run(
61
+ self,
62
+ steps: int,
63
+ every: int = 1,
64
+ ) -> Iterator[NDArray]:
65
+ if steps % every:
66
+ raise ValueError(f"{every} is not a divisor {steps} steps")
67
+
68
+ dt = self.T / steps
69
+ for i in range(0, steps + 1):
70
+ if i % every == 0:
71
+ yield self.x
72
+ self.step(dt)
73
+
74
+ def even_spacing(self, n: int) -> Iterator[NDArray]:
75
+ m = self.e * self.e
76
+ P = 4 * self.a * ellipk([m])[0]
77
+
78
+ def func(phi, arc_length):
79
+ return self.a * ellipkinc(phi, m) - arc_length
80
+
81
+ for i in range(n + 1):
82
+ phi = np.pi / 2 - newton(func, x0=np.pi / 2 * i / n, args=[P * i / n])
83
+ r = self.b / np.sqrt(1 - (self.e * np.cos(phi)) ** 2)
84
+ yield np.array([-self.F + r * np.cos(phi), r * np.sin(phi)])
85
+
86
+ def get_acceleration(self) -> NDArray:
87
+ x = np.sqrt(self.x.dot(self.x))
88
+ return -self.mu / (x * x * x) * self.x
89
+
90
+ def get_circle_tangent_to_ellipse(self) -> tuple[NDArray, float]:
91
+ # get the norm of the velocity
92
+ vt = np.sqrt(self.v.dot(self.v))
93
+
94
+ # define unit vectors tangent and perp to ellipse
95
+ vec_t = self.v / vt
96
+ vec_p = np.array([-vec_t[1], vec_t[0]])
97
+
98
+ # compute cetripetal acceleration
99
+ a = self.get_acceleration()
100
+ ac = a.dot(vec_p)
101
+
102
+ # compute radius of circle
103
+ r = vt * vt / ac
104
+ if self.v[0]:
105
+ m = -self.v[0] / self.v[1]
106
+ beta = r / np.sqrt(1 + m * m)
107
+ if self.x[0] > -self.c:
108
+ x0 = self.x[0] - beta
109
+ y0 = self.x[1] - m * beta
110
+ else:
111
+ x0 = self.x[0] + beta
112
+ y0 = self.x[1] + m * beta
113
+ else:
114
+ y0 = 0
115
+ if self.x[0] > -self.c:
116
+ x0 = self.x[0] - r
117
+ else:
118
+ x0 = self.x[0] + r
119
+
120
+ return np.array([x0, y0]), r