示例#1
0
def read_compared_result_from_json(filename='structure compare.json'):
    import json
    import re
    from method.atom import Atom

    with open(filename, 'r+') as fp:
        result_json = json.load(fp)
    result = []
    for element_json in result_json:
        element_json = json.loads(element_json)
        for key, value in element_json.items():
            if re.match('type', key):
                continue
            elif re.match('su', key) or re.match('un', key):
                atom_list = []
                for pair in value:
                    tmp = []
                    for atom in pair:
                        atom_json = json.loads(atom)
                        tmp.append(Atom(atom_json['pos'], type=atom_json['type'], num=atom_json['num']))
                    atom_list.append(tmp)
                element_json[key] = atom_list
            else:
                atom_list = []
                for atom in value:
                    atom_json = json.loads(atom)
                    atom_list.append(Atom(atom_json['pos'], type=atom_json['type'], num=atom_json['num']))
                element_json[key] = atom_list
        result.append(element_json)
    return result
示例#2
0
def remove_doped_atoms(structure, remove_dict):
    temp = []
    for atom in structure:
        if atom.type in remove_dict.keys():
            value = remove_dict[atom.type]
            if value != '':
                temp.append(Atom(atom.pos, value))
        else:
            temp.append(Atom(atom.pos, atom.type))
    structure.clear()
    structure.extend(temp)
    return structure
示例#3
0
def get_species(structure):
    species = {}
    i = 0
    for atom in structure:
        if species.get(atom.type):
            species[atom.type].append(Atom(atom.pos, atom.type, num=i))
        else:
            species[atom.type] = [
                Atom(atom.pos, atom.type, num=i),
            ]
        i = i + 1
    return species
def remove_doped_atoms(structure, remove_dict):
    temp = []
    for atom in structure:
        if atom.type in remove_dict.keys():
            value = remove_dict[atom.type]
            if value != '':
                temp.append(Atom(atom.pos, value))
        else:
            temp.append(Atom(atom.pos, atom.type))
    new_structure = Structure(structure.cell, scale=structure.scale)
    new_structure.extend(temp)
    return new_structure
示例#5
0
def symmetrically_inequivalent_sites(structure,
                                     specie=None,
                                     center=None,
                                     tolerance=1e-3,
                                     symprec=0.1):
    from method import error
    from method.atom import Atom
    from method.utilities import are_periodic_images
    from numpy import dot
    from numpy.linalg import norm

    if specie is None:
        raise error.RuntimeError("specie is None!")
    ops = get_symmetrical_operations(structure, symprec=symprec)
    temp = structure.copy()
    result = []
    for i in range(len(temp)):
        equivalent_sites = []
        if temp[i].type != specie:
            continue
        else:
            atom = Atom(temp[i].pos, type=temp[i].type, index=i)
            equivalent_sites.append(atom)
            for op in ops:
                rotation = op[:3]
                translation = op[3]
                transform = dot(rotation, temp[i].pos) + translation
                for j in range(i + 1, len(temp)):
                    if temp[j].type != specie:
                        continue
                    if are_periodic_images(transform,
                                           temp[j].pos,
                                           cell=structure.cell,
                                           tolerance=tolerance):
                        atom = Atom(temp[j].pos, type=temp[j].type, index=j)
                        equivalent_sites.append(atom)
                        temp[j].type = 'Used'
        result.append(equivalent_sites)
    indices = []
    for equivalent in result:
        if center is None:
            indices.append(equivalent[0].index)
        else:
            center = dot(temp.cell, center)
            minimum = norm(equivalent[0].pos - center)
            index = equivalent[0].index
            for site in equivalent:
                if norm(site.pos - center) < minimum:
                    minimum = norm(site.pos - center)
                    index = site.index
            indices.append(index)
    return indices
