def GetGdirOutofplane(coords1,
                      coords2,
                      coords3,
                      coords4,
                      oop,
                      r_31=None,
                      r_32=None,
                      r_34=None):
    """Calculate direction of energy gradients between outofplane atoms.
  
  Args:
    coords1 (float*): 3 cartesian coordinates [Angstrom] of atom1.
    coords2 (float*): 3 cartesian coordinates [Angstrom] of atom2.
    coords3 (float*): 3 cartesian coordinates [Angstrom] of atom3.
    coords4 (float*): 3 cartesian coordinates [Angstrom] of atom4.
    oop (float): Out-of-plane angles bewteen atoms 1, 2, 3, and 4.
    r_31 (float): Distance between atom3 and atom1 (default None).
    r_32 (float): Distance between atom3 and atom2 (default None).
    r_34 (float): Distance between atom3 and atom4 (default None).
  
  Returns:
    gdir1 (float*), gdir2 (float*), gdir3 (float*), gdir4 (float*): Vectors in
        the direction of max increasing outofplane angle.
  """
    if r_31 is not None:
        r_31 = geomcalc.GetRij(coords3, coords1)
    if r_32 is not None:
        r_32 = geomcalc.GetRij(coords3, coords2)
    if r_34 is not None:
        r_34 = geomcalc.GetRij(coords3, coords4)
    u_31 = geomcalc.GetUij(coords3, coords1, r_31)
    u_32 = geomcalc.GetUij(coords3, coords2, r_32)
    u_34 = geomcalc.GetUij(coords3, coords4, r_34)
    cp_3234 = geomcalc.GetCp(u_32, u_34)
    cp_3431 = geomcalc.GetCp(u_34, u_31)
    cp_3132 = geomcalc.GetCp(u_31, u_32)
    a_132 = geomcalc.GetAijk(coords1, coords3, coords2)
    s_132 = math.sin(const.DEG2RAD * a_132)
    c_132 = math.cos(const.DEG2RAD * a_132)
    c_oop = math.cos(const.DEG2RAD * oop)
    t_oop = math.tan(const.DEG2RAD * oop)
    gdir1 = ((1.0 / r_31) * (cp_3234 / (c_oop * s_132) - (t_oop / s_132**2) *
                             (u_31 - c_132 * u_32)))
    gdir2 = ((1.0 / r_32) * (cp_3431 / (c_oop * s_132) - (t_oop / s_132**2) *
                             (u_32 - c_132 * u_31)))
    gdir4 = ((1.0 / r_34) * (cp_3132 / (c_oop * s_132) - (t_oop * u_34)))
    gdir3 = -1.0 * (gdir1 + gdir2 + gdir4)
    return gdir1, gdir2, gdir3, gdir4
 def testAntiReflexive(self):
     """Asserts opposite value with inverted input order."""
     params = ARBITRARY_XYZ2, ARBITRARY_XYZ1
     self.assertListAlmostEqual(geomcalc.GetCp(*params), CROSS_VECTOR_21)
 def testArbitrary(self):
     """Asserts correct value with two arbitrary unit vectors."""
     params = ARBITRARY_XYZ1, ARBITRARY_XYZ2
     self.assertListAlmostEqual(geomcalc.GetCp(*params), CROSS_VECTOR_12)
 def testInPlaneYZ(self):
     """Asserts x-axis as result of two xz-plane vectors."""
     params = ARBITRARY_YZ1, ARBITRARY_YZ2
     self.assertListAlmostEqual(geomcalc.GetCp(*params), CROSS_VECTOR_YZ12)
 def testInPlaneXY(self):
     """Asserts z-axis as result of two xy-plane vectors."""
     params = ARBITRARY_XY1, ARBITRARY_XY2
     self.assertListAlmostEqual(geomcalc.GetCp(*params), CROSS_VECTOR_XY12)
 def testUnitZX(self):
     """Asserts positive y-axis as result of z-axis and x-axis cross."""
     params = POSITIVE_UNIT_Z, POSITIVE_UNIT_X
     self.assertListAlmostEqual(geomcalc.GetCp(*params), POSITIVE_UNIT_Y)
 def testUnitYX(self):
     """Asserts negative z-axis as result of y-axis and x-axis cross."""
     params = POSITIVE_UNIT_Y, POSITIVE_UNIT_X
     self.assertListAlmostEqual(geomcalc.GetCp(*params), NEGATIVE_UNIT_Z)
 def testZeroVector(self):
     """Asserts zero vector result for zero vector input."""
     params = ORIGIN, ARBITRARY_XYZ1
     self.assertListAlmostEqual(geomcalc.GetCp(*params), ORIGIN)