relativistic-simulator 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.
- relativistic_simulator-0.1.0/.gitignore +20 -0
- relativistic_simulator-0.1.0/.python-version +1 -0
- relativistic_simulator-0.1.0/CHANGELOG.md +21 -0
- relativistic_simulator-0.1.0/LICENSE +21 -0
- relativistic_simulator-0.1.0/PKG-INFO +196 -0
- relativistic_simulator-0.1.0/README.md +164 -0
- relativistic_simulator-0.1.0/docs/benchmarks.md +11 -0
- relativistic_simulator-0.1.0/docs/physics.md +65 -0
- relativistic_simulator-0.1.0/docs/validation.md +15 -0
- relativistic_simulator-0.1.0/examples/basic_simulation.py +43 -0
- relativistic_simulator-0.1.0/examples/benchmark.py +21 -0
- relativistic_simulator-0.1.0/examples/generate_dataset.py +87 -0
- relativistic_simulator-0.1.0/examples/high_beta.py +46 -0
- relativistic_simulator-0.1.0/pyproject.toml +66 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/__init__.py +120 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/_common.py +168 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/classical.py +105 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/constants.py +16 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/dataset.py +389 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/dynamics.py +348 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/exceptions.py +55 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/plotting.py +204 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/relativity.py +361 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/simulator.py +126 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/trajectory.py +189 -0
- relativistic_simulator-0.1.0/src/relativistic_simulator/validation.py +411 -0
- relativistic_simulator-0.1.0/tests/conftest.py +60 -0
- relativistic_simulator-0.1.0/tests/test_dataset.py +155 -0
- relativistic_simulator-0.1.0/tests/test_dynamics.py +156 -0
- relativistic_simulator-0.1.0/tests/test_plotting.py +66 -0
- relativistic_simulator-0.1.0/tests/test_relativity.py +240 -0
- relativistic_simulator-0.1.0/tests/test_simulator.py +141 -0
- relativistic_simulator-0.1.0/tests/test_validation.py +134 -0
- relativistic_simulator-0.1.0/uv.lock +1341 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
.wheel-test
|
|
12
|
+
|
|
13
|
+
# Example and benchmark output
|
|
14
|
+
examples/output/
|
|
15
|
+
benchmark-results.txt
|
|
16
|
+
|
|
17
|
+
# Tool caches
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.mypy_cache/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented here.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-09-13
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- 1D special-relativistic massive-particle dynamics under constant force.
|
|
10
|
+
- Numerically stable relativistic kinematics, energy, momentum, and proper-time functions.
|
|
11
|
+
- Exact analytical solver and independent RK4 cross-check integrator.
|
|
12
|
+
- Vectorized reproducible NumPy dataset generation.
|
|
13
|
+
- Quantitative physical validation reports.
|
|
14
|
+
- Optional pandas conversion and matplotlib plotting utilities.
|
|
15
|
+
- Pytest test suite, examples, and uv/PyPI packaging configuration.
|
|
16
|
+
|
|
17
|
+
### Scientific scope
|
|
18
|
+
|
|
19
|
+
The model assumes flat Minkowski spacetime, one spatial dimension, constant rest mass,
|
|
20
|
+
and an externally applied constant 1D force. It does not model gravity, fields,
|
|
21
|
+
radiation reaction, quantum effects, or faster-than-light trajectories.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mayank
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: relativistic-simulator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 1D special-relativistic constant-force massive-particle dynamics simulator: a ground-truth physics engine for machine-learning research.
|
|
5
|
+
Project-URL: Homepage, https://github.com/mayank/relativistic-simulator
|
|
6
|
+
Project-URL: Repository, https://github.com/mayank/relativistic-simulator
|
|
7
|
+
Project-URL: Changelog, https://github.com/mayank/relativistic-simulator/blob/main/CHANGELOG.md
|
|
8
|
+
Author: Mayank
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: machine-learning,physics,relativity,scientific-computing,simulation,special-relativity,synthetic-data
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: numpy>=1.24
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: matplotlib>=3.5; extra == 'all'
|
|
26
|
+
Requires-Dist: pandas>=2.0; extra == 'all'
|
|
27
|
+
Provides-Extra: pandas
|
|
28
|
+
Requires-Dist: pandas>=2.0; extra == 'pandas'
|
|
29
|
+
Provides-Extra: plot
|
|
30
|
+
Requires-Dist: matplotlib>=3.5; extra == 'plot'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# relativistic-simulator
|
|
34
|
+
|
|
35
|
+
Research-grade, lightweight Python simulator for **1D special-relativistic massive-particle dynamics under a constant external force**.
|
|
36
|
+
|
|
37
|
+
This package is the ground-truth physics engine for a synthetic-data/ML research pipeline. It generates data from known equations; it does not discover physics and it does not contain an ML model.
|
|
38
|
+
|
|
39
|
+
## Scientific assumptions
|
|
40
|
+
|
|
41
|
+
- flat Minkowski spacetime and special relativity;
|
|
42
|
+
- one spatial dimension;
|
|
43
|
+
- constant rest mass;
|
|
44
|
+
- externally applied constant 1D force;
|
|
45
|
+
- SI units;
|
|
46
|
+
- no gravity, curved spacetime, electromagnetic-field model, radiation reaction, quantum effects, or FTL dynamics.
|
|
47
|
+
|
|
48
|
+
The governing equation is `dp/dt = F` with `p = gamma*m*v`, not classical `F = m*a`.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install relativistic-simulator
|
|
54
|
+
pip install "relativistic-simulator[all]" # optional pandas + matplotlib
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Development uses uv:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv sync
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick start
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from relativistic_simulator import C, simulate
|
|
67
|
+
|
|
68
|
+
result = simulate(
|
|
69
|
+
mass=1000.0, force=1e6, initial_velocity=0.9 * C,
|
|
70
|
+
duration=100.0, dt=0.01,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
print(result.beta)
|
|
74
|
+
print(result.gamma)
|
|
75
|
+
print(result.momentum)
|
|
76
|
+
print(result.kinetic_energy)
|
|
77
|
+
print(result.total_energy)
|
|
78
|
+
print(result.proper_time)
|
|
79
|
+
print(result.validate().summary())
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`simulate()` returns a `Trajectory` exposing `time`, `position`, `velocity`, `beta`, `gamma`, `momentum`, `kinetic_energy`, `total_energy`, and `proper_time`, plus `to_numpy()`, `to_dict()`, `to_dataframe()`, and `final_state()`.
|
|
83
|
+
|
|
84
|
+
## Equations and numerical method
|
|
85
|
+
|
|
86
|
+
For initial momentum `p0 = gamma0*m*v0`:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
p(t) = p0 + F*t
|
|
90
|
+
q(t) = p(t)/(m*c)
|
|
91
|
+
gamma(t) = hypot(1, q(t))
|
|
92
|
+
v(t) = c*q(t)/gamma(t)
|
|
93
|
+
E(t) = c*hypot(m*c, p(t))
|
|
94
|
+
K(t) = p(t)^2*c^2 / (E(t) + m*c^2)
|
|
95
|
+
x(t) = x0 + c*t*(q(t) + q0)/(gamma(t) + gamma0) [F != 0]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The position formula is algebraically equivalent to `(K-K0)/F`, but avoids catastrophic cancellation at high beta and small impulse. Proper time uses `dτ = dt/gamma` and a stable `log1p` rapidity-increment form. `simulate(method="numerical")` supplies an independent RK4 cross-check.
|
|
99
|
+
|
|
100
|
+
See [`docs/physics.md`](docs/physics.md) for derivations and precision details.
|
|
101
|
+
|
|
102
|
+
## Relativity API
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from relativistic_simulator import (
|
|
106
|
+
C, beta_from_velocity, velocity_from_beta, gamma_from_beta,
|
|
107
|
+
gamma_from_velocity, momentum_from_velocity, velocity_from_momentum,
|
|
108
|
+
energy_from_velocity, energy_from_momentum,
|
|
109
|
+
kinetic_energy_from_velocity, kinetic_energy_from_momentum, rest_energy,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
gamma = gamma_from_beta(0.99999)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
All functions accept scalars and NumPy arrays where practical. Massive-particle states must satisfy `abs(v) < C` and `abs(beta) < 1`; invalid states raise typed exceptions and are never silently clipped.
|
|
116
|
+
|
|
117
|
+
## Dataset generation
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from relativistic_simulator import generate_dataset
|
|
121
|
+
|
|
122
|
+
dataset = generate_dataset(
|
|
123
|
+
n_samples=100_000,
|
|
124
|
+
mass_range=(100.0, 10_000.0),
|
|
125
|
+
force_range=(1e4, 1e7),
|
|
126
|
+
beta_range=(0.0, 0.8),
|
|
127
|
+
time_range=(0.0, 100.0),
|
|
128
|
+
random_seed=42,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
dataset.to_csv("train.csv")
|
|
132
|
+
print(dataset.input_columns)
|
|
133
|
+
print(dataset.output_columns)
|
|
134
|
+
print(dataset.validate().summary())
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Generation is fully vectorized with NumPy and uses `numpy.random.default_rng`, so seeded datasets are reproducible without global randomness. Inputs are `mass`, `force`, `initial_velocity`, `initial_beta`, and `time`; targets are exact `position`, `velocity`, `beta`, `gamma`, `momentum`, `kinetic_energy`, `total_energy`, and `proper_time`.
|
|
138
|
+
|
|
139
|
+
Regimes are configurable rather than hard-coded:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
low = generate_dataset(beta_range=(0.0, 0.5), random_seed=1)
|
|
143
|
+
relativistic = generate_dataset(beta_range=(0.5, 0.9), random_seed=2)
|
|
144
|
+
ultra = generate_dataset(beta_range=(0.9, 0.9999), random_seed=3)
|
|
145
|
+
training = generate_dataset(beta_range=(0.0, 0.8), random_seed=42)
|
|
146
|
+
extrapolation = generate_dataset(beta_range=(0.8, 0.9999), random_seed=43)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Validation
|
|
150
|
+
|
|
151
|
+
`validate_trajectory` and `validate_dataset` report quantitative errors for `p = gamma*m*v`, `E = gamma*m*c²`, the energy-momentum invariant, central finite differences for `dp/dt` and `dx/dt`, proper time, initial conditions, velocity bound, and `tau <= t`. They use independent routes rather than merely repeating the generating expression.
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
report = result.validate()
|
|
155
|
+
print(report.max_energy_momentum_error)
|
|
156
|
+
print(report.max_force_error)
|
|
157
|
+
print(report.max_velocity_difference_error)
|
|
158
|
+
print(report.passed)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Optional plotting and classical comparison
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from relativistic_simulator.plotting import plot_trajectory, plot_gamma_vs_beta
|
|
165
|
+
plot_trajectory(result, path="trajectory.png", show=False)
|
|
166
|
+
plot_gamma_vs_beta(path="gamma.png", show=False)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The `classical` module is comparison-only: it provides Newtonian `p=m*v`, `K=0.5*m*v**2`, and `x=x0+v0*t+0.5*(F/m)*t**2`. It is not used by the relativistic engine.
|
|
170
|
+
|
|
171
|
+
## Examples
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uv run python examples/basic_simulation.py
|
|
175
|
+
uv run python examples/high_beta.py
|
|
176
|
+
uv run python examples/generate_dataset.py
|
|
177
|
+
uv run python examples/benchmark.py
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Development, testing, and build
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
uv sync
|
|
184
|
+
uv run pytest
|
|
185
|
+
uv build
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The suite covers high beta through `0.99999c`, invalid physical states, exact/RK4 agreement, vectorization, reproducibility, dataset validation, and optional plotting. `uv build` creates wheel and source distributions in `dist/`. Review and test those artifacts before any deliberate `uv publish`.
|
|
189
|
+
|
|
190
|
+
## Precision and limitations
|
|
191
|
+
|
|
192
|
+
The numerical representation is IEEE-754 float64. The package rejects `|v| >= c` rather than clipping and rejects states for which floating-point arithmetic cannot represent a strictly subluminal velocity. It does not model gravity, curved spacetime, electromagnetic fields, variable mass, radiation reaction, quantum effects, or FTL/spacelike trajectories.
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT License. See [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# relativistic-simulator
|
|
2
|
+
|
|
3
|
+
Research-grade, lightweight Python simulator for **1D special-relativistic massive-particle dynamics under a constant external force**.
|
|
4
|
+
|
|
5
|
+
This package is the ground-truth physics engine for a synthetic-data/ML research pipeline. It generates data from known equations; it does not discover physics and it does not contain an ML model.
|
|
6
|
+
|
|
7
|
+
## Scientific assumptions
|
|
8
|
+
|
|
9
|
+
- flat Minkowski spacetime and special relativity;
|
|
10
|
+
- one spatial dimension;
|
|
11
|
+
- constant rest mass;
|
|
12
|
+
- externally applied constant 1D force;
|
|
13
|
+
- SI units;
|
|
14
|
+
- no gravity, curved spacetime, electromagnetic-field model, radiation reaction, quantum effects, or FTL dynamics.
|
|
15
|
+
|
|
16
|
+
The governing equation is `dp/dt = F` with `p = gamma*m*v`, not classical `F = m*a`.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install relativistic-simulator
|
|
22
|
+
pip install "relativistic-simulator[all]" # optional pandas + matplotlib
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Development uses uv:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
uv sync
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from relativistic_simulator import C, simulate
|
|
35
|
+
|
|
36
|
+
result = simulate(
|
|
37
|
+
mass=1000.0, force=1e6, initial_velocity=0.9 * C,
|
|
38
|
+
duration=100.0, dt=0.01,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
print(result.beta)
|
|
42
|
+
print(result.gamma)
|
|
43
|
+
print(result.momentum)
|
|
44
|
+
print(result.kinetic_energy)
|
|
45
|
+
print(result.total_energy)
|
|
46
|
+
print(result.proper_time)
|
|
47
|
+
print(result.validate().summary())
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`simulate()` returns a `Trajectory` exposing `time`, `position`, `velocity`, `beta`, `gamma`, `momentum`, `kinetic_energy`, `total_energy`, and `proper_time`, plus `to_numpy()`, `to_dict()`, `to_dataframe()`, and `final_state()`.
|
|
51
|
+
|
|
52
|
+
## Equations and numerical method
|
|
53
|
+
|
|
54
|
+
For initial momentum `p0 = gamma0*m*v0`:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
p(t) = p0 + F*t
|
|
58
|
+
q(t) = p(t)/(m*c)
|
|
59
|
+
gamma(t) = hypot(1, q(t))
|
|
60
|
+
v(t) = c*q(t)/gamma(t)
|
|
61
|
+
E(t) = c*hypot(m*c, p(t))
|
|
62
|
+
K(t) = p(t)^2*c^2 / (E(t) + m*c^2)
|
|
63
|
+
x(t) = x0 + c*t*(q(t) + q0)/(gamma(t) + gamma0) [F != 0]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The position formula is algebraically equivalent to `(K-K0)/F`, but avoids catastrophic cancellation at high beta and small impulse. Proper time uses `dτ = dt/gamma` and a stable `log1p` rapidity-increment form. `simulate(method="numerical")` supplies an independent RK4 cross-check.
|
|
67
|
+
|
|
68
|
+
See [`docs/physics.md`](docs/physics.md) for derivations and precision details.
|
|
69
|
+
|
|
70
|
+
## Relativity API
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from relativistic_simulator import (
|
|
74
|
+
C, beta_from_velocity, velocity_from_beta, gamma_from_beta,
|
|
75
|
+
gamma_from_velocity, momentum_from_velocity, velocity_from_momentum,
|
|
76
|
+
energy_from_velocity, energy_from_momentum,
|
|
77
|
+
kinetic_energy_from_velocity, kinetic_energy_from_momentum, rest_energy,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
gamma = gamma_from_beta(0.99999)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
All functions accept scalars and NumPy arrays where practical. Massive-particle states must satisfy `abs(v) < C` and `abs(beta) < 1`; invalid states raise typed exceptions and are never silently clipped.
|
|
84
|
+
|
|
85
|
+
## Dataset generation
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from relativistic_simulator import generate_dataset
|
|
89
|
+
|
|
90
|
+
dataset = generate_dataset(
|
|
91
|
+
n_samples=100_000,
|
|
92
|
+
mass_range=(100.0, 10_000.0),
|
|
93
|
+
force_range=(1e4, 1e7),
|
|
94
|
+
beta_range=(0.0, 0.8),
|
|
95
|
+
time_range=(0.0, 100.0),
|
|
96
|
+
random_seed=42,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
dataset.to_csv("train.csv")
|
|
100
|
+
print(dataset.input_columns)
|
|
101
|
+
print(dataset.output_columns)
|
|
102
|
+
print(dataset.validate().summary())
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Generation is fully vectorized with NumPy and uses `numpy.random.default_rng`, so seeded datasets are reproducible without global randomness. Inputs are `mass`, `force`, `initial_velocity`, `initial_beta`, and `time`; targets are exact `position`, `velocity`, `beta`, `gamma`, `momentum`, `kinetic_energy`, `total_energy`, and `proper_time`.
|
|
106
|
+
|
|
107
|
+
Regimes are configurable rather than hard-coded:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
low = generate_dataset(beta_range=(0.0, 0.5), random_seed=1)
|
|
111
|
+
relativistic = generate_dataset(beta_range=(0.5, 0.9), random_seed=2)
|
|
112
|
+
ultra = generate_dataset(beta_range=(0.9, 0.9999), random_seed=3)
|
|
113
|
+
training = generate_dataset(beta_range=(0.0, 0.8), random_seed=42)
|
|
114
|
+
extrapolation = generate_dataset(beta_range=(0.8, 0.9999), random_seed=43)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Validation
|
|
118
|
+
|
|
119
|
+
`validate_trajectory` and `validate_dataset` report quantitative errors for `p = gamma*m*v`, `E = gamma*m*c²`, the energy-momentum invariant, central finite differences for `dp/dt` and `dx/dt`, proper time, initial conditions, velocity bound, and `tau <= t`. They use independent routes rather than merely repeating the generating expression.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
report = result.validate()
|
|
123
|
+
print(report.max_energy_momentum_error)
|
|
124
|
+
print(report.max_force_error)
|
|
125
|
+
print(report.max_velocity_difference_error)
|
|
126
|
+
print(report.passed)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Optional plotting and classical comparison
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from relativistic_simulator.plotting import plot_trajectory, plot_gamma_vs_beta
|
|
133
|
+
plot_trajectory(result, path="trajectory.png", show=False)
|
|
134
|
+
plot_gamma_vs_beta(path="gamma.png", show=False)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The `classical` module is comparison-only: it provides Newtonian `p=m*v`, `K=0.5*m*v**2`, and `x=x0+v0*t+0.5*(F/m)*t**2`. It is not used by the relativistic engine.
|
|
138
|
+
|
|
139
|
+
## Examples
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
uv run python examples/basic_simulation.py
|
|
143
|
+
uv run python examples/high_beta.py
|
|
144
|
+
uv run python examples/generate_dataset.py
|
|
145
|
+
uv run python examples/benchmark.py
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Development, testing, and build
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
uv sync
|
|
152
|
+
uv run pytest
|
|
153
|
+
uv build
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The suite covers high beta through `0.99999c`, invalid physical states, exact/RK4 agreement, vectorization, reproducibility, dataset validation, and optional plotting. `uv build` creates wheel and source distributions in `dist/`. Review and test those artifacts before any deliberate `uv publish`.
|
|
157
|
+
|
|
158
|
+
## Precision and limitations
|
|
159
|
+
|
|
160
|
+
The numerical representation is IEEE-754 float64. The package rejects `|v| >= c` rather than clipping and rejects states for which floating-point arithmetic cannot represent a strictly subluminal velocity. It does not model gravity, curved spacetime, electromagnetic fields, variable mass, radiation reaction, quantum effects, or FTL/spacelike trajectories.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT License. See [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
Run the benchmark yourself with:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
uv run python examples/benchmark.py
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The script reports wall-clock time, samples per second, and the NumPy storage footprint
|
|
10
|
+
for 10,000, 100,000, and 1,000,000 vectorized observations. Benchmark values are
|
|
11
|
+
machine-dependent and are intentionally not hard-coded in this document.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Physics and numerical method
|
|
2
|
+
|
|
3
|
+
## Model
|
|
4
|
+
|
|
5
|
+
The package models a massive particle in one spatial dimension in flat Minkowski
|
|
6
|
+
spacetime. Units are SI: mass in kg, force in N, position in m, velocity in m/s,
|
|
7
|
+
time in s, momentum in kg m/s, and energy in J. The speed of light is the exact
|
|
8
|
+
constant `C = 299792458.0 m/s`.
|
|
9
|
+
|
|
10
|
+
The dynamical law is
|
|
11
|
+
|
|
12
|
+
\[
|
|
13
|
+
\frac{dp}{dt}=F, \qquad p=\gamma m v,
|
|
14
|
+
\]
|
|
15
|
+
|
|
16
|
+
not `F = m a`.
|
|
17
|
+
|
|
18
|
+
## Exact solution
|
|
19
|
+
|
|
20
|
+
For initial momentum \(p_0=\gamma_0mv_0\),
|
|
21
|
+
|
|
22
|
+
\[
|
|
23
|
+
p(t)=p_0+Ft,
|
|
24
|
+
\quad q=\frac{p}{mc},
|
|
25
|
+
\quad \gamma=\sqrt{1+q^2},
|
|
26
|
+
\quad v=c\frac{q}{\gamma}.
|
|
27
|
+
\]
|
|
28
|
+
|
|
29
|
+
The total and kinetic energies are
|
|
30
|
+
|
|
31
|
+
\[
|
|
32
|
+
E=\sqrt{m^2c^4+p^2c^2},\qquad
|
|
33
|
+
K=\frac{p^2c^2}{E+mc^2}.
|
|
34
|
+
\]
|
|
35
|
+
|
|
36
|
+
For nonzero force, position is evaluated in the cancellation-free form
|
|
37
|
+
|
|
38
|
+
\[
|
|
39
|
+
x(t)=x_0+ct\frac{q+q_0}{\gamma+\gamma_0}.
|
|
40
|
+
\]
|
|
41
|
+
|
|
42
|
+
This is algebraically equivalent to \(x_0+(K-K_0)/F\), but avoids subtracting two
|
|
43
|
+
large nearly equal kinetic energies in high-beta, small-impulse cases. For zero force,
|
|
44
|
+
\(x=x_0+v_0t\).
|
|
45
|
+
|
|
46
|
+
Proper time is accumulated from \(d\tau=dt/\gamma\). The implementation uses a
|
|
47
|
+
`log1p` rapidity-increment form, avoiding cancellation in
|
|
48
|
+
`asinh(q) - asinh(q0)` when the impulse is tiny compared with the initial momentum.
|
|
49
|
+
|
|
50
|
+
## Numerical safety
|
|
51
|
+
|
|
52
|
+
- Inputs with `|v| >= c`, `|beta| >= 1`, nonpositive mass, nonfinite values, or invalid
|
|
53
|
+
integration steps raise typed exceptions.
|
|
54
|
+
- Values are never silently clipped to the light cone.
|
|
55
|
+
- `hypot` is used for square roots of sums of squares.
|
|
56
|
+
- `gamma - 1` and `E - mc²` are evaluated through rationalized identities.
|
|
57
|
+
- The exact solver is independent of the RK4 integrator used for cross-checking.
|
|
58
|
+
|
|
59
|
+
## Validity limits
|
|
60
|
+
|
|
61
|
+
This is not a general relativistic engine. It excludes gravity, curved spacetime,
|
|
62
|
+
electromagnetic-field models, radiation reaction, variable mass, quantum effects,
|
|
63
|
+
and spacelike/FTL trajectories. Float64 precision also limits how close a represented
|
|
64
|
+
state can be to the light cone; such states are rejected if the computed velocity can
|
|
65
|
+
no longer be represented as strictly subluminal.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Validation methodology
|
|
2
|
+
|
|
3
|
+
`validate_trajectory` and `validate_dataset` return measured errors rather than a
|
|
4
|
+
single opaque boolean. Checks include:
|
|
5
|
+
|
|
6
|
+
- `p = gamma*m*v`;
|
|
7
|
+
- `E = gamma*m*c²`;
|
|
8
|
+
- `E² - p²c² = m²c⁴`;
|
|
9
|
+
- central finite differences for `dp/dt = F` and `dx/dt = v`;
|
|
10
|
+
- trapezoidal integration of `dt/gamma` against proper time;
|
|
11
|
+
- initial conditions and `tau <= t`;
|
|
12
|
+
- independent RK4 versus analytical trajectory comparison in tests.
|
|
13
|
+
|
|
14
|
+
The finite-difference checks intentionally use interior central differences. One-sided
|
|
15
|
+
edge stencils can amplify floating-point roundoff even for bitwise-constant arrays.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Example 1: basic simulation of a massive particle under constant force.
|
|
2
|
+
|
|
3
|
+
A 1000 kg object starting at rest, pushed by a constant 1e6 N force in +x
|
|
4
|
+
for 100 seconds. In the classical picture this would reach 1e5 m/s
|
|
5
|
+
(0.03% of c) after 100 s; the relativistic solution is essentially identical
|
|
6
|
+
because beta stays tiny.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
from relativistic_simulator import C, simulate
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
result = simulate(
|
|
16
|
+
mass=1000.0, # kg
|
|
17
|
+
force=1e6, # N
|
|
18
|
+
initial_velocity=0.0, # m/s (at rest)
|
|
19
|
+
duration=100.0, # s
|
|
20
|
+
dt=0.01, # s
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
final = result.final_state()
|
|
24
|
+
classical_v = (1e6 / 1000.0) * 100.0 # v = (F/m) * t, Newtonian
|
|
25
|
+
classical_K = 0.5 * 1000.0 * classical_v**2
|
|
26
|
+
|
|
27
|
+
print("Basic simulation: 1000 kg at rest, F = 1e6 N, t = 100 s")
|
|
28
|
+
print(f" n_points : {result.n_points}")
|
|
29
|
+
print(f" final position : {final['position']:.6e} m")
|
|
30
|
+
print(f" final velocity : {final['velocity']:.6e} m/s (beta = {final['beta']:.6e})")
|
|
31
|
+
print(f" classical velocity : {classical_v:.6e} m/s")
|
|
32
|
+
print(f" final gamma : {final['gamma']:.12f}")
|
|
33
|
+
print(f" final momentum : {final['momentum']:.6e} kg*m/s (classical m*v = {1000*classical_v:.6e})")
|
|
34
|
+
print(f" final kinetic energy: {final['kinetic_energy']:.6e} J (classical = {classical_K:.6e} J)")
|
|
35
|
+
print(f" proper time : {final['proper_time']:.9f} s (<= 100 s: {final['proper_time'] <= 100.0})")
|
|
36
|
+
|
|
37
|
+
report = result.validate()
|
|
38
|
+
print()
|
|
39
|
+
print(report.summary())
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
main()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Measure vectorized dataset-generation throughput on the current machine."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
from relativistic_simulator import generate_dataset
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> None:
|
|
10
|
+
print(f"{'samples':>12} {'seconds':>12} {'samples/sec':>16} {'MiB':>12}")
|
|
11
|
+
print("-" * 56)
|
|
12
|
+
for n in (10_000, 100_000, 1_000_000):
|
|
13
|
+
start = time.perf_counter()
|
|
14
|
+
dataset = generate_dataset(n_samples=n, random_seed=42)
|
|
15
|
+
elapsed = time.perf_counter() - start
|
|
16
|
+
mib = dataset.to_numpy().nbytes / (1024.0**2)
|
|
17
|
+
print(f"{n:12,d} {elapsed:12.6f} {n / elapsed:16,.0f} {mib:12.2f}")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Example 3: generate a ground-truth dataset for the future ML experiment.
|
|
2
|
+
|
|
3
|
+
Research pipeline this supports (the ML part is NOT part of this package):
|
|
4
|
+
|
|
5
|
+
physics equations
|
|
6
|
+
-> relativistic-simulator (this package, exact physics)
|
|
7
|
+
-> thousands/millions of synthetic observations
|
|
8
|
+
-> (external) ML model
|
|
9
|
+
-> predictions on unseen ultra-relativistic regimes
|
|
10
|
+
-> comparison against exact physics
|
|
11
|
+
|
|
12
|
+
Here we generate:
|
|
13
|
+
* a training regime beta in (0.0, 0.8)
|
|
14
|
+
* an extrapolation regime beta in (0.8, 0.9999)
|
|
15
|
+
with a fixed random seed for reproducibility, and save both to CSV.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from relativistic_simulator import generate_dataset
|
|
24
|
+
|
|
25
|
+
OUTPUT_DIR = Path(__file__).parent / "output"
|
|
26
|
+
N_TRAIN = 100_000
|
|
27
|
+
N_EXTRAP = 20_000
|
|
28
|
+
SEED = 42
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main() -> None:
|
|
32
|
+
OUTPUT_DIR.mkdir(exist_ok=True)
|
|
33
|
+
|
|
34
|
+
print("Generating ground-truth data (exact physics, seeded) ...")
|
|
35
|
+
train = generate_dataset(
|
|
36
|
+
n_samples=N_TRAIN,
|
|
37
|
+
mass_range=(100.0, 10_000.0),
|
|
38
|
+
force_range=(1e4, 1e7),
|
|
39
|
+
beta_range=(0.0, 0.8), # training regime
|
|
40
|
+
time_range=(0.0, 100.0),
|
|
41
|
+
random_seed=SEED,
|
|
42
|
+
)
|
|
43
|
+
extrap = generate_dataset(
|
|
44
|
+
n_samples=N_EXTRAP,
|
|
45
|
+
mass_range=(100.0, 10_000.0),
|
|
46
|
+
force_range=(1e4, 1e7),
|
|
47
|
+
beta_range=(0.8, 0.9999), # unseen ultra-relativistic regime
|
|
48
|
+
time_range=(0.0, 100.0),
|
|
49
|
+
random_seed=SEED + 1,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
train_csv = OUTPUT_DIR / "train_beta_0_0.8.csv"
|
|
53
|
+
extrap_csv = OUTPUT_DIR / "extrap_beta_0.8_0.9999.csv"
|
|
54
|
+
train.to_csv(str(train_csv))
|
|
55
|
+
extrap.to_csv(str(extrap_csv))
|
|
56
|
+
|
|
57
|
+
print()
|
|
58
|
+
print(f"train : {len(train):>7} rows, beta in [{train.initial_beta.min():.4f}, "
|
|
59
|
+
f"{train.initial_beta.max():.4f}] -> {train_csv.name}")
|
|
60
|
+
print(f"extrap : {len(extrap):>7} rows, beta in [{extrap.initial_beta.min():.4f}, "
|
|
61
|
+
f"{extrap.initial_beta.max():.4f}] -> {extrap_csv.name}")
|
|
62
|
+
print()
|
|
63
|
+
print("input columns :", train.input_columns)
|
|
64
|
+
print("target columns:", train.output_columns)
|
|
65
|
+
|
|
66
|
+
report = train.validate()
|
|
67
|
+
assert report.passed, report.summary()
|
|
68
|
+
print()
|
|
69
|
+
print(f"train physics validation: passed={report.passed}, "
|
|
70
|
+
f"max invariant err = {report.max_energy_momentum_error:.2e}, "
|
|
71
|
+
f"max momentum err = {report.max_momentum_relation_error:.2e}")
|
|
72
|
+
|
|
73
|
+
# Reproducibility check: same seed -> bitwise-identical data
|
|
74
|
+
again = generate_dataset(
|
|
75
|
+
n_samples=N_TRAIN,
|
|
76
|
+
mass_range=(100.0, 10_000.0),
|
|
77
|
+
force_range=(1e4, 1e7),
|
|
78
|
+
beta_range=(0.0, 0.8),
|
|
79
|
+
time_range=(0.0, 100.0),
|
|
80
|
+
random_seed=SEED,
|
|
81
|
+
)
|
|
82
|
+
assert np.array_equal(train.momentum, again.momentum)
|
|
83
|
+
print("reproducibility: same seed reproduces bitwise-identical data")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
main()
|