Skill Tracer
Skills › Scientific Agent Skills › qutip › time_evolution.md

time_evolution.md

390 lines · skills/qutip/references/time_evolution.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# QuTiP 5.3 Time Evolution
2
3Research and API verification date: **2026-10-01**. All signatures and examples
4target `qutip==5.3.1`.
5

QuTiP 5.3 Time Evolution

Research and API verification date: 2026-10-01. All signatures and examples target qutip==5.3.1.

Raw lines 1 to 5
6## Solver selection
7
8| Solver | State/model | Main uncertainty |
9|---|---|---|
10| `sesolve` | Schrödinger equation, pure state, no collapse channels | ODE and model approximation |
11| `mesolve` | Lindblad master equation, mixed state, or Liouvillian | channel validity and ODE error |
12| `mcsolve` | quantum-jump trajectories | ODE error plus sampling error |
13| `brmesolve` | microscopic weak-coupling bath spectra | Born-Markov/secular approximation and positivity |
14| `ssesolve` | stochastic Schrödinger equation | diffusive record sampling |
15| `smesolve` | stochastic master equation with monitored/unmonitored channels | diffusive record sampling |
16| `fsesolve`/`fmmesolve` | periodic Floquet dynamics | period, basis, harmonic and bath approximations |
18Do not use `mcsolve` merely to make a deterministic calculation parallel. Do
19not use `brmesolve` as a generic replacement for a Lindblad model.

Solver selection

SolverState/modelMain uncertainty
sesolveSchrödinger equation, pure state, no collapse channelsODE and model approximation
mesolveLindblad master equation, mixed state, or Liouvillianchannel validity and ODE error
mcsolvequantum-jump trajectoriesODE error plus sampling error
brmesolvemicroscopic weak-coupling bath spectraBorn-Markov/secular approximation and positivity
ssesolvestochastic Schrödinger equationdiffusive record sampling
smesolvestochastic master equation with monitored/unmonitored channelsdiffusive record sampling
fsesolve/fmmesolveperiodic Floquet dynamicsperiod, basis, harmonic and bath approximations

Do not use mcsolve merely to make a deterministic calculation parallel. Do not use brmesolve as a generic replacement for a Lindblad model.

Raw lines 6 to 20
21## Current function signatures
23The important QuTiP 5.3 call boundaries are:
25```text
26sesolve(H, psi0, tlist, *, e_ops=None, args=None, options=None)
27mesolve(H, rho0, tlist, c_ops=None, *, e_ops=None, args=None, options=None)
28mcsolve(H, state, tlist, c_ops=(), *, e_ops=None, ntraj=500,
29 args=None, options=None, seeds=None, target_tol=None, timeout=None)
30brmesolve(H, psi0, tlist, a_ops=None, sec_cutoff=0.1, *,
31 c_ops=None, e_ops=None, args=None, options=None)
32ssesolve(H, psi0, tlist, sc_ops=(), heterodyne=False, *,
33 e_ops=None, args=None, ntraj=500, options=None, seeds=None,
34 target_tol=None, timeout=None)
35smesolve(H, rho0, tlist, c_ops=(), sc_ops=(), heterodyne=False, *,
36 e_ops=None, args=None, ntraj=500, options=None, seeds=None,
37 target_tol=None, timeout=None)
38```
40In 5.3, `e_ops`, `args`, and `options` are keyword-only. Passing solver options
41as arbitrary solver keyword arguments was removed. The old `qutip.Options`
42export is no longer present; pass an ordinary dictionary.

Current function signatures

The important QuTiP 5.3 call boundaries are:

sesolve(H, psi0, tlist, *, e_ops=None, args=None, options=None)
mesolve(H, rho0, tlist, c_ops=None, *, e_ops=None, args=None, options=None)
mcsolve(H, state, tlist, c_ops=(), *, e_ops=None, ntraj=500,
        args=None, options=None, seeds=None, target_tol=None, timeout=None)
brmesolve(H, psi0, tlist, a_ops=None, sec_cutoff=0.1, *,
          c_ops=None, e_ops=None, args=None, options=None)
