Development Guide¶
Contribute to the project and extend the simulation.
Setting Up Development Environment¶
# Clone and setup
git clone https://github.com/ml3m/quantum-collider-sandbox.git
cd quantum-collider-sandbox
# Virtual environment
python -m venv .venv
source .venv/bin/activate
# Install with dev tools
make install
# Verify
make test
make lint
Project Structure¶
quantum-collider-sandbox/
├── src/quantum_collider_sandbox/
│ ├── __init__.py
│ ├── __main__.py # CLI entry, main loop
│ ├── config.py # Constants, presets
│ ├── simulation.py # GPU physics (2900 lines)
│ ├── particles.py # Taichi field management
│ ├── renderer.py # UI, visualization
│ ├── pdg_table.py # 40 particles catalog
│ └── data_loader.py # I/O (HDF5, JSONL)
├── tests/ # Pytest suite
│ ├── test_*.py # 5 test files, ~50 assertions
│ └── conftest.py
├── docs/ # Sphinx documentation
│ ├── source/
│ │ ├── conf.py # Sphinx config
│ │ └── *.rst # Documentation files
│ └── build/ # Generated HTML
├── data/ # Simulation data
│ ├── exports/ # HDF5 state files
│ └── logs/ # JSONL physics events
├── Makefile # Build automation
├── pyproject.toml # Package metadata
├── .pre-commit-config.yaml # CI/CD hooks
└── README.rst
Code Style & Linting¶
Automated checks (pre-commit):
# Install pre-commit hooks
pre-commit install
# Run checks (automatic on git commit)
pre-commit run --all-files
Manual checks:
# Run linter
make lint
# Specific tools:
ruff check src/ # Fast linter
black src/ # Code formatter
pylint src/ # Detailed analysis
Code standards:
Black formatting: Line length 88
Ruff rules: Default (PEP 8 subset)
Pylint: Target 9.5+ / 10.0 score
Imports: Sorted, no circular dependencies
Docstrings: PEP 257, triple-quote format
Example docstring:
def compute_collision_products(particle_a, particle_b):
"""Generate collision products from two particles.
Args:
particle_a: First particle (dict with type, mass, velocity)
particle_b: Second particle
Returns:
list: Product particles (may be empty if no reaction occurs)
Raises:
ValueError: If particle types invalid
"""
...
Testing¶
Run all tests:
make test
Test files:
test_config.py— Configuration loadingtest_particles.py— Particle data structurestest_pdg_table.py— Particle catalogtest_data_loader.py— I/O operationstest_simulation.py— Physics correctness (optional)
Example test:
import pytest
from quantum_collider_sandbox.pdg_table import PARTICLES
def test_electron_properties():
"""Verify electron mass and charge."""
e = PARTICLES["electron"]
assert e["mass"] == pytest.approx(0.511, rel=0.01)
assert e["charge"] == -1
Adding New Features¶
1. New particle type:
Edit pdg_table.py:
PARTICLES["my_particle"] = {
"name": "My Particle",
"pdg_id": 9999,
"mass": 5.0, # MeV/c²
"lifetime": 1e-10, # seconds
"charge": 0,
"color": (1.0, 0.5, 0.0), # RGB
"decay_channels": [
{"products": [22, 22], "branching_ratio": 1.0}, # 100% → 2 photons
]
}
2. New force:
Edit simulation.py, in compute_forces() kernel:
@ti.kernel
def compute_forces(...):
for i in range(n):
for j in range(i+1, n):
# ... existing forces ...
# Add new force
dist = pos[j] - pos[i]
r_mag = dist.norm()
if r_mag > 1e-6:
# Custom force calculation
f_mag = my_custom_force(...)
force_a = f_mag * dist / r_mag
acc[i] += force_a / mass[i]
acc[j] -= force_a / mass[j]
Add constant to config.py:
MY_FORCE_K = 1.0 # Tunable parameter
3. New preset:
Edit config.py:
PRESETS["my_scenario"] = {
"preset_name": "My Scenario",
"initial_particles": 50,
"coulomb_k": 40.0,
"gravity_g": 6.0,
"initial_geometry": "sphere", # or "beam", "cluster", etc.
}
Then in __main__.py, add to preset dropdown:
preset_name = ui.label("Presets", choices=["default", "my_scenario", ...])
4. New UI control:
Edit renderer.py, in the ImGui panel building:
my_slider = ui.slider("My Control", min=0.0, max=100.0, value=50.0)
if my_slider:
config.MY_FORCE_K = my_slider
Documentation¶
Build Sphinx docs locally:
make docs
# Open docs/build/index.html in browser
Edit documentation:
Docs source in
docs/source/*.rst(reStructuredText format)Edit, rebuild with
make docsTest links and formatting
Add new page:
Create
docs/source/mypage.rstAdd to toctree in
docs/source/index.rstRun
make docsto verify
Debugging Physics¶
Print particle state:
@ti.kernel
def debug_particle(i: ti.i32):
pos_i = pos[i]
vel_i = vel[i]
ti.print(f"Particle {i}: pos={pos_i}, vel={vel_i}")
debug_particle(0) # Print first particle
Check energy conservation:
# Before/after step
ke_before = sim.compute_kinetic_energy()
sim.step()
ke_after = sim.compute_kinetic_energy()
print(f"ΔKE = {ke_after - ke_before:.6f}")
Verify force magnitudes:
forces = sim.get_forces() # Nx3 array
print(f"Max force: {np.max(np.linalg.norm(forces, axis=1)):.2f}")
print(f"Median force: {np.median(np.linalg.norm(forces, axis=1)):.4f}")
Profiling & Performance¶
Profile a simulation:
import cProfile
import pstats
from quantum_collider_sandbox.simulation import Simulation
sim = Simulation(preset="default", particles=100)
profiler = cProfile.Profile()
profiler.enable()
for _ in range(100):
sim.step()
profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats("cumulative").print_stats(20) # Top 20
GPU profiling:
# NVIDIA
nvidia-smi dmon -s pucvmet
# AMD
rocm-smi --showuse
Continuous Integration¶
Pre-commit checks (automatic on commit):
ruff — Fast linting
black — Code formatting
pylint — Detailed analysis (9.5+ score minimum)
pytest — Run all tests (27 must pass)
All checks must pass before commit is accepted.
Contributing Guidelines¶
Before submitting a PR:
Fork the repository
Create a feature branch:
git checkout -b feature/my-featureMake changes
Run
make lint && make testlocallyCommit with descriptive message:
perf: improve trail rendering (Phase 1 optimization)Push and open PR
Commit message format:
feat:New featurefix:Bug fixperf:Performance improvementdocs:Documentation updaterefactor:Code restructuringtest:Test additionschore:Maintenance
Keep commits atomic:
One logical change per commit
Run tests after each commit
Clean git history (rebase if needed)
Phase 1 Optimization Development¶
(The recent optimization implemented)
Changes made:
Reduced
TRAIL_LENGTH400 → 40 inconfig.pyAdded skip logic to
build_trail_lines()kernel insimulation.pyExtracted duplicate spawn code into
_spawn_random_particles_internal()helperUpdated
__main__.pyto use helper functionFixed .pre-commit-config.yaml for venv independence
Impact:
10x vertex reduction (80ok → 80k vertices/frame)
2-3x FPS improvement (3-5 → 8-15 FPS at 1k particles)
All 27 tests passing, 10.0/10 pylint score
Next phases (planned):
Phase 2: GPU kernel consolidation (reduce launch overhead)
Phase 3: Adaptive trail density (motion-based sampling)
Phase 4: GPU LOD rendering (distance-based culling)
Troubleshooting Development¶
Import errors after editing:
# Reinstall package
pip install -e ".[dev]"
Tests fail after changes:
# Run single test file
pytest tests/test_physics.py -v
Linting errors:
# Auto-fix with black
black src/
# Fix some ruff issues
ruff check --fix src/
Release Process¶
(For maintainers)
Update version in
pyproject.tomlUpdate
CHANGELOG.rstEnsure all tests pass:
make test4. Ensure all lints pass:make lint
Tag commit:
git tag v1.0.5Push:
git push origin v1.0.5