示例#6
0
def build_shell(structure,
                pure_substrate=False,
                doped_atom=None,
                remove_dict=None,
                cluster_r=5,
                shell_r=30):
    """

    :param structure: Pylada.crystal.Structure
    :param pure_substrate: Bool type
    :param doped_atom: Pylada.crystal.Atom
    :param remove_dict: dict
    :param cluster_r: float
    :param shell_r: float
    :return:
    """
    if pure_substrate is True:
        pass
    else:
        if doped_atom is None:
            species = structure_species(structure)
            doped_name = species[0][0]
            num = species[0][1]
            if num != 1:
                print(
                    'WARNING: The number of doped atom is not exclusive, please give doped atom name and position.\n'
                )
            for atom in structure:
                if atom.type == doped_name:
                    doped_atom = Atom(atom.pos, atom.type)
                    break
    if pure_substrate is False:
        if remove_dict is None:
            print(
                'ERROR: remove_list can not be None when substrate includes doped atoms.\n'
            )
            exit(1)
        structure = remove_doped_atoms(structure, remove_dict)
    supercell = extend_structure(structure, shell_r)
    shell = Structure(structure.cell, scale=structure.scale)
    doped_center = doped_atom.pos
    temp = []
    for atom in supercell:
        position = atom.pos
        d = np.linalg.norm(position - doped_center)
        if cluster_r < d <= shell_r:
            temp.append(Atom(position - doped_center, atom.type))
    shell.extend(temp)
    return shell
def extend_structure(structure, shell_r, pure_substrate=True, remove_dict=None):
    if pure_substrate is False:
        if remove_dict is None:
            print('ERROR: remove_list can not be None when substrate includes doped atoms.\n')
            exit(1)
        structure = remove_doped_atoms(structure, remove_dict)
    cell = structure.cell.T
    volume = structure.volume
    hz = volume/np.linalg.norm(np.cross(cell[0], cell[1]))
    hx = volume/np.linalg.norm(np.cross(cell[1], cell[2]))
    hy = volume/np.linalg.norm(np.cross(cell[2], cell[0]))
    if min(hx, hy, hz)/2 >= shell_r:
        return structure
    nz = int(np.ceil(shell_r/hz - 0.5))
    nx = int(np.ceil(shell_r/hx - 0.5))
    ny = int(np.ceil(shell_r/hy - 0.5))
    temp = []
    for i in range(-nx, nx+1):
        for j in range(-ny, ny+1):
            for k in range(-nz, nz+1):
                for atom in structure:
                    position = atom.pos + i*cell[0] + j*cell[1] + k*cell[2]
                    temp.append(Atom(position, atom.type))
    supercell = Structure(structure.cell, scale=structure.scale)
    supercell.extend(temp)
    return supercell
示例#8
0
 def insert(self, index, *args, **kwargs):
     """ Insert atoms in given position """
     from method.atom import Atom
     if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], Atom):
         atom = args[0]
     else:
         atom = Atom(*args, **kwargs)
     self._atoms.insert(index, atom)
示例#9
0
 def extend(self, args):
     """ Adds atoms to structure """
     from collections import Sequence
     from method.atom import Atom
     from method import error
     for arg in args:
         if isinstance(arg, Atom):
             self._atoms.append(arg)
         elif isinstance(arg, Sequence):
             self._atoms.append(Atom(*arg))
         else:
             raise error.TypeError("Cannot convert argument to Atom")
示例#10
0
def supercell(structure, transform):
    from method.structure import Structure
    from method.atom import Atom
    import numpy as np
    from numpy import dot
    epsilon = 1e-3

    r = []
    surface = []
    for j in range(3):
        minimum = 0
        maximum = 0
        for i in range(3):
            if transform[i][j] <= 0:
                minimum += transform[i][j]
            else:
                maximum += transform[i][j]
        r.append([minimum, maximum])
    result = Structure(dot(structure.cell, transform.T), scale=structure.scale)
    inverse = np.linalg.inv(transform)
    inv_cell = np.linalg.inv(structure.cell)
    for i in range(len(structure)):
        fractional = dot(inv_cell, structure[i].pos)
        for a0 in range(r[0][0] - 1, r[0][1] + 1):
            for a1 in range(r[1][0] - 1, r[1][1] + 1):
                for a2 in range(r[2][0] - 1, r[2][1] + 1):
                    translation = np.array([a0, a1, a2])
                    temp = dot((translation + fractional), inverse)
                    if is_in_cell(temp, epsilon):
                        result.add_atom(dot(result.cell, temp),
                                        structure[i].type)
                    elif is_in_surface(temp, epsilon):
                        surface.append(
                            Atom(dot(result.cell, temp),
                                 structure[i].type,
                                 flag=0))
    surface = remove_reduplicate(surface, dot(structure.cell, transform.T),
                                 epsilon)
    result.extend(surface)
    return result
