Esempio n. 1
0
def niggli_to_lengths_and_angles(niggli_matrix):
    niggli_matrix = FracVector.use(niggli_matrix)

    pi = niggli_matrix.pi()

    s11, s22, s33 = niggli_matrix[0][0], niggli_matrix[0][1], niggli_matrix[0][
        2]
    s23, s13, s12 = niggli_matrix[1][0] / 2, niggli_matrix[1][
        1] / 2, niggli_matrix[1][2] / 2

    a, b, c = vectormath.sqrt(s11), vectormath.sqrt(s22), vectormath.sqrt(s33)
    alpha, beta, gamma = vectormath.acos(
        s23 / (b * c)) * 180 / pi, vectormath.acos(
            s13 / (c * a)) * 180 / pi, vectormath.acos(s12 /
                                                       (a * b)) * 180 / pi

    return [a, b, c], [alpha, beta, gamma]
Esempio n. 2
0
def niggli_scale_to_vol(niggli_matrix, scale):
    niggli_matrix = FracVector.use(niggli_matrix)
    metric = niggli_to_metric(niggli_matrix)
    volsqr = metric.det()
    if volsqr == 0:
        raise Exception("niggli_vol_to_scale: singular cell matrix.")
    det = vectormath.sqrt(float(volsqr))
    if abs(det) < 1e-12:
        raise Exception("niggli_scale_to_vol: singular cell matrix.")
    return (((scale)**3) * det)
Esempio n. 3
0
def lengths_and_cosangles_to_conventional_basis(lengths,
                                                cosangles,
                                                lattice_system=None,
                                                orientation=1,
                                                eps=0):
    """
    Returns the conventional cell basis given a list of lengths and cosine of angles

    Note: if your basis vector order does not follow the conventions for hexagonal and monoclinic cells,
    you get the triclinic conventional cell.

    Conventions: in hexagonal cell gamma=120 degrees, i.e, cosangles[2]=-1/2, in monoclinic cells beta =/= 90 degrees.
    """
    if lattice_system is None:
        lattice_system = lattice_system_from_lengths_and_cosangles(
            lengths, cosangles)

    a, b, c = lengths
    cosalpha, cosbeta, cosgamma = cosangles
    #sinalpha = vectormath.sqrt(1-cosalpha**2)
    sinbeta = vectormath.sqrt(1 - cosbeta**2)
    singamma = vectormath.sqrt(1 - cosgamma**2)

    basis = None

    if lattice_system == 'cubic' or lattice_system == 'tetragonal' or lattice_system == 'orthorhombic':
        basis = FracVector.create([[a, 0, 0], [0, b, 0], [0, 0, c]
                                   ]) * orientation

    elif lattice_system == 'hexagonal':
        #basis = FracVector.create([[singamma*a, a*cosgamma, 0],
        #                           [0, b, 0],
        #                           [0, 0, c]])*orientation
        basis = FracVector.create([[a, 0, 0], [cosgamma * b, b * singamma, 0],
                                   [0, 0, c]]) * orientation

    elif lattice_system == 'monoclinic':
        basis = FracVector.create([[a, 0, 0], [0, b, 0],
                                   [c * cosbeta, 0, c * sinbeta]
                                   ]) * orientation

    elif lattice_system == 'rhombohedral':
        vc = cosalpha
        tx = vectormath.sqrt((1 - vc) / 2.0)
        ty = vectormath.sqrt((1 - vc) / 6.0)
        tz = vectormath.sqrt((1 + 2 * vc) / 3.0)
        basis = FracVector.create([[2 * a * ty, 0, a * tz],
                                   [-b * ty, b * tx, b * tz],
                                   [-c * ty, -c * tx, c * tz]]) * orientation
    else:
        angfac1 = (cosalpha - cosbeta * cosgamma) / singamma
        angfac2 = vectormath.sqrt(singamma**2 - cosbeta**2 - cosalpha**2 +
                                  2 * cosalpha * cosbeta * cosgamma) / singamma
        basis = FracVector.create([[a, 0, 0], [b * cosgamma, b * singamma, 0],
                                   [c * cosbeta, c * angfac1, c * angfac2]
                                   ]) * orientation
    return basis
Esempio n. 4
0
def niggli_to_lengths_and_trigangles(niggli_matrix):
    niggli_matrix = FracVector.use(niggli_matrix)

    s11, s22, s33 = niggli_matrix[0][0], niggli_matrix[0][1], niggli_matrix[0][
        2]
    s23, s13, s12 = niggli_matrix[1][0] / 2, niggli_matrix[1][
        1] / 2, niggli_matrix[1][2] / 2

    a, b, c = vectormath.sqrt(s11), vectormath.sqrt(s22), vectormath.sqrt(s33)
    cosalpha, cosbeta, cosgamma = s23 / (b * c), s13 / (c * a), s12 / (a * b)
    sinalpha, sinbeta, singamma = vectormath.sqrt(
        1 - cosalpha), vectormath.sqrt(1 - cosbeta), vectormath.sqrt(1 -
                                                                     cosgamma)

    return [a, b, c], [cosalpha, cosbeta,
                       cosgamma], [sinalpha, sinbeta, singamma]
