ParallelMCWF.jl
Simple package providing parallelised versions of QuantumOptics.jl's timeevolution.mcwf
Monte-Carlo wave-function algorithm. Most feature implementations are suboptimal, it has not been fully tested yet and thus it is not expected to be totally stable.
Features
- Setup parallel Monte Carlo simulations based on
timeevolution.mcwf
. Multithreading (Threads.@threads for
), distributed computing (bothpmap
and@distributed for
) and multithreading on split processes are supported. - Support for progress bar. Only the default ProgressMeter progress bar is currently supported.
- Support for memory-efficient real-time saving of Monte Carlo trajectories.
- Build density matrices in parallel from arrays of kets with support for both multithreading (
Threads.@threads for
one single or split processes) and distributed computing (pmap
,@distributed for
). - Average operators in parallel over arrays of kets with support for both multithreading (
Threads.@threads for
one single or split processes) and distributed computing (pmap
,@distributed for
). - Save to and load from disk MCWF trajectories specifying the range for both the trajectories and the times.
Monte-Carlo wave-function problem
In addition to the parameters accepted by QuantumOptics.jl's timeevolution.mcwf
, pmcwf
takes the following supplementary keyword arguments:
Ntrajectories=1
: Number of MCWF trajectories.parallel_type=:none
: The type of parallelism to employ. The types of parallelism included are::none
,:threads
,:split_threads
,:parfor
and:pmap
. In practice, use:threads
on a local machine and:pmap
otherwise.:none
just loops overNtrajectories
in a conventionalfor
loop.:threads
loops overNtrajectories
in aThreads.@threads for
loop.:split_threads
makesDistributed.nworkers()
batches of trajectories, each multithreaded on its one process.:parfor
asynchronously distributesNtrajectories
among the workers via a@sync @distributed for
loop.:pmap
asynchronously distributesNtrajectories
among the workers via apmap
.
progressbar=true
: Iftrue
, a ProgressMeter progress bar is displayed with default settings.return_data=true
: Iftrue
, the solution is returned as aTuple
.save_data=true
: Iftrue
, the solution is saved to disk. Ifreturn_data=false
, less RAM is used (except forparallel_type=:threads
).fpath=missing
: savefile path (e.g.some/valid/path/filename.jld2
). Directory must pre-exist, the savefile is created.additional_data=missing
: If given aDict
, entries are added to the savefile.
Except for parallel_type=:threads
, trajectories are computed in various processes each of which puts its finished MC trajectories into a remote channel from which they are retrieved and written to disk from the main process. The main process also carries out the update of the progress bar.
Density matrix from an array of kets
The function ket_to_dm
allows one to build a density matrix from kets in parallel. It takes the following arguments:
kets
: 1-dimensional array of kets that sample the desired density matrix.parallel_type=:none
: The type of parallelism to employ. The types of parallelism included are::none
,:threads
,:split_threads
,:parfor
and:pmap
. The most efficient option is:threads
for small Hilbert space sizes and:pmap
when the basis' dimension is above a few thousand states.traceout
: When the basis vectors are tensor products of some local basis, the reduced density matrix can efficiently computed on some desired subspace by specifying the indices to be traced out as an array.
Observable average from an array of kets
op
: Some operator to be averaged.parallel_type=:none
: The type of parallelism to employ. The types of parallelism included are::none
,:threads
,:split_threads
,:parfor
and:pmap
. The most efficient option is always:threads
. Other options perform very badly here.index
: Indices of the subspace where one wants to evaluateop
as passed to QuantumOptics.jl'sexpect
function.
Examples
pmcwf
using Distributed
# Get 10 processes
if nprocs() < 10 addprocs(10-nprocs()); end
using ParallelMCWF, QuantumOptics
tspan = collect(0:10);
fb = FockBasis(10); ψ0 = fockstate(fb,0); a = destroy(fb);
H = randoperator(fb); H = H + dagger(H); γ = 1.;
# 3000 MCWF trajectories
t, trajs = pmcwf(tspan, ψ0, H, [sqrt(γ)*a]; Ntrajectories=3000, progressbar=true,
parallel_type=:pmap, return_data=true, save_data=true, fpath="/some/valid/path/filename.jld2");
Saving data to /some/valid/path/filename.jld2
Progress: 100%|█████████████████████████████████████████| Time: 0:00:05
kets_to_dm
, kets_to_obs
ρ = kets_to_dm([trajs[i][end] for i in 1:length(trajs)];parallel_type=:pmap);
E = kets_to_obs(H,[trajs[i][end] for i in 1:length(trajs)];parallel_type=:threads);
save_trajs
, load_trajs
params = Dict("H" => H, "J" => [sqrt(γ)*a])
save_trajs("/some/valid/path/filename2.jld2",(t,trajs); additional_data=params)
t, trajs2 = load_trajs("/some/valid/path/filename2.jld2")
jldopen("/some/valid/path/filename2.jld2",r) do file
println(file["H"] == H)
end
julia> true