ssesolve(H, psi0, tlist, sc_ops=(), heterodyne=False, *,
         e_ops=None, args=None, ntraj=500, options=None, seeds=None,
         target_tol=None, timeout=None)
smesolve(H, rho0, tlist, c_ops=(), sc_ops=(), heterodyne=False, *,
         e_ops=None, args=None, ntraj=500, options=None, seeds=None,
         target_tol=None, timeout=None)

In 5.3, e_ops, args, and options are keyword-only. Passing solver options as arbitrary solver keyword arguments was removed. The old qutip.Options export is no longer present; pass an ordinary dictionary.

Raw lines 21 to 43
44## `sesolve`: closed unitary evolution
46```python
47import numpy as np
48from qutip import basis, sesolve, sigmax, sigmaz
50H = 0.5 * sigmax()
51psi0 = basis(2, 0)
52tlist = np.linspace(0.0, 10.0, 201)
54result = sesolve(
55 H,
56 psi0,
57 tlist,
58 e_ops={"z": sigmaz()},
59 options={"atol": 1e-10, "rtol": 1e-8, "progress_bar": ""},
61z = np.asarray(result.e_data["z"])
62```
64For an ODE norm/trace audit, set `options["normalize_output"] = False`:
65`sesolve`/`mesolve` normally normalize an initially normalized state on output,
66which can conceal integrator drift. Quantum-jump trajectory normalization is
67part of the unravelling and is a different operation.
69Audit Hamiltonian Hermiticity and state norm. If norm drift is material, tighten
70tolerances or investigate the model; do not normalize away unexplained error.

sesolve: closed unitary evolution

import numpy as np
from qutip import basis, sesolve, sigmax, sigmaz

H = 0.5 * sigmax()
psi0 = basis(2, 0)
tlist = np.linspace(0.0, 10.0, 201)

result = sesolve(
    H,
    psi0,
    tlist,
    e_ops={"z": sigmaz()},
    options={"atol": 1e-10, "rtol": 1e-8, "progress_bar": ""},
)
z = np.asarray(result.e_data["z"])

For an ODE norm/trace audit, set options["normalize_output"] = False: sesolve/mesolve normally normalize an initially normalized state on output, which can conceal integrator drift. Quantum-jump trajectory normalization is part of the unravelling and is a different operation.

Audit Hamiltonian Hermiticity and state norm. If norm drift is material, tighten tolerances or investigate the model; do not normalize away unexplained error.

Raw lines 44 to 71
72## `mesolve`: Lindblad or explicit Liouvillian evolution
74```python
75import numpy as np
76from qutip import basis, mesolve, sigmam, sigmaz
78gamma = 0.2
79excited = basis(2, 0)
80tlist = np.linspace(0.0, 12.0, 241)
82result = mesolve(
83 0.5 * sigmaz(),
84 excited,
85 tlist,
86 c_ops=[np.sqrt(gamma) * sigmam()],
87 e_ops={"p_excited": excited.proj()},
88 options={
89 "method": "adams",
90 "atol": 1e-10,
91 "rtol": 1e-8,
92 "store_final_state": True,
93 "progress_bar": "",
94 },
96```
98When no collapse operators are supplied and `H` is not a superoperator,
99`mesolve` may defer to `sesolve`. If `H` is an explicit Liouvillian, document
100whether it is in valid Lindblad form or represents a deliberate approximation.

mesolve: Lindblad or explicit Liouvillian evolution

import numpy as np
from qutip import basis, mesolve, sigmam, sigmaz

gamma = 0.2
excited = basis(2, 0)
tlist = np.linspace(0.0, 12.0, 241)

result = mesolve(
    0.5 * sigmaz(),
    excited,
    tlist,
    c_ops=[np.sqrt(gamma) * sigmam()],
    e_ops={"p_excited": excited.proj()},
    options={
        "method": "adams",
        "atol": 1e-10,
        "rtol": 1e-8,
        "store_final_state": True,
        "progress_bar": "",
    },
)

When no collapse operators are supplied and H is not a superoperator, mesolve may defer to sesolve. If H is an explicit Liouvillian, document whether it is in valid Lindblad form or represents a deliberate approximation.

