Files

349 lines
7.7 KiB
Markdown

# QuTiP Time Evolution and Dynamics Solvers
## Overview
QuTiP provides multiple solvers for quantum dynamics:
- `sesolve` - Schrödinger equation (unitary evolution)
- `mesolve` - Master equation (open systems with dissipation)
- `mcsolve` - Monte Carlo (quantum trajectories)
- `brmesolve` - Bloch-Redfield master equation
- `fmmesolve` - Floquet-Markov master equation
- `ssesolve/smesolve` - Stochastic Schrödinger/master equations
## Schrödinger Equation Solver (sesolve)
For closed quantum systems evolving unitarily.
### Basic Usage
```python
from qutip import *
import numpy as np
# System setup
N = 10
psi0 = basis(N, 0) # Initial state
H = num(N) # Hamiltonian
# Time points
tlist = np.linspace(0, 10, 100)
# Solve
result = sesolve(H, psi0, tlist)
# Access results
states = result.states # List of states at each time
final_state = result.states[-1]
```
### With Expectation Values
```python
# Operators to compute expectation values
e_ops = [num(N), destroy(N), create(N)]
result = sesolve(H, psi0, tlist, e_ops=e_ops)
# Access expectation values
n_t = result.expect[0] # ⟨n⟩(t)
a_t = result.expect[1] # ⟨a⟩(t)
```
### Time-Dependent Hamiltonians
```python
# Method 1: String-based (faster, requires Cython)
H = [num(N), [destroy(N) + create(N), 'cos(w*t)']]
args = {'w': 1.0}
result = sesolve(H, psi0, tlist, args=args)
# Method 2: Function-based
def drive(t, args):
return np.exp(-t/args['tau']) * np.sin(args['w'] * t)
H = [num(N), [destroy(N) + create(N), drive]]
args = {'w': 1.0, 'tau': 5.0}
result = sesolve(H, psi0, tlist, args=args)
# Method 3: QobjEvo (most flexible)
from qutip import QobjEvo
H_td = QobjEvo([num(N), [destroy(N) + create(N), drive]], args=args)
result = sesolve(H_td, psi0, tlist)
```
## Master Equation Solver (mesolve)
For open quantum systems with dissipation and decoherence.
### Basic Usage
```python
# System Hamiltonian
H = num(N)
# Collapse operators (Lindblad operators)
kappa = 0.1 # Decay rate
c_ops = [np.sqrt(kappa) * destroy(N)]
# Initial state
psi0 = coherent(N, 2.0)
# Solve
result = mesolve(H, psi0, tlist, c_ops, e_ops=[num(N)])
# Result is a density matrix evolution
rho_t = result.states # List of density matrices
n_t = result.expect[0] # ⟨n⟩(t)
```
### Multiple Dissipation Channels
```python
# Photon loss
kappa = 0.1
# Dephasing
gamma = 0.05
# Thermal excitation
nth = 0.5 # Thermal photon number
c_ops = [
np.sqrt(kappa * (1 + nth)) * destroy(N), # Thermal decay
np.sqrt(kappa * nth) * create(N), # Thermal excitation
np.sqrt(gamma) * num(N) # Pure dephasing
]
result = mesolve(H, psi0, tlist, c_ops)
```
### Time-Dependent Dissipation
```python
# Time-dependent decay rate
def kappa_t(t, args):
return args['k0'] * (1 + np.sin(args['w'] * t))
c_ops = [[np.sqrt(1.0) * destroy(N), kappa_t]]
args = {'k0': 0.1, 'w': 1.0}
result = mesolve(H, psi0, tlist, c_ops, args=args)
```
## Monte Carlo Solver (mcsolve)
Simulates quantum trajectories for open systems.
### Basic Usage
```python
# Same setup as mesolve
H = num(N)
c_ops = [np.sqrt(0.1) * destroy(N)]
psi0 = coherent(N, 2.0)
# Number of trajectories
ntraj = 500
result = mcsolve(H, psi0, tlist, c_ops, e_ops=[num(N)], ntraj=ntraj)
# Results averaged over trajectories
n_avg = result.expect[0]
n_std = result.std_expect[0] # Standard deviation
# Individual trajectories (if options.store_states=True)
options = Options(store_states=True)
result = mcsolve(H, psi0, tlist, c_ops, ntraj=ntraj, options=options)
trajectories = result.states # List of trajectory lists
```
### Photon Counting
```python
# Track quantum jumps
result = mcsolve(H, psi0, tlist, c_ops, ntraj=ntraj, options=options)
# Access jump times and which operator caused the jump
for traj in result.col_times:
print(f"Jump times: {traj}")
for traj in result.col_which:
print(f"Jump operator indices: {traj}")
```
## Bloch-Redfield Solver (brmesolve)
For weak system-bath coupling in the secular approximation.
```python
# System Hamiltonian
H = sigmaz()
# Coupling operators and spectral density
a_ops = [[sigmax(), lambda w: 0.1 * w if w > 0 else 0]] # Ohmic bath
psi0 = basis(2, 0)
result = brmesolve(H, psi0, tlist, a_ops, e_ops=[sigmaz(), sigmax()])
```
## Floquet Solver (fmmesolve)
For time-periodic Hamiltonians.
```python
# Time-periodic Hamiltonian
w_d = 1.0 # Drive frequency
H0 = sigmaz()
H1 = sigmax()
H = [H0, [H1, 'cos(w*t)']]
args = {'w': w_d}
# Floquet modes and quasi-energies
T = 2 * np.pi / w_d # Period
f_modes, f_energies = floquet_modes(H, T, args)
# Initial state in Floquet basis
psi0 = basis(2, 0)
# Dissipation in Floquet basis
c_ops = [np.sqrt(0.1) * sigmam()]
result = fmmesolve(H, psi0, tlist, c_ops, e_ops=[num(2)], T=T, args=args)
```
## Stochastic Solvers
### Stochastic Schrödinger Equation (ssesolve)
```python
# Diffusion operator
sc_ops = [np.sqrt(0.1) * destroy(N)]
# Heterodyne detection
result = ssesolve(H, psi0, tlist, sc_ops=sc_ops, e_ops=[num(N)],
ntraj=500, noise=1) # noise=1 for heterodyne
```
### Stochastic Master Equation (smesolve)
```python
result = smesolve(H, psi0, tlist, c_ops=[], sc_ops=sc_ops,
e_ops=[num(N)], ntraj=500)
```
## Propagators
### Time-Evolution Operator
```python
# Evolution operator U(t) such that ψ(t) = U(t)ψ(0)
U = (-1j * H * t).expm()
psi_t = U * psi0
# For master equation (superoperator propagator)
L = liouvillian(H, c_ops)
U_super = (L * t).expm()
rho_t = vector_to_operator(U_super * operator_to_vector(rho0))
```
### Propagator Function
```python
# Generate propagators for multiple times
U_list = propagator(H, tlist, c_ops)
# Apply to states
psi_t = [U_list[i] * psi0 for i in range(len(tlist))]
```
## Steady State Solutions
### Direct Steady State
```python
# Find steady state of Liouvillian
rho_ss = steadystate(H, c_ops)
# Check it's steady
L = liouvillian(H, c_ops)
assert (L * operator_to_vector(rho_ss)).norm() < 1e-10
```
### Pseudo-Inverse Method
```python
# For degenerate steady states
rho_ss = steadystate(H, c_ops, method='direct')
# or 'eigen', 'svd', 'power'
```
## Correlation Functions
### Two-Time Correlation
```python
# ⟨A(t+τ)B(t)⟩
A = destroy(N)
B = create(N)
# Emission spectrum
taulist = np.linspace(0, 10, 200)
corr = correlation_2op_1t(H, None, taulist, c_ops, A, B)
# Power spectrum
w, S = spectrum_correlation_fft(taulist, corr)
```
### Multi-Time Correlation
```python
# ⟨A(t3)B(t2)C(t1)⟩
corr = correlation_3op_1t(H, None, taulist, c_ops, A, B, C)
```
## Solver Options
```python
from qutip import Options
options = Options()
options.nsteps = 10000 # Max internal steps
options.atol = 1e-8 # Absolute tolerance
options.rtol = 1e-6 # Relative tolerance
options.method = 'adams' # or 'bdf' for stiff problems
options.store_states = True # Store all states
options.store_final_state = True # Store only final state
result = mesolve(H, psi0, tlist, c_ops, options=options)
```
### Progress Bar
```python
options.progress_bar = True
result = mesolve(H, psi0, tlist, c_ops, options=options)
```
## Saving and Loading Results
```python
# Save results
result.save("my_simulation.dat")
# Load results
from qutip import Result
loaded_result = Result.load("my_simulation.dat")
```
## Tips for Efficient Simulations
1. **Sparse matrices**: QuTiP automatically uses sparse matrices
2. **Small Hilbert spaces**: Truncate when possible
3. **Time-dependent terms**: String format is fastest (requires compilation)
4. **Parallel trajectories**: mcsolve automatically parallelizes
5. **Convergence**: Check by varying `ntraj`, `nsteps`, tolerances
6. **Solver selection**:
- Pure states: Use `sesolve` (faster)
- Mixed states/dissipation: Use `mesolve`
- Noise/measurements: Use `mcsolve`
- Weak coupling: Use `brmesolve`
- Periodic driving: Use Floquet methods