• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wexlergroup / FreeBird.jl / 14718001377

28 Apr 2025 09:13PM UTC coverage: 90.613% (-4.3%) from 94.924%
14718001377

Pull #96

github

web-flow
Merge a1b479fd5 into afefded03
Pull Request #96: Feature/distributed ns loop

26 of 95 new or added lines in 5 files covered. (27.37%)

4 existing lines in 1 file now uncovered.

1448 of 1598 relevant lines covered (90.61%)

134178.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.4
/src/SamplingSchemes/nested_sampling.jl
1
"""
2
    mutable struct NestedSamplingParameters <: SamplingParameters
3

4
The `NestedSamplingParameters` struct represents the parameters used in the nested sampling scheme.
5

6
# Fields
7
- `mc_steps::Int64`: The number of total Monte Carlo moves to perform.
8
- `initial_step_size::Float64`: The initial step size, which is the fallback step size if MC routine fails to accept a move.
9
- `step_size::Float64`: The on-the-fly step size used in the sampling process.
10
- `step_size_lo::Float64`: The lower bound of the step size.
11
- `step_size_up::Float64`: The upper bound of the step size.
12
- `accept_range::Tuple{Float64, Float64}`: The range of acceptance rates for adjusting the step size.
13
e.g. (0.25, 0.75) means that the step size will decrease if the acceptance rate is below 0.25 and increase if it is above 0.75.
14
- `fail_count::Int64`: The number of failed MC moves in a row.
15
- `allowed_fail_count::Int64`: The maximum number of failed MC moves allowed before resetting the step size.
16
- `random_seed::Int64`: The seed for the random number generator.
17
"""
18
mutable struct NestedSamplingParameters <: SamplingParameters
19
    mc_steps::Int64
40✔
20
    initial_step_size::Float64
21
    step_size::Float64
22
    step_size_lo::Float64
23
    step_size_up::Float64
24
    accept_range::Tuple{Float64, Float64}
25
    fail_count::Int64
26
    allowed_fail_count::Int64
27
    random_seed::Int64
28
end
29

30
function NestedSamplingParameters(;
14✔
31
            mc_steps::Int64=200,
32
            initial_step_size::Float64=0.01,
33
            step_size::Float64=0.1,
34
            step_size_lo::Float64=1e-6,
35
            step_size_up::Float64=1.0,
36
            accept_range::Tuple{Float64, Float64}=(0.25, 0.75),
37
            fail_count::Int64=0,
38
            allowed_fail_count::Int64=100,
39
            random_seed::Int64=1234,
40
            )
41
    NestedSamplingParameters(mc_steps, initial_step_size, step_size, step_size_lo, step_size_up, accept_range, fail_count, allowed_fail_count, random_seed)  
8✔
42
end
43

44
"""
45
    mutable struct LatticeNestedSamplingParameters <: SamplingParameters
46

47
The `LatticeNestedSamplingParameters` struct represents the parameters used in the lattice nested sampling scheme.
48

49
# Fields
50
- `mc_steps::Int64`: The number of total Monte Carlo moves to perform.
51
- `energy_perturbation::Float64`: The energy perturbation used in the sampling process.
52
- `fail_count::Int64`: The number of failed MC moves in a row.
53
- `allowed_fail_count::Int64`: The maximum number of failed MC moves allowed before resetting the step size.
54
- `random_seed::Int64`: The seed for the random number generator.
55
"""
56
mutable struct LatticeNestedSamplingParameters <: SamplingParameters
57
    mc_steps::Int64
32✔
58
    energy_perturbation::Float64
59
    fail_count::Int64
60
    allowed_fail_count::Int64
61
    random_seed::Int64
62
end
63

64
function LatticeNestedSamplingParameters(;
14✔
65
            mc_steps::Int64=100,
66
            energy_perturbation::Float64=1e-12,
67
            fail_count::Int64=0,
68
            allowed_fail_count::Int64=10,
69
            random_seed::Int64=1234,
70
            )
