Architecture#
soliton_solver is built on a modular, object-oriented architecture that separates the theory-agnostic numerical infrastructure from theory-specific physics implementations.
Design Philosophy#
The core principle is separation of concerns:
Numerical core — Generic PDE solver, finite-difference operators, time integrators, and CUDA utilities
Physics theories — Theory-specific parameter sets, energy functionals, initial conditions, observables, and visualization
This separation enables:
Rapid theory development without touching the solver
Reuse of optimized CUDA kernels across different models
Easy testing and validation of numerical methods
Clean, maintainable codebase
Plug-and-Play Theory Registry#
Theories are discovered and loaded dynamically via the theory registry (soliton_solver.theories.registry).
Registration mechanism#
Each theory package provides a THEORY_SPEC descriptor:
from soliton_solver.theories.registry import TheorySpec
THEORY_SPEC = TheorySpec(
name="Chiral magnet",
aliases=("Chiral ferromagnet", "DM magnet"),
import_path="soliton_solver.theories.chiral_magnet",
description="Chiral ferromagnet with Dzyaloshinskii-Moriya interaction",
version="1.0"
)
The registry maintains a mapping of theory names to their specifications:
from soliton_solver.theories import list_theories, load_theory
# List all registered theories
theories = list_theories()
# Load a theory
theory = load_theory("Chiral magnet")
Dynamic theory discovery#
Theories are automatically registered on import. The registry validates that each theory package contains required submodules:
params— Parameter definitionskernels— CUDA kernelsinitial_config— Initial field configurations
Dependency Injection#
soliton_solver uses dependency injection to decouple the numerical solver from physics-specific code.
Dependency injection pattern#
The Simulation class accepts both the parameters and the theory as constructor arguments:
from soliton_solver.core.simulation import Simulation
from soliton_solver.theories import load_theory
theory = load_theory("Chiral magnet")
params = theory.params.default_params(xlen=256, ylen=256, ...)
sim = Simulation(params, theory)
The theory provides:
theory.kernels.do_gradient_step_kernel— Energy gradient computation kerneltheory.kernels.do_rk4_kernel— RK4 integrator kernel (optional)theory.initial_config— Initial field setuptheory.observables— Observable calculationstheory.params— Parameter managementtheory.io— Checkpoint/output routinestheory.render_gl— Visualization backend
Benefits#
This design allows:
Isolation — The solver doesn’t know or care about specific physics
Testability — Numerical methods can be tested against any theory
Extensibility — New theories plug in without modifying the solver
Reusability — Solver improvements benefit all theories immediately
Numerical Infrastructure#
The core numerical components live in soliton_solver.core:
Modules#
simulation.py — Main Simulation class
Grid initialization and memory management
Energy and gradient computation
Integration time-stepping
Observable evaluation and checkpoint I/O
integrator.py — Time-stepping algorithms
Arrested Newton flow minimization
Runge-Kutta 4th order (RK4) integration
Velocity reset logic for flow arrest
derivatives.py — Finite-difference operators
First and second spatial derivatives
Laplacian operator
Curl operator for gauge fields
params.py — Parameter management
Paramsbase class for user-facing parameter definitionResolvedParamsfor computed grid quantities (lattice spacing, etc.)Device parameter packing/unpacking utilities
io.py — Input/output utilities
Checkpoint saving and loading
Field data serialization
Observable and energy history I/O
utils.py — GPU utilities
CUDA kernel launch wrappers
Grid indexing utilities
Device memory allocation helpers
colormaps.py — Color mapping for visualization
Standard colormaps
Custom colormap definition
Theory Model Interface#
Each theory must implement these components:
Required modules#
params.py
Extends
CoreParamswith theory-specific parametersDefines
pack_device_params()to prepare data for CUDA kernelsProvides
default_params()factory method
Example:
from dataclasses import dataclass
from soliton_solver.core.params import Params as CoreParams
@dataclass(frozen=True)
class Params(CoreParams):
"""Theory-specific parameters."""
J: float = 1.0 # Exchange coupling
K: float = 0.1 # Anisotropy
D: float = 0.01 # DMI interaction
# ... additional parameters
kernels.py
Implements
do_gradient_step_kernel— computes energy gradient at each grid pointOptionally implements
do_rk4_kernel— custom RK4 integratorMay include auxiliary kernels for energy density, intermediate calculations, etc.
Gradients are typically generated via make_do_gradient_step_kernel() factory:
from soliton_solver.core.integrator import make_do_gradient_step_kernel
def compute_energy_point(Field, d1fd1x, x, y, p_i, p_f):
"""Compute local energy at (x, y)."""
# Theory-specific energy functional
...
def compute_gradient_point(Field, d1fd1x, x, y, p_i, p_f):
"""Compute local gradient at (x, y)."""
# Theory-specific energy gradient
...
do_gradient_step_kernel = make_do_gradient_step_kernel(
compute_energy_point,
compute_gradient_point
)
initial_config.py
Implements
get_initial_config()— sets up field configurationsHandles different ansätze (vortex types, skyrmion patterns, etc.)
Example:
def get_initial_config(theory, sim, mode="ground"):
"""Initialize fields based on mode."""
if mode == "ground":
# Vacuum configuration
...
elif mode == "vortex":
# Single vortex
...
observables.py
Computes quantities of interest: energy, field norms, topological charge, etc.
Each observable is a function that reads field data and returns a scalar or array
Example:
def compute_energy(Field, p_i, p_f):
"""Compute total energy."""
...
def compute_topological_charge(Field, p_i, p_f):
"""Compute winding number."""
...
io.py
Saves and loads checkpoint files
Formats output data (HDF5, NetCDF, etc.)
render_gl.py
Visualization and real-time rendering
run_viewer()launches the interactive windowColormap and field-to-texture mapping
Optional modules#
instructions.py — Terminal help text and theory description
results/ — Post-processing and analysis scripts
Module Organization#
soliton_solver/
├── core/ # Theory-agnostic numerical infrastructure
│ ├── simulation.py # Main Simulation driver
│ ├── integrator.py # Time integrators
│ ├── derivatives.py # Finite-difference operators
│ ├── params.py # Parameter management
│ ├── io.py # I/O utilities
│ ├── utils.py # GPU utilities
│ └── colormaps.py # Color mapping
│
├── theories/ # Physics models
│ ├── registry.py # Theory discovery and registration
│ ├── chiral_magnet/ # Example theory
│ │ ├── __init__.py # THEORY_SPEC
│ │ ├── params.py # Theory parameters
│ │ ├── kernels.py # CUDA kernels
│ │ ├── initial_config.py
│ │ ├── observables.py
│ │ ├── io.py
│ │ ├── render_gl.py
│ │ └── results/ # Analysis and plotting
│ │
│ ├── baby_skyrme/ # Another theory...
│ ├── ginzburg_landau_superconductor/
│ └── ... (other theories)
│
├── visualization/ # Shared visualization backend
│ └── gl_backend.py # OpenGL/CUDA rendering
│
├── examples/ # Runnable demonstrations
│ ├── chiral_magnet_gl.py
│ └── ... (other examples)
│
└── assets/ # Logos, images
Extensibility#
To add a new theory, implement the required modules above and register it with the registry. See Extending the Solver for a step-by-step guide.
Example: Theory Loading and Simulation Setup#
from soliton_solver.theories import load_theory
from soliton_solver.core.simulation import Simulation
# Load theory
theory = load_theory("Chiral magnet")
# Create parameters
params = theory.params.default_params(
xlen=256, ylen=256,
xsize=10.0, ysize=10.0,
J=40e-12,
K=0.8e+6,
D=4e-3,
)
# Inject theory into solver
sim = Simulation(params, theory)
# Initialize fields
sim.initialize({"mode": "ground"})
# Minimize energy
result = sim.minimize(tol=1e-4, max_iterations=10000)
# Compute observables
energy = sim.compute_observable("energy")
charge = sim.compute_observable("topological_charge")
The Simulation class handles all GPU memory management, CUDA kernel launches, and integration logic without knowing anything specific about the theory’s physics.