示例#11
0
def extend_structure(structure, shell_r=30):
    cell = structure.cell.T
    volume = structure.volume
    hz = volume / np.linalg.norm(np.cross(cell[0], cell[1]))
    hx = volume / np.linalg.norm(np.cross(cell[1], cell[2]))
    hy = volume / np.linalg.norm(np.cross(cell[2], cell[0]))
    if min(hx, hy, hz) >= shell_r:
        return structure
    nz = int(np.ceil(shell_r / hz - 0.5))
    nx = int(np.ceil(shell_r / hx - 0.5))
    ny = int(np.ceil(shell_r / hy - 0.5))
    temp = []
    for i in range(-nx, nx + 1):
        for j in range(-ny, ny + 1):
            for k in range(-nz, nz + 1):
                for atom in structure:
                    position = atom.pos + i * cell[0] + j * cell[1] + k * cell[
                        2]
                    temp.append(Atom(position, atom.type))
    supercell = Structure(structure.cell, scale=structure.scale)
    supercell.extend(temp)
    return supercell
示例#12
0
def build_shell(structure,
                center,
                cluster_r,
                shell_r,
                pure_substrate=False,
                remove_dict=None):

    if pure_substrate is False:
        if remove_dict is None:
            print(
                'ERROR: remove_list can not be None when substrate includes doped atoms.\n'
            )
            exit(1)
        structure = remove_doped_atoms(structure, remove_dict)
    supercell = extend_structure(structure, shell_r)
    shell = Structure(structure.cell, scale=structure.scale)
    temp = []
    for atom in supercell:
        position = atom.pos
        d = np.linalg.norm(position - center)
        if cluster_r < d <= shell_r:
            temp.append(Atom(position - center, atom.type))
    shell.extend(temp)
    return shell
示例#13
0
 def append(self, *args, **kwargs):
     from method.atom import Atom
     if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], Atom):
         self._atoms.append(args[0])
     else:
         self._atoms.append(Atom(*args, **kwargs))
示例#14
0
        result_json = json.load(fp)
    result = []
    for element in result_json:
        element = json.loads(element)
        for key, value in element.items():
            if re.match('type', key):
                continue
            elif re.match('su', key) or re.match('un', key):
                atom_list = []
                for pair in value:
                    tmp = []
                    for atom in pair:
                        atom_json = json.loads(atom)
                        tmp.append(
                            Atom(atom_json['pos'],
                                 type=atom_json['type'],
                                 num=atom_json['num']))
                    atom_list.append(tmp)
                element[key] = atom_list
            else:
                atom_list = []
                for atom in value:
                    atom_json = json.loads(atom)
                    atom_list.append(
                        Atom(atom_json['pos'],
                             type=atom_json['type'],
                             num=atom_json['num']))
                element[key] = atom_list
        result.append(element)
    print(result)
def build_cluster(structure,
                  cluster_r,
                  doped_atom_type=None,
                  center=None,
                  core_r=None,
                  tolerance=0.2):
    from method.coordination_shells import coordination_shells

    position = np.array([0.0, 0.0, 0.0])
    species = structure_species(structure)
    if doped_atom_type is None:
        doped_atom_type = species[0][0]
        print('\nTry to use *{0}* atoms as doped atoms\n'.format(
            doped_atom_type))
    if center is None:
        num = 0
        for atom in structure:
            if atom.type == doped_atom_type:
                position += atom.pos
                num += 1
        center = position / num
    if cluster_r > min(distance_of_center_and_surface(center,
                                                      structure.cell.T)):
        print(
            '\nERROR: the cluster is out range of the CONTCAR supercell structure. '
            'Please use a bigger supercell or a smaller cluster_r parameter\n')
        exit(1)

    cluster = Structure(structure.cell, scale=structure.scale)
    if core_r is None:
        print(
            '\nTry to use the nearest neighbor of doped atoms to build core structure.\n'
        )
        nearest_neighbors = []
        for atom in structure:
            if atom.type == doped_atom_type:
                neighbors = coordination_shells(structure,
                                                nshells=5,
                                                center=atom.pos,
                                                tolerance=tolerance)
                nearest_neighbors.append(atom)
                atom.pseudo = 0
                for item in neighbors[0]:
                    atom = item[0]
                    nearest_neighbors.append(atom)
                    atom.pseudo = 0
                atom = neighbors[0][0][0]
                nearest_name = atom.type
                print('\nSet *{0}* atoms as nearest neighbor.\n'.format(
                    nearest_name))
                flag = 0
                for i in range(1, 5):
                    temp = []
                    if flag != 0:
                        break
                    for item in neighbors[i]:
                        atom = item[0]
                        if nearest_name == atom.type:
                            if not hasattr(atom, 'pseudo'):
                                temp.append(atom)
                                atom.pseudo = 0
                        else:
                            flag = 1
                    nearest_neighbors.extend(temp)
        # nearest neighbor might be outside of CONTCAR
        with open('core structure.txt', 'w+') as fp:
            for atom in nearest_neighbors:
                fp.writelines(atom.type + '   ' + str(atom.pos) + '\n')
        for atom in structure:
            position = atom.pos
            d = np.linalg.norm(center - position)
            if d <= cluster_r:
                if hasattr(atom, 'pseudo'):
                    cluster.append(Atom(atom.pos - center, atom.type,
                                        pseudo=0))
                else:
                    cluster.append(
                        Atom(atom.pos - center, atom.type, pseudo=-1))
    else:
        for atom in structure:
            d = np.linalg.norm(center - atom.pos)
            if d <= core_r:
                cluster.append(Atom(atom.pos - center, atom.type, pseudo=0))
            elif d <= cluster_r:
                cluster.append(Atom(atom.pos - center, atom.type, pseudo=-1))
    return cluster, center
