-
Notifications
You must be signed in to change notification settings - Fork 10
/
reduce.jl
79 lines (67 loc) · 3.08 KB
/
reduce.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
export niggli_reduce, delaunay_reduce
"""
niggli_reduce(lattice::AbstractMatrix, symprec=1e-5)
niggli_reduce(cell::Cell, symprec=1e-5)
Apply Niggli reduction to input basis vectors `lattice`.
The transformation from original basis vectors
``\\begin{bmatrix} \\mathbf{a} & \\mathbf{b} & \\mathbf{c} \\end{bmatrix}``
to final basis vectors
``\\begin{bmatrix} \\mathbf{a}' & \\mathbf{b}' & \\mathbf{c}' \\end{bmatrix}``
is achieved by linear
combination of basis vectors with integer coefficients without
rotating coordinates. Therefore the transformation matrix is obtained
by
```math
\\mathbf{P} = \\begin{bmatrix} \\mathbf{a} & \\mathbf{b} & \\mathbf{c} \\end{bmatrix}
\\begin{bmatrix} \\mathbf{a}' & \\mathbf{b}' & \\mathbf{c}' \\end{bmatrix}^{-1}
```
and the matrix elements have to be almost integers.
See also [Computing rigid rotation introduced by idealization](@ref).
"""
function niggli_reduce(lattice::Lattice, symprec=1e-5)
niggli_lattice = Base.cconvert(Matrix{Cdouble}, transpose(lattice)) # `transpose` must before `cconvert`!
@ccall libsymspg.spg_niggli_reduce(niggli_lattice::Ptr{Cdouble}, symprec::Cdouble)::Cint
check_error()
return Lattice(transpose(niggli_lattice))
end
function niggli_reduce(cell::Cell, symprec=1e-5)
lattice = Lattice(cell)
new_lattice = Matrix(niggli_reduce(lattice, symprec))
𝐏⁻¹ = inv(new_lattice) * Matrix(lattice) # Keep cartesian coordinates, see #106
new_positions = [𝐏⁻¹ * position for position in cell.positions]
return Cell(new_lattice, new_positions, cell.atoms)
end
"""
delaunay_reduce(lattice::AbstractMatrix, symprec=1e-5)
delaunay_reduce(cell::Cell, symprec=1e-5)
Apply Delaunay reduction to input basis vectors `lattice`.
The transformation from original basis vectors
``\\begin{bmatrix} \\mathbf{a} & \\mathbf{b} & \\mathbf{c} \\end{bmatrix}``
to final basis vectors
``\\begin{bmatrix} \\mathbf{a}' & \\mathbf{b}' & \\mathbf{c}' \\end{bmatrix}``
is achieved by linear
combination of basis vectors with integer coefficients without
rotating coordinates. Therefore the transformation matrix is obtained
by
```math
\\mathbf{P} = \\begin{bmatrix} \\mathbf{a} & \\mathbf{b} & \\mathbf{c} \\end{bmatrix}
\\begin{bmatrix} \\mathbf{a}' & \\mathbf{b}' & \\mathbf{c}' \\end{bmatrix}^{-1}
```
and the matrix elements have to be almost integers.
See also [Computing rigid rotation introduced by idealization](@ref).
"""
function delaunay_reduce(lattice::Lattice, symprec=1e-5)
delaunay_lattice = Base.cconvert(Matrix{Cdouble}, transpose(lattice)) # `transpose` must before `cconvert`!
@ccall libsymspg.spg_delaunay_reduce(
delaunay_lattice::Ptr{Cdouble}, symprec::Cdouble
)::Cint
check_error()
return Lattice(transpose(delaunay_lattice))
end
function delaunay_reduce(cell::Cell, symprec=1e-5)
lattice = Lattice(cell)
new_lattice = Matrix(delaunay_reduce(lattice, symprec))
𝐏⁻¹ = inv(new_lattice) * Matrix(lattice) # Keep cartesian coordinates, see #106
new_positions = [𝐏⁻¹ * position for position in cell.positions]
return Cell(new_lattice, new_positions, cell.atoms)
end