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.
151 lines
5.3 KiB
151 lines
5.3 KiB
"""Function-like objects creating orthorhombic lattices. |
|
|
|
The following lattice creators are defined: |
|
SimleOrthorhombic |
|
BaseCenteredOrthorhombic |
|
BodyCenteredOrthorhombic |
|
FaceCenteredOrthorhombic |
|
""" |
|
|
|
from ase.lattice.bravais import Bravais |
|
import numpy as np |
|
from ase.data import reference_states as _refstate |
|
|
|
|
|
class SimpleOrthorhombicFactory(Bravais): |
|
"A factory for creating simple orthorhombic lattices." |
|
|
|
# The name of the crystal structure in ChemicalElements |
|
xtal_name = "orthorhombic" |
|
|
|
# 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 orhtorhombic 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'] |
|
else: |
|
if len(lattice) == 3: |
|
(a, b, c) = lattice |
|
else: |
|
raise ValueError("Improper lattice constants for orthorhombic crystal.") |
|
|
|
lattice = np.array([[a, 0, 0], [0, b, 0], [0, 0, c]]) |
|
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) |
|
self.check_basis_volume() |
|
|
|
def check_basis_volume(self): |
|
"Check the volume of the unit cell." |
|
vol1 = abs(np.linalg.det(self.basis)) |
|
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) |
|
if self.bravais_basis is not None: |
|
vol2 /= len(self.bravais_basis) |
|
if abs(vol1-vol2) > 1e-5: |
|
print("WARNING: Got volume %f, expected %f" % (vol1, vol2)) |
|
|
|
|
|
SimpleOrthorhombic = SimpleOrthorhombicFactory() |
|
|
|
|
|
class BaseCenteredOrthorhombicFactory(SimpleOrthorhombicFactory): |
|
"A factory for creating base-centered orthorhombic lattices." |
|
|
|
# The natural basis vectors of the crystal structure |
|
int_basis = np.array([[1, -1, 0], |
|
[1, 1, 0], |
|
[0, 0, 2]]) |
|
basis_factor = 0.5 |
|
|
|
# Converts the natural basis back to the crystallographic basis |
|
inverse_basis = np.array([[1, 1, 0], |
|
[-1, 1, 0], |
|
[0, 0, 1]]) |
|
inverse_basis_factor = 1.0 |
|
|
|
def check_basis_volume(self): |
|
"Check the volume of the unit cell." |
|
vol1 = abs(np.linalg.det(self.basis)) |
|
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0 |
|
if abs(vol1-vol2) > 1e-5: |
|
print("WARNING: Got volume %f, expected %f" % (vol1, vol2)) |
|
|
|
|
|
BaseCenteredOrthorhombic = BaseCenteredOrthorhombicFactory() |
|
|
|
|
|
class BodyCenteredOrthorhombicFactory(SimpleOrthorhombicFactory): |
|
"A factory for creating body-centered orthorhombic lattices." |
|
|
|
int_basis = np.array([[-1, 1, 1], |
|
[1, -1, 1], |
|
[1, 1, -1]]) |
|
basis_factor = 0.5 |
|
inverse_basis = np.array([[0, 1, 1], |
|
[1, 0, 1], |
|
[1, 1, 0]]) |
|
inverse_basis_factor = 1.0 |
|
|
|
def check_basis_volume(self): |
|
"Check the volume of the unit cell." |
|
vol1 = abs(np.linalg.det(self.basis)) |
|
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0 |
|
if abs(vol1-vol2) > 1e-5: |
|
print("WARNING: Got volume %f, expected %f" % (vol1, vol2)) |
|
|
|
|
|
BodyCenteredOrthorhombic = BodyCenteredOrthorhombicFactory() |
|
|
|
|
|
class FaceCenteredOrthorhombicFactory(SimpleOrthorhombicFactory): |
|
"A factory for creating face-centered orthorhombic lattices." |
|
|
|
int_basis = np.array([[0, 1, 1], |
|
[1, 0, 1], |
|
[1, 1, 0]]) |
|
basis_factor = 0.5 |
|
inverse_basis = np.array([[-1, 1, 1], |
|
[1, -1, 1], |
|
[1, 1, -1]]) |
|
inverse_basis_factor = 1.0 |
|
|
|
def check_basis_volume(self): |
|
"Check the volume of the unit cell." |
|
vol1 = abs(np.linalg.det(self.basis)) |
|
vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 4.0 |
|
if abs(vol1-vol2) > 1e-5: |
|
print("WARNING: Got volume %f, expected %f" % (vol1, vol2)) |
|
|
|
|
|
FaceCenteredOrthorhombic = FaceCenteredOrthorhombicFactory()
|
|
|