コード例 #1
0
def cell_to_basis(cell):
    if cell is None:
        raise Exception("cell_to_basis: bad cell specification.")

    try:
        return cell.basis
    except AttributeError:
        pass

    if isinstance(cell, dict):
        if 'niggli_matrix' in cell:
            niggli_matrix = FracVector.use(cell['niggli_matrix'])
            if 'orientation' in cell:
                orientation = cell['orientation']
            else:
                orientation = 1
            basis = FracVector.use(
                niggli_to_basis(niggli_matrix, orientation=orientation))
        elif 'a' in cell:
            lengths = FracVector.create((cell['a'], cell['b'], cell['c']))
            cosangles = FracVector.create_cos(
                (cell['a'], cell['b'], cell['c']), degrees=True)
            basis = lengths_and_cosangles_to_conventional_basis(
                lengths, cosangles)
            #niggli_matrix = lengths_cosangles_to_niggli(lengths,cosangles)
            #basis = FracVector.use(niggli_to_basis(niggli_matrix, orientation=1))
    else:
        basis = FracVector.use(cell)

    return basis
コード例 #2
0
def niggli_to_metric(niggli):
    niggli = FracVector.use(niggli)

    m = niggli.noms

    # Since the niggli matrix contains 2*the product of the off diagonal elements, we increase the denominator by cell.denom*2
    return FracVector(
        ((2 * m[0][0], m[1][2], m[1][1]), (m[1][2], 2 * m[0][1], m[1][0]),
         (m[1][1], m[1][0], 2 * m[0][2])), niggli.denom * 2).simplify()
コード例 #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
コード例 #4
0
def simplex_le_solver(a, b, c):
    """
    Minimizie func = a[0]*x + a[1]*y + a[2]*z + ...
    With constraints::

        b[0,0]x + b[0,1]y + b[0,2]z + ... <= c[0]
        b[1,0]x + b[1,1]y + b[1,2]z + ... <= c[1]
        ...
        x,y,z, ... >= 0

    Algorithm adapted from 'taw9', http://taw9.hubpages.com/hub/Simplex-Algorithm-in-Python

    """
    Na = len(a)
    Nc = len(c)
    obj = a.get_insert(0, 1)
    M = []
    for i in range(Nc):
        obj = obj.get_append(0)
        ident = [0] * Nc
        ident[i] = 1
        M += [b[i].get_insert(0, 0).get_extend(ident).get_append(c[i])]
    M = MutableFracVector.create(M)
    obj = obj.get_append(0)
    base = list(range(Na, Na + Nc))

    while not min(obj[1:-1]) >= 0:
        pivot_col = obj[1:-1].argmin() + 1
        rhs = M[:, -1]
        lhs = M[:, pivot_col]

        nonzero = [i for i in range(len(rhs)) if lhs[i] != 0]
        pivot_row = min(nonzero, key=lambda i: rhs[i] / lhs[i])

        M[pivot_row] = (M[pivot_row] / (M[pivot_row][pivot_col])).simplify()
        for i in range(Nc):
            if i == pivot_row:
                continue
            M[i] = (M[i] - M[i][pivot_col] * M[pivot_row]).simplify()
        obj = (obj - obj[pivot_col] * M[pivot_row]).simplify()
        base[pivot_row] = pivot_col - 1

    solution = [0] * Na
    for j in range(Nc):
        if obj[base[j] + 1] == 0 and base[j] < Na:
            solution[base[j]] = M[j][-1].simplify()

    return FracVector.create(-obj[-1]), FracVector.create(solution)
コード例 #5
0
def trivial_symmetry_reduce(coordgroups):
    """
    Looks for 'trivial' ways to reduce the coordinates in the given coordgroups by a standard set of symmetry operations.
    This is not a symmetry finder (and it is not intended to be), but for a standard primitive cell taken from a standard
    conventional cell, it reverses the primitive unit cell coordgroups into the symmetry reduced coordgroups.
    """
    # TODO: Actually implement, instead of this placeholder that just gives up and returns P 1

    symops = []
    symopvs = []
    for symop in all_symops:
        symopv = FracVector.create(symop)
        if check_symop(coordgroups, symopv):
            symops += [all_symops[symop]]
            symopvs += [symopv]

    shash = symopshash(symops)
    if shash in symops_hash_index:
        hall_symbol = symops_hash_index[shash]
        rc_reduced_coordgroups, wyckoff_symbols, multiplicities = reduce_by_symops(coordgroups, symopvs, hall_symbol)
        return rc_reduced_coordgroups, hall_symbol, wyckoff_symbols, multiplicities

    rc_reduced_coordgroups = coordgroups
    hall_symbol = 'P 1'
    wyckoff_symbols = ['a']*sum([len(x) for x in coordgroups])
    multiplicities = [1]*sum([len(x) for x in coordgroups])

    return rc_reduced_coordgroups, hall_symbol, wyckoff_symbols, multiplicities