71
    LatticeNestedSamplingParameters(mc_steps, energy_perturbation, fail_count, allowed_fail_count, random_seed)  
8✔
72
end
73

74

75

76
"""
77
    abstract type MCRoutine
78

79
An abstract type representing a Monte Carlo routine.
80

81
Currently, the following concrete types are supported:
82
- `MCRandomWalkMaxE`: A type for generating a new walker by performing a random walk for decorrelation on the
83
highest-energy walker.
84
- `MCRandomWalkClone`: A type for generating a new walker by cloning an existing walker and performing a random walk
85
for decorrelation.
86
- `MCNewSample`: A type for generating a new walker from a random configuration. Currently, it is intended to use 
87
this routine for lattice gas systems.
88
- `MCMixedMoves`: A type for generating a new walker by performing random walks and swapping atoms. Currently, it is
89
intended to use this routine for multi-component systems. The actual number of random walks and swaps to perform is
90
determined by the weights of the fields `walks_freq` and `swaps_freq`. See [`MCMixedMoves`](@ref).
91
- `MCRejectionSampling`: A type for generating a new walker by performing rejection sampling. Currently, it is intended
92
to use this routine for lattice gas systems.
93
"""
94
abstract type MCRoutine end
95

96
"""
97
    abstract type MCRoutineParallel <: MCRoutine
98
(Internal) An abstract type representing a parallel Monte Carlo routine.
99
"""
100
abstract type MCRoutineParallel <: MCRoutine end
101

102
"""
103
    struct MCRandomWalkMaxE <: MCRoutine
104
A type for generating a new walker by performing a random walk for decorrelation on the highest-energy walker.
105
"""
106
struct MCRandomWalkMaxE <: MCRoutine 
107
    dims::Vector{Int64}
108
    function MCRandomWalkMaxE(dims::Vector{Int64}=[1, 2, 3])
154✔
109
        new(dims)
176✔
110
    end
111
end
112

113
"""
114
    struct MCRandomWalkClone <: MCRoutine
115
A type for generating a new walker by cloning an existing walker and performing a random walk for decorrelation.
116
"""
117
struct MCRandomWalkClone <: MCRoutine 
118
    dims::Vector{Int64}
119
    function MCRandomWalkClone(;dims::Vector{Int64}=[1, 2, 3])
84✔
120
        new(dims)
48✔
121
    end
122
end
123

124
"""
125
    MCRandomWalkMaxEParallel <: MCRoutineParallel
126
A type for generating a new walker by performing a random walk for decorrelation on the highest-energy walker(s) in parallel.
127
"""
128
struct MCRandomWalkCloneParallel <: MCRoutineParallel
129
    dims::Vector{Int64}
NEW
130
    function MCRandomWalkCloneParallel(;dims::Vector{Int64}=[1, 2, 3])
×
NEW
131
        new(dims)
×
132
    end
133
end
134

135
struct MCRandomWalkMaxEParallel <: MCRoutineParallel
136
    dims::Vector{Int64}
NEW
137
    function MCRandomWalkMaxEParallel(;dims::Vector{Int64}=[1, 2, 3])
×
NEW
138
        new(dims)
×
139
    end
140
end
141

142
"""
143
    struct MCNewSample <: MCRoutine
144
A type for generating a new walker from a random configuration. Currently, it is intended to use this routine for lattice gas systems.
145
"""
146
struct MCNewSample <: MCRoutine end
32✔
147

148
""" 
149
    struct MCMixedMoves <: MCRoutine
150
A type for generating a new walker by performing random walks and swapping atoms. Currently, it is intended to use this routine for
151
multi-component systems. The actual number of random walks and swaps to perform is determined by the weights of the fields `walks_freq` and `swaps_freq`.
152
For example, if `walks_freq=4` and `swaps_freq=1`, then the probability of performing a random walk is 4/5, and the probability of performing a swap is 1/5.
153

154
# Fields
155
- `walks_freq::Int`: The frequency of random walks to perform.
156
- `swaps_freq::Int`: The frequency of atom swaps to perform.
157
"""
158
mutable struct MCMixedMoves <: MCRoutine
159
    walks_freq::Int
