def _calculate_reciprocal_angles(self): self.alpha_ = acos( (cos(self.beta) * cos(self.gamma) - cos(self.alpha)) / (sin(self.beta) * sin(self.gamma))) self.beta_ = acos( (cos(self.alpha) * cos(self.gamma) - cos(self.beta)) / (sin(self.alpha) * sin(self.gamma))) self.gamma_ = acos( (cos(self.alpha) * cos(self.beta) - cos(self.gamma)) / (sin(self.alpha) * sin(self.beta)))
def testinterplanarangle_triclinic(self): lat = self.triclinic s11 = lat.b**2 * lat.c**2 * sin(lat.alpha)**2 s22 = lat.a**2 * lat.c**2 * sin(lat.beta)**2 s33 = lat.a**2 * lat.b**2 * sin(lat.gamma)**2 s12 = lat.a * lat.b * lat.c**2 * (cos(lat.alpha) * cos(lat.beta) - cos(lat.gamma)) s23 = lat.a**2 * lat.b * lat.c * (cos(lat.beta) * cos(lat.gamma) - cos(lat.alpha)) s13 = lat.a * lat.b**2 * lat.c * (cos(lat.gamma) * cos(lat.alpha) - cos(lat.beta)) v = lat.a * lat.b * lat.c * sqrt(1 - cos(lat.alpha) ** 2 - \ cos(lat.beta) ** 2 - \ cos(lat.gamma) ** 2 + \ 2 * cos(lat.alpha) * cos(lat.beta) * cos(lat.gamma)) equation = lambda lat, h1, k1, l1, h2, k2, l2: \ d1 * d2 / v ** 2 * (s11 * h1 * h2 + \ s22 * k1 * k2 + \ s33 * l1 * l2 + \ s23 * (k1 * l2 + k2 * l1) + \ s13 * (l1 * h2 + l2 * h1) + \ s12 * (h1 * k2 + h2 * k1)) for plane1 in self.planes: for plane2 in self.planes: d1 = calculations.planespacing(plane1, self.triclinic) d2 = calculations.planespacing(plane2, self.triclinic) angle = calculations.interplanarangle(plane1, plane2, self.triclinic) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.triclinic, *args)) self.assertAlmostEqual(angle, expected_angle, 6)
def testinterplanarangle_triclinic(self): lat = self.triclinic s11 = lat.b ** 2 * lat.c ** 2 * sin(lat.alpha) ** 2 s22 = lat.a ** 2 * lat.c ** 2 * sin(lat.beta) ** 2 s33 = lat.a ** 2 * lat.b ** 2 * sin(lat.gamma) ** 2 s12 = lat.a * lat.b * lat.c ** 2 * (cos(lat.alpha) * cos(lat.beta) - cos(lat.gamma)) s23 = lat.a ** 2 * lat.b * lat.c * (cos(lat.beta) * cos(lat.gamma) - cos(lat.alpha)) s13 = lat.a * lat.b ** 2 * lat.c * (cos(lat.gamma) * cos(lat.alpha) - cos(lat.beta)) v = lat.a * lat.b * lat.c * sqrt(1 - cos(lat.alpha) ** 2 - \ cos(lat.beta) ** 2 - \ cos(lat.gamma) ** 2 + \ 2 * cos(lat.alpha) * cos(lat.beta) * cos(lat.gamma)) equation = lambda lat, h1, k1, l1, h2, k2, l2: \ d1 * d2 / v ** 2 * (s11 * h1 * h2 + \ s22 * k1 * k2 + \ s33 * l1 * l2 + \ s23 * (k1 * l2 + k2 * l1) + \ s13 * (l1 * h2 + l2 * h1) + \ s12 * (h1 * k2 + h2 * k1)) for plane1 in self.planes: for plane2 in self.planes: d1 = calculations.planespacing(plane1, self.triclinic) d2 = calculations.planespacing(plane2, self.triclinic) angle = calculations.interplanarangle(plane1, plane2, self.triclinic) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.triclinic, *args)) self.assertAlmostEqual(angle, expected_angle, 6)
def zoneaxis_goniometricangles(zoneaxis, unitcell): """ Return the goniometric angles (:math:`\\phi` and :math:`\\rho`) for a zone axis of a given unit cell. :type zoneaxis: :class:`vectors.Vector3D` :type unitcell: :class:`unitcell.UnitCell` :return: (:math:`\\phi`, :math:`\\rho`) :rtype: :class:`tuple` **References** Example 2.20 from Mathematical Crystallography """ a = unitcell.cartesianmatrix # Change basis of zone axis (lattice basis) into the cartesian basis r_c = a * zoneaxis # Normalize r_c to have a unit length r_c.normalize() # Find phi and rho rho = acos(r_c[2]) phi = atan2(r_c[0], r_c[1]) return phi, rho
def facepole_goniometricangles(facepole, unitcell): """ Return the goniometric angles (:math:`\\phi` and :math:`\\rho`) for a face pole of a given unit cell. :type facepole: :class:`vectors.Vector3D` :type unitcell: :class:`unitcell.UnitCell` :return: (:math:`\\phi`, :math:`\\rho`) :rtype: :class:`tuple` **References** Example 2.20 from Mathematical Crystallography """ b = matrices.inverse(matrices.transpose(unitcell.cartesianmatrix)) # Change basis of face pole (reciprocal basis) into the cartesian basis s_c = b * facepole # Normalize r_c to have a unit length s_c.normalize() # Find phi and rho rho = acos(s_c[2]) phi = atan2(s_c[0], s_c[1]) return phi, rho
def testinterplanarangle_cubic(self): equation = lambda h1, k1, l1, h2, k2, l2: \ (h1 * h2 + k1 * k2 + l1 * l2) / \ sqrt((h1 ** 2 + k1 ** 2 + l1 ** 2) * (h2 ** 2 + k2 ** 2 + l2 ** 2)) for plane1 in self.planes: for plane2 in self.planes: angle = calculations.interplanarangle(plane1, plane2, self.cubic) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(*args)) self.assertAlmostEqual(angle, expected_angle)
def testinterplanarangle_tetragonal(self): equation = lambda lat, h1, k1, l1, h2, k2, l2: \ ((h1 * h2 + k1 * k2) / lat.a ** 2 + l1 * l2 / lat.c ** 2) / \ sqrt(((h1 ** 2 + k1 ** 2) / lat.a ** 2 + l1 ** 2 / lat.c ** 2) * \ ((h2 ** 2 + k2 ** 2) / lat.a ** 2 + l2 ** 2 / lat.c ** 2)) for plane1 in self.planes: for plane2 in self.planes: angle = calculations.interplanarangle(plane1, plane2, self.tetragonal) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.tetragonal, *args)) self.assertAlmostEqual(angle, expected_angle)
def angle(v1, v2): """ Return the angle in radians between *v1* and *v2*. :arg v1: the first vector :type v1: :class:`vectors.Vector` :arg v2: the second vector :type v2: :class:`vectors.Vector` :return: angle in radians :rtype: :class:`float` """ costheta = directioncosine(v1, v2) return acos(costheta)
def testinterplanarangle_hexagonal(self): equation = lambda lat, h1, k1, l1, h2, k2, l2: \ (h1 * h2 + k1 * k2 + 0.5 * (h1 * k2 + h2 * k1) + \ (3 * lat.a ** 2) / (4 * lat.c ** 2) * l1 * l2) / \ sqrt((h1 ** 2 + k1 ** 2 + h1 * k1 + (3 * lat.a ** 2) / \ (4 * lat.c ** 2) * l1 ** 2) * \ (h2 ** 2 + k2 ** 2 + h2 * k2 + (3 * lat.a ** 2) / \ (4 * lat.c ** 2) * l2 ** 2)) for plane1 in self.planes: for plane2 in self.planes: angle = calculations.interplanarangle(plane1, plane2, self.hexagonal) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.hexagonal, *args)) self.assertAlmostEqual(angle, expected_angle)
def testinterplanarangle_monoclinic(self): equation = lambda lat, h1, k1, l1, h2, k2, l2: \ d1 * d2 / sin(lat.beta) ** 2 * \ (h1 * h2 / lat.a ** 2 + \ k1 * k2 * sin(lat.beta) ** 2 / lat.b ** 2 + \ l1 * l2 / lat.c ** 2 - \ (l1 * h2 + l2 * h1) * cos(lat.beta) / (lat.a * lat.c)) for plane1 in self.planes: for plane2 in self.planes: d1 = calculations.planespacing(plane1, self.monoclinic) d2 = calculations.planespacing(plane2, self.monoclinic) angle = calculations.interplanarangle(plane1, plane2, self.monoclinic) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.monoclinic, *args)) self.assertAlmostEqual(angle, expected_angle, 6)
def testinterplanarangle_orthorhombic(self): equation = lambda lat, h1, k1, l1, h2, k2, l2: \ (h1 * h2 / lat.a ** 2 + k1 * k2 / lat.b ** 2 + l1 * l2 / lat.c ** 2) / \ sqrt((h1 ** 2 / lat.a ** 2 + \ k1 ** 2 / lat.b ** 2 + \ l1 ** 2 / lat.c ** 2) \ * (h2 ** 2 / lat.a ** 2 + \ k2 ** 2 / lat.b ** 2 + \ l2 ** 2 / lat.c ** 2)) for plane1 in self.planes: for plane2 in self.planes: angle = calculations.interplanarangle(plane1, plane2, self.orthorhombic) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.orthorhombic, *args)) self.assertAlmostEqual(angle, expected_angle, 6)
def bondangle(atom1, atom2, atom3, unitcell): """ Calculate the bond angle (in radians) between the vector from *atom1* to *atom2* and the vector from *atom1* to *atom3*. :type atom1: :class:`atomsite.AtomSite` :type atom2: :class:`atomsite.AtomSite` :type atom3: :class:`atomsite.AtomSite` :type unitcell: :class:`unitcell.UnitCell` :rtype: :class:`float` **References** Equation 1.13 from Mathematical Crystallography """ atom1vector = atom1.position atom2vector = atom2.position atom3vector = atom3.position metricalmatrix = unitcell.metricalmatrix # Interatom vectors vector12 = atom2vector - atom1vector vector13 = atom3vector - atom1vector # Dot product dotproduct = vector12 * (metricalmatrix * vector13) # Bond distance bonddistance12 = bonddistance(atom1, atom2, unitcell) bonddistance13 = bonddistance(atom1, atom3, unitcell) # Cosine cosine = dotproduct / (bonddistance12 * bonddistance13) # Angle angle = acos(cosine) return angle
def testinterplanarangle_trigonal(self): lat = self.trigonal v = lat.a ** 3 * sqrt(1 - 3 * cos(lat.alpha) ** 2 + 2 * cos(lat.alpha) ** 3) equation = lambda lat, h1, k1, l1, h2, k2, l2: \ (lat.a ** 4 * d1 * d2) / v ** 2 * \ (sin(lat.alpha) ** 2 * (h1 * h2 + k1 * k2 + l1 * l2) + \ (cos(lat.alpha) ** 2 - cos(lat.alpha)) * \ (k1 * l2 + k2 * l1 + l1 * h2 + l2 * h1 + h1 * k2 + h2 * k1)) for plane1 in self.planes: for plane2 in self.planes: d1 = calculations.planespacing(plane1, lat) d2 = calculations.planespacing(plane2, lat) angle = calculations.interplanarangle(plane1, plane2, self.trigonal) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.trigonal, *args)) self.assertAlmostEqual(angle, expected_angle, 6)
def testinterplanarangle_trigonal(self): lat = self.trigonal v = lat.a**3 * sqrt(1 - 3 * cos(lat.alpha)**2 + 2 * cos(lat.alpha)**3) equation = lambda lat, h1, k1, l1, h2, k2, l2: \ (lat.a ** 4 * d1 * d2) / v ** 2 * \ (sin(lat.alpha) ** 2 * (h1 * h2 + k1 * k2 + l1 * l2) + \ (cos(lat.alpha) ** 2 - cos(lat.alpha)) * \ (k1 * l2 + k2 * l1 + l1 * h2 + l2 * h1 + h1 * k2 + h2 * k1)) for plane1 in self.planes: for plane2 in self.planes: d1 = calculations.planespacing(plane1, lat) d2 = calculations.planespacing(plane2, lat) angle = calculations.interplanarangle(plane1, plane2, self.trigonal) args = copy.deepcopy(plane1) args.extend(plane2) expected_angle = acos(equation(self.trigonal, *args)) self.assertAlmostEqual(angle, expected_angle, 6)
def _calculate_reciprocal_angles(self): self.alpha_ = acos((cos(self.beta) * cos(self.gamma) - cos(self.alpha)) / (sin(self.beta) * sin(self.gamma))) self.beta_ = acos((cos(self.alpha) * cos(self.gamma) - cos(self.beta)) / (sin(self.alpha) * sin(self.gamma))) self.gamma_ = acos((cos(self.alpha) * cos(self.beta) - cos(self.gamma)) / (sin(self.alpha) * sin(self.beta)))
def testacos(self): self.assertEqual(trigo.acos(4), 0) self.assertEqual(trigo.acos(-4), pi) self.assertAlmostEqual(trigo.acos(0.5), 60 / 180.0 * pi) self.assertAlmostEqual(trigo.acos(0.45675), acos(0.45675))