コード例 #6
0
def is_point_inside_cell(cell, point):
    """
    Checks if a given triple-vector is inside the cell given by the basis matrix in cell
    """
    p1 = FracVector((0, 0, 0))
    p2 = cell[0]
    p3 = cell[1]
    p4 = cell[0] + cell[1]
    p5 = cell[2]
    p6 = cell[0] + cell[2]
    p7 = cell[1] + cell[2]
    p8 = cell[0] + cell[1] + cell[2]

    tetras = [None] * 6
    tetras[0] = [p1, p2, p3, p6]
    tetras[1] = [p2, p3, p4, p6]
    tetras[2] = [p3, p4, p6, p8]
    tetras[3] = [p3, p6, p7, p8]
    tetras[4] = [p3, p5, p6, p7]
    tetras[5] = [p1, p3, p5, p6]

    for tetra in tetras:
        if is_point_inside_tetra(tetra, point):
            return True
    return False
コード例 #7
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)
コード例 #8
0
def is_any_part_of_cube_inside_cell(cell, midpoint, side):
    """
    Checks if any part of a cube is inside the cell spanned by the vectors in cell
    """
    ps = [
        midpoint + FracVector((x, y, z)) * side for x in [-1, 1]
        for y in [-1, 1] for z in [-1, 1]
    ]
    for p in ps:
        if is_point_inside_cell(cell, p):
            return True
    return False
コード例 #9
0
def basis_to_niggli_and_orientation(basis):
    basis = FracVector.use(basis)

    A = basis.noms
    det = basis.det()
    if det == 0:
        raise Exception("basis_to_niggli: singular cell matrix.")

    if det > 0:
        orientation = 1
    else:
        orientation = -1

    s11 = A[0][0] * A[0][0] + A[0][1] * A[0][1] + A[0][2] * A[0][2]
    s22 = A[1][0] * A[1][0] + A[1][1] * A[1][1] + A[1][2] * A[1][2]
    s33 = A[2][0] * A[2][0] + A[2][1] * A[2][1] + A[2][2] * A[2][2]

    s23 = A[1][0] * A[2][0] + A[1][1] * A[2][1] + A[1][2] * A[2][2]
    s13 = A[0][0] * A[2][0] + A[0][1] * A[2][1] + A[0][2] * A[2][2]
    s12 = A[0][0] * A[1][0] + A[0][1] * A[1][1] + A[0][2] * A[1][2]

    new = FracVector.create(((s11, s22, s33), (2 * s23, 2 * s13, 2 * s12)),
                            denom=basis.denom**2).simplify()
    return new, orientation
コード例 #10
0
ファイル: cell.py プロジェクト: hpleva/httk
    def __init__(self, basis, lattice_system, orientation=1):
        """
        Private constructor, as per httk coding guidelines. Use Cell.create instead.
        """
        self.basis = basis
        self.orientation = orientation
        self.lattice_system = lattice_system
        self.niggli_matrix, self.orientation = basis_to_niggli_and_orientation(basis)

        self.det = basis.det()
        self.inv = basis.inv()
        self._volume = abs(self.det)
        self.metric = niggli_to_metric(self.niggli_matrix)

        self.lengths, self.angles = niggli_to_lengths_and_angles(self.niggli_matrix)

        self.lengths = [FracVector.use(x).simplify() for x in self.lengths]
        self.angles = [FracVector.use(x).simplify() for x in self.angles]
        _dummy, self.cosangles, self.sinangles = niggli_to_lengths_and_trigangles(self.niggli_matrix)

        self.a, self.b, self.c = self.lengths
        self.alpha, self.beta, self.gamma = self.angles
        self.cosalpha, self.cosbeta, self.cosgamma = self.cosangles
        self.sinalpha, self.sinbeta, self.singamma = self.sinangles