Esempio n. 5
0
def niggli_to_basis(niggli_matrix, orientation=1):
    #cell = FracVector.use(niggli_matrix)
    niggli_matrix = niggli_matrix.to_floats()

    s11, s22, s33 = niggli_matrix[0][0], niggli_matrix[0][1], niggli_matrix[0][
        2]
    s23, s13, s12 = niggli_matrix[1][0] / 2.0, niggli_matrix[1][
        1] / 2.0, niggli_matrix[1][2] / 2.0

    a, b, c = vectormath.sqrt(s11), vectormath.sqrt(s22), vectormath.sqrt(s33)
    alpha_rad, beta_rad, gamma_rad = vectormath.acos(
        s23 / (b * c)), vectormath.acos(s13 / (c * a)), vectormath.acos(
            s12 / (a * b))

    iv = 1 - vectormath.cos(alpha_rad)**2 - vectormath.cos(
        beta_rad)**2 - vectormath.cos(gamma_rad)**2 + 2 * vectormath.cos(
            alpha_rad) * vectormath.cos(beta_rad) * vectormath.cos(gamma_rad)

    # Handle that iv may be very, very slightly < 0 by the floating point accuracy limit
    if iv > 0:
        v = vectormath.sqrt(iv)
    else:
        v = 0.0

    if c * v < 1e-14:
        raise Exception(
            "niggli_to_cell: Physically unreasonable cell, cell vectors degenerate or very close to degenerate."
        )

    if orientation < 0:
        basis = [[-a, 0.0, 0.0],
                 [
                     -b * vectormath.cos(gamma_rad),
                     -b * vectormath.sin(gamma_rad), 0.0
                 ],
                 [
                     -c * vectormath.cos(beta_rad), -c *
                     (vectormath.cos(alpha_rad) -
                      vectormath.cos(beta_rad) * vectormath.cos(gamma_rad)) /
                     vectormath.sin(gamma_rad),
                     -c * v / vectormath.sin(gamma_rad)
                 ]]
    else:
        basis = [[a, 0.0, 0.0],
                 [
                     b * vectormath.cos(gamma_rad),
                     b * vectormath.sin(gamma_rad), 0.0
                 ],
                 [
                     c * vectormath.cos(beta_rad), c *
                     (vectormath.cos(alpha_rad) -
                      vectormath.cos(beta_rad) * vectormath.cos(gamma_rad)) /
                     vectormath.sin(gamma_rad),
                     c * v / vectormath.sin(gamma_rad)
                 ]]

    for i in range(3):
        for j in range(3):
            basis[i][j] = round(basis[i][j], 14)

    return basis
Esempio n. 6
0
def niggli_to_conventional_basis(niggli_matrix,
                                 lattice_system=None,
                                 orientation=1,
                                 eps=1e-4):
    """
    Returns the conventional cell given a niggli_matrix

    Note: if your basis vector order does not follow the conventions for hexagonal and monoclinic cells,
    you get the triclinic conventional cell.

    Conventions: in hexagonal cell gamma=120 degrees., in monoclinic cells beta =/= 90 degrees.
    """
    if lattice_system is None:
        lattice_system = lattice_system_from_niggli(niggli_matrix)

    niggli_matrix = niggli_matrix.to_floats()

    s11, s22, s33 = niggli_matrix[0][0], niggli_matrix[0][1], niggli_matrix[0][
        2]
    s23, s13, s12 = niggli_matrix[1][0] / 2.0, niggli_matrix[1][
        1] / 2.0, niggli_matrix[1][2] / 2.0

    a, b, c = vectormath.sqrt(s11), vectormath.sqrt(s22), vectormath.sqrt(s33)
    alphar, betar, gammar = vectormath.acos(s23 / (b * c)), vectormath.acos(
        s13 / (c * a)), vectormath.acos(s12 / (a * b))

    basis = None

    if lattice_system == 'cubic' or lattice_system == 'tetragonal' or lattice_system == 'orthorhombic':
        basis = FracVector.create([[a, 0, 0], [0, b, 0], [0, 0, c]
                                   ]) * orientation

    elif lattice_system == 'hexagonal':
        basis = FracVector.create(
            [[a, 0, 0], [-0.5 * b, b * vectormath.sqrt(3.0) / 2.0, 0],
             [0, 0, c]]) * orientation

    elif lattice_system == 'monoclinic':
        basis = FracVector.create([
            [a, 0, 0], [0, b, 0],
            [c * vectormath.cos(gammar), 0, c * vectormath.sin(gammar)]
        ]) * orientation

    elif lattice_system == 'rhombohedral':
        vc = vectormath.cos(alphar)
        tx = vectormath.sqrt((1 - vc) / 2.0)
        ty = vectormath.sqrt((1 - vc) / 6.0)
        tz = vectormath.sqrt((1 + 2 * vc) / 3.0)
        basis = FracVector.create([[2 * a * ty, 0, a * tz],
                                   [-b * ty, b * tx, b * tz],
                                   [-c * ty, -c * tx, c * tz]]) * orientation
    else:
        angfac1 = (vectormath.cos(alphar) - vectormath.cos(betar) *
                   vectormath.cos(gammar)) / vectormath.sin(gammar)
        angfac2 = vectormath.sqrt(
            vectormath.sin(gammar)**2 - vectormath.cos(betar)**2 -
            vectormath.cos(alphar)**2 +
            2 * vectormath.cos(alphar) * vectormath.cos(betar) *
            vectormath.cos(gammar)) / vectormath.sin(gammar)
        basis = FracVector.create([
            [a, 0, 0],
            [b * vectormath.cos(gammar), b * vectormath.sin(gammar), 0],
            [c * vectormath.cos(betar), c * angfac1, c * angfac2]
        ]) * orientation
    return basis