示例#16
0
def build_cluster(structure,
                  doped_atom=None,
                  cluster_r=5,
                  core_r=None,
                  tolerance=0.2):
    from coordination_shells import coordination_shells
    """

    :param structure: Pylada.crystal.Structure
    :param doped_atom: Pylada.crystal.Atom
    :param cluster_r: float
    :param core_r: float
    :return: cluster, Pylada.crystal.Structure
    """

    if doped_atom is None:
        species = structure_species(structure)
        doped_name = species[0][0]
        num = species[0][1]
        if num != 1:
            print(
                'WARNING: The number of doped atom is not exclusive, please give doped atom name and position.\n'
            )
        for atom in structure:
            if atom.type == doped_name:
                doped_atom = Atom(atom.pos, atom.type)
                break
    cluster = Structure(structure.cell, scale=structure.scale)
    doped_center = doped_atom.pos
    if core_r is not None:
        for atom in structure:
            position = atom.pos
            d = np.linalg.norm(doped_center - position)
            if d <= core_r:
                cluster.append(
                    Atom(atom.pos - doped_center, atom.type, pseudo=0))
            elif d <= cluster_r:
                cluster.append(
                    Atom(atom.pos - doped_center, atom.type, pseudo=-1))
    else:
        # try to find the nearest neighbors of doped atom
        neighbors = coordination_shells(structure,
                                        nshells=4,
                                        center=doped_center,
                                        tolerance=tolerance)
        nearest_neighbors = []
        flag = 0
        for item in neighbors[0]:
            atom = item[0]
            nearest_neighbors.append(atom)
            atom.pseudo = 0
        if len(sorted({a.type for a in nearest_neighbors})) > 1:
            print(
                'WARNING: The species of nearest neighbor atoms are more than one.\n'
            )
        atom = neighbors[0][0][0]
        nearest_name = atom.type
        for i in range(1, 4):
            if flag != 0:
                break
            temp = [item[0] for item in neighbors[i]]
            if len(sorted({a.type for a in temp})) > 1:
                print('WARNING: The species of next nearest neighbor atoms:\n')
                print(sorted({a.type for a in temp}))
                print(
                    '\nwhich means the tolerance parameter might be too big to distinguish different shell of '
                    'neighbors\n')
                # when this situation happened, we discard this shell.
                break
            for item in neighbors[i]:
                atom = item[0]
                if nearest_name == atom.type:
                    nearest_neighbors.append(atom)
                    atom.pseudo = 0
                else:
                    flag = 1
        for atom in structure:
            position = atom.pos
            d = np.linalg.norm(doped_center - position)
            if d <= cluster_r:
                if hasattr(atom, 'pseudo'):
                    cluster.append(
                        Atom(atom.pos - doped_center, atom.type, pseudo=0))
                elif atom.type == doped_atom.type and d < 0.01:
                    cluster.append(
                        Atom(atom.pos - doped_center, atom.type, pseudo=0))
                else:
                    cluster.append(
                        Atom(atom.pos - doped_center, atom.type, pseudo=-1))
    return cluster
示例#17
0
def build_mosaic_structure(cluster, shell):
    for atom in shell:
        cluster.append(Atom(atom.pos, atom.type, pseudo=-1))
    return cluster