Raw lines 72 to 101
102## `mcsolve`: quantum jumps
104```python
105result = mcsolve(
106 0.5 * sigmaz(),
107 excited,
108 tlist,
109 [np.sqrt(gamma) * sigmam()],
110 e_ops=[excited.proj()],
111 ntraj=500,
112 seeds=20260723,
113 options={
114 "keep_runs_results": False,
115 "progress_bar": "",
116 },
119mean_population = result.average_expect[0]
120trajectory_spread = result.std_expect[0]
121seed_manifest = result.seeds
122```
124`seeds` may be one integer/`SeedSequence` used to spawn trajectory seeds, or a
125list with one seed per trajectory. QuTiP stores the realized seeds in the
126result. Reusing them enables a paired comparison, but paired runs are not
127independent replicates.
129Trajectory rigor:
131- increase `ntraj` and report stabilization or a target uncertainty;
132- distinguish trajectory standard deviation from standard error of the mean;
133- set `options={"keep_runs_results": True}` only when individual trajectories
134 are actually required, because memory scales with trajectories and time
135 points;
136- collapse records are available per trajectory through result attributes such
137 as `collapse`; do not print unbounded records by default;
138- `target_tol` may stop before `ntraj`, so report the number actually run;
139- report timeout termination and solver stats.
141For mixed initial conditions, current QuTiP can sample the initial mixture; the
142result then includes initial-state accounting. State this extra source of
143sampling explicitly.

mcsolve: quantum jumps

result = mcsolve(
    0.5 * sigmaz(),
    excited,
    tlist,
    [np.sqrt(gamma) * sigmam()],
    e_ops=[excited.proj()],
    ntraj=500,
    seeds=20260723,
    options={
        "keep_runs_results": False,
        "progress_bar": "",
    },
)

mean_population = result.average_expect[0]
trajectory_spread = result.std_expect[0]
seed_manifest = result.seeds

seeds may be one integer/SeedSequence used to spawn trajectory seeds, or a list with one seed per trajectory. QuTiP stores the realized seeds in the result. Reusing them enables a paired comparison, but paired runs are not independent replicates.

Trajectory rigor:

  • increase ntraj and report stabilization or a target uncertainty;
  • distinguish trajectory standard deviation from standard error of the mean;
  • set options={"keep_runs_results": True} only when individual trajectories are actually required, because memory scales with trajectories and time points;
  • collapse records are available per trajectory through result attributes such as collapse; do not print unbounded records by default;
  • target_tol may stop before ntraj, so report the number actually run;
  • report timeout termination and solver stats.

For mixed initial conditions, current QuTiP can sample the initial mixture; the result then includes initial-state accounting. State this extra source of sampling explicitly.

Raw lines 102 to 144
Starts an agent spawn :124
145## `brmesolve`: Bloch-Redfield evolution
147```python
148import numpy as np
149from qutip import basis, brmesolve, sigmax, sigmaz
151def one_sided_spectrum(w):
152 return 0.03 * w if w > 0.0 else 0.0
154tlist = np.linspace(0.0, 30.0, 601)
155result = brmesolve(
156 0.5 * sigmaz(),
157 basis(2, 0),
158 tlist,
159 a_ops=[(sigmax(), one_sided_spectrum)],
160 e_ops={"z": sigmaz()},
161 sec_cutoff=0.1,
162 options={"atol": 1e-10, "rtol": 1e-8, "progress_bar": ""},
164```
166The coupling operator in each `a_ops` pair is normally Hermitian, and the
167spectrum is a function of **angular frequency**. Prefer a current QuTiP
168Environment object when it represents the bath more clearly.
170Required checks:
172- weak system-bath coupling (Born approximation);
173- short bath memory compared with system dynamics (Markov approximation);
174- stationary bath and correct positive/negative-frequency convention;
175- secular choice: `sec_cutoff=-1` disables secularization and can worsen
176 positivity;
177- density-matrix trace, Hermiticity, and minimum eigenvalue over time.
179See `advanced.md` for the physical boundaries.

brmesolve: Bloch-Redfield evolution