16✔
160
    swaps_freq::Int
161
end
162

163
"""
164
    struct MCRejectionSampling <: MCRoutine
165
A type for generating a new walker by performing rejection sampling. Currently, it is intended to use this routine for lattice gas systems.
166
"""
167
struct MCRejectionSampling <: MCRoutine end
8✔
168

169
"""
170
    sort_by_energy!(liveset::LJAtomWalkers)
171

172
Sorts the walkers in the liveset by their energy in descending order.
173

174
# Arguments
175
- `liveset::LJAtomWalkers`: The liveset of walkers to be sorted.
176

177
# Returns
178
- `liveset::LJAtomWalkers`: The sorted liveset.
179
"""
180
function sort_by_energy!(liveset::AbstractLiveSet)
424✔
181
    sort!(liveset.walkers, by = x -> x.energy, rev=true)
2,254✔
182
    # println("after sort ats[1].system_data.energy: ", ats[1].system_data.energy)
183
    return liveset
424✔
184
end
185

186
"""
187
    update_iter!(liveset::AtomWalkers)
188

189
Update the iteration count for each walker in the liveset.
190

191
# Arguments
192
- `liveset::AtomWalkers`: The set of walkers to update.
193

194
"""
195
function update_iter!(liveset::AbstractLiveSet)
416✔
196
    for at in liveset.walkers
416✔
197
        at.iter += 1
1,224✔
198
    end
1,224✔
199
end
200

201
"""
202
    estimate_temperature(n_walker::Int, n_cull::Int, ediff::Float64)
203
Estimate the temperature for the nested sampling algorithm from dlog(ω)/dE.
204
"""
NEW
205
function estimate_temperature(n_walkers::Int, n_cull::Int, ediff::Float64, iter::Int=1)
×
NEW
206
    ω = (n_cull / (n_walkers + n_cull)) * (n_walkers / (n_walkers + n_cull))^iter
×
NEW
207
    β = log(ω) / ediff
×
NEW
208
    kb = 8.617333262145e-5 # eV/K
×
NEW
209
    T = 1 / (kb * β) # in Kelvin
×
NEW
210
    return T
×
211
end
212

213

214
"""
215
    nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutine)
216

217
Perform a single step of the nested sampling algorithm using the Monte Carlo random walk routine.
218

219
Arguments
220
- `liveset::AtomWalkers`: The set of atom walkers.
221
- `ns_params::NestedSamplingParameters`: The parameters for nested sampling.
222
- `mc_routine::MCRoutine`: The Monte Carlo routine for generating new samples. See [`MCRoutine`](@ref).
223

224
Returns
225
- `iter`: The iteration number after the step.
226
- `emax`: The highest energy recorded during the step.
227
- `liveset`: The updated set of atom walkers.
228
- `ns_params`: The updated nested sampling parameters.
229
"""
230
function nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutine)
192✔
231
    sort_by_energy!(liveset)
192✔
232
    ats = liveset.walkers
192✔
233
    lj = liveset.lj_potential
192✔
234
    iter::Union{Missing,Int} = missing
192✔
235
    emax::Union{Missing,typeof(0.0u"eV")} = liveset.walkers[1].energy
192✔
236
    if mc_routine isa MCRandomWalkMaxE
192✔
237
        to_walk = deepcopy(ats[1])
320✔
238
    elseif mc_routine isa MCRandomWalkClone
32✔
239
        to_walk = deepcopy(rand(ats[2:end]))
48✔
240
    else
241
        error("Unsupported MCRoutine type: $mc_routine")
8✔
242
    end
243
    if length(mc_routine.dims) == 3
184✔
244
        accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
168✔
245
    elseif length(mc_routine.dims) == 2
16✔
246
        accept, rate, at = MC_random_walk_2D!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax; dims=mc_routine.dims)
8✔
247
        # @info "Doing a 2D random walk"
248
    elseif length(mc_routine.dims) == 1
8✔
249
        error("Unsupported dimensions: $(mc_routine.dims)")
8✔
250
    end
251
    # accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
252
    # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: $(round(ns_params.step_size; sigdigits=4))"
253
    if accept
176✔
254
        push!(ats, at)
176✔
255
        popfirst!(ats)
176✔
256
        update_iter!(liveset)
176✔
257
        ns_params.fail_count = 0
176✔
258
        iter = liveset.walkers[1].iter
176✔
259
    else
260
        # @warn "Failed to accept MC move"
261
        emax = missing
×
262
        ns_params.fail_count += 1
×
263
    end
264
    adjust_step_size(ns_params, rate)
230✔
265
    return iter, emax, liveset, ns_params
176✔
266
end
267

268

269

NEW
270
function nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutineParallel)
×
NEW
271
    sort_by_energy!(liveset)
×
NEW
272
    ats = liveset.walkers
×
NEW
273
    lj = liveset.lj_potential
×
NEW
274
    iter::Union{Missing,Int} = missing
×
NEW
275
    emax::Union{Vector{Missing},Vector{typeof(0.0u"eV")}} = [liveset.walkers[i].energy for i in 1:nworkers()]
×
276

NEW
277
    if mc_routine isa MCRandomWalkMaxEParallel
×
NEW
278
        to_walk_inds = 1:nworkers()
×
NEW
279
    elseif mc_routine isa MCRandomWalkCloneParallel
×
NEW
280
        to_walk_inds = sort!(sample(2:length(ats), nworkers()))
×
281
    end
282
    
NEW
283
    to_walks = deepcopy.(ats[to_walk_inds])
×
284

NEW
285
    if length(mc_routine.dims) == 3
×
NEW
286
        random_walk_function = MC_random_walk!
×
NEW
287
    elseif length(mc_routine.dims) == 2
×
NEW
288
        random_walk_function = MC_random_walk_2D!
×
289
    else
NEW
290
        error("Unsupported dimensions: $(mc_routine.dims)")
×
291
    end
292

293

NEW
294
    walking = [remotecall(random_walk_function, workers()[i], ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax[end]) for (i,to_walk) in enumerate(to_walks)]
×
NEW
295
    walked = fetch.(walking)
×
NEW
296
    finalize.(walking) # finalize the remote calls, clear the memory
×
297

NEW
298
    accepted_rates = [x[2] for x in walked]
×
NEW
299
    rate = mean(accepted_rates)
×
300

NEW
301
    sort!(walked, by = x -> x[3].energy, rev=true)
×
NEW
302
    filter!(x -> x[1], walked) # remove the failed ones
×
303

NEW
304
    if isempty(walked)
×
NEW
305
        emax = [missing]
×
NEW
306
        ns_params.fail_count += nworkers()
×
307
    else
NEW
308
        for (i, at) in enumerate(walked)
×
NEW
309
            ats[i] = at[3]
×
NEW
310
        end
×
NEW
311
        update_iter!(liveset)
×
NEW
312
        ns_params.fail_count = 0
×
NEW
313
        iter = liveset.walkers[1].iter
×
NEW
314
        emax = emax[1:length(walked)]
×
315
    end
316

NEW
317
    adjust_step_size(ns_params, rate)
×
NEW
318
    return iter, emax, liveset, ns_params
×
319
end
320

321
"""
322
    nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCMixedMoves)
323

324
Perform a single step of the nested sampling algorithm using the Monte Carlo mixed moves routine.
325

326
Arguments
327
- `liveset::AtomWalkers`: The set of atom walkers.
328
- `ns_params::NestedSamplingParameters`: The parameters for nested sampling.
329
- `mc_routine::MCMixedMoves`: The Monte Carlo mixed moves routine.
330

331
Returns
332
- `iter`: The iteration number after the step.
333
- `emax`: The highest energy recorded during the step.
334
- `liveset`: The updated set of atom walkers.
335
- `ns_params`: The updated nested sampling parameters.
336
"""
337
function nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCMixedMoves)
8✔
338
    sort_by_energy!(liveset)
