# RAD-tools - Sandbox (mainly condense matter plotting).
# Copyright (C) 2022-2024 Andrey Rybakov
#
# e-mail: anry@uv.es, web: rad-tools.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from math import cos, sin, sqrt
import numpy as np
import radtools.crystal.cell as Cell
from radtools.constants import TORADIANS
from radtools.crystal.lattice import Lattice
__all__ = [
"CUB",
"FCC",
"BCC",
"TET",
"BCT",
"ORC",
"ORCF",
"ORCI",
"ORCC",
"HEX",
"RHL",
"MCL",
"MCLC",
"TRI",
]
# Primitive cell`s construction
[docs]
def CUB(a: float, return_cell=False):
r"""
Construct cubic primitive lattice.
See :ref:`guide_cub` for the definition of primitive and conventional cells.
Parameters
----------
a : float or int
Length of the all three lattice vectors of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Cubic lattice or cell.
"""
cell = np.array([[a, 0, 0], [0, a, 0], [0, 0, a]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def FCC(a: float, return_cell=False):
r"""
Construct face-centred cubic primitive lattice.
See :ref:`guide_fcc` for the definition of primitive and conventional cells.
Parameters
----------
a : float
Length of the all three lattice vectors of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Face-centred cubic lattice or cell.
"""
cell = np.array([[0, a / 2, a / 2], [a / 2, 0, a / 2], [a / 2, a / 2, 0]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def BCC(a: float, return_cell=False):
r"""
Construct body-centred cubic primitive lattice.
See :ref:`guide_bcc` for the definition of primitive and conventional cells.
Parameters
----------
a : float
Length of the all three lattice vectors of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Body-centred cubic lattice or cell.
"""
cell = np.array(
[[-a / 2, a / 2, a / 2], [a / 2, -a / 2, a / 2], [a / 2, a / 2, -a / 2]]
)
if return_cell:
return cell
return Lattice(cell)
[docs]
def TET(a: float, c: float, return_cell=False):
r"""
Construct tetragonal primitive lattice.
See :ref:`guide_tet` for the definition of primitive and conventional cells.
Parameters
----------
a : float
Length of the two equal lattice vectors of the conventional cell.
c : float
Length of the third lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Tetragonal lattice or cell.
"""
cell = np.array([[a, 0, 0], [0, a, 0], [0, 0, c]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def BCT(a: float, c: float, return_cell=False):
r"""
Construct body-centred tetragonal primitive lattice.
See :ref:`guide_bct` for the definition of primitive and conventional cells.
Parameters
----------
a : float
Length of the two equal lattice vectors of the conventional cell.
c : float
Length of the third lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Body-centred tetragonal lattice cell.
"""
cell = np.array(
[[-a / 2, a / 2, c / 2], [a / 2, -a / 2, c / 2], [a / 2, a / 2, -c / 2]]
)
if return_cell:
return cell
return Lattice(cell)
[docs]
def ORC(a: float, b: float, c: float, return_cell=False):
r"""
Construct orthorhombic primitive lattice.
See :ref:`guide_orc` for the definition of primitive and conventional cells.
Order: :math:`a < b < c`. Input is reordered if necessary.
Parameters
----------
a : float
Length of the smallest lattice vector of the conventional cell.
b : float
Length of the medium lattice vector of the conventional cell.
c : float
Length of the largest lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Orthorhombic lattice or cell.
"""
a, b, c = tuple(sorted([a, b, c]))
cell = np.array([[a, 0, 0], [0, b, 0], [0, 0, c]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def ORCF(a: float, b: float, c: float, return_cell=False):
r"""
Construct face-centred orthorhombic primitive lattice.
See :ref:`guide_orcf` for the definition of primitive and conventional cells.
Order: :math:`a < b < c`. Input is reordered if necessary.
Parameters
----------
a : float
Length of the smallest lattice vector of the conventional cell.
b : float
Length of the medium lattice vector of the conventional cell.
c : float
Length of the largest lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Face-centred orthorhombic lattice or cell.
"""
a, b, c = tuple(sorted([a, b, c]))
cell = np.array([[0, b / 2, c / 2], [a / 2, 0, c / 2], [a / 2, b / 2, 0]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def ORCI(a: float, b: float, c: float, return_cell=False):
r"""
Construct body-centred orthorhombic primitive lattice.
See :ref:`guide_orci` for the definition of primitive and conventional cells.
Order: :math:`a < b < c`. Input is reordered if necessary.
Parameters
----------
a : float
Length of the smallest lattice vector of the conventional cell.
b : float
Length of the medium lattice vector of the conventional cell.
c : float
Length of the largest lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Body-centred orthorhombic lattice or cell.
"""
a, b, c = tuple(sorted([a, b, c]))
cell = np.array(
[[-a / 2, b / 2, c / 2], [a / 2, -b / 2, c / 2], [a / 2, b / 2, -c / 2]]
)
if return_cell:
return cell
return Lattice(cell)
[docs]
def ORCC(a: float, b: float, c: float, return_cell=False):
r"""
Construct base-centred orthorhombic primitive lattice.
See :ref:`guide_orcc` for the definition of primitive and conventional cells.
Order: :math:`a < b < c`. Input is reordered if necessary.
Parameters
----------
a : float
Length of the smallest lattice vector of the conventional cell.
b : float
Length of the medium lattice vector of the conventional cell.
c : float
Length of the largest lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Base-centred orthorhombic lattice or cell.
"""
a, b = tuple(sorted([a, b]))
cell = np.array([[a / 2, -b / 2, 0], [a / 2, b / 2, 0], [0, 0, c]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def HEX(a: float, c: float, return_cell=False):
r"""
Construct hexagonal primitive lattice.
See :ref:`guide_hex` for the definition of primitive and conventional cells.
Parameters
----------
a : float
Length of the lattice vector of the conventional cell.
c : float
Length of the lattice vector of the conventional cell.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Hexagonal lattice or cell.
"""
cell = np.array(
[[a / 2, -a * sqrt(3) / 2, 0], [a / 2, a * sqrt(3) / 2, 0], [0, 0, c]]
)
if return_cell:
return cell
return Lattice(cell)
[docs]
def RHL(a: float, alpha: float, return_cell=False):
r"""
Construct rhombohedral primitive lattice.
See :ref:`guide_rhl` for the definition of primitive and conventional cells.
Condition :math:`\alpha < 120^{\circ}` is assumed.
Parameters
----------
a : float
Length of the lattice vector of the conventional cell.
alpha : float
Angle between vectors :math:`a_2` and :math:`a_3` of the conventional cell. In degrees.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Rhombohedral lattice or cell.
"""
if alpha >= 120:
raise ValueError("alpha has to be < 120 degrees.")
alpha *= TORADIANS
cell = np.array(
[
[a * cos(alpha / 2), -a * sin(alpha / 2), 0],
[a * cos(alpha / 2), a * sin(alpha / 2), 0],
[
a * cos(alpha) / cos(alpha / 2),
0,
a * sqrt(1 - cos(alpha) ** 2 / cos(alpha / 2) ** 2),
],
]
)
if return_cell:
return cell
return Lattice(cell)
[docs]
def MCL(a: float, b: float, c: float, alpha: float, return_cell=False):
r"""
Construct monoclinic primitive lattice.
See :ref:`guide_mcl` for the definition of primitive and conventional cells.
Order: :math:`b \le c`, :math:`\alpha < 90^{\circ}`. Input is reordered if necessary.
Parameters
----------
a : float
Length of the first lattice vector of the conventional cell. (The one oriented along x axis)
b : float
Length of the shorter of the two remaining lattice vectors of the conventional cell.
c : float
Length of the longer of the two remaining lattice vectors of the conventional cell.
alpha : float
Angle between vectors :math:`a_2` and :math:`a_3` of the conventional cell. In degrees.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Monoclinic lattice or cell.
"""
b, c = tuple(sorted([b, c]))
if alpha > 90:
alpha = 180 - alpha
alpha *= TORADIANS
cell = np.array([[a, 0, 0], [0, b, 0], [0, c * cos(alpha), c * sin(alpha)]])
if return_cell:
return cell
return Lattice(cell)
[docs]
def MCLC(a: float, b: float, c: float, alpha: float, return_cell=False):
r"""
Construct base-centred monoclinic primitive lattice.
See :ref:`guide_mclc` for the definition of primitive and conventional cells.
Order: :math:`b \le c`, :math:`\alpha < 90^{\circ}`. Input is reordered if necessary.
Parameters
----------
a : float
Length of the first lattice vector of the conventional cell. (The one oriented along x axis)
b : float
Length of the shorter of the two remaining lattice vectors of the conventional cell.
c : float
Length of the longer of the two remaining lattice vectors of the conventional cell.
alpha : float
Angle between vectors :math:`a_2` and :math:`a_3` of the conventional cell. In degrees.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Base-centred monoclinic lattice or cell.
"""
b, c = tuple(sorted([b, c]))
if alpha > 90:
alpha = 180.0 - alpha
alpha *= TORADIANS
cell = np.array(
[
[a / 2, b / 2, 0],
[-a / 2, b / 2, 0],
[0, c * cos(alpha), c * sin(alpha)],
]
)
if return_cell:
return cell
return Lattice(cell)
[docs]
def TRI(
a: float,
b: float,
c: float,
alpha: float,
beta: float,
gamma: float,
reciprocal=False,
return_cell=False,
):
r"""
Construct triclinic primitive lattice.
See :ref:`guide_tri` for the definition of primitive and conventional cells.
Parameters
----------
a : float
Length of the lattice vector of the conventional cell.
b : float
Length of the lattice vector of the conventional cell.
c : float
Length of the lattice vector of the conventional cell.
alpha : float
Angle between vectors :math:`a_2` and :math:`a_3` of the conventional cell. In degrees.
beta : float
Angle between vectors :math:`a_1` and :math:`a_3` of the conventional cell. In degrees.
gamma : float
Angle between vectors :math:`a_1` and :math:`a_2` of the conventional cell. In degrees.
reciprocal : bool, default False
Whether to interpret input as reciprocal parameters.
return_cell : bool, default False
Whether to return the cell instead of the :py:class:`.Lattice` object.
Returns
-------
lattice : :py:class:`.Lattice` or (3, 3) :numpy:`ndarray`
Triclinic lattice or cell.
"""
cell = Cell.from_params(a, b, c, alpha, beta, gamma)
if reciprocal:
cell = Cell.reciprocal(cell)
if return_cell:
return cell
return Lattice(cell)