# 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, tan
import numpy as np
from radtools.constants import TORADIANS
__all__ = [
"CUB_hs_points",
"FCC_hs_points",
"BCC_hs_points",
"TET_hs_points",
"BCT_hs_points",
"ORC_hs_points",
"ORCF_hs_points",
"ORCI_hs_points",
"ORCC_hs_points",
"HEX_hs_points",
"RHL_hs_points",
"MCL_hs_points",
"MCLC_hs_points",
"TRI_hs_points",
]
[docs]
def CUB_hs_points():
r"""
Get high-symmetry points for the CUB lattice.
See :ref:`guide_cub` for the details.
Returns
-------
kpoints : dict
High-symmetry points.
"""
return {
"G": np.array([0, 0, 0]),
"M": np.array([1 / 2, 1 / 2, 0]),
"R": np.array([1 / 2, 1 / 2, 1 / 2]),
"X": np.array([0, 1 / 2, 0]),
}
[docs]
def FCC_hs_points():
r"""
Get high-symmetry points for the FCC lattice.
See :ref:`guide_fcc` for the details.
Returns
-------
kpoints : dict
High-symmetry points.
"""
return {
"G": np.array([0, 0, 0]),
"K": np.array([3 / 8, 3 / 8, 3 / 4]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"U": np.array([5 / 8, 1 / 4, 5 / 8]),
"W": np.array([1 / 2, 1 / 4, 3 / 4]),
"X": np.array([1 / 2, 0, 1 / 2]),
}
[docs]
def BCC_hs_points():
r"""
Get high-symmetry points for the CUB lattice.
See :ref:`guide_bcc` for the details.
Returns
-------
kpoints : dict
High-symmetry points.
"""
return {
"G": np.array([0, 0, 0]),
"H": np.array([1 / 2, -1 / 2, 1 / 2]),
"P": np.array([1 / 4, 1 / 4, 1 / 4]),
"N": np.array([0, 0, 1 / 2]),
}
[docs]
def TET_hs_points():
r"""
Get high-symmetry points for the TET lattice.
See :ref:`guide_tet` for the details.
Returns
-------
kpoints : dict
High-symmetry points.
"""
return {
"G": np.array([0, 0, 0]),
"A": np.array([1 / 2, 1 / 2, 1 / 2]),
"M": np.array([1 / 2, 1 / 2, 0]),
"R": np.array([0, 1 / 2, 1 / 2]),
"X": np.array([0, 1 / 2, 0]),
"Z": np.array([0, 0, 1 / 2]),
}
[docs]
def BCT_hs_points(variation, conv_a, conv_c):
r"""
Get high-symmetry points for the BCT lattice.
See :ref:`guide_bct` for the details.
Parameters
----------
variation : str
BCT variation.
conv_a : float
Length of the lattice vector of the conventional cell.
conv_c : float
Length of the lattice vector of the conventional cell.
Returns
-------
kpoints : dict
High-symmetry points.
"""
if variation == "BCT1":
eta = (1 + conv_c**2 / conv_a**2) / 4
kpoints = {
"G": np.array([0, 0, 0]),
"M": np.array([-1 / 2, 1 / 2, 1 / 2]),
"N": np.array([0, 1 / 2, 0]),
"P": np.array([1 / 4, 1 / 4, 1 / 4]),
"X": np.array([0, 0, 1 / 2]),
"Z": np.array([eta, eta, -eta]),
"Z1": np.array([-eta, 1 - eta, eta]),
}
elif variation == "BCT2":
eta = (1 + conv_a**2 / conv_c**2) / 4
zeta = conv_a**2 / (2 * conv_c**2)
kpoints = {
"G": np.array([0, 0, 0]),
"N": np.array([0, 1 / 2, 0]),
"P": np.array([1 / 4, 1 / 4, 1 / 4]),
"S": np.array([-eta, eta, eta]),
"S1": np.array([eta, 1 - eta, -eta]),
"X": np.array([0, 0, 1 / 2]),
"Y": np.array([-zeta, zeta, 1 / 2]),
"Y1": np.array([1 / 2, 1 / 2, -zeta]),
"Z": np.array([1 / 2, 1 / 2, -1 / 2]),
}
return kpoints
[docs]
def ORC_hs_points():
r"""
Get high-symmetry points for the ORC lattice.
See :ref:`guide_orc` for the details.
Returns
-------
kpoints : dict
High-symmetry points.
"""
return {
"G": np.array([0, 0, 0]),
"R": np.array([1 / 2, 1 / 2, 1 / 2]),
"S": np.array([1 / 2, 1 / 2, 0]),
"T": np.array([0, 1 / 2, 1 / 2]),
"U": np.array([1 / 2, 0, 1 / 2]),
"X": np.array([1 / 2, 0, 0]),
"Y": np.array([0, 1 / 2, 0]),
"Z": np.array([0, 0, 1 / 2]),
}
[docs]
def ORCF_hs_points(variation, conv_a, conv_b, conv_c):
r"""
Get high-symmetry points for the ORCF lattice.
See :ref:`guide_orcf` for the details.
Parameters
----------
variation : str
ORCF variation.
conv_a : float
Length of the lattice vector of the conventional cell.
conv_b : float
Length of the lattice vector of the conventional cell.
conv_c : float
Length of the lattice vector of the conventional cell.
Returns
-------
kpoints : dict
High-symmetry points.
"""
if variation == "ORCF1":
eta = (1 + conv_a**2 / conv_b**2 + conv_a**2 / conv_c**2) / 4
zeta = (1 + conv_a**2 / conv_b**2 - conv_a**2 / conv_c**2) / 4
kpoints = {
"G": np.array([0, 0, 0]),
"A": np.array([1 / 2, 1 / 2 + zeta, zeta]),
"A1": np.array([1 / 2, 1 / 2 - zeta, 1 - zeta]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"T": np.array([1, 1 / 2, 1 / 2]),
"X": np.array([0, eta, eta]),
"X1": np.array([1, 1 - eta, 1 - eta]),
"Y": np.array([1 / 2, 0, 1 / 2]),
"Z": np.array([1 / 2, 1 / 2, 0]),
}
elif variation == "ORCF2":
eta = (1 + conv_a**2 / conv_b**2 - conv_a**2 / conv_c**2) / 4
delta = (1 + conv_b**2 / conv_a**2 - conv_b**2 / conv_c**2) / 4
phi = (1 + conv_c**2 / conv_b**2 - conv_c**2 / conv_a**2) / 4
kpoints = {
"G": np.array([0, 0, 0]),
"C": np.array([1 / 2, 1 / 2 - eta, 1 - eta]),
"C1": np.array([1 / 2, 1 / 2 + eta, eta]),
"D": np.array([1 / 2 - delta, 1 / 2, 1 - delta]),
"D1": np.array([1 / 2 + delta, 1 / 2, delta]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"H": np.array([1 - phi, 1 / 2 - phi, 1 / 2]),
"H1": np.array([phi, 1 / 2 + phi, 1 / 2]),
"X": np.array([0, 1 / 2, 1 / 2]),
"Y": np.array([1 / 2, 0, 1 / 2]),
"Z": np.array([1 / 2, 1 / 2, 0]),
}
elif variation == "ORCF3":
eta = (1 + conv_a**2 / conv_b**2 + conv_a**2 / conv_c**2) / 4
zeta = (1 + conv_a**2 / conv_b**2 - conv_a**2 / conv_c**2) / 4
kpoints = {
"G": np.array([0, 0, 0]),
"A": np.array([1 / 2, 1 / 2 + zeta, zeta]),
"A1": np.array([1 / 2, 1 / 2 - zeta, 1 - zeta]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"T": np.array([1, 1 / 2, 1 / 2]),
"X": np.array([0, eta, eta]),
"Y": np.array([1 / 2, 0, 1 / 2]),
"Z": np.array([1 / 2, 1 / 2, 0]),
}
return kpoints
[docs]
def ORCI_hs_points(conv_a, conv_b, conv_c):
r"""
Get high-symmetry points for the ORCI lattice.
See :ref:`guide_orci` for the details.
Parameters
----------
conv_a : float
Length of the lattice vector of the conventional cell.
conv_b : float
Length of the lattice vector of the conventional cell.
conv_c : float
Length of the lattice vector of the conventional cell.
Returns
-------
kpoints : dict
High-symmetry points.
"""
zeta = (1 + conv_a**2 / conv_c**2) / 4
eta = (1 + conv_b**2 / conv_c**2) / 4
delta = (conv_b**2 - conv_a**2) / (4 * conv_c**2)
mu = (conv_a**2 + conv_b**2) / (4 * conv_c**2)
return {
"G": np.array([0, 0, 0]),
"L": np.array([-mu, mu, 1 / 2 - delta]),
"L1": np.array([mu, -mu, 1 / 2 + delta]),
"L2": np.array([1 / 2 - delta, 1 / 2 + delta, -mu]),
"R": np.array([0, 1 / 2, 0]),
"S": np.array([1 / 2, 0, 0]),
"T": np.array([0, 0, 1 / 2]),
"W": np.array([1 / 4, 1 / 4, 1 / 4]),
"X": np.array([-zeta, zeta, zeta]),
"X1": np.array([zeta, 1 - zeta, -zeta]),
"Y": np.array([eta, -eta, eta]),
"Y1": np.array([1 - eta, eta, -eta]),
"Z": np.array([1 / 2, 1 / 2, -1 / 2]),
}
[docs]
def ORCC_hs_points(conv_a, conv_b):
r"""
Get high-symmetry points for the ORCC lattice.
See :ref:`guide_orcc` for the details.
Parameters
----------
conv_a : float
Length of the lattice vector of the conventional cell.
conv_b : float
Length of the lattice vector of the conventional cell.
Returns
-------
kpoints : dict
High-symmetry points.
"""
zeta = (1 + conv_a**2 / conv_b**2) / 4
return {
"G": np.array([0, 0, 0]),
"A": np.array([zeta, zeta, 1 / 2]),
"A1": np.array([-zeta, 1 - zeta, 1 / 2]),
"R": np.array([0, 1 / 2, 1 / 2]),
"S": np.array([0, 1 / 2, 0]),
"T": np.array([-1 / 2, 1 / 2, 1 / 2]),
"X": np.array([zeta, zeta, 0]),
"X1": np.array([-zeta, 1 - zeta, 0]),
"Y": np.array([-1 / 2, 1 / 2, 0]),
"Z": np.array([0, 0, 1 / 2]),
}
[docs]
def HEX_hs_points():
r"""
Get high-symmetry points for the HEX lattice.
See :ref:`guide_hex` for the details.
Returns
-------
kpoints : dict
High-symmetry points.
"""
return {
"G": np.array([0, 0, 0]),
"A": np.array([0, 0, 1 / 2]),
"H": np.array([1 / 3, 1 / 3, 1 / 2]),
"K": np.array([1 / 3, 1 / 3, 0]),
"L": np.array([1 / 2, 0, 1 / 2]),
"M": np.array([1 / 2, 0, 0]),
}
[docs]
def RHL_hs_points(variation, conv_alpha):
r"""
Get high-symmetry points for the RHL lattice.
See :ref:`guide_rhl` for the details.
Parameters
----------
variation : str
RHL variation.
alpha : float
Angle between the lattice vectors.
Returns
-------
kpoints : dict
High-symmetry points.
"""
conv_alpha *= TORADIANS
if variation == "RHL1":
eta = (1 + 4 * cos(conv_alpha)) / (2 + 4 * cos(conv_alpha))
nu = 3 / 4 - eta / 2
return {
"G": np.array([0, 0, 0]),
"B": np.array([eta, 1 / 2, 1 - eta]),
"B1": np.array([1 / 2, 1 - eta, eta - 1]),
"F": np.array([1 / 2, 1 / 2, 0]),
"L": np.array([1 / 2, 0, 0]),
"L1": np.array([0, 0, -1 / 2]),
"P": np.array([eta, nu, nu]),
"P1": np.array([1 - nu, 1 - nu, 1 - eta]),
"P2": np.array([nu, nu, eta - 1]),
"Q": np.array([1 - nu, nu, 0]),
"X": np.array([nu, 0, -nu]),
"Z": np.array([1 / 2, 1 / 2, 1 / 2]),
}
elif variation == "RHL2":
eta = 1 / (2 * tan(conv_alpha / 2) ** 2)
nu = 3 / 4 - eta / 2
return {
"G": np.array([0, 0, 0]),
"F": np.array([1 / 2, -1 / 2, 0]),
"L": np.array([1 / 2, 0, 0]),
"P": np.array([1 - nu, -nu, 1 - nu]),
"P1": np.array([nu, nu - 1, nu - 1]),
"Q": np.array([eta, eta, eta]),
"Q1": np.array([1 - eta, -eta, -eta]),
"Z": np.array([1 / 2, -1 / 2, 1 / 2]),
}
[docs]
def MCL_hs_points(conv_b, conv_c, conv_alpha):
r"""
Get high-symmetry points for the MCL lattice.
See :ref:`guide_mcl` for the details.
Parameters
----------
conv_b : float
Length of the lattice vector of the conventional cell.
conv_c : float
Length of the lattice vector of the conventional cell.
conv_alpha : float
Angle between the lattice vectors.
Returns
-------
kpoints : dict
High-symmetry points.
"""
conv_alpha *= TORADIANS
eta = (1 - conv_b * cos(conv_alpha) / conv_c) / (2 * sin(conv_alpha) ** 2)
nu = 1 / 2 - eta * conv_c * cos(conv_alpha) / conv_b
return {
"G": np.array([0, 0, 0]),
"A": np.array([1 / 2, 1 / 2, 0]),
"C": np.array([0, 1 / 2, 1 / 2]),
"D": np.array([1 / 2, 0, 1 / 2]),
"D1": np.array([1 / 2, 0, -1 / 2]),
"E": np.array([1 / 2, 1 / 2, 1 / 2]),
"H": np.array([0, eta, 1 - nu]),
"H1": np.array([0, 1 - eta, nu]),
"H2": np.array([0, eta, -nu]),
"M": np.array([1 / 2, eta, 1 - nu]),
"M1": np.array([1 / 2, 1 - eta, nu]),
"M2": np.array([1 / 2, eta, -nu]),
"X": np.array([0, 1 / 2, 0]),
"Y": np.array([0, 0, 1 / 2]),
"Y1": np.array([0, 0, -1 / 2]),
"Z": np.array([1 / 2, 0, 0]),
}
[docs]
def MCLC_hs_points(variation, conv_a, conv_b, conv_c, conv_alpha):
r"""
Get high-symmetry points for the MCLC lattice.
See :ref:`guide_mclc` for the details.
Parameters
----------
variation : str
MCLC variation.
conv_a : float
Length of the lattice vector of the conventional cell.
conv_b : float
Length of the lattice vector of the conventional cell.
conv_c : float
Length of the lattice vector of the conventional cell.
conv_alpha : float
Angle between the lattice vectors.
Returns
-------
kpoints : dict
High-symmetry points.
"""
conv_alpha *= TORADIANS
# Parameters
if variation in ["MCLC1", "MCLC2"]:
zeta = (2 - conv_b * cos(conv_alpha) / conv_c) / (4 * sin(conv_alpha) ** 2)
eta = 1 / 2 + 2 * zeta * conv_c * cos(conv_alpha) / conv_b
psi = 3 / 4 - conv_a**2 / (4 * conv_b**2 * sin(conv_alpha) ** 2)
phi = psi + (3 / 4 - psi) * conv_b * cos(conv_alpha) / conv_c
elif variation in ["MCLC3", "MCLC4"]:
mu = (1 + conv_b**2 / conv_a**2) / 4
delta = conv_b * conv_c * cos(conv_alpha) / (2 * conv_a**2)
zeta = (
mu
- 1 / 4
+ (1 - conv_b * cos(conv_alpha) / conv_c) / (4 * sin(conv_alpha) ** 2)
)
eta = 1 / 2 + 2 * zeta * conv_c * cos(conv_alpha) / conv_b
phi = 1 + zeta - 2 * mu
psi = eta - 2 * delta
elif variation == "MCLC5":
zeta = (
conv_b**2 / conv_a**2
+ (1 - conv_b * cos(conv_alpha) / conv_c) / sin(conv_alpha) ** 2
) / 4
eta = 1 / 2 + 2 * zeta * conv_c * cos(conv_alpha) / conv_b
mu = (
eta / 2
+ conv_b**2 / (4 * conv_a**2)
- conv_b * conv_c * cos(conv_alpha) / (2 * conv_a**2)
)
nu = 2 * mu - zeta
rho = 1 - zeta * conv_a**2 / conv_b**2
omega = (
(4 * nu - 1 - conv_b**2 * sin(conv_alpha) ** 2 / conv_a**2)
* conv_c
/ (2 * conv_b * cos(conv_alpha))
)
delta = zeta * conv_c * cos(conv_alpha) / conv_b + omega / 2 - 1 / 4
# Path
if variation == "MCLC1":
return {
"G": np.array([0, 0, 0]),
"N": np.array([1 / 2, 0, 0]),
"N1": np.array([0, -1 / 2, 0]),
"F": np.array([1 - zeta, 1 - zeta, 1 - eta]),
"F1": np.array([zeta, zeta, eta]),
"F2": np.array([-zeta, -zeta, 1 - eta]),
"I": np.array([phi, 1 - phi, 1 / 2]),
"I1": np.array([1 - phi, phi - 1, 1 / 2]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"M": np.array([1 / 2, 0, 1 / 2]),
"X": np.array([1 - psi, psi - 1, 0]),
"X1": np.array([psi, 1 - psi, 0]),
"X2": np.array([psi - 1, -psi, 0]),
"Y": np.array([1 / 2, 1 / 2, 0]),
"Y1": np.array([-1 / 2, -1 / 2, 0]),
"Z": np.array([0, 0, 1 / 2]),
}
elif variation == "MCLC2":
return {
"G": np.array([0, 0, 0]),
"N": np.array([1 / 2, 0, 0]),
"N1": np.array([0, -1 / 2, 0]),
"F": np.array([1 - zeta, 1 - zeta, 1 - eta]),
"F1": np.array([zeta, zeta, eta]),
"F2": np.array([-zeta, -zeta, 1 - eta]),
"F3": np.array([1 - zeta, -zeta, 1 - eta]),
"I": np.array([phi, 1 - phi, 1 / 2]),
"I1": np.array([1 - phi, phi - 1, 1 / 2]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"M": np.array([1 / 2, 0, 1 / 2]),
"X": np.array([1 - psi, psi - 1, 0]),
"Y": np.array([1 / 2, 1 / 2, 0]),
"Y1": np.array([-1 / 2, -1 / 2, 0]),
"Z": np.array([0, 0, 1 / 2]),
}
elif variation == "MCLC3":
return {
"G": np.array([0, 0, 0]),
"F": np.array([1 - phi, 1 - phi, 1 - psi]),
"F1": np.array([phi, phi - 1, psi]),
"F2": np.array([1 - phi, -phi, 1 - psi]),
"H": np.array([zeta, zeta, eta]),
"H1": np.array([1 - zeta, -zeta, 1 - eta]),
"H2": np.array([-zeta, -zeta, 1 - eta]),
"I": np.array([1 / 2, -1 / 2, 1 / 2]),
"M": np.array([1 / 2, 0, 1 / 2]),
"N": np.array([1 / 2, 0, 0]),
"N1": np.array([0, -1 / 2, 0]),
"X": np.array([1 / 2, -1 / 2, 0]),
"Y": np.array([mu, mu, delta]),
"Y1": np.array([1 - mu, -mu, -delta]),
"Y2": np.array([-mu, -mu, -delta]),
"Y3": np.array([mu, mu - 1, delta]),
"Z": np.array([0, 0, 1 / 2]),
}
elif variation == "MCLC4":
return {
"G": np.array([0, 0, 0]),
"F": np.array([1 - phi, 1 - phi, 1 - psi]),
"H": np.array([zeta, zeta, eta]),
"H1": np.array([1 - zeta, -zeta, 1 - eta]),
"H2": np.array([-zeta, -zeta, 1 - eta]),
"I": np.array([1 / 2, -1 / 2, 1 / 2]),
"M": np.array([1 / 2, 0, 1 / 2]),
"N": np.array([1 / 2, 0, 0]),
"N1": np.array([0, -1 / 2, 0]),
"X": np.array([1 / 2, -1 / 2, 0]),
"Y": np.array([mu, mu, delta]),
"Y1": np.array([1 - mu, -mu, -delta]),
"Y2": np.array([-mu, -mu, -delta]),
"Y3": np.array([mu, mu - 1, delta]),
"Z": np.array([0, 0, 1 / 2]),
}
elif variation == "MCLC5":
return {
"G": np.array([0, 0, 0]),
"F": np.array([nu, nu, omega]),
"F1": np.array([1 - nu, 1 - nu, 1 - omega]),
"F2": np.array([nu, nu - 1, omega]),
"H": np.array([zeta, zeta, eta]),
"H1": np.array([1 - zeta, -zeta, 1 - eta]),
"H2": np.array([-zeta, -zeta, 1 - eta]),
"I": np.array([rho, 1 - rho, 1 / 2]),
"I1": np.array([1 - rho, rho - 1, 1 / 2]),
"L": np.array([1 / 2, 1 / 2, 1 / 2]),
"M": np.array([1 / 2, 0, 1 / 2]),
"N": np.array([1 / 2, 0, 0]),
"N1": np.array([0, -1 / 2, 0]),
"X": np.array([1 / 2, -1 / 2, 0]),
"Y": np.array([mu, mu, delta]),
"Y1": np.array([1 - mu, -mu, -delta]),
"Y2": np.array([-mu, -mu, -delta]),
"Y3": np.array([mu, mu - 1, delta]),
"Z": np.array([0, 0, 1 / 2]),
}
[docs]
def TRI_hs_points(variation):
r"""
Get high-symmetry points for the TRI lattice.
See :ref:`guide_tri` for the details.
Parameters
----------
variation : str
TRI variation.
Returns
-------
kpoints : dict
High-symmetry points.
"""
if variation in ["TRI1a", "TRI2a"]:
return {
"G": np.array([0, 0, 0]),
"L": np.array([1 / 2, 1 / 2, 0]),
"M": np.array([0, 1 / 2, 1 / 2]),
"N": np.array([1 / 2, 0, 1 / 2]),
"R": np.array([1 / 2, 1 / 2, 1 / 2]),
"X": np.array([1 / 2, 0, 0]),
"Y": np.array([0, 1 / 2, 0]),
"Z": np.array([0, 0, 1 / 2]),
}
elif variation in ["TRI1b", "TRI2b"]:
return {
"G": np.array([0, 0, 0]),
"L": np.array([1 / 2, -1 / 2, 0]),
"M": np.array([0, 0, 1 / 2]),
"N": np.array([-1 / 2, -1 / 2, 1 / 2]),
"R": np.array([0, -1 / 2, 1 / 2]),
"X": np.array([0, -1 / 2, 0]),
"Y": np.array([1 / 2, 0, 0]),
"Z": np.array([-1 / 2, 0, 1 / 2]),
}