You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
3.2 KiB
85 lines
3.2 KiB
2 years ago
|
"""Function-like object creating triclinic lattices.
|
||
|
|
||
|
The following lattice creator is defined:
|
||
|
Triclinic
|
||
|
"""
|
||
|
|
||
|
from ase.lattice.bravais import Bravais
|
||
|
import numpy as np
|
||
|
from ase.data import reference_states as _refstate
|
||
|
|
||
|
|
||
|
class TriclinicFactory(Bravais):
|
||
|
"A factory for creating triclinic lattices."
|
||
|
|
||
|
# The name of the crystal structure in ChemicalElements
|
||
|
xtal_name = "triclinic"
|
||
|
|
||
|
# The natural basis vectors of the crystal structure
|
||
|
int_basis = np.array([[1, 0, 0],
|
||
|
[0, 1, 0],
|
||
|
[0, 0, 1]])
|
||
|
basis_factor = 1.0
|
||
|
|
||
|
# Converts the natural basis back to the crystallographic basis
|
||
|
inverse_basis = np.array([[1, 0, 0],
|
||
|
[0, 1, 0],
|
||
|
[0, 0, 1]])
|
||
|
inverse_basis_factor = 1.0
|
||
|
|
||
|
def get_lattice_constant(self):
|
||
|
"Get the lattice constant of an element with triclinic crystal structure."
|
||
|
if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name:
|
||
|
raise ValueError(('Cannot guess the %s lattice constant of'
|
||
|
+ ' an element with crystal structure %s.')
|
||
|
% (self.xtal_name,
|
||
|
_refstate[self.atomicnumber]['symmetry']))
|
||
|
return _refstate[self.atomicnumber].copy()
|
||
|
|
||
|
def make_crystal_basis(self):
|
||
|
"Make the basis matrix for the crystal unit cell and the system unit cell."
|
||
|
lattice = self.latticeconstant
|
||
|
if isinstance(lattice, type({})):
|
||
|
a = lattice['a']
|
||
|
try:
|
||
|
b = lattice['b']
|
||
|
except KeyError:
|
||
|
b = a * lattice['b/a']
|
||
|
try:
|
||
|
c = lattice['c']
|
||
|
except KeyError:
|
||
|
c = a * lattice['c/a']
|
||
|
alpha = lattice['alpha']
|
||
|
beta = lattice['beta']
|
||
|
gamma = lattice['gamma']
|
||
|
else:
|
||
|
if len(lattice) == 6:
|
||
|
(a, b, c, alpha, beta, gamma) = lattice
|
||
|
else:
|
||
|
raise ValueError("Improper lattice constants for triclinic crystal.")
|
||
|
|
||
|
degree = np.pi / 180.0
|
||
|
cosa = np.cos(alpha*degree)
|
||
|
cosb = np.cos(beta*degree)
|
||
|
sinb = np.sin(beta*degree)
|
||
|
cosg = np.cos(gamma*degree)
|
||
|
sing = np.sin(gamma*degree)
|
||
|
lattice = np.array([[a, 0, 0],
|
||
|
[b*cosg, b*sing, 0],
|
||
|
[c*cosb, c*(cosa-cosb*cosg)/sing,
|
||
|
c*np.sqrt(sinb**2 - ((cosa-cosb*cosg)/sing)**2)]])
|
||
|
self.latticeconstant = lattice
|
||
|
self.miller_basis = lattice
|
||
|
self.crystal_basis = (self.basis_factor *
|
||
|
np.dot(self.int_basis, lattice))
|
||
|
self.basis = np.dot(self.directions, self.crystal_basis)
|
||
|
assert abs(np.dot(lattice[0], lattice[1]) - a*b*cosg) < 1e-5
|
||
|
assert abs(np.dot(lattice[0], lattice[2]) - a*c*cosb) < 1e-5
|
||
|
assert abs(np.dot(lattice[1], lattice[2]) - b*c*cosa) < 1e-5
|
||
|
assert abs(np.dot(lattice[0], lattice[0]) - a*a) < 1e-5
|
||
|
assert abs(np.dot(lattice[1], lattice[1]) - b*b) < 1e-5
|
||
|
assert abs(np.dot(lattice[2], lattice[2]) - c*c) < 1e-5
|
||
|
|
||
|
|
||
|
Triclinic = TriclinicFactory()
|