8✔
339
    ats = liveset.walkers
8✔
340
    lj = liveset.lj_potential
8✔
341
    iter::Union{Missing,Int} = missing
8✔
342
    emax::Union{Missing,typeof(0.0u"eV")} = liveset.walkers[1].energy
8✔
343

344
    # clone one of the lower energy walkers
345
    to_walk = deepcopy(rand(ats[2:end]))
16✔
346
    # determine whether to perform a random walk or a swap
347
    swap_prob = mc_routine.swaps_freq / (mc_routine.walks_freq + mc_routine.swaps_freq)
8✔
348
    
349
    # @show mc_routine
350
    if rand() > swap_prob
8✔
351
        accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
6✔
352
        @info "Swap move performed at iter: $(liveset.walkers[1].iter), accepted: $accept"
6✔
353
        # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: $(round(ns_params.step_size; sigdigits=4))"
354
    else
355
        accept, rate, at = MC_random_swap!(ns_params.mc_steps, to_walk, lj, emax)
2✔
356
        # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: swap"
357
    end
358
    
359
    if accept
8✔
360
        push!(ats, at)
8✔
361
        popfirst!(ats)
8✔
362
        update_iter!(liveset)
8✔
363
        ns_params.fail_count = 0
8✔
364
        iter = liveset.walkers[1].iter
8✔
365
    else
366
        # @warn "Failed to accept MC move"
367
        emax = missing
×
368
        ns_params.fail_count += 1
×
369
    end
370
    adjust_step_size(ns_params, rate)
8✔
371
    return iter, emax, liveset, ns_params
8✔
372
end
373

374
"""
375
    nested_sampling_step!(liveset::LatticeGasWalkers, ns_params::LatticeNestedSamplingParameters, mc_routine::MCRoutine)
376

377
Perform a single step of the nested sampling algorithm.
378

379
This function takes a `liveset` of lattice gas walkers, `ns_params` containing the parameters for nested sampling, and `mc_routine` representing the Monte Carlo 
380
routine for generating new samples. It performs a single step of the nested sampling algorithm by updating the liveset with a new walker.
381

382
## Arguments
383
- `liveset::LatticeGasWalkers`: The liveset of lattice gas walkers.
384
- `ns_params::LatticeNestedSamplingParameters`: The parameters for nested sampling.
385
- `mc_routine::MCRoutine`: The Monte Carlo routine for generating new samples.
386

387
## Returns
388
- `iter`: The iteration number of the liveset after the step.
389
- `emax`: The maximum energy of the liveset after the step.
390
"""
391
function nested_sampling_step!(liveset::LatticeGasWalkers, 
192✔
392
                               ns_params::LatticeNestedSamplingParameters, 
393
                               mc_routine::MCRoutine)
394
    sort_by_energy!(liveset)
192✔
395
    ats = liveset.walkers
192✔
396
    h = liveset.hamiltonian
192✔
397
    iter::Union{Missing,Int} = missing
192✔
398
    emax::Union{Missing,Float64} = liveset.walkers[1].energy.val
192✔
399
    if mc_routine isa MCRandomWalkMaxE
192✔
400
        to_walk = deepcopy(ats[1])
368✔
401
    elseif mc_routine isa MCRandomWalkClone
8✔
402
        to_walk = deepcopy(rand(ats[2:end]))
16✔
403
    else
404
        error("Unsupported MCRoutine type: $mc_routine")
×
405
    end
406
    accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, h, emax; energy_perturb=ns_params.energy_perturbation)
192✔
407

408
    # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $rate, emax: $emax, is_accepted: $accept"
409
    if accept
192✔
410
        push!(ats, at)
172✔
411
        popfirst!(ats)
172✔
412
        update_iter!(liveset)
172✔
413
        ns_params.fail_count = 0
172✔
414
        iter = liveset.walkers[1].iter
172✔
415
    else
416
        # @warn "Failed to accept MC move"
417
        emax = missing
