A Go-based simulator for gravitational lensing and relativistic effects.
GRLens is a small personal project that explores how light and time behave near massive objects according to Einstein’s General Relativity.
It simulates gravitational lensing (how light bends around mass) and gravitational time dilation (how time slows near strong gravity).
The goal isn’t to build a production-ready physics engine — but rather a learning journey, built from scratch in Go, using clean concurrency and numerical integration to visualize the beauty of spacetime.
I’ve always been fascinated by space, black holes, and the strange geometry of spacetime.
At the same time, I’ve always loved programming — especially in Go for its clarity and concurrency model.
GRLens combines those two passions:
to learn the mathematical core of relativity while building something visual, tangible, and interactive.
It’s both a personal learning lab and a growing foundation for future GR simulations.
The project uses the Schwarzschild metric in geometric units ((G = c = 1)):
From this, geodesic equations are integrated numerically using the Runge–Kutta 4th order method to trace photon paths (null geodesics).
For time-dilation experiments, stationary clocks at different radii satisfy:
A full explanation and derivation live in
docs/math_background.md
git clone https://github.com/moisesvega/grlens
cd grlens
mise install # Install tools (go, gotestsum, etc.)
mise run build # Build the binary
mise run test # Run testsQuick start - generate example images:
mise run render-disk-inclined # EHT-style black hole with accretion disk
mise run render-lensing # Gravitational lensing with starfield
mise run render-all # Generate all example rendersAvailable mise tasks:
mise run build- Build the grlens binarymise run test- Run all tests with coveragemise run lint- Run lintermise run render-disk- Render black hole with accretion diskmise run render-disk-inclined- Render with 17° inclination (EHT-style)mise run render-lensing- Render gravitational lensing with starfieldmise run render-all- Generate all example rendersmise run plot- Generate scientific plotsmise run dilation- Run time dilation example
go mod tidy
go build -o grlens ./cmd/grlensRender realistic gravitational lensing with starfield background:
./grlens render --width 800 --height 800 --mass 1.0 --r0 15 --out lensing.png
# With accretion disk (like famous EHT black hole images)
./grlens render --width 800 --height 800 --mass 1.0 --r0 15 --disk --out blackhole.pngOptions:
--width,--height- Image dimensions--mass- Black hole mass (geometric units)--r0- Observer distance from black hole--stars- Number of background stars (default: 3000)--no-stars- Disable starfield background--disk- Render accretion disk with Doppler boosting--analyze-ring- Analyze and report Einstein ring radius
Output: PNG image showing:
- Black hole shadow (~5.2M radius for non-rotating BH)
- Einstein rings from gravitational lensing
- Lensed starfield with realistic stellar colors
- Accretion disk with temperature gradient and relativistic effects (if
--diskenabled) - Multiple image formation from strong lensing
./grlens dilation --mass 1.0 --radii 4,6,10,20 --hours 10Shows how much slower time flows at various radii compared to infinity.
Output: Formatted table with:
- Proper time elapsed at each radius
- Time dilation factor
- Time "lost" compared to distant observer
- Special radii markers (event horizon, photon sphere)
Generate publication-quality plots using gonum:
# Effective potential for photon orbits
./grlens plot --type potential --mass 1.0 --impact 5.0 --out potential.png
# Gravitational time dilation curve
./grlens plot --type dilation --mass 1.0 --out dilation.png
# Schwarzschild metric function
./grlens plot --type metric --mass 1.0 --out metric.png
# Photon geodesic trajectory
./grlens plot --type geodesic --mass 1.0 --impact 4.5 --out geodesic.png| Feature | Status | Description |
|---|---|---|
| Schwarzschild metric | ✅ Complete | Geodesic equations with Christoffel symbols |
| RK4 integrator | ✅ Complete | 4th order Runge-Kutta with adaptive stepping |
| Parallel ray tracing | ✅ Complete | Multi-core photon geodesic integration |
| Black hole shadow | ✅ Complete | Realistic shadow rendering (~5.2M radius) |
| Starfield lensing | ✅ Complete | 3000+ stars with gravitational lensing |
| Accretion disk | ✅ Complete | Temperature profile, Doppler boosting, ISCO |
| Einstein ring detection | ✅ Complete | Automatic ring radius analysis |
| Time dilation calculator | ✅ Complete | Proper time vs coordinate time |
| Scientific plotting | ✅ Complete | Gonum-based graphs (potential, geodesics) |
| CLI interface | ✅ Complete | Cobra-based commands with flags |
| Unit tests | ✅ Complete | Physics validation tests |
- Language: Go 1.25+
- Math:
gonumfor plotting & numerics - Rendering:
image/png(CLI), optionalEbitenfor UI - Structure: clean modular packages (
relativity,render,experiments)
- Understand metric tensors, Christoffel symbols, and geodesics.
- Practice numerical integration and physical correctness checks.
- Explore Go concurrency for scientific simulation.
- Visualize relativistic phenomena in an accessible, playful way.
- Implement Kerr metric (rotating black holes).
- Add Shapiro delay (signal time delay).
- Integrate redshift coloring in lensing render.
- Compile WASM version for browser-based demo.
- S. Carroll – Spacetime and Geometry
- C. Misner, K. Thorne, J. Wheeler – Gravitation
- Event Horizon Telescope Collaboration – First M87 Black Hole Image
- NASA – First Image of a Black Hole
- MIT News – Astronomers capture first image of a black hole
- arXiv – First M87 Event Horizon Telescope Results
- NASA/ESA – Einstein Ring Visualizations
- Wikipedia – Schwarzschild Metric
- Wikipedia – Event Horizon Telescope