Skip to content

Instantly share code, notes, and snippets.

@unkcpz
Created May 18, 2018 02:03
Show Gist options
  • Save unkcpz/bbff51c9f285f1429bbeaca74ddcaf6e to your computer and use it in GitHub Desktop.
Save unkcpz/bbff51c9f285f1429bbeaca74ddcaf6e to your computer and use it in GitHub Desktop.
import numpy as np
#
# Delaunay reduction (originally from phonopy)
#
def get_Delaunay_reduction(lattice, tolerance):
extended_bases = np.zeros((4, 3), dtype=float)
extended_bases[:3,:] = np.transpose(lattice)
extended_bases[3] = -np.sum(lattice, axis=1)
for i in range(100):
if reduce_bases(extended_bases, tolerance):
break
if i == 99:
print("Delaunary reduction failed.")
shortest3 = get_shortest_bases(extended_bases, tolerance)
return shortest3.T.copy()
def reduce_bases(extended_bases, tolerance):
metric = np.dot(extended_bases, extended_bases.T)
for i in range(4):
for j in range(i+1, 4):
if metric[i, j] > tolerance:
for k in range(4):
if (not k == i) and (not k == j):
extended_bases[k] += extended_bases[i]
extended_bases[i] = -extended_bases[i]
extended_bases[j] = extended_bases[j]
return False
# All non diagonal elements of metric tensor is negative.
# Reduction is completed.
return True
def get_shortest_bases(extended_bases, tolerance):
def mycmp(x, y):
return cmp(np.vdot(x, x), np.vdot(y, y))
basis = np.zeros((7, 3), dtype=float)
basis[:4] = extended_bases
basis[4] = extended_bases[0] + extended_bases[1]
basis[5] = extended_bases[1] + extended_bases[2]
basis[6] = extended_bases[2] + extended_bases[0]
# Sort bases by the lengthes (shorter is earlier)
basis = sorted(basis, cmp=mycmp)
# Choose shortest and linearly independent three bases
# This algorithm may not be perfect.
for i in range(7):
for j in range(i+1, 7):
for k in range(j+1, 7):
if abs(np.linalg.det([basis[i],
basis[j],
basis[k]])) > tolerance:
return np.array([basis[i],
basis[j],
basis[k]])
print("Delaunary reduction is failed.")
return basis[:3]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment