Пример #1
0
def cluster(S, tol=1.1, seed_index=0, write_poscar_from_cluster=False):
    # S = Structure object
    # tol = tolerance bonding

    S = SpacegroupAnalyzer(S, 0.1).get_conventional_standard_structure()

    if len(S) < 20: S.make_supercell(2)
    Distance_matrix = S.distance_matrix
    #np.fill_diagonal(Distance_matrix,100)

    radii = [Elem_radius[site.species_string] for site in S.sites]
    radiiT = np.array(radii)[np.newaxis].T  #transpose of radii list
    radii_matrix = radii + radiiT * tol
    temp = Distance_matrix - radii_matrix
    binary_matrix = (temp < 0).astype(int)

    original = list(range(len(S)))
    final = []
    difference = []
    counter = 0
    while (len(original) != len(final)):
        seed = set((np.where(binary_matrix[seed_index] == 1))[0])
        cluster = seed
        NEW = seed
        check = True
        while check:
            Ss = set()
            for n in NEW:
                Ss.update(set(np.where(binary_matrix[n] == 1)[0]))
                #print n,set(np.where( binary_matrix[n]==1 )[0])

            if Ss.issubset(cluster):
                check = False
            else:
                NEW = Ss - cluster
                cluster.update(Ss)
        L = []
        cl = list(cluster)
        sites = [S[i] for i in cl]
        S.from_sites(sites).to('POSCAR', 'POSCAR{}'.format(str(counter)))
        counter += 1
        final = set(final)
        final.update(cluster)
        final = list(final)
        difference = list(set(original) - set(final))
        if (len(difference) > 0):
            seed_index = difference[0]
Пример #2
0
def get_structure_type(structure,
                       tol=0.1,
                       seed_index=0,
                       write_poscar_from_cluster=False):
    """
    This is a topology-scaling algorithm used to describe the
    periodicity of bonded clusters in a bulk structure.
    Args:
        structure (structure): Pymatgen structure object to classify.
        tol (float): Additional percent of atomic radii to allow
            for overlap, thereby defining bonds
            (0.1 = +10%, -0.1 = -10%)
        seed_index (int): Atom number to start the cluster.
        write_poscar_from_cluster (bool): Set to True to write a
            POSCAR file from the sites in the cluster.
    Returns:
        string. "molecular" (0D), "chain" (1D), "layered" (2D), or
            "conventional" (3D). Also includes " heterogeneous"
            if the cluster's composition is not equal to that
            of the overal structure.
    """

    # Get conventional structure to orthogonalize the lattice as
    # much as possible. A tolerance of 0.1 Angst. was suggested by
    # pymatgen developers.
    s = SpacegroupAnalyzer(structure,
                           0.1).get_conventional_standard_structure()
    heterogeneous = False

    noble_gases = ["He", "Ne", "Ar", "Kr", "Xe", "Rn"]
    if len([e for e in structure.composition if e.symbol in noble_gases]) != 0:
        type = "noble gas"
    else:
        # make 2x2x2 supercell to ensure sufficient number of atoms
        # for cluster building.
        s.make_supercell(2)

        # Distance matrix (rowA, columnB) shows distance between
        # atoms A and B, taking PBCs into account.
        distance_matrix = s.distance_matrix

        # Fill diagonal with a large number, so the code knows that
        # each atom is not bonded to itself.
        np.fill_diagonal(distance_matrix, 100)

        # Rows (`radii`) and columns (`radiiT`) of radii.
        radii = [ELEMENT_RADII[site.species_string] for site in s.sites]
        radiiT = np.array(radii)[np.newaxis].T
        radii_matrix = radii + radiiT * (1 + tol)

        # elements of temp that have value less than 0 are bonded.
        temp = distance_matrix - radii_matrix
        # True (1) is placed where temp < 0, and False (0) where
        # it is not.
        binary_matrix = (temp < 0).astype(int)

        # list of atoms bonded to the seed atom of a cluster
        seed = set((np.where(binary_matrix[seed_index] == 1))[0])
        cluster = seed
        NEW = seed
        while True:
            temp_set = set()
            for n in NEW:
                # temp_set will have all atoms, without duplicates,
                # that are connected to all atoms in NEW.
                temp_set.update(set(np.where(binary_matrix[n] == 1)[0]))

            if temp_set.issubset(cluster):
                # if temp_set has no new atoms, the search is done.
                break
            else:
                NEW = temp_set - cluster  # List of newly discovered atoms
                cluster.update(temp_set)  # cluster is updated with new atoms

        if len(cluster) == 0:  # i.e. the cluster is a single atom.
            cluster = [seed_index]  # Make sure it's not empty to write POSCAR.
            type = "molecular"

        elif len(cluster) == len(s.sites):  # i.e. all atoms are bonded.
            type = "conventional"

        else:
            cmp = Composition.from_dict(
                Counter([s[l].specie.name for l in list(cluster)]))
            if cmp.reduced_formula != s.composition.reduced_formula:
                # i.e. the cluster does not have the same composition
                # as the overall crystal; therefore there are other
                # clusters of varying composition.
                heterogeneous = True

            old_cluster_size = len(cluster)
            # Increase structure to determine whether it is
            # layered or molecular, then perform the same kind
            # of cluster search as before.
            s.make_supercell(2)
            distance_matrix = s.distance_matrix
            np.fill_diagonal(distance_matrix, 100)
            radii = [ELEMENT_RADII[site.species_string] for site in s.sites]
            radiiT = np.array(radii)[np.newaxis].T
            radii_matrix = radii + radiiT * (1 + tol)
            temp = distance_matrix - radii_matrix
            binary_matrix = (temp < 0).astype(int)

            seed = set((np.where(binary_matrix[seed_index] == 1))[0])
            cluster = seed
            NEW = seed
            check = True
            while check:
                temp_set = set()
                for n in NEW:
                    temp_set.update(set(np.where(binary_matrix[n] == 1)[0]))

                if temp_set.issubset(cluster):
                    check = False
                else:
                    NEW = temp_set - cluster
                    cluster.update(temp_set)

            if len(cluster) != 4 * old_cluster_size:
                type = "molecular"
            else:
                type = "layered"
    if heterogeneous:
        type += " heterogeneous"

    cluster_sites = [s.sites[n] for n in cluster]
    if write_poscar_from_cluster:
        s.from_sites(cluster_sites).get_primitive_structure().to(
            "POSCAR", "POSCAR")

    return type