コード例 #11
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]
コード例 #12
0
def scaling_to_volume(basis, scaling):
    volume = None
    if isinstance(scaling, dict):
        if 'volume' in scaling:
            volume = scaling['volume']
        elif 'scale' in scaling:
            scale = scaling['scale']
    elif scaling > 0:
        scale = scaling
    else:
        volume = -scaling

    if volume is None:
        scale = FracVector.use(scale)
        volume = scale_to_vol(basis, scale)

    return volume
コード例 #13
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]
コード例 #14
0
def get_primitive_to_conventional_basis_transform(basis, eps=1e-4):
    """
    Figures out how the 'likley' transform of a primitive cell for getting to the conventional basis

    This may not be foolproof, and mostly works for re-inverting cells generated by lengths_and_cosangles_to_conventional_basis.
    (It should only be used when getting something that isn't really the conventional cell does not equal catastrophic failure, just,
    e.g., a non-optimal representation.)
    """
    half = Fraction(1, 2)

    lattrans = None
    unit = FracVector.create([[1, 0, 0], [0, 1, 0], [0, 0, 1]])

    c = basis
    maxele = max(c[0, 0], c[0, 1], c[0, 2], c[1, 0], c[1, 1], c[1, 2], c[2, 0],
                 c[2, 1], c[2, 2])
    maxeleneg = max(-c[0, 0], -c[0, 1], -c[0, 2], -c[1, 0], -c[1, 1], -c[1, 2],
                    -c[2, 0], -c[2, 1], -c[2, 2])
    if maxeleneg > maxele:
        scale = (-maxeleneg).simplify()
    else:
        scale = (maxele).simplify()
    rebase = basis / (2 * scale)

    #niggli, orientation = basis_to_niggli_and_orientation(basis)
    #lengths, angles = niggli_to_lengths_and_angles(niggli)

    #rebase = FracVector.create([basis[0]/lengths[0], basis[1]/lengths[1], basis[2]/lengths[2]]).simplify()
    invrebase = rebase.inv().simplify()
    #invrebase = FracVector.create([invrebase[0]*lengths[0], invrebase[1]*lengths[1], invrebase[2]*lengths[2]]).simplify()

    #print("BASIS",basis)
    #print("BASIS",basis.to_floats())
    #print("INVREBASE:", invrebase.to_floats())
    #print("TRANSFORMED", (basis*invrebase).to_floats())

    for rows in invrebase:
        for val in rows:
            if val != 0 and val != 1 and val != -1:
                #if val != half and val != -half and val != 0 and val != 1 and val != -1:
                # This is not a primitive cell that can easily be turned into a cubic conventional cell
                #print("HUH",val)
                return unit
    #print("INVREBASE:", invrebase)
    return invrebase
コード例 #15
0
def symopsmatrix(symop):
    transf, transl = symopstuple(symop, val_transform=lambda x: x)
    return FracVector.create(transf), FracVector.create(transl)
コード例 #16
0
def angles_to_cosangles(angles):
    return FracVector.create_cos(angles, degrees=True)
コード例 #17
0
def is_point_inside_tetra(tetra, point):
    """
    Checks if a point is inside the tretrahedra spanned by the coordinates in tetra
    """
    D0 = FracVector(((tetra[0][0], tetra[0][1], tetra[0][2],
                      1), (tetra[1][0], tetra[1][1], tetra[1][2],
                           1), (tetra[2][0], tetra[2][1], tetra[2][2], 1),
                     (tetra[3][0], tetra[3][1], tetra[3][2], 1)))
    D1 = FracVector(((point[0], point[1], point[2],
                      1), (tetra[1][0], tetra[1][1], tetra[1][2],
                           1), (tetra[2][0], tetra[2][1], tetra[2][2], 1),
                     (tetra[3][0], tetra[3][1], tetra[3][2], 1)))
    D2 = FracVector(((tetra[0][0], tetra[0][1], tetra[0][2],
                      1), (point[0], point[1], point[2],
                           1), (tetra[2][0], tetra[2][1], tetra[2][2], 1),
                     (tetra[3][0], tetra[3][1], tetra[3][2], 1)))
    D3 = FracVector(((tetra[0][0], tetra[0][1], tetra[0][2],
                      1), (tetra[1][0], tetra[1][1], tetra[1][2],
                           1), (point[0], point[1], point[2], 1),
                     (tetra[3][0], tetra[3][1], tetra[3][2], 1)))
    D4 = FracVector(((tetra[0][0], tetra[0][1], tetra[0][2],
                      1), (tetra[1][0], tetra[1][1], tetra[1][2],
                           1), (tetra[2][0], tetra[2][1], tetra[2][2], 1),
                     (point[0], point[1], point[2], 1)))
    d0 = D0.det()
    if d0 < 0:
        s0 = -1
    else:
        s0 = 1
    d1 = D1.det()
    d2 = D2.det()
    d3 = D3.det()
    d4 = D4.det()

    if abs(d0) == 0:
        return False

    if (d1.sign() == s0 or d1 == 0) and (d2.sign() == s0 or d2 == 0) and (
            d3.sign() == s0 or d3 == 0) and (d4.sign() == s0 or d4 == 0):
        return True

    return False