20✔
418
        ns_params.fail_count += 1
20✔
419
    end
420
    # adjust_step_size(ns_params, rate)
421
    return iter, emax, liveset, ns_params
192✔
422
end
423

424
"""
425
    nested_sampling_step!(liveset::LatticeGasWalkers, ns_params::LatticeNestedSamplingParameters, mc_routine::MCNewSample)
426

427
Perform a single step of the nested sampling algorithm.
428

429
This function takes a `liveset` of lattice gas walkers, `ns_params` containing the parameters for nested sampling, and `mc_routine` representing the Monte Carlo routine for generating new samples. It performs a single step of the nested sampling algorithm by updating the liveset with a new walker.
430

431
## Arguments
432
- `liveset::LatticeGasWalkers`: The liveset of lattice gas walkers.
433
- `ns_params::LatticeNestedSamplingParameters`: The parameters for nested sampling.
434
- `mc_routine::MCNewSample`: The Monte Carlo routine for generating new samples.
435

436
## Returns
437
- `iter`: The iteration number of the liveset after the step.
438
- `emax`: The maximum energy of the liveset after the step.
439
- `liveset::LatticeGasWalkers`: The updated liveset after the step.
440
- `ns_params::LatticeNestedSamplingParameters`: The updated nested sampling parameters after the step.
441
"""
442
function nested_sampling_step!(liveset::LatticeGasWalkers, 
8✔
443
                               ns_params::LatticeNestedSamplingParameters, 
444
                               mc_routine::MCNewSample)
445
    sort_by_energy!(liveset)
8✔
446
    ats = liveset.walkers
8✔
447
    h = liveset.hamiltonian
8✔
448
    iter::Union{Missing,Int} = missing
8✔
449
    emax::Union{Missing,Float64} = liveset.walkers[1].energy.val
8✔
450

451
    to_walk = deepcopy(ats[1])
16✔
452

453
    accept, at = MC_new_sample!(to_walk, h, emax; energy_perturb=ns_params.energy_perturbation)
8✔
454

455
    # @info "iter: $(liveset.walkers[1].iter), emax: $emax, is_accepted: $accept"
456
    if accept
8✔
457
        push!(ats, at)
4✔
458
        popfirst!(ats)
4✔
459
        update_iter!(liveset)
4✔
460
        ns_params.fail_count = 0
4✔
461
        iter = liveset.walkers[1].iter
4✔
462
    else
463
        # @warn "Failed to accept MC move"
464
        emax = missing
4✔
465
        ns_params.fail_count += 1
4✔
466
    end
467
    # adjust_step_size(ns_params, rate)
468
    return iter, emax, liveset, ns_params
8✔
469
end
470

471

472
function nested_sampling_step!(liveset::LatticeGasWalkers, 
8✔
473
                               ns_params::LatticeNestedSamplingParameters, 
474
                               mc_routine::MCRejectionSampling)
475
    sort_by_energy!(liveset)
8✔
476
    ats = liveset.walkers
8✔
477
    h = liveset.hamiltonian
8✔
478
    iter::Union{Missing,Int} = missing
8✔
479
    emax::Union{Missing,Float64} = liveset.walkers[1].energy.val
8✔
480

481
    to_walk = deepcopy(ats[1])
16✔
482

483
    accept, at = MC_rejection_sampling!(to_walk, h, emax; energy_perturb=ns_params.energy_perturbation)
8✔
484

485
    # @info "iter: $(liveset.walkers[1].iter), emax: $emax, is_accepted: $accept"
486
    if accept
8✔
487
        push!(ats, at)
8✔
488
        popfirst!(ats)
8✔
489
        update_iter!(liveset)
8✔
490
        ns_params.fail_count = 0
8✔
491
        iter = liveset.walkers[1].iter
8✔
492
    else
493
        # @warn "Failed to accept MC move"
494
        emax = missing
×
495
        ns_params.fail_count += 1
×
496
    end
497
    # adjust_step_size(ns_params, rate)
498
    return iter, emax, liveset, ns_params