import numpy as np
from qutip import basis, brmesolve, sigmax, sigmaz

def one_sided_spectrum(w):
    return 0.03 * w if w > 0.0 else 0.0

tlist = np.linspace(0.0, 30.0, 601)
result = brmesolve(
    0.5 * sigmaz(),
    basis(2, 0),
    tlist,
    a_ops=[(sigmax(), one_sided_spectrum)],
    e_ops={"z": sigmaz()},
    sec_cutoff=0.1,
    options={"atol": 1e-10, "rtol": 1e-8, "progress_bar": ""},
)

The coupling operator in each a_ops pair is normally Hermitian, and the spectrum is a function of angular frequency. Prefer a current QuTiP Environment object when it represents the bath more clearly.

Required checks:

  • weak system-bath coupling (Born approximation);
  • short bath memory compared with system dynamics (Markov approximation);
  • stationary bath and correct positive/negative-frequency convention;
  • secular choice: sec_cutoff=-1 disables secularization and can worsen positivity;
  • density-matrix trace, Hermiticity, and minimum eigenvalue over time.

See advanced.md for the physical boundaries.

Raw lines 145 to 180
181## Stochastic Schrödinger and master equations
183Use these for diffusive continuous-measurement unravellings, not jump
184trajectories:
186```python
187result = smesolve(
188 H,
189 rho0,
190 tlist,
191 c_ops=unmonitored_channels,
192 sc_ops=monitored_channels,
193 heterodyne=False, # homodyne
194 e_ops={"signal": measured_quadrature},
195 ntraj=200,
196 seeds=20260723,
197 options={"dt": 0.001, "store_measurement": "end", "progress_bar": ""},
199```
201- `c_ops` are unmonitored deterministic dissipation channels. Even from a ket,
202 use `smesolve` if any such channel is present; `ssesolve` has no `c_ops`.
203- Stochastic methods include `platen`, `rouchon`, and `euler`, each with its
204 own options. Do not pass deterministic `adams`/`bdf` or their `atol`/`rtol`
205 to a fixed-step stochastic integrator; converge `dt` instead.
206- `sc_ops` are monitored stochastic channels.
207- `heterodyne=False` is homodyne; `True` is heterodyne.
208- Legacy integer `noise` selectors are not current API.
209- Measurement records can be much larger than expectation summaries; store
210 them only when needed.
211- Converge the stochastic integration step `dt` separately from `ntraj`.
212- `result.measurement` has shape `(ntraj, n_sc_ops, len(tlist)-1)` for homodyne
213 and `(ntraj, n_sc_ops, 2, len(tlist)-1)` for heterodyne. Use
214 `store_measurement="start"` for replay with `run_from_experiment(...,
215 measurement=True)`; the default/end record uses different state timing.

Stochastic Schrödinger and master equations

Use these for diffusive continuous-measurement unravellings, not jump trajectories:

result = smesolve(
    H,
    rho0,
    tlist,
    c_ops=unmonitored_channels,
    sc_ops=monitored_channels,
    heterodyne=False,  # homodyne
    e_ops={"signal": measured_quadrature},
    ntraj=200,
    seeds=20260723,
    options={"dt": 0.001, "store_measurement": "end", "progress_bar": ""},
)
  • c_ops are unmonitored deterministic dissipation channels. Even from a ket, use smesolve if any such channel is present; ssesolve has no c_ops.
  • Stochastic methods include platen, rouchon, and euler, each with its own options. Do not pass deterministic adams/bdf or their atol/rtol to a fixed-step stochastic integrator; converge dt instead.
  • sc_ops are monitored stochastic channels.
  • heterodyne=False is homodyne; True is heterodyne.
  • Legacy integer noise selectors are not current API.
  • Measurement records can be much larger than expectation summaries; store them only when needed.
  • Converge the stochastic integration step dt separately from ntraj.
  • result.measurement has shape (ntraj, n_sc_ops, len(tlist)-1) for homodyne and (ntraj, n_sc_ops, 2, len(tlist)-1) for heterodyne. Use store_measurement="start" for replay with run_from_experiment(..., measurement=True); the default/end record uses different state timing.