コード例 #18
0
def hull_z(points, zs):
    """
    points: a list of points=(x,y,..) with zs= a list of z values;
    a convex half-hull is constructed over negative z-values

    returns data on the following format.::

      {
        'hull_points': indices in points list for points that make up the convex hull,
         'interior_points':indices for points in the interior,
         'interior_zs':interior_zs
         'zs_on_hull': hull z values for each point (for points on the hull, the value of the hull if this point is excluded)
         'closest_points': list of best linear combination of other points for each point
         'closest_weights': weights of best linear combination of other points for each point
      }

    where hull_points and interior_points are lists of the points on the hull and inside the hull.
    and

       hull_zs is a list of z-values that the hull *would have* at that point, had this point not been included.
       interior_zs is a list of z-values that the hull has at the interior points.

    """
    hull_points = []
    non_hull_points = []
    hull_distances = []
    closest_points = []
    closest_weights = []

    zvalues = len(zs)
    coeffs = len(points[0])
    #print("zvalues",zvalues)
    #print("coeffs",coeffs)
    for i in range(zvalues):
        #print("SEND IN",[zs[j] for j in range(zvalues) if j != i])
        a = FracVector.create([zs[j] for j in range(zvalues) if j != i])
        b = [None] * coeffs
        c = [None] * coeffs
        includepoints = [j for j in range(len(points)) if i != j]

        for j in range(coeffs):
            b[j] = FracVector.create([points[x][j] for x in includepoints])
            c[j] = points[i][j]

#         if i == 0:
#             print("A",a.to_floats())
#             print("B",[x.to_floats() for x in b])
#             print("C",c)

        solution = simplex_le_solver(a, b, c)
        val = solution[0]

        #         if i == 0:
        #             print("VAL",val)
        #             print("SOL",solution[1])
        #             print("MAPPED SOL",[(solution[1][i],includepoints[i]) for i in range(len(solution[1]))])
        #
        closest = solution[1]
        thisclosestpoints = []
        thisclosestweights = []
        for j in range(len(closest)):
            sol = closest[j]
            if sol != 0:
                thisclosestpoints += [includepoints[j]]
                thisclosestweights += [sol]
                #print("I AM",i,"I disolve into:",includepoints[j],"*",float(sol),"(",j,")")

        closest_points += [thisclosestpoints]
        closest_weights += [thisclosestweights]
        hull_distances += [zs[i] - val]

        if zs[i] <= val:
            hull_points += [i]
        else:
            non_hull_points += [i]

    return {
        'hull_indices': hull_points,
        'interior_indices': non_hull_points,
        'hull_distances': hull_distances,
        'competing_indices': closest_points,
        'competing_weights': closest_weights,
    }