8✔
499
end
500

501

502

503
"""
504
    nested_sampling(liveset::AtomWalkers, ns_params::NestedSamplingParameters, n_steps::Int64, mc_routine::MCRoutine; args...)
505

506
Perform a nested sampling loop for a given number of steps.
507

508
# Arguments
509
- `liveset::AtomWalkers`: The initial set of walkers.
510
- `ns_params::NestedSamplingParameters`: The parameters for nested sampling.
511
- `n_steps::Int64`: The number of steps to perform.
512
- `mc_routine::MCRoutine`: The Monte Carlo routine to use.
513

514
# Returns
515
- `df`: A DataFrame containing the iteration number and maximum energy for each step.
516
- `liveset`: The updated set of walkers.
517
- `ns_params`: The updated nested sampling parameters.
518
"""
519
function nested_sampling(liveset::AtomWalkers, 
24✔
520
                                ns_params::NestedSamplingParameters, 
521
                                n_steps::Int64, 
522
                                mc_routine::MCRoutine,
523
                                save_strategy::DataSavingStrategy)
524
    df = DataFrame(iter=Int[], emax=Float64[])
24✔
525
    for i in 1:n_steps
24✔
526
        print_info = i % save_strategy.n_info == 0
152✔
527
        write_walker_every_n(liveset.walkers[1], i, save_strategy)
152✔
528
        iter, emax, liveset, ns_params = nested_sampling_step!(liveset, ns_params, mc_routine)
152✔
529
        @debug "n_step $i, iter: $iter, emax: $emax"
152✔
530
        if ns_params.fail_count >= ns_params.allowed_fail_count
152✔
531
            @warn "Failed to accept MC move $(ns_params.allowed_fail_count) times in a row. Reset step size!"
×
532
            ns_params.fail_count = 0
×
533
            ns_params.step_size = ns_params.initial_step_size
×
534
        end
535
        if !(iter isa typeof(missing))
152✔
536
            push!(df, (iter, emax.val))
190✔
537
            if print_info
152✔
538
                @info "iter: $(liveset.walkers[1].iter), emax: $(emax-liveset.walkers[1].energy_frozen_part), step_size: $(round(ns_params.step_size; sigdigits=4))"
144✔
539
            end
NEW
540
        elseif iter isa typeof(missing) && print_info
×
NEW
541
            @info "MC move failed, step: $(i), emax: $(liveset.walkers[1].energy-liveset.walkers[1].energy_frozen_part), step_size: $(round(ns_params.step_size; sigdigits=4))"
×
542
        end
543
        write_df_every_n(df, i, save_strategy)
152✔
544
        write_ls_every_n(liveset, i, save_strategy)
152✔
545
    end
280✔
546
    return df, liveset, ns_params
24✔
547
end
548

NEW
549
function nested_sampling(liveset::AtomWalkers, 
×
550
                                ns_params::NestedSamplingParameters, 
551
                                n_steps::Int64, 
552
                                mc_routine::MCRoutineParallel,
553
                                save_strategy::DataSavingStrategy)
NEW
554
    df = DataFrame(iter=Int[], emax=Float64[])
×
NEW
555
    for i in 1:n_steps # main loop
×
NEW
556
        print_info = i % save_strategy.n_info == 0
×
NEW
557
        write_walker_every_n(liveset.walkers[1], i, save_strategy)
×
NEW
558
        iter, emax, liveset, ns_params = nested_sampling_step!(liveset, ns_params, mc_routine)
×
NEW
559
        @debug "n_step $i, iter: $iter, emax: $emax"
×
560

NEW
561
        if ns_params.fail_count >= ns_params.allowed_fail_count
×
NEW
562
            @warn "Failed to accept MC move $(ns_params.allowed_fail_count) times in a row. Reset step size!"
×
NEW
563
            ns_params.fail_count = 0
×
NEW
564
            ns_params.step_size = ns_params.initial_step_size
×
565
        end
566

NEW
567
        if !(iter isa typeof(missing))