Пример #3
0
def get_structure_type(structure, tol=0.1, seed_index=0,
                       write_poscar_from_cluster=False):

    """
    This is a topology-scaling algorithm used to describe the
    periodicity of bonded clusters in a bulk structure.
    Args:
        structure (structure): Pymatgen structure object to classify.
        tol (float): Additional percent of atomic radii to allow
            for overlap, thereby defining bonds
            (0.1 = +10%, -0.1 = -10%)
        seed_index (int): Atom number to start the cluster.
        write_poscar_from_cluster (bool): Set to True to write a
            POSCAR file from the sites in the cluster.
    Returns:
        string. "molecular" (0D), "chain" (1D), "layered" (2D), or
            "conventional" (3D). Also includes " heterogeneous"
            if the cluster's composition is not equal to that
            of the overal structure.
    """

    # Get conventional structure to orthogonalize the lattice as
    # much as possible. A tolerance of 0.1 Angst. was suggested by
    # pymatgen developers.
    s = SpacegroupAnalyzer(structure, 0.1).get_conventional_standard_structure()
    heterogeneous = False

    noble_gases = ["He", "Ne", "Ar", "Kr", "Xe", "Rn"]
    if len([e for e in structure.composition if e.symbol in noble_gases]) != 0:
        type = "noble gas"
    else:
        # make 2x2x2 supercell to ensure sufficient number of atoms
        # for cluster building.
        s.make_supercell(2)

        # Distance matrix (rowA, columnB) shows distance between
        # atoms A and B, taking PBCs into account.
        distance_matrix = s.distance_matrix

        # Fill diagonal with a large number, so the code knows that
        # each atom is not bonded to itself.
        np.fill_diagonal(distance_matrix, 100)

        # Rows (`radii`) and columns (`radiiT`) of radii.
        radii = [ELEMENT_RADII[site.species_string] for site in s.sites]
        radiiT = np.array(radii)[np.newaxis].T
        radii_matrix = radii + radiiT*(1+tol)

        # elements of temp that have value less than 0 are bonded.
        temp = distance_matrix - radii_matrix
        # True (1) is placed where temp < 0, and False (0) where
        # it is not.
        binary_matrix = (temp < 0).astype(int)

        # list of atoms bonded to the seed atom of a cluster
        seed = set((np.where(binary_matrix[seed_index]==1))[0])
        cluster = seed
        NEW = seed
        while True:
            temp_set = set()
            for n in NEW:
                # temp_set will have all atoms, without duplicates,
                # that are connected to all atoms in NEW.
                temp_set.update(set(np.where(binary_matrix[n]==1)[0]))

            if temp_set.issubset(cluster):
                # if temp_set has no new atoms, the search is done.
                break
            else:
                NEW = temp_set - cluster # List of newly discovered atoms
                cluster.update(temp_set) # cluster is updated with new atoms

        if len(cluster) == 0:  # i.e. the cluster is a single atom.
            cluster = [seed_index]  # Make sure it's not empty to write POSCAR.
            type = "molecular"

        elif len(cluster) == len(s.sites): # i.e. all atoms are bonded.
            type = "conventional"

        else:
            cmp = Composition.from_dict(Counter([s[l].specie.name for l in
                                        list(cluster)]))
            if cmp.reduced_formula != s.composition.reduced_formula:
                # i.e. the cluster does not have the same composition
                # as the overall crystal; therefore there are other
                # clusters of varying composition.
                heterogeneous = True

            old_cluster_size = len(cluster)
            # Increase structure to determine whether it is
            # layered or molecular, then perform the same kind
            # of cluster search as before.
            s.make_supercell(2)
            distance_matrix = s.distance_matrix
            np.fill_diagonal(distance_matrix,100)
            radii = [ELEMENT_RADII[site.species_string] for site in s.sites]
            radiiT = np.array(radii)[np.newaxis].T
            radii_matrix = radii + radiiT*(1+tol)
            temp = distance_matrix-radii_matrix
            binary_matrix = (temp < 0).astype(int)

            seed = set((np.where(binary_matrix[seed_index]==1))[0])
            cluster = seed
            NEW = seed
            check = True
            while check:
                temp_set = set()
                for n in NEW:
                    temp_set.update(set(np.where(binary_matrix[n]==1)[0]))

                if temp_set.issubset(cluster):
                    check = False
                else:
                    NEW = temp_set - cluster
                    cluster.update(temp_set)

            if len(cluster) != 4 * old_cluster_size:
                type = "molecular"
            else:
                type = "layered"
    if heterogeneous:
        type += " heterogeneous"

    cluster_sites = [s.sites[n] for n in cluster]
    if write_poscar_from_cluster:
        s.from_sites(cluster_sites).get_primitive_structure().to("POSCAR",
                                                                 "POSCAR")

    return type