コード例 #19
0
def standard_order_axes_transform(
        niggli_matrix,
        lattice_system,
        eps=0,
        return_identity_if_no_transform_needed=False):
    """
    Returns the transform that re-orders the axes to standard order for each possible lattice system.

    Note: returns None if no transform is needed, to make it easy to skip the transform in that case.
    If you want the identity matrix instead, set parameter return_identity_if_no_transform_needed = True,
    """

    # Determine lattice system even if axes are mis-ordered
    qrtr = Fraction(1, 4)

    abeq = abs(niggli_matrix[0][0] - niggli_matrix[0][1]) <= eps
    aceq = abs(niggli_matrix[0][0] - niggli_matrix[0][2]) <= eps
    bceq = abs(niggli_matrix[0][1] - niggli_matrix[0][2]) <= eps
    alpha90 = abs(niggli_matrix[1][0]) <= eps
    beta90 = abs(niggli_matrix[1][1]) <= eps
    gamma90 = abs(niggli_matrix[1][2]) <= eps
    alpha120 = (abs(niggli_matrix[1][0]**2 /
                    (niggli_matrix[0][1] * niggli_matrix[0][2]) - qrtr) <=
                eps) and niggli_matrix[1][0] < 0
    beta120 = (abs(niggli_matrix[1][1]**2 /
                   (niggli_matrix[0][0] * niggli_matrix[0][2]) - qrtr) <=
               eps) and niggli_matrix[1][1] < 0
    gamma120 = (abs(niggli_matrix[1][2]**2 /
                    (niggli_matrix[0][0] * niggli_matrix[0][1]) - qrtr) <=
                eps) and niggli_matrix[1][2] < 0

    equals = sum([abeq, aceq, bceq])
    if equals == 1:
        equals = 2
    orthos = sum([alpha90, beta90, gamma90])
    hexangles = sum([alpha120, beta120, gamma120])
    if equals == 3 and orthos == 3:
        lattice_system = 'cubic'
    elif equals == 2 and orthos == 3:
        lattice_system = 'tetragonal'
    elif equals == 0 and orthos == 3:
        lattice_system = 'orthorombic'
    elif hexangles == 1 and orthos == 2 and equals == 2:
        lattice_system = 'hexagonal'
    elif orthos == 2:
        lattice_system = 'monoclinic'
    elif equals == 3:
        lattice_system = 'rhombohedral'
    else:
        lattice_system = 'triclinic'

    if lattice_system == 'hexagonal' and not gamma120:
        if alpha120:
            return FracVector.create([[0, 0, -1], [0, -1, 0], [-1, 0, 0]])
        elif beta120:
            return FracVector.create([[-1, 0, 0], [0, 0, -1], [0, -1, 0]])
        raise Exception(
            "axis_standard_order_transform: unexpected cell geometry.")

    elif lattice_system == 'monoclinic' and not (alpha90 and gamma90
                                                 and not beta90):
        if (alpha90 and beta90 and not gamma90):
            return FracVector.create([[-1, 0, 0], [0, 0, -1], [0, -1, 0]])
        elif (beta90 and gamma90 and not alpha90):
            return FracVector.create([[0, 0, -1], [0, -1, 0], [-1, 0, 0]])
        raise Exception(
            "axis_standard_order_transform: unexpected cell geometry.")

    return None
コード例 #20
0
ファイル: cell.py プロジェクト: hpleva/httk
    def create(cls, cell=None, basis=None, metric=None, niggli_matrix=None,
               a=None, b=None, c=None, alpha=None, beta=None, gamma=None,
               lengths=None, angles=None, cosangles=None, scale=None,
               scaling=None, volume=None, periodicity=None,
               nonperiodic_vecs=None, orientation=1, hall=None,
               lattice_system=None, eps=0):
        """
        Create a new cell object,

        cell: any one of the following:

          - a 3x3 array with (in rows) the three basis vectors of the cell (a non-periodic system should conventionally use an identity matrix)

          - a dict with a single key 'niggli_matrix' with a 3x2 array with the Niggli Matrix representation of the cell

          - a dict with 6 keys, 'a', 'b', 'c', 'alpha', 'beta', 'gamma' giving the cell parameters as floats

        scaling: free form input parsed for a scale.
            positive value = multiply basis vectors by this value
            negative value = rescale basis vectors so that cell volume becomes abs(value).

        scale: set to non-None to multiply all cell vectors with this factor

        volume: set to non-None if the basis vectors only give directions, and the volume of the cell should be this value (overrides scale)

        periodicity: free form input parsed for periodicity
            sequence: True/False for each basis vector being periodic
            integer: number of non-periodic basis vectors

        hall: giving the hall symbol makes it possible to determine the lattice system without numerical inaccuracy

        lattice_system: any one of: 'cubic', 'hexagonal', 'tetragonal', 'orthorhombic', 'trigonal', 'triclinic', 'monoclinic', 'unknown'
        """
        #print("Create cell:",cell,basis,angles, lengths,cosangles,a,b,c,alpha,beta,gamma)

        if cell is not None:
            return Cell.use(cell)

        if basis is not None:
            basis = FracVector.use(basis)

        if angles is None and not (alpha is None or beta is None or gamma is None):
            angles = [alpha, beta, gamma]

        if lengths is None and not (a is None or b is None or c is None):
            lengths = [a, b, c]

        if cosangles is None and angles is not None:
            cosangles = angles_to_cosangles(angles)

        if basis is None and lengths is not None and cosangles is not None:
            if hall is not None:
                lattice_system = lattice_system_from_hall(hall)
            else:
                lattice_system = lattice_system_from_lengths_and_cosangles(lengths, cosangles)
            basis = lengths_and_cosangles_to_conventional_basis(lengths, cosangles, lattice_system, orientation=orientation, eps=eps)

        if niggli_matrix is not None:
            niggli_matrix = FracVector.use(niggli_matrix)

        if niggli_matrix is None and basis is not None:
            niggli_matrix, orientation = basis_to_niggli_and_orientation(basis)

        #if niggli_matrix is None and lengths is not None and cosangles is not None:
        #    niggli_matrix = lengths_and_cosangles_to_niggli(lengths, cosangles)
        #    niggli_matrix = FracVector.use(niggli_matrix)

        #if niggli_matrix is None and lengths is not None and angles is not None:
        #    niggli_matrix = lengths_and_angles_to_niggli(lengths, angles)
        #    niggli_matrix = FracVector.use(niggli_matrix)

        #if niggli_matrix is None and not (a is None or b is None or c is None or alpha is None or beta is None or gamma is None):
        #    niggli_matrix = lengths_and_angles_to_niggli([a, b, c], [alpha, beta, gamma])
        #    niggli_matrix = FracVector.use(niggli_matrix)

        if basis is None:
            raise Exception("cell.create: Not enough information to specify a cell given.")

        if scaling is None and scale is not None:
            scaling = scale

        if scaling is not None and volume is not None:
            raise Exception("Cell.create: cannot specify both scaling and volume!")

        if volume is not None:
            scaling = vol_to_scale(basis, volume)

        if scaling is not None:
            scaling = FracVector.use(scaling)
            basis = (basis*scaling).simplify()

        # Determination of the lattice system can only be made approximately, so it is recommended
        # that it is given to the constructor if possible

        if (lattice_system is None or lattice_system == 'unknown') and hall is not None:
            lattice_system = lattice_system_from_hall(hall)

        if lattice_system is None or lattice_system == 'unknown':
            lattice_system = lattice_system_from_niggli(niggli_matrix)

        if basis is None:
            basis = FracVector.use(niggli_to_conventional_basis(niggli_matrix, lattice_system, orientation=orientation))

        return cls(basis, lattice_system, orientation)
コード例 #21
0
                continue
            M[i] = (M[i] - M[i][pivot_col] * M[pivot_row]).simplify()
        obj = (obj - obj[pivot_col] * M[pivot_row]).simplify()
        base[pivot_row] = pivot_col - 1

    solution = [0] * Na
    for j in range(Nc):
        if obj[base[j] + 1] == 0 and base[j] < Na:
            solution[base[j]] = M[j][-1].simplify()

    return FracVector.create(-obj[-1]), FracVector.create(solution)


if __name__ == '__main__':

    a = FracVector.create([-3, -2])
    b = FracVector.create([[2, 1], [2, 3], [3, 1]])
    c = FracVector.create([18, 42, 24])

    print(simplex_le_solver(a, b, c))

    exit(0)

    from pylab import *

    xsample = FracVector.random((5, 1), 0, 100, 100)
    xsample = FracVector.create([[x[0], 1 - x[0]]
                                 for x in xsample] + [[1, 0]] + [[0, 1]])
    ysample = (-1 * FracVector.random((5, ), 0, 100, 100)).get_extend([0, 0])

    hull = hull_z(xsample, ysample)
コード例 #22
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
コード例 #23
0
ファイル: cell.py プロジェクト: hpleva/httk
 def coordgroups_cartesian_to_reduced(self, coordgroups):
     newcoordgroups = []
     for coordgroup in coordgroups:
         newcoordgroups += [self.coords_cartesian_to_reduced(coordgroup)]
     return FracVector.stack(newcoordgroups)
コード例 #24
0
ファイル: cell.py プロジェクト: hpleva/httk
 def coords_cartesian_to_reduced(self, coords):
     coords = FracVector.use(coords)
     return coords*self.inv
コード例 #25
0
ファイル: cell.py プロジェクト: hpleva/httk
 def coords_reduced_to_cartesian(self, coords):
     coords = FracVector.use(coords)
     return coords*self.basis
コード例 #26
0
def metric_to_niggli(cell):
    m = cell.noms
    return FracVector(
        ((m[0][0], m[1][1], m[2][2]), (2 * m[1][2], 2 * m[0][2], 2 * m[0][1])),
        cell.denom).simplify()