×
NEW
568
            for (n, e) in enumerate(emax)
×
NEW
569
                push!(df, (iter, e.val))
×
NEW
570
                if print_info
×
NEW
571
                    if i == 1
×
NEW
572
                        @info "iter: $(liveset.walkers[1].iter)_$n, emax: $(e-liveset.walkers[1].energy_frozen_part), step_size: $(round(ns_params.step_size; sigdigits=4))"
×
573
                    else
NEW
574
                        T_est = estimate_temperature(length(liveset.walkers), nworkers(), df.emax[end] - df.emax[end-nworkers()])
×
NEW
575
                        @info "iter: $(liveset.walkers[1].iter)_$n, emax: $(e-liveset.walkers[1].energy_frozen_part), step_size: $(round(ns_params.step_size; sigdigits=4)), estimated T: $(T_est) K"
×
576
                    end
577
                end
578
            end
×
579
        elseif iter isa typeof(missing) && print_info
×
NEW
580
            @info "MC move failed, step: $(i), emax: $(liveset.walkers[1].energy-liveset.walkers[1].energy_frozen_part), step_size: $(round(ns_params.step_size; sigdigits=4))"
×
581
        end
582

UNCOV
583
        write_df_every_n(df, i, save_strategy)
×
UNCOV
584
        write_ls_every_n(liveset, i, save_strategy)
×
UNCOV
585
    end
×
UNCOV
586
    return df, liveset, ns_params
×
587
end
588

589
"""
590
    nested_sampling(liveset::LatticeGasWalkers, ns_params::LatticeNestedSamplingParameters, n_steps::Int64, mc_routine::MCRoutine, save_strategy::DataSavingStrategy)
591

592
Perform a nested sampling loop on a lattice gas system for a given number of steps.
593

594
# Arguments
595
- `liveset::LatticeGasWalkers`: The initial set of walkers.
596
- `ns_params::LatticeNestedSamplingParameters`: The parameters for nested sampling.
597
- `n_steps::Int64`: The number of steps to perform.
598
- `mc_routine::MCRoutine`: The Monte Carlo routine to use.
599
- `save_strategy::DataSavingStrategy`: The strategy for saving data.
600

601
# Returns
602
- `df`: A DataFrame containing the iteration number and maximum energy for each step.
603
- `liveset`: The updated set of walkers.
604
- `ns_params`: The updated nested sampling parameters.
605
"""
606
function nested_sampling(liveset::LatticeGasWalkers,
32✔
607
                                ns_params::LatticeNestedSamplingParameters, 
608
                                n_steps::Int64, 
609
                                mc_routine::MCRoutine,
610
                                save_strategy::DataSavingStrategy)
611

612
    df = DataFrame(iter=Int[], emax=Float64[], config=Any[])
32✔
613
    for i in 1:n_steps
32✔
614
        # write_walker_every_n(liveset.walkers[1], i, save_strategy)
615
        
616
        config = liveset.walkers[1].configuration.components
176✔
617

618
        iter, emax, liveset, ns_params = nested_sampling_step!(liveset, ns_params, mc_routine)
176✔
619
        @debug "n_step $i, iter: $iter, emax: $emax"
176✔
620
        if ns_params.fail_count >= ns_params.allowed_fail_count
176✔
621
            @warn "Failed to accept MC move $(ns_params.allowed_fail_count) times in a row. Break!"
×
622
            ns_params.fail_count = 0
×
623
            break
×
624
        end
625
        if !(iter isa typeof(missing))
176✔
626
            push!(df, (iter, emax, config))
156✔
627
            @info "iter: $(liveset.walkers[1].iter), emax: $emax"
312✔
628
        elseif iter isa typeof(missing)
20✔
629
            @info "MC move failed, step: $(i), emax: $(liveset.walkers[1].energy)"
20✔
630
        end
631
        write_df_every_n(df, i, save_strategy)
176✔
632
        write_ls_every_n(liveset, i, save_strategy)
176✔
633
    end
176✔
634
    return df, liveset, ns_params
32✔
635
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc