-
Notifications
You must be signed in to change notification settings - Fork 83
/
bzmesh.jl
132 lines (108 loc) · 5 KB
/
bzmesh.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
using DFTK
using LinearAlgebra
using Test
using Spglib
using Unitful
using Logging
include("testcases.jl")
@testset "bzmesh_uniform agrees with spglib" begin
using DFTK: normalize_kpoint_coordinate
function test_against_spglib(kgrid_size; kshift=[0, 0, 0])
kgrid_size = Vec3(kgrid_size)
is_shift = ifelse.(kshift .== 0, false, true)
diagonal = Matrix{Int64}(I, 3, 3)
spg_mesh = Spglib.get_stabilized_reciprocal_mesh([diagonal], kgrid_size;
is_shift, is_time_reversal=false)
kcoords_spglib = normalize_kpoint_coordinate.(Spglib.eachpoint(spg_mesh))
sort!(kcoords_spglib)
kcoords, _ = bzmesh_uniform(kgrid_size; kshift)
sort!(kcoords)
@test kcoords == kcoords_spglib
end
test_against_spglib([ 2, 3, 2])
test_against_spglib([ 3, 3, 3])
test_against_spglib([ 3, 3, 3], kshift=[1//2, 0, 0])
test_against_spglib([ 2, 3, 4])
test_against_spglib([ 9, 11, 13])
end
if mpi_nprocs() == 1 # PythonCall does not play nicely with MPI
@testset "bzmesh_ir_wedge is correct reduction" begin
using ASEconvert
function test_reduction(testcase, kgrid_size, kirredsize;
supercell=(1, 1, 1), kshift=[0, 0, 0])
system = atomic_system(testcase.lattice, testcase.atoms, testcase.positions)
# Make supercell
if supercell != (1, 1, 1)
ase_atoms = with_logger(() -> convert_ase(system), NullLogger())
system = pyconvert(AbstractSystem, ase_atoms * pytuple(supercell))
end
red_kcoords, _ = bzmesh_uniform(kgrid_size; kshift)
symmetries = symmetry_operations(system)
irred_kcoords, _ = bzmesh_ir_wedge(kgrid_size, symmetries; kshift)
@test length(irred_kcoords) == kirredsize
# Try to reproduce all kcoords from irred_kcoords
all_kcoords = Vector{Vec3{Rational{Int}}}()
sym_preserving_grid = DFTK.symmetries_preserving_kgrid(symmetries, red_kcoords)
for (ik, k) in enumerate(irred_kcoords)
append!(all_kcoords, [symop.S * k for symop in sym_preserving_grid])
end
# Normalize the obtained k-points and test for equality
red_kcoords = unique(sort([mod.(k .* kgrid_size, kgrid_size) for k in red_kcoords]))
all_kcoords = unique(sort([mod.(k .* kgrid_size, kgrid_size) for k in all_kcoords]))
@test all_kcoords == red_kcoords
end
test_reduction(silicon, [ 2, 3, 2], 6)
test_reduction(silicon, [ 3, 3, 3], 4)
test_reduction(silicon, [ 2, 3, 4], 14)
test_reduction(silicon, [ 9, 11, 13], 644)
test_reduction(silicon, [ 3, 3, 3], 6, kshift=[1//2, 1//2, 1//2])
test_reduction(silicon, [ 3, 3, 3], 6, kshift=[1//2, 0, 1//2])
test_reduction(silicon, [ 3, 3, 3], 6, kshift=[0, 1//2, 0])
test_reduction(silicon, [ 1, 4, 4], 7, supercell=[2, 1, 1])
test_reduction(silicon, [ 1, 16, 16], 73, supercell=[4, 1, 1])
test_reduction(magnesium, [ 2, 3, 2], 8)
test_reduction(magnesium, [ 3, 3, 3], 6)
test_reduction(magnesium, [ 2, 3, 4], 12)
test_reduction(magnesium, [ 9, 11, 13], 350)
test_reduction(platinum_hcp, [5, 5, 5], 63)
end
end
@testset "standardize_atoms" begin
# Test unperturbed structure
std = standardize_atoms(silicon.lattice, silicon.atoms, silicon.positions, primitive=true)
@test length(std.atoms) == 2
@test std.atoms[1].symbol == :Si
@test std.atoms[2].symbol == :Si
@test length(std.positions) == 2
@test std.positions[1] - std.positions[2] ≈ 0.25ones(3)
@test std.lattice ≈ silicon.lattice
# Perturb structure
plattice = silicon.lattice .+ 1e-8rand(3, 3)
patoms = silicon.atoms
ppositions = [p + 1e-8rand(3) for p in silicon.positions]
std = standardize_atoms(plattice, patoms, ppositions, primitive=true)
# And check we get the usual silicon primitive cell back:
a = std.lattice[1, 2]
@test std.lattice == [0 a a; a 0 a; a a 0]
@test length(std.atoms) == 2
@test std.atoms[1].symbol == :Si
@test std.atoms[2].symbol == :Si
@test length(std.positions) == 2
@test std.positions[1] - std.positions[2] ≈ 0.25ones(3)
end
@testset "kgrid_from_minimal_spacing" begin
# Test that units are stripped from both the lattice and the spacing
lattice = [[-1.0 1 1]; [1 -1 1]; [1 1 -1]]
@test kgrid_from_minimal_spacing(lattice * u"angstrom", 0.5 / u"angstrom") == [9; 9; 9]
end
@testset "kgrid_from_minimal_n_kpoints" begin
lattice = [[-1.0 1 1]; [1 -1 1]; [1 1 -1]]
@test kgrid_from_minimal_n_kpoints(lattice * u"Å", 1000) == [10, 10, 10]
@test kgrid_from_minimal_n_kpoints(magnesium.lattice, 1) == [1, 1, 1]
for n_kpt in [10, 20, 100, 400, 900, 1200]
@test prod(kgrid_from_minimal_n_kpoints(magnesium.lattice, n_kpt)) ≥ n_kpt
end
lattice = diagm([4., 10, 0])
@test kgrid_from_minimal_n_kpoints(lattice, 1000) == [50, 20, 1]
@test kgrid_from_minimal_n_kpoints(diagm([10, 0, 0]), 913) == [913, 1, 1]
end