def test_abs_cap(self): self.assertEqual(abs_cap(1.000000001), 1.0) self.assertEqual(abs_cap(-1.000000001), -1.0) v = random.uniform(-1, 1) self.assertEqual(abs_cap(v), v) self.assertEqual(abs_cap(1.000000001, 2), 1.000000001) self.assertEqual(abs_cap(-2.000000001, 2), -2.0)
def __init__(self, matrix): """ Create a lattice from any sequence of 9 numbers. Note that the sequence is assumed to be read one row at a time. Each row represents one lattice vector. Args: matrix: Sequence of numbers in any form. Examples of acceptable input. i) An actual numpy array. ii) [[1, 0, 0], [0, 1, 0], [0, 0, 1]] iii) [1, 0, 0 , 0, 1, 0, 0, 0, 1] iv) (1, 0, 0, 0, 1, 0, 0, 0, 1) Each row should correspond to a lattice vector. E.g., [[10, 0, 0], [20, 10, 0], [0, 0, 30]] specifies a lattice with lattice vectors [10, 0, 0], [20, 10, 0] and [0, 0, 30]. """ m = np.array(matrix, dtype=np.float64).reshape((3, 3)) lengths = np.sqrt(np.sum(m**2, axis=1)) angles = np.zeros(3) for i in range(3): j = (i + 1) % 3 k = (i + 2) % 3 angles[i] = abs_cap(dot(m[j], m[k]) / (lengths[j] * lengths[k])) self._angles = np.arccos(angles) * 180. / pi self._lengths = lengths self._matrix = m self._inv_matrix = None self._metric_tensor = None self._diags = None self._lll_matrix_mappings = {} self._lll_inverse = None self.is_orthogonal = all([abs(a - 90) < 1e-5 for a in self._angles])
def from_parameters(a, b, c, alpha, beta, gamma): """ Create a Lattice using unit cell lengths and angles (in degrees). Args: a (float): *a* lattice parameter. b (float): *b* lattice parameter. c (float): *c* lattice parameter. alpha (float): *alpha* angle in degrees. beta (float): *beta* angle in degrees. gamma (float): *gamma* angle in degrees. Returns: Lattice with the specified lattice parameters. """ alpha_r = radians(alpha) beta_r = radians(beta) gamma_r = radians(gamma) val = (np.cos(alpha_r) * np.cos(beta_r) - np.cos(gamma_r))\ / (np.sin(alpha_r) * np.sin(beta_r)) # Sometimes rounding errors result in values slightly > 1. val = abs_cap(val) gamma_star = np.arccos(val) vector_a = [a * np.sin(beta_r), 0.0, a * np.cos(beta_r)] vector_b = [ -b * np.sin(alpha_r) * np.cos(gamma_star), b * np.sin(alpha_r) * np.sin(gamma_star), b * np.cos(alpha_r) ] vector_c = [0.0, 0.0, float(c)] return Lattice([vector_a, vector_b, vector_c])
def __init__(self, matrix): """ Create a lattice from any sequence of 9 numbers. Note that the sequence is assumed to be read one row at a time. Each row represents one lattice vector. Args: matrix: Sequence of numbers in any form. Examples of acceptable input. i) An actual numpy array. ii) [[1, 0, 0], [0, 1, 0], [0, 0, 1]] iii) [1, 0, 0 , 0, 1, 0, 0, 0, 1] iv) (1, 0, 0, 0, 1, 0, 0, 0, 1) Each row should correspond to a lattice vector. E.g., [[10, 0, 0], [20, 10, 0], [0, 0, 30]] specifies a lattice with lattice vectors [10, 0, 0], [20, 10, 0] and [0, 0, 30]. """ m = np.array(matrix, dtype=np.float64).reshape((3, 3)) lengths = np.sqrt(np.sum(m ** 2, axis=1)) angles = np.zeros(3) for i in range(3): j = (i + 1) % 3 k = (i + 2) % 3 angles[i] = abs_cap(dot(m[j], m[k]) / (lengths[j] * lengths[k])) self._angles = np.arccos(angles) * 180. / pi self._lengths = lengths self._matrix = m self._inv_matrix = None self._metric_tensor = None self._diags = None self._lll_matrix_mappings = {} self._lll_inverse = None self.is_orthogonal = all([abs(a - 90) < 1e-5 for a in self._angles])
def from_parameters(a, b, c, alpha, beta, gamma): """ Create a Lattice using unit cell lengths and angles (in degrees). Args: a (float): *a* lattice parameter. b (float): *b* lattice parameter. c (float): *c* lattice parameter. alpha (float): *alpha* angle in degrees. beta (float): *beta* angle in degrees. gamma (float): *gamma* angle in degrees. Returns: Lattice with the specified lattice parameters. """ alpha_r = radians(alpha) beta_r = radians(beta) gamma_r = radians(gamma) val = (np.cos(alpha_r) * np.cos(beta_r) - np.cos(gamma_r))\ / (np.sin(alpha_r) * np.sin(beta_r)) # Sometimes rounding errors result in values slightly > 1. val = abs_cap(val) gamma_star = np.arccos(val) vector_a = [a * np.sin(beta_r), 0.0, a * np.cos(beta_r)] vector_b = [-b * np.sin(alpha_r) * np.cos(gamma_star), b * np.sin(alpha_r) * np.sin(gamma_star), b * np.cos(alpha_r)] vector_c = [0.0, 0.0, float(c)] return Lattice([vector_a, vector_b, vector_c])
def set_matrix(self,matrix): ''' Set the values of the matrix of lattice vectors and reset lengths and angles accordingly Args: matrix (list) of length n_dim x n_dim ''' m = np.array(matrix, dtype=np.float64).reshape((self.n_dim, self.n_dim)) lengths = np.sqrt(np.sum(m ** 2, axis=1)) angles = np.zeros(self.n_dim) for i in range(self.n_dim): j = (i + 1) % self.n_dim k = (i + 2) % self.n_dim angles[i] = abs_cap(dot(m[j], m[k]) / (lengths[j] * lengths[k])) self._angles = np.arccos(angles) * 180. / pi self._lengths = lengths self._matrix = m self._inv_matrix = None self._metric_tensor = None self._diags = None self._lll_matrix_mappings = {} self._lll_inverse = None self.is_orthogonal = all([abs(a - 90) < 1e-5 for a in self._angles])
def from_parameters( a: float, b: float, c: float, alpha: float, beta: float, gamma: float, vesta: bool = False, ): """ Create a Lattice using unit cell lengths and angles (in degrees). Args: a (float): *a* lattice parameter. b (float): *b* lattice parameter. c (float): *c* lattice parameter. alpha (float): *alpha* angle in degrees. beta (float): *beta* angle in degrees. gamma (float): *gamma* angle in degrees. vesta: True if you import Cartesian coordinates from VESTA. Returns: Lattice with the specified lattice parameters. """ alpha_r = radians(alpha) beta_r = radians(beta) gamma_r = radians(gamma) if vesta: cos_alpha = np.cos(alpha_r) cos_beta = np.cos(beta_r) cos_gamma = np.cos(gamma_r) sin_gamma = np.sin(gamma_r) c1 = c * cos_beta c2 = (c * (cos_alpha - (cos_beta * cos_gamma))) / sin_gamma vector_a = [float(a), 0.0, 0.0] vector_b = [b * cos_gamma, b * sin_gamma, 0] vector_c = [c1, c2, math.sqrt(c ** 2 - c1 ** 2 - c2 ** 2)] else: val = (np.cos(alpha_r) * np.cos(beta_r) - np.cos(gamma_r)) / ( np.sin(alpha_r) * np.sin(beta_r) ) # Sometimes rounding errors result in values slightly > 1. val = abs_cap(val) gamma_star = np.arccos(val) vector_a = [a * np.sin(beta_r), 0.0, a * np.cos(beta_r)] vector_b = [ -b * np.sin(alpha_r) * np.cos(gamma_star), b * np.sin(alpha_r) * np.sin(gamma_star), b * np.cos(alpha_r), ] vector_c = [0.0, 0.0, float(c)] return Lattice([vector_a, vector_b, vector_c])
def from_parameters( a: float, b: float, c: float, alpha: float, beta: float, gamma: float, vesta: bool = False, ): """ Create a Lattice using unit cell lengths and angles (in degrees). Args: a (float): *a* lattice parameter. b (float): *b* lattice parameter. c (float): *c* lattice parameter. alpha (float): *alpha* angle in degrees. beta (float): *beta* angle in degrees. gamma (float): *gamma* angle in degrees. vesta: True if you import Cartesian coordinates from VESTA. Returns: Lattice with the specified lattice parameters. """ alpha_r = radians(alpha) beta_r = radians(beta) gamma_r = radians(gamma) if vesta: cos_alpha = np.cos(alpha_r) cos_beta = np.cos(beta_r) cos_gamma = np.cos(gamma_r) sin_gamma = np.sin(gamma_r) c1 = c * cos_beta c2 = (c * (cos_alpha - (cos_beta * cos_gamma))) / sin_gamma vector_a = [float(a), 0.0, 0.0] vector_b = [b * cos_gamma, b * sin_gamma, 0] vector_c = [c1, c2, math.sqrt(c**2 - c1**2 - c2**2)] else: val = (np.cos(alpha_r) * np.cos(beta_r) - np.cos(gamma_r)) / (np.sin(alpha_r) * np.sin(beta_r)) # Sometimes rounding errors result in values slightly > 1. val = abs_cap(val) gamma_star = np.arccos(val) vector_a = [a * np.sin(beta_r), 0.0, a * np.cos(beta_r)] vector_b = [ -b * np.sin(alpha_r) * np.cos(gamma_star), b * np.sin(alpha_r) * np.sin(gamma_star), b * np.cos(alpha_r), ] vector_c = [0.0, 0.0, float(c)] return Lattice([vector_a, vector_b, vector_c])
def get_angles(matrix, lengths=None): """Returns the angles (alpha, beta, gamma) of the lattice.""" if lengths is not None: lengths = get_lengths(matrix) m = matrix angles = np.zeros(3) for i in range(3): j = (i + 1) % 3 k = (i + 2) % 3 angles[i] = abs_cap(dot(m[j], m[k]) / (lengths[j] * lengths[k])) angles = np.arccos(angles) * 180.0 / pi return tuple(angles.tolist()) # type: ignore
def angles(self) -> Tuple[float]: """ Returns the angles (alpha, beta, gamma) of the lattice. """ m = self._matrix lengths = self.lengths angles = np.zeros(3) for i in range(3): j = (i + 1) % 3 k = (i + 2) % 3 angles[i] = abs_cap(dot(m[j], m[k]) / (lengths[j] * lengths[k])) angles = np.arccos(angles) * 180.0 / pi return tuple(angles.tolist())
def solid_angle(center, coords): """ Helper method to calculate the solid angle of a set of coords from the center. Args: center (3x1 array): Center to measure solid angle from. coords (Nx3 array): List of coords to determine solid angle. Returns: The solid angle. """ o = np.array(center) r = [np.array(c) - o for c in coords] r.append(r[0]) n = [np.cross(r[i + 1], r[i]) for i in range(len(r) - 1)] n.append(np.cross(r[1], r[0])) vals = [] for i in range(len(n) - 1): v = -np.dot(n[i], n[i + 1]) \ / (np.linalg.norm(n[i]) * np.linalg.norm(n[i + 1])) vals.append(acos(abs_cap(v))) phi = sum(vals) return phi + (3 - len(r)) * pi