# Copyright (c) 2019-2020 The Regents of the University of Michigan
# This file is part of the fedorov project, released under the BSD 3-Clause
# License.
import copy
import warnings
import numpy as np
from . import data
class Lattice:
"""Base class for 2D and 3D lattices."""
pass
[docs]class Oblique2D:
"""A class for constructing a 2D oblique unitcell
This class provides method to initialize a 2D oblique unitcell
"""
lattice_params = {"a": 1, "b": 1, "theta": np.pi / 2}
@classmethod
def update_lattice_params(cls, user_lattice_params):
params = copy.deepcopy(cls.lattice_params)
for param, value in user_lattice_params.items():
if param in params:
if value is not None:
params[param] = value
else:
warnings.warn(
f"warning: {param} is not used to define this structure",
RuntimeWarning,
)
return params
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a 2D oblique unitcell and return lattice vectors [a1, a2].
:param user_lattice_params:
unit cell parameters, provide a, b, theta where applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = data.translate_to_vector_2D(**params)
return lattice_vectors
[docs]class Rectangular2D(Oblique2D):
"""A class for constructing a 2D rectangular unitcell
This class provides method to initialize a 2D rectangular unitcell
"""
lattice_params = {"a": 1, "b": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a 2D rectangular unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, theta where applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array([[params["a"], 0.0], [0.0, params["b"]]])
return lattice_vectors
[docs]class Hexagonal2D(Oblique2D):
"""A class for constructing a 2D hexagonal unitcell
This class provides method to initialize a 2D hexagonal unitcell
"""
lattice_params = {"a": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a 2D hexagonal unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, theta where applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array(
[
[params["a"], 0.0],
[-0.5 * params["a"], params["a"] * np.sqrt(3) / 2],
]
)
return lattice_vectors
[docs]class Square2D(Rectangular2D):
"""A class for constructing a 2D square unitcell
This class provides method to initialize a 2D square unitcell
"""
lattice_params = {"a": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a 2D square unitcell and return lattice vectors [a1, a2].
:param user_lattice_params:
unit cell parameters, provide a, b, theta where applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array([[params["a"], 0.0], [0.0, params["a"]]])
return lattice_vectors
lattice_system_dict_2D = {
"oblique": Oblique2D,
"rectangular": Rectangular2D,
"hexagonal": Hexagonal2D,
"square": Square2D,
}
# 3D systems
[docs]class Triclinic:
"""A class for constructing a triclinic unitcell."""
Pearson = "a"
dimensions = 3
lattice_params = {
"a": 1,
"b": 1,
"c": 1,
"alpha": np.pi / 2,
"beta": np.pi / 2,
"gamma": np.pi / 2,
}
@classmethod
def update_lattice_params(cls, user_lattice_params):
params = copy.deepcopy(cls.lattice_params)
for param, value in user_lattice_params.items():
if param in params:
if value is not None:
params[param] = value
else:
warnings.warn(
f"warning: {param} is not used to define this structure",
RuntimeWarning,
)
return params
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a triclinic unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = data.translate_to_vector(**params)
return lattice_vectors
[docs]class Monoclinic(Triclinic):
"""A class for constructing a monoclinic unitcell
This class provides method to initialize a monoclinic unitcell
"""
Pearson = "m"
lattice_params = {"a": 1, "b": 1, "c": 1, "beta": np.pi / 2}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a monoclinic unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = data.translate_to_vector(
a=params["a"], b=params["b"], c=params["c"], beta=params["beta"]
)
return lattice_vectors
[docs]class Orthorhombic(Monoclinic):
"""A class for constructing a orthorhombic unitcell."""
Pearson = "o"
lattice_params = {"a": 1, "b": 1, "c": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a orthorhombi unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array(
[
[params["a"], 0.0, 0.0],
[0.0, params["b"], 0.0],
[0.0, 0.0, params["c"]],
]
)
return lattice_vectors
[docs]class Tetragonal(Orthorhombic):
"""A class for constructing a tetragonal unitcell."""
Pearson = "t"
lattice_params = {"a": 1, "c": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a tetragona unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array(
[
[params["a"], 0.0, 0.0],
[0.0, params["a"], 0.0],
[0.0, 0.0, params["c"]],
]
)
return lattice_vectors
[docs]class Hexagonal(Triclinic):
"""A class for constructing a hexagonal unitcell."""
Pearson = "hP"
lattice_params = {"a": 1, "c": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a hexagonal unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array(
[
[params["a"], 0.0, 0.0],
[-0.5 * params["a"], np.sqrt(3.0) / 2.0 * params["a"], 0.0],
[0.0, 0.0, params["c"]],
]
)
return lattice_vectors
[docs]class Rhombohedral(Triclinic):
"""A class for constructing a rhombohedral unitcell."""
Pearson = "hR"
lattice_params = {"a": 1, "alpha": np.pi / 2}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a rhombohedral unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = data.translate_to_vector(
a=params["a"],
b=params["a"],
c=params["a"],
alpha=params["alpha"],
beta=params["alpha"],
gamma=params["alpha"],
)
return lattice_vectors
[docs]class Cubic(Tetragonal):
"""A class for constructing a cubic unitcell."""
Pearson = "c"
lattice_params = {"a": 1}
[docs] @classmethod
def get_lattice_vectors(cls, **user_lattice_params):
"""Initialize a cubicc unitcell and return lattice vectors.
:param user_lattice_params:
unit cell parameters, provide a, b, c, alpha, beta, gamma where
applicable
:type user_lattice_params:
float
:return:
lattice_vectors
:rtype:
np.ndarray
"""
params = cls.update_lattice_params(user_lattice_params)
lattice_vectors = np.array(
[
[params["a"], 0.0, 0.0],
[0.0, params["a"], 0.0],
[0.0, 0.0, params["a"]],
]
)
return lattice_vectors
lattice_system_dict_3D = {
"triclinic": Triclinic,
"monoclinic": Monoclinic,
"orthorhombic": Orthorhombic,
"tetragonal": Tetragonal,
"hexagonal": Hexagonal,
"rhombohedral": Rhombohedral,
"cubic": Cubic,
}