Raw lines 181 to 216
217## Time-dependent systems and QobjEvo

Time-dependent systems and QobjEvo

Raw lines 217 to 218
219### Pythonic callable coefficients
221```python
222import numpy as np
223from qutip import QobjEvo, sigmax, sigmaz
225def pulse(t, amplitude, center, width):
226 return amplitude * np.exp(-0.5 * ((t - center) / width) ** 2)
228H = QobjEvo(
229 [0.5 * sigmaz(), [sigmax(), pulse]],
230 args={"amplitude": 0.2, "center": 5.0, "width": 1.0},
232H_at_t = H(5.0)
233H.arguments(amplitude=0.15)
234```
236The Pythonic form `f(t, parameter, ...)` is current. The legacy
237`f(t, args_dictionary)` form is deprecated in 5.3 and scheduled for removal in
2385.5.

Pythonic callable coefficients

import numpy as np
from qutip import QobjEvo, sigmax, sigmaz

def pulse(t, amplitude, center, width):
    return amplitude * np.exp(-0.5 * ((t - center) / width) ** 2)

H = QobjEvo(
    [0.5 * sigmaz(), [sigmax(), pulse]],
    args={"amplitude": 0.2, "center": 5.0, "width": 1.0},
)
H_at_t = H(5.0)
H.arguments(amplitude=0.15)

The Pythonic form f(t, parameter, ...) is current. The legacy f(t, args_dictionary) form is deprecated in 5.3 and scheduled for removal in 5.5.

Raw lines 219 to 239
240### Sampled coefficients
242```python
243coefficient_times = np.linspace(0.0, 10.0, 501)
244samples = np.cos(coefficient_times)
245H = QobjEvo(
246 [0.5 * sigmaz(), [sigmax(), samples]],
247 tlist=coefficient_times,
248 order=3,
250```
252Sample times must be sorted and match coefficient length. `order=0` gives a
253left/previous-value step function; the default cubic spline can overshoot.
254Converge the coefficient sampling independently of solver output times.
256QuTiP also accepts expression strings and may compile them, but this skill does
257not construct such expressions from configuration or user text. Use trusted
258callables or numeric arrays in generated workflows.

Sampled coefficients

coefficient_times = np.linspace(0.0, 10.0, 501)
samples = np.cos(coefficient_times)
H = QobjEvo(
    [0.5 * sigmaz(), [sigmax(), samples]],
    tlist=coefficient_times,
    order=3,
)

Sample times must be sorted and match coefficient length. order=0 gives a left/previous-value step function; the default cubic spline can overshoot. Converge the coefficient sampling independently of solver output times.

QuTiP also accepts expression strings and may compile them, but this skill does not construct such expressions from configuration or user text. Use trusted callables or numeric arrays in generated workflows.

Raw lines 240 to 259
260## Option dictionaries and integrators
262Common solver options:
264```python
265options = {
266 "method": "adams",
267 "atol": 1e-10,
268 "rtol": 1e-8,
269 "nsteps": 10000,
270 "store_states": False,
271 "store_final_state": True,
272 "progress_bar": "",
274```
276Options are solver- and integrator-specific. Consult the selected solver's
277`.options` documentation before using a key.
279Common integration choices:
281- `adams`: non-stiff default for many deterministic solvers;
282- `bdf`: stiff systems;
283- `lsoda`: switches between non-stiff and stiff methods;
284- explicit high-order methods such as `dop853`, `vern7`, or `vern9`;
285- `diag`: diagonalization-based constant-system evolution;
286- `krylov`: suitable cases where Krylov evolution is beneficial.
288An integrator label is not an accuracy certificate. Compare at least two
289tolerance levels, inspect warnings/stats, and compare a second method for a
290representative stiff or difficult case.
292QuTiP 5.3 adds `matrix_form` for `mesolve`/`MESolver`:
294```python
295options = {"matrix_form": True, "atol": 1e-10, "rtol": 1e-8}
296```
298It uses matrix-matrix products and may reduce memory in suitable models.
299Benchmark both time and verified observables before adopting it.

Option dictionaries and integrators

Common solver options:

options = {
    "method": "adams",
    "atol": 1e-10,
    "rtol": 1e-8,
    "nsteps": 10000,
    "store_states": False,
    "store_final_state": True,
    "progress_bar": "",
}

Options are solver- and integrator-specific. Consult the selected solver's .options documentation before using a key.

Common integration choices:

  • adams: non-stiff default for many deterministic solvers;
  • bdf: stiff systems;
  • lsoda: switches between non-stiff and stiff methods;
  • explicit high-order methods such as dop853, vern7, or vern9;
  • diag: diagonalization-based constant-system evolution;
  • krylov: suitable cases where Krylov evolution is beneficial.

An integrator label is not an accuracy certificate. Compare at least two tolerance levels, inspect warnings/stats, and compare a second method for a representative stiff or difficult case.

QuTiP 5.3 adds matrix_form for mesolve/MESolver:

options = {"matrix_form": True, "atol": 1e-10, "rtol": 1e-8}

It uses matrix-matrix products and may reduce memory in suitable models. Benchmark both time and verified observables before adopting it.

Raw lines 260 to 300
301## Time grids
303`tlist` is the requested output grid, not necessarily the integrator's internal
304step sequence.
306Checks:
3081. finite, strictly increasing values;
3092. includes the physically intended initial time;
3103. resolves the fastest Hamiltonian, decay, drive-envelope, and measurement
311 scales in the returned output;
3124. long enough to capture transients or steady behavior;
3135. converged under a denser output grid where downstream interpolation, FFT, or
314 peak detection depends on sampling.
316For FFT spectra, a uniform `taulist` is required and its spacing/window set
317Nyquist range and frequency resolution.

Time grids

tlist is the requested output grid, not necessarily the integrator's internal step sequence.

Checks:

  1. finite, strictly increasing values;
  2. includes the physically intended initial time;
  3. resolves the fastest Hamiltonian, decay, drive-envelope, and measurement scales in the returned output;
  4. long enough to capture transients or steady behavior;
  5. converged under a denser output grid where downstream interpolation, FFT, or peak detection depends on sampling.

For FFT spectra, a uniform taulist is required and its spacing/window set Nyquist range and frequency resolution.

Raw lines 301 to 318
319## Result semantics
321Current solver results can contain:
323| Attribute | Meaning |
324|---|---|
325| `times` | returned times |
326| `states` | stored states; may be empty depending on options and `e_ops` |
327| `final_state` | final state when requested |
328| `expect` | list aligned with list-form `e_ops` |
329| `e_data` | dictionary keyed like dict-form `e_ops` |
330| `options` | effective result/solver options |
331| `solver` | solver name |
332| `stats` | timing and diagnostic statistics |
334Multi-trajectory results add trajectory counts, seeds, standard deviations,
335average states, measurements, and optionally individual run results. Never
336assume `.states` means individual trajectories; inspect
337`keep_runs_results` and the concrete result type. For multi-trajectory results,
338`.expect`/`.e_data` and `.states` switch to per-run arrays when runs are retained.
339Use `.average_expect`/`.average_e_data` and `.average_states` explicitly for
340ensemble means, and `.runs_expect`/`.runs_states` for individual trajectories.
341Trajectory count is an unravelling sample count, not hardware measurement shots.
343QuTiP 5.3 adds `Result.plot_expect()` and `MultiTrajResult.plot_expect()`.
344Prefer explicit axes in reusable code.

Result semantics

Current solver results can contain:

AttributeMeaning
timesreturned times
statesstored states; may be empty depending on options and e_ops
final_statefinal state when requested
expectlist aligned with list-form e_ops
e_datadictionary keyed like dict-form e_ops
optionseffective result/solver options
solversolver name
statstiming and diagnostic statistics

Multi-trajectory results add trajectory counts, seeds, standard deviations, average states, measurements, and optionally individual run results. Never assume .states means individual trajectories; inspect keep_runs_results and the concrete result type. For multi-trajectory results, .expect/.e_data and .states switch to per-run arrays when runs are retained. Use .average_expect/.average_e_data and .average_states explicitly for ensemble means, and .runs_expect/.runs_states for individual trajectories. Trajectory count is an unravelling sample count, not hardware measurement shots.

QuTiP 5.3 adds Result.plot_expect() and MultiTrajResult.plot_expect(). Prefer explicit axes in reusable code.

Raw lines 319 to 345
346## Repeated systems
348Solver classes (`SESolver`, `MESolver`, `MCSolver`, `BRSolver`, `SMESolver`,
349and others) can reuse a constructed right-hand side across runs:
351```python
352from qutip import MESolver
354solver = MESolver(H, c_ops, options={"atol": 1e-10, "rtol": 1e-8})
355first = solver.run(rho_a, tlist, e_ops=e_ops)
356second = solver.run(rho_b, tlist, e_ops=e_ops)
357```
359Use the class interface when repeated setup is material, and verify that
360updated arguments and initial states are the intended ones.

Repeated systems

Solver classes (SESolver, MESolver, MCSolver, BRSolver, SMESolver, and others) can reuse a constructed right-hand side across runs:

from qutip import MESolver

solver = MESolver(H, c_ops, options={"atol": 1e-10, "rtol": 1e-8})
first = solver.run(rho_a, tlist, e_ops=e_ops)
second = solver.run(rho_b, tlist, e_ops=e_ops)

Use the class interface when repeated setup is material, and verify that updated arguments and initial states are the intended ones.

Raw lines 346 to 361
362## Portable output
364Do not load untrusted serialized Python or QuTiP objects. For exchange and
365audit, save:
367- scalar configuration and assumptions;
368- real/imaginary numeric arrays;
369- dimensions, versions, tolerances, seeds, and solver stats;
370- checksums and schema versions where long-term provenance matters.
372The bundled CLIs use bounded strict JSON and never pickle results.

Portable output

Do not load untrusted serialized Python or QuTiP objects. For exchange and audit, save:

  • scalar configuration and assumptions;
  • real/imaginary numeric arrays;
  • dimensions, versions, tolerances, seeds, and solver stats;
  • checksums and schema versions where long-term provenance matters.

The bundled CLIs use bounded strict JSON and never pickle results.

Raw lines 362 to 373
374## Local tools
376- `../scripts/two_level_simulation.py`: bounded `mesolve`/`mcsolve` example.
377- `../scripts/solver_config_planner.py`: solver and option checklist.
378- `../scripts/convergence_sweep.py`: deterministic or trajectory convergence.
379- `../scripts/result_audit.py`: portable JSON audit.

Local tools

  • ../scripts/two_level_simulation.py: bounded mesolve/mcsolve example.
  • ../scripts/solver_config_planner.py: solver and option checklist.
  • ../scripts/convergence_sweep.py: deterministic or trajectory convergence.
  • ../scripts/result_audit.py: portable JSON audit.
Raw lines 374 to 380
Runs code scripts/two_level_simulation.py :376
Runs code scripts/solver_config_planner.py :377
Runs code scripts/convergence_sweep.py :378
Runs code scripts/result_audit.py :379
381## Sources (verified 2026-10-01)
383- [Dynamics API](https://qutip.readthedocs.io/en/stable/apidoc/solver.html)
384- [QobjEvo and coefficients API](https://qutip.readthedocs.io/en/stable/apidoc/time_dep.html)
385- [Dynamics user guide](https://qutip.readthedocs.io/en/stable/guide/guide-dynamics.html)
386- [Monte Carlo guide](https://qutip.readthedocs.io/en/stable/guide/dynamics/dynamics-monte.html)
387- [Stochastic solver guide](https://qutip.readthedocs.io/en/stable/guide/dynamics/dynamics-stochastic.html)
388- [Bloch-Redfield guide](https://qutip.readthedocs.io/en/stable/guide/dynamics/dynamics-bloch-redfield.html)
389- [QuTiP 5.3.1 release](https://github.com/qutip/qutip/releases/tag/v5.3.1)
390- [QuTiP 5 migration changelog](https://qutip.readthedocs.io/en/stable/changelog.html#qutip-5-0-0-2024-03-28)