Getting Started
OpenSpinDynamics.jl provides a compact interface for simulating closed and open quantum spin dynamics.
A typical workflow has four steps:
- define the coupling,
- construct a
SpinModel, - prepare an initial state and observables,
- call
evolve.
This page introduces the core public API with small examples.
Installation
OpenSpinDynamics.jl can be added from its repository while the package is under active development.
using Pkg
Pkg.add(
url="https://github.com/javahedi/OpenSpinDynamics.jl",
)Then load the package with
using OpenSpinDynamics
using SparseArraysBuild a spin model
As a first example, consider a four-spin nearest-neighbor XXZ chain.
N = 4
coupling = NearestNeighborCoupling(
0.0,
N,
)
model = SpinModel(
N;
Jxy=1.0,
Jz=0.5,
coupling=coupling,
)
size(model.hamiltonian)(16, 16)For N spin-1/2 degrees of freedom, the Hilbert-space dimension is $2^N$.
The main model keywords are:
Jxy: transverse exchange strength,Jz: longitudinal interaction strength,hx: local $x$ fields,hz: local $z$ fields,coupling: a coupling object,Jmn: an explicit coupling matrix for custom interactions.
For example, a model with local fields can be written as
field_model = SpinModel(
N;
Jxy=1.0,
Jz=0.5,
hx=fill(0.2, N),
hz=zeros(N),
coupling=coupling,
)Couplings
OpenSpinDynamics.jl provides several coupling constructors.
Nearest-neighbor coupling
nearest = NearestNeighborCoupling(
0.2,
N,
)
nearest.matrix4×4 Matrix{Float64}:
0.0 0.8 0.0 0.0
0.8 0.0 1.2 0.0
0.0 1.2 0.0 0.8
0.0 0.0 0.8 0.0The parameter δ controls alternating nearest-neighbor bond strengths.
Clean long-range coupling
long_range = LongRangeCouplingClean(
2.0,
N,
)
long_range.matrix4×4 Matrix{Float64}:
0.0 1.0 0.25 0.111111
1.0 0.0 1.0 0.25
0.25 1.0 0.0 1.0
0.111111 0.25 1.0 0.0For this coupling,
\[J_{ij} \propto \frac{1}{|i-j|^\alpha}.\]
Disordered long-range coupling
disordered = LongRangeCouplingDisorder(
2.0,
20,
N;
reordered=false,
)
size(disordered.matrix)(4, 4)Here N spins are sampled from a lattice containing L=20 available sites.
Initial states
Two common product states are available directly.
Néel state
ψ_neel = neel_state(
N;
direction=:z,
)
size(ψ_neel)(16,)This produces the alternating state
\[|\uparrow\downarrow\uparrow\downarrow\cdots\rangle.\]
Polarized state
ψ_polarized = polarized_state(
N;
direction=:z,
)
size(ψ_polarized)(16,)This produces
\[|\uparrow\uparrow\uparrow\uparrow\cdots\rangle.\]
Both state constructors also support direction=:x.
Spin operators
Use spin_operators to construct single-site observables on the full Hilbert space.
ops = spin_operators(N)
size(ops.z[1])(16, 16)The returned SpinOperators object contains:
ops.x[i],ops.z[i],ops.plus[i],ops.minus[i].
For example, the average longitudinal magnetization is
\[M_z = \frac{1}{N} \sum_{i=1}^{N}\sigma_i^z.\]
Mz = sum(
ops.z[i]
for i in 1:N
) / NClosed-system evolution
For pure-state dynamics, pass a wavefunction to evolve.
times = collect(
range(0.0, 2.0; length=51)
)
result = evolve(
model,
ψ_neel,
times,
[Mz];
method=:krylov,
)
size(result)(51, 1)The rows correspond to time points and the columns correspond to observables.
The closed-system methods are:
method=:krylov,method=:arnoldi.
For example,
result_arnoldi = evolve(
model,
ψ_neel,
times,
[Mz];
method=:arnoldi,
)
maximum(
abs.(
result[:, 1] .-
result_arnoldi[:, 1]
)
)0.0Lindblad evolution
For Markovian open-system dynamics, provide a density matrix and collapse operators.
Consider local spontaneous emission,
\[L_i = \sqrt{\gamma}\,\sigma_i^-.\]
γ = 0.2
lindblad_ops = [
sqrt(γ) * ops.minus[i]
for i in 1:N
]
ρ0 = sparse(
ψ_neel * ψ_neel'
)The density matrix can then be evolved with
open_result = evolve(
model,
ρ0,
times,
[Mz];
method=:expm,
lindblad_ops=lindblad_ops,
)
size(open_result)(51, 1)The supported density-matrix methods are:
method=:expm,method=:ode.
For small Hilbert spaces, :expm is often a convenient reference method.
Quantum trajectories
The same dissipative problem can be treated with stochastic quantum trajectories.
trajectory_mean, trajectory_std = evolve(
model,
ψ_neel,
times,
[Mz];
method=:trajectories,
lindblad_ops=lindblad_ops,
num_samples=20,
)
size(trajectory_mean)(51, 1)The trajectory method returns both the sample mean and sample standard deviation.
For accurate Monte Carlo estimates, increase num_samples.
Updating a model
An existing model can be updated in place.
update_model!(
model;
hz=fill(0.1, N),
)
model.hz4-element Vector{Float64}:
0.1
0.1
0.1
0.1Couplings can also be replaced directly:
update_model!(
model;
coupling=LongRangeCouplingClean(2.0, N),
)
size(model.hamiltonian)(16, 16)Unspecified parameters retain their current values.
Where to go next
The worked examples explore the main workflows in more detail:
For all exported functions and types, see the API Reference.