/
runMC.jl
158 lines (138 loc) · 4.6 KB
/
runMC.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using Serialization
using Distributed
import Distributed.pmap
export runMC
@doc """
runMC(param::Parameter)
runMC(params::AbstractArray{Parameter}
;
parallel::Bool=false,
autoID::Bool=true)
Runs Monte Carlo simulation(s) and returns calculated observables.
# Restart
If a checkpoint file named `"\$(param["Checkpoint Filename Prefix"])_\$(param["ID"]).dat"` exists and
`param["Checkpoint Interval"] > 0.0`, `runMC` loads this file and restarts the pending simulation.
NOTE: Restart will fail if the version or the system image of julia change (see the doc of `Serialization.serialize` ).
# Keyward arguments
- `autoID`: If true, `"ID"`s will be set (overwritten) as `params[i]["ID"] = i`.
- `parallel`: If true, runs simulations in parallel (uses `pmap` instead of `map`).
# Required keys in `param`
- "Model"
- "Lattice"
- "Update Method"
# Optional keys in `param`
- "MCS": The number of Monte Carlo steps after thermalization
- Default: `8192`
- "Thermalization": The number of Monte Carlo steps for thermalization
- Default: `MCS>>3`
- "Seed": The initial seed of the random number generator, `MersenneTwister`
- Default: determined randomly (see the doc of `Random.seed!`)
- "Checkpoint Filename Prefix": See the "Restart" section.
- Default: `"cp"`
- "ID": See the "Restart" section.
- Default: `0`
- "Checkpoint Interval": Time interval between writing checkpoint file in seconds.
- Default: `0.0`, this means that NO checkpoint file will be loaded and saved.
"""
function runMC(params::AbstractArray{T}; parallel::Bool=false, autoID::Bool=true) where T<:Dict
map_fn = ifelse(parallel, pmap, map)
return map_fn(enumerate(params)) do (id,p)
if autoID
p["ID"] = id
end
return runMC(p)
end
end
function runMC(param::Parameter)
model = param["Model"](param)
if "Seed" in keys(param)
seed!(model, param["Seed"])
end
ret = runMC(model, param)
return ret
end
function runMC(model, param::Parameter)
MODEL = typeof(model)
verbose = get(param, "Verbose", false) :: Bool
if verbose
println("Start: ", param)
end
cp_filename = @sprintf("%s_%d.dat",
get(param, "Checkpoint Filename Prefix", "cp")::String,
get(param, "ID", 0)::Int)
cp_interval = get(param, "Checkpoint Interval", 0.0) :: Float64
tm = time()
MCS = get(param, "MCS", 8192) :: Int
Therm = get(param, "Thermalization", MCS>>3) :: Int
mcs = 0
MCS += Therm
obs = BinningObservableSet()
makeMCObservable!(obs, "Time per MCS")
makeMCObservable!(obs, "MCS per Second")
if cp_interval > 0.0 && ispath(cp_filename)
open(cp_filename) do io
model = deserialize(io)
obs = deserialize(io)
mcs = deserialize(io)
end
end
update! = param["Update Method"] :: Function
if haskey(param, "Estimator")
estimator = param["Estimator"] :: Function
else
estimator = default_estimator(model, update!)
end
pp = get(param, "Post Process", postproc) :: Function
p = convert_parameter(model, param)
while mcs < MCS
if mcs < Therm
update!(model, p...)
else
t = @elapsed begin
st = update!(model,p...)
localobs = estimator(model, p..., st)
end
obs["Time per MCS"] << t
obs["MCS per Second"] << (1.0/t)
accumulateObservables!(model, obs, localobs)
end
mcs += 1
if cp_interval > 0.0 && time() - tm > cp_interval
open(cp_filename, "w") do io
serialize(io, model)
serialize(io, obs)
serialize(io, mcs)
end
tm += cp_interval
end
end
if cp_interval > 0.0
open(cp_filename, "w") do io
serialize(io, model)
serialize(io, obs)
serialize(io, mcs)
end
end
jk = pp(model, param, obs)
if verbose
println("Finish: ", param)
end
return jk
end
@doc """
accumulateObservables!(model, obs::MCObservableSet, localobs::Dict)
Accumulates `localobs` into `obs`. For example, `obs["Energy"] << localobs["Energy"]`.
"""
function accumulateObservables!(::Model, obs::MCObservableSet, localobs::Measurement)
if length(obs) < 3
@inbounds for key in keys(localobs)
makeMCObservable!(obs, key)
obs[key] << localobs[key]
end
else
@inbounds for key in keys(localobs)
obs[key] << localobs[key]
end
end
return obs
end