-
Notifications
You must be signed in to change notification settings - Fork 83
/
serialisation.jl
100 lines (83 loc) · 4.17 KB
/
serialisation.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
using DFTK
using JLD2
using WriteVTK
using MPI
import DFTK: ScfDefaultCallback, ScfSaveCheckpoints
using Test
include("testcases.jl")
function test_scfres_agreement(tested, ref)
@test tested.basis.model.lattice == ref.basis.model.lattice
@test tested.basis.model.temperature == ref.basis.model.temperature
@test tested.basis.model.smearing == ref.basis.model.smearing
@test tested.basis.model.εF == ref.basis.model.εF
@test tested.basis.model.symmetries == ref.basis.model.symmetries
@test tested.basis.model.spin_polarization == ref.basis.model.spin_polarization
@test tested.basis.model.positions == ref.basis.model.positions
@test atomic_symbol.(tested.basis.model.atoms) == atomic_symbol.(ref.basis.model.atoms)
@test tested.basis.Ecut == ref.basis.Ecut
@test tested.basis.kweights == ref.basis.kweights
@test tested.basis.fft_size == ref.basis.fft_size
kcoords_test = getproperty.(tested.basis.kpoints, :coordinate)
kcoords_ref = getproperty.(ref.basis.kpoints, :coordinate)
@test kcoords_test == kcoords_ref
# Note: Apart from the energy (which is recomputed on loading) the other quantities
# should be exactly as stored. For MPI runs it is possible that the density differs
# slightly for non-master processes as the version from the master process is stored.
@test tested.n_iter == ref.n_iter
@test tested.energies.total ≈ ref.energies.total atol=1e-13
@test tested.eigenvalues == ref.eigenvalues
@test tested.occupation == ref.occupation
@test tested.ψ == ref.ψ
@test tested.ρ ≈ ref.ρ rtol=1e-14
end
@testset "SCF checkpointing" begin
model = model_PBE(o2molecule.lattice, o2molecule.atoms, o2molecule.positions;
temperature=0.02, smearing=Smearing.Gaussian(),
magnetic_moments=[1., 1.], symmetries=false)
kgrid = [1, mpi_nprocs(), 1] # Ensure at least 1 kpt per process
basis = PlaneWaveBasis(model; Ecut=4, kgrid)
# Run SCF and do checkpointing along the way
mktempdir() do tmpdir
checkpointfile = joinpath(tmpdir, "scfres.jld2")
checkpointfile = MPI.bcast(checkpointfile, 0, MPI.COMM_WORLD) # master -> everyone
callback = ScfDefaultCallback() ∘ ScfSaveCheckpoints(checkpointfile; keep=true)
nbandsalg = FixedBands(; n_bands_converge=20)
scfres = self_consistent_field(basis; tol=1e-2, nbandsalg, callback)
test_scfres_agreement(scfres, load_scfres(checkpointfile))
end
end
function test_serialisation(label;
modelargs=(; spin_polarization=:collinear, temperature=0.01),
basisargs=(; Ecut=5, kgrid=(2, 3, 4)))
model = model_LDA(silicon.lattice, silicon.atoms, silicon.positions; modelargs...)
basis = PlaneWaveBasis(model; basisargs...)
nbandsalg = FixedBands(; n_bands_converge=20)
scfres = self_consistent_field(basis; tol=1e-1, nbandsalg)
@test_throws ErrorException save_scfres("MyVTKfile.random", scfres)
@test_throws ErrorException save_scfres("MyVTKfile", scfres)
@testset "JLD2 ($label)" begin
mktempdir() do tmpdir
dumpfile = joinpath(tmpdir, "scfres.jld2")
dumpfile = MPI.bcast(dumpfile, 0, MPI.COMM_WORLD) # master -> everyone
save_scfres(dumpfile, scfres)
@test isfile(dumpfile)
test_scfres_agreement(scfres, load_scfres(dumpfile))
end
end
@testset "VTK ($label)" begin
mktempdir() do tmpdir
dumpfile = joinpath(tmpdir, "scfres.vts")
dumpfile = MPI.bcast(dumpfile, 0, MPI.COMM_WORLD) # master -> everyone
save_scfres(dumpfile, scfres; save_ψ=true)
@test isfile(dumpfile)
end
end
end
@testset "Serialisation" begin
test_serialisation("nospin notemp")
test_serialisation("collinear temp";
modelargs=(; spin_polarization=:collinear, temperature=0.01))
test_serialisation("fixed Fermi";
modelargs=(; εF=0.5, disable_electrostatics_check=true,
temperature=1e-3))
end