Пример #1
0
def find_correspondences(structure, symmetry, tolerance):
    """
    Map each symmetry operation to a permutation over the atoms in
    structure.
    """
    natoms = structure.get_number_of_atoms()
    operations = symmetry.get_symmetry_operations()
    translations = operations["translations"]
    rotations = operations["rotations"]

    correspondences = []
    positions = structure.get_scaled_positions()
    nsym = len(translations)
    for isym in range(nsym):
        remaining = list(range(natoms))
        perm = []
        for iatom in range(natoms):
            dest = np.dot(rotations[isym, :, :],
                          positions[iatom, :]) + translations[isym, :]
            dest %= 1.
            for jatom in remaining:
                delta = dest - positions[jatom, :]
                delta -= np.round(delta)
                if np.allclose(delta, 0., atol=tolerance):
                    remaining.remove(jatom)
                    perm.append(jatom)
                    break
            else:
                raise ValueError(
                    "the structure must have the specified symmetry")
        correspondences.append(perm)
    return tuplify(correspondences)
Пример #2
0
def get_crotations(structure, symmetry):
    """
    Return the matrices representing the rotations in Cartesian
    coordinates.
    """
    lattvec = structure.cell.T
    operations = symmetry.get_symmetry_operations()
    rotations = operations["rotations"]
    nruter = []
    for r in rotations:
        crotation = (np.dot(np.linalg.solve(lattvec.T, r.T), lattvec.T)).T
        nruter.append(crotation * (np.fabs(crotation) >= 1e-12))
    return nruter
Пример #3
0
def get_symmetry_information(sposcar_file):
    """
    Obtain the symmetry information useful to compute the 2nd order force
    constants irreducible elements.
    """

    logging.basicConfig(level=0)
    SYMPREC = 1e-5

    if not os.path.isfile(sposcar_file):
        sys.exit("The specified SPOSCAR file does not exist.")

    supercell_matrix = np.diag([1, 1, 1])

    structure = phonopy.interface.read_crystal_structure(sposcar_file,
                                                         "vasp")[0]
    natoms = structure.get_number_of_atoms()

    symmetry = phonopy.structure.symmetry.Symmetry(structure, symprec=SYMPREC)

    dataset = symmetry.get_dataset()
    print("Space group {0} ({1}) detected".format(dataset["international"],
                                                  dataset["number"]))
    crotations = get_crotations(structure, symmetry)

    operations = symmetry.get_symmetry_operations()
    translations = operations["translations"]
    rotations = operations["rotations"]

    logging.debug("About to classify atom pairs")
    permutations = find_correspondences(structure, symmetry, SYMPREC)
    print("permutations: " + str(permutations))
    equivalences = classify_pairs(structure, permutations)
    logging.debug("{0} equivalence classes found".format(len(equivalences)))

    for i, eq in enumerate(equivalences):
        logging.debug("Equivalence class #{0}".format(i))
        for il, l in enumerate(eq):
            logging.debug("\t{0}. {1}".format(il + 1, l))

    kernels = []
    irreducible = []
    for i, eq in enumerate(equivalences):
        logging.debug("Representative of equivalence class #{0}".format(i))
        invariances = find_invariances(eq[0][0], permutations)
        logging.debug("is left invariant by {0} operations".format(
            len(invariances)))
        for iinv, inv in enumerate(invariances):
            logging.debug("\t{0}. {1}".format(iinv, inv))
        logging.debug("About to build the constraint matrix")
        coefficients = get_constraints(
            [crotations[inv] for inv in invariances])
        rank = np.linalg.matrix_rank(coefficients)
        logging.debug("{0} constraints".format(coefficients.shape[0]))
        logging.debug(
            "{0} independent components in this equivalence class:".format(
                9 - rank))
        if (rank > 0):
            v = sp.linalg.svd(coefficients, full_matrices=False)[2].T
            kernels.append(v[:, rank - 9:])
            irreducible.append(complete_constraints(coefficients))
        else:
            kernels.append(np.identity(9))
            irreducible.append([0, 1, 2, 3, 4, 5, 6, 7, 8])
        for iirr, irr in enumerate(irreducible[-1]):
            c1, c2 = np.unravel_index(irr, (3, 3))
            logging.debug("\t{0}. {1}{2},{3}{4}".format(
                iirr, eq[0][0][0], "xyz"[c1], eq[0][0][1], "xyz"[c2]))
    irreducible = tuplify(irreducible)

    todo = []
    for eq, irr in zip(equivalences, irreducible):
        a1, a2 = eq[0][0]
        for i in irr:
            print("a1", a1, "a2", a2, "i", np.unravel_index(i, (3, 3)))
        todo += [dof2dof(a1, a2, i, natoms) for i in irr]
    todo = tuplify(todo)

    with open('out_sym', 'a') as file:
        file.write("2nd order todo list before acoustic sum rule: " +
                   str(todo) + "\n")
        file.write(
            "number of irreducible elements before acoustic sum rule: " +
            str(len(todo)) + "\n")
    return [natoms, crotations, equivalences, kernels, irreducible, todo]