A Computational Soap Box Slide
Project description
A Computational Soap Box Slide
This Python package is written by Toon Verstraelen for students of the course "Python for Scientists" (C004212) of the B.Sc. Physics and Astronomy at Ghent University. It is distributed under the conditions of the GPLv3 license.
Quick Start
You can install the soapboxslide Python module with:
pip install soapboxslide
This module implements a 2D surface that resembles a curved slide, suitable for computational soapbox racing.
To give you a quick idea, the following figure is created with the plot.py script in this repository, and visualizes the slides boxcar_blitz.toml and brutal_bends.toml included in this repository:
Your eyes may need some time to adapt to the correct depth perception: black ridges are high-altitude separations between the colored valleys.
Note that the starting point and the finish are denoted as green and red circles, respectively. All other circles are waypoints that must be reached on the way down.
Concept
The idea is for students to use the surface implemented in soapboxslide to simulate the dynamics of a particle (or a connected set of particles) sliding down.
In addition to correctly implementing the dynamics, students must do so as quickly as possible without missing any of the waypoints shown as dotted circles.
Two classes of physical models can be considered:
-
The most convenient is to assume a model of point particles strictly bound to the surface with holonomic constraints. In this case, equations of motion can be derived using a Lagrangian, possibly with a generalized force to include non-conservative friction forces.
-
A more challenging scenario (not used for now, but closer in spirit to real soap box races) is to impose inequality constraints, allowing particles to detach from the surface.
Slide Class Usage
One can load a surface from a TOML file and calculate slide properties at a given point, e.g. $x=5$ and $y=38$, as follows:
import numpy as np
from soapboxslide import Slide
slide = Slide.from_file("boxcar_blitz.toml")
print(slide(np.array([5.0, 38.0])))
This will show three results:
(array(2.05331579), array(0.20172586), array(14.75904983))
These three values have the following meaning (in meter):
- The progress along the track.
- The orthogonal(ish) deviation from the bottom of the track.
- The altitude of the track.
The slide() function is fully vectorized: one may also provide an array of points to calculate many altitudes efficiently.
(This is useful for plotting.)
The slide() function optionally supports alternative NumPy wrappers, such as those of JAX and its predecessor Autograd.
This allows for an efficient evaluation of analytical partial derivatives of the altitude.
For example, a vectorized calculation of many gradients is implemented as follows:
from functools import partial
import jax
import jax.numpy as jnp
import numpy as np
from soapboxslide import Slide
# We recommend double precision:
jax.config.update("jax_enable_x64", True)
# Define the slide and its gradient
slide = Slide.from_file("boxcar_blitz.toml")
alt_grad = jax.jit(jax.vmap(jax.grad(
lambda pos: slide(pos, npw=jnp)[2]
)))
# Compute the gradient at several points
pos = np.array([
[5.0, 38.0],
[12.1, 7.3],
[10.7, 25.5],
])
print(alt_grad(pos))
This will show three gradients, one for each row of pos:
[[ 0.21289734 0.10176584]
[-1.85311237 1.84445056]
[-2.16704263 -2.9280058 ]]
In addition, a Slide instance has the following attributes:
width: the width of the slide arena in meter.height: the height of the slide arena in meter.waypoints: A 2D NumPy array with three columns (and at least two rows) defining the shape and altitude of the slide track. These are also intended as points that must be visited by a particle or a system sliding down, to ensure that it followed a legitimate trajectory.target_radius: a required proximity between a particle (or the center of mass of a system of particles) to a waypoint, to mark this waypoint as properly visited. The distance is only measured in the $xy$-plane.
Note that the above surface plots show dashed circles centered on the waypoints, whose radius is the target radius.
The Slide class also features two potentially useful methods:
Slide.plotcan be used to prepare a drawing of the slide on which one can overlay additional results.Slide.get_hitscan be used to check which waypoints were reached by a given trajectory.
Consult their respective docstrings for more information on how to use these methods.
Storing and Sharing Trajectory Data
The soapboxslide module also implements a Trajectory class for storing the results of a numerical integration of one or more particles sliding over the surface.
This class performs an initial validation of the trajectory data upon construction.
It also features to_file and from_file methods with which trajectories can be dumped to and loaded from NPZ files.
This is useful if you want to share your trajectory with someone, e.g. for review, and to implement separate computation and visualization scripts (or notebooks).
To use the Trajectory class, create an instance as follows after completing the numerical integration of the equations of motion:
traj = Trajectory(
time=..., # NDArray[float], shape = (ntime, )
mass=..., # NDArray[float], shape = (npoint, )
gamma=..., # NDArray[float], shape = (npoint, )
pos=..., # NDArray[float], shape = (ntime, npoint, 3), (x, y and z coordinates)
vel=..., # NDArray[float], shape = (ntime, npoint, 3), (x, y and z coordinates)
grad=..., # NDArray[float], shape = (ntime, npoint, 2), (h_x and h_y derivatives)
hess=..., # NDArray[float], shape = (ntime, npoint, 3), (h_xx, h_xy and h_yy derivatives)
spring_idx=..., # NDArray[int], shape = (nspring, 2), (each row is a pair of point indexes)
spring_par=..., # NDArray[float], shape = (nspring, 3), (force constant, rest length, damping coeff)
end_state=..., # One of the EndState enumeration
stop_time=..., # Optional, time that last target was reached
stop_pos=..., # Optional, NDArray[float], shape = (npoint, 3), positions at stop time
stop_vel=..., # Optional, NDArray[float], shape = (npoint, 3), velocities at stop time
)
traj.to_file("traj.npz")
In this Python snippet, you need to replace all triple dots by arrays you defined or computed. Some guidelines:
- If there are no springs yet, use arrays with zero rows for the spring definitions.
- If there is just one particle, several arrays will have a size 1 axis, i.e.
npoint=1. - You can first store all fields in a dictionary, e.g.
data = {"time": ..., ...}and optionally add thestop_*fields to the dictionary. The trajectory is then created withTrajectory(**data). - The end state can be specified to indicate when the numerical integration has ended, using one of the
EndStateinstances defined in thesoapboxslidemodule:EndState.STOP: last target was reached in time.EndState.CRASH: the numerical integration failed (e.g. due to Inf or Nan results).EndState.FAR: the particle moved more than 5 m out of the arena.EndState.TIMEOUT: the maximum time, e.g. 60 s, was reached.
- When creating a
Trajectoryinstance, you will get aTypeErrororValueErrorif some of the data do not meet basic expectations.
The meaning of and requirements for all attributes is further elaborated in the docstrings in soapboxslide.py.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file soapboxslide-1.0.2.tar.gz.
File metadata
- Download URL: soapboxslide-1.0.2.tar.gz
- Upload date:
- Size: 161.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1aa73e6c7bfc4b5a5140427bbb9d15f5f4b87b5384bcf47508eccaaeca4545ee
|
|
| MD5 |
d9320b893ab243d9c062f3766f9b3cd8
|
|
| BLAKE2b-256 |
60281ea545668a5cfe29512f805fcf981c2b652789cdbebfdda99fc2982502d8
|
Provenance
The following attestation bundles were made for soapboxslide-1.0.2.tar.gz:
Publisher:
release.yaml on molmod/soapboxslide
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
soapboxslide-1.0.2.tar.gz -
Subject digest:
1aa73e6c7bfc4b5a5140427bbb9d15f5f4b87b5384bcf47508eccaaeca4545ee - Sigstore transparency entry: 601241789
- Sigstore integration time:
-
Permalink:
molmod/soapboxslide@a7ff67e3550cde1afc01ba1b630104be34f771ec -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/molmod
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@a7ff67e3550cde1afc01ba1b630104be34f771ec -
Trigger Event:
push
-
Statement type:
File details
Details for the file soapboxslide-1.0.2-py3-none-any.whl.
File metadata
- Download URL: soapboxslide-1.0.2-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c985fafdd7f3c2c97f7d209d83eef9f056a4858821a1f46424410fc65249089
|
|
| MD5 |
e39a7d3074b1ee0d1280d301a9b9c8d4
|
|
| BLAKE2b-256 |
2dd25c193520565660cdcf1657345ebe65be08e70c12fae84c1d9cff10602aae
|
Provenance
The following attestation bundles were made for soapboxslide-1.0.2-py3-none-any.whl:
Publisher:
release.yaml on molmod/soapboxslide
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
soapboxslide-1.0.2-py3-none-any.whl -
Subject digest:
3c985fafdd7f3c2c97f7d209d83eef9f056a4858821a1f46424410fc65249089 - Sigstore transparency entry: 601241794
- Sigstore integration time:
-
Permalink:
molmod/soapboxslide@a7ff67e3550cde1afc01ba1b630104be34f771ec -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/molmod
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@a7ff67e3550cde1afc01ba1b630104be34f771ec -
Trigger Event:
push
-
Statement type: