Exemplo n.º 1
0
    def test3(self):
        l = Lattice.cubic(100)
        s1 = PeriodicSite('Li', [99.5, 0, 1], l, coords_are_cartesian=True)
        s2 = PeriodicSite('Sn', [99.5, 1, 0], l, coords_are_cartesian=True)
        s3 = PeriodicSite('Li', [0.5, 0, 0], l, coords_are_cartesian=True)

        s = Structure.from_sites([s1, s2, s3])
        coords = np.array(s.cart_coords)[:, None, :]
        cd = CoordData(coords, s)
        gtc = GaussianTripletColumns(rrange=[1, 10], c=0.5)
        f = gtc.make(cd)
        self.assertAlmostEqual(f[0, 0], 0)
        self.assertAlmostEqual(f[1, 8], -0.41849511)
        self.assertAlmostEqual(f[2, 8], 0.83699023)
        self.assertAlmostEqual(f[3, 32], -0.83699023)
Exemplo n.º 2
0
 def _make_sites(self):
     """ """
     self.sites = []
     self.coords = []
     for raw in self.atoms:
         proc = [
             s.strip()
             for s in (raw[:6], raw[6:11], raw[12:16], raw[16], raw[17:20],
                       raw[21], raw[22:26], raw[26], raw[30:38], raw[38:46],
                       raw[46:54], raw[54:60], raw[60:66], raw[72:76],
                       raw[76:78], raw[78:])
         ]
         coord = np.dot(self.cart_to_lat, np.array(
             proc[8:11], dtype=float)) + self.translate
         props = dict(serial=proc[1],
                      name=proc[2],
                      altloc=proc[3],
                      residue=proc[4],
                      chain=proc[5],
                      sequence=proc[6],
                      segment=proc[13])
         self.coords.append(coord)
         self.sites.append(
             PeriodicSite(Composition({proc[-2]: float(proc[11])}),
                          coord,
                          self.lattice,
                          coords_are_cartesian=True,
                          properties=props))
     return
Exemplo n.º 3
0
    def make_supercell(self, scaling_matrix):
        """
        Create a supercell. Very similar to pymatgen's Structure.make_supercell
        However, we need to make sure that all fractional coordinates that equal
        to 1 will become 0 and the lattice are redefined so that x_c = [0, 0, c]

        Args:
            scaling_matrix (3x3 matrix): The scaling matrix to make supercell.
        """
        s = self * scaling_matrix
        for i, site in enumerate(s):
            f_coords = np.mod(site.frac_coords, 1)
            # The following for loop is probably not necessary. But I will leave
            # it here for now.
            for j, v in enumerate(f_coords):
                if abs(v - 1) < 1e-6:
                    f_coords[j] = 0
            s[i] = PeriodicSite(site.specie,
                                f_coords,
                                site.lattice,
                                properties=site.properties)
        self._sites = s.sites
        self._lattice = s.lattice
        new_lat = Lattice.from_lengths_and_angles(
            *s.lattice.lengths_and_angles)
        self.modify_lattice(new_lat)
Exemplo n.º 4
0
 def periodic_muon_site(self):
     """The periodic single muon site"""
     structure = self.pristine_structure_supercell.copy()
     mupos = self.relax_muon_site.frac_coords
     return PeriodicSite("H",
                         mupos,
                         structure.lattice,
                         coords_are_cartesian=False)
Exemplo n.º 5
0
    def from_dict(cls, d):
        lattice = Lattice.from_dict(d["lattice"])
        sites = [PeriodicSite.from_dict(sd, lattice) for sd in d["sites"]]
        s = Structure.from_sites(sites)

        return cls(
            lattice=lattice,
            species=s.species_and_occu, coords=s.frac_coords,
            miller_index=d["miller_index"],
            oriented_unit_cell=Structure.from_dict(d["oriented_unit_cell"]),
            shift=d["shift"],
            scale_factor=MontyDecoder().process_decoded(d["scale_factor"]),
            site_properties=s.site_properties, energy=d["energy"]
        )
Exemplo n.º 6
0
    def get_sitej(self, site_index, image_index):
        """
        Assuming there is some value in the connectivity array at indices
        (1, 3, 12). sitei can be obtained directly from the input structure
        (structure[1]). sitej can be obtained by passing 3, 12 to this function

        Args:
            site_index (int): index of the site (3 in the example)
            image_index (int): index of the image (12 in the example)
        """
        atoms_n_occu = self.s[site_index].species
        lattice = self.s.lattice
        coords = self.s[site_index].frac_coords + self.offsets[image_index]
        return PeriodicSite(atoms_n_occu, coords, lattice)
Exemplo n.º 7
0
    def __init__(self, supercell_matrix, cluster_expansion):
        """
        Args:
            supercell matrix: array describing the supercell, e.g. [[1,0,0],[0,1,0],[0,0,1]]
            cluster_expansion: ClusterExpansion object
        """
        self.basis = cluster_expansion.basis
        self.supercell_matrix = np.array(supercell_matrix)
        self.prim_to_supercell = np.linalg.inv(self.supercell_matrix)
        self.cluster_expansion = cluster_expansion

        self.supercell = cluster_expansion.structure.copy()
        self.supercell.make_supercell(self.supercell_matrix)
        self.size = int(round(np.abs(np.linalg.det(self.supercell_matrix))))

        self.bits = get_bits(self.supercell)
        self.nbits = np.array([len(b)-1 for b in self.bits])
        self.fcoords = np.array(self.supercell.frac_coords)

        self._generate_mappings()

        if self.cluster_expansion.use_ewald:
            #lazily generate the difficult ewald parts
            self.ewald_inds = []
            ewald_sites = []
            for bits, s in zip(self.bits, self.supercell):
                inds = np.zeros(max(self.nbits) + 1) - 1
                for i, b in enumerate(bits):
                    if b == 'Vacancy':
                        #inds.append(-1)
                        continue
                    inds[i] = len(ewald_sites)
                    ewald_sites.append(PeriodicSite(b, s.frac_coords, s.lattice))
                self.ewald_inds.append(inds)
            self.ewald_inds = np.array(self.ewald_inds, dtype=np.int)
            self._ewald_structure = Structure.from_sites(ewald_sites)
            self._ewald_matrix = None
            self._partial_ems = None
            self._all_ewalds = None
            self._range = np.arange(len(self.nbits))
        else:
            self._all_ewalds = np.zeros((0, 0, 0), dtype=np.float)
            self.ewald_inds = np.zeros((0, 0), dtype=np.int)
Exemplo n.º 8
0
 def periodic_muon_site(self):
     """get muon position as a PeriodicSite
     
     Parameters
     ----------
     positions : nd.array
         numpy.array of fractional position of host atoms (including muon)                    
     Returns: 
     mu_positions : PeriodicSite
         Periodic muon site positions            
     """
     structure = self.structure_sc.copy()
     positions = self.positions
     mu_positions = list()
     for mu_i, mu in enumerate(self.positions):
         mu_positions.append(
             PeriodicSite("H", [mu_p for mu_p in positions[mu_i][-1]],
                          structure.lattice,
                          coords_are_cartesian=False))
     return mu_positions
Exemplo n.º 9
0
 def test_symmetrized_structure(self):
     t = OrderDisorderedStructureTransformation(symmetrized_structures=True)
     c = []
     sp = []
     c.append([0.5, 0.5, 0.5])
     sp.append('Si4+')
     c.append([0.45, 0.45, 0.45])
     sp.append({"Si4+": 0.5})
     c.append([0.56, 0.56, 0.56])
     sp.append({"Si4+": 0.5})
     c.append([0.25, 0.75, 0.75])
     sp.append({"Si4+": 0.5})
     c.append([0.75, 0.25, 0.25])
     sp.append({"Si4+": 0.5})
     l = Lattice.cubic(5)
     s = Structure(l, sp, c)
     test_site = PeriodicSite("Si4+", c[2], l)
     s = SymmetrizedStructure(s, 'not_real', [0, 1, 1, 2, 2])
     output = t.apply_transformation(s)
     self.assertTrue(test_site in output.sites)
Exemplo n.º 10
0
    def periodic_muon_equivalent_site(self):
        """get muon position as a PeriodicSite
        
        Parameters
        ----------
        positions : numpy.ndarray
                    3D muon positions (including muon)
        Returns: 
               PeriodicSite of muon positions
        """

        #frac_coords = self.ase_muon_find_equiv()
        positions = self.muon_equivalent_sites
        structure = self.pristine_structure_supercell.copy()
        periodic_sites = list()
        for mu, i in enumerate(positions):
            periodic_sites.append(
                PeriodicSite("H", [mu_i for mu_i in positions[mu]],
                             structure.lattice,
                             coords_are_cartesian=False))
        return periodic_sites
Exemplo n.º 11
0
    def delete_bt_layer(self, bt, tol=0.25, axis=2):
        """
        Delete bottom or top layer of the structure.
        Args:
            bt (str): Specify whether it's a top or bottom layer delete. "b"
                means bottom layer and "t" means top layer.
            tol (float), Angstrom: Tolerance factor to determine whether two
                atoms are at the same plane.
                Default to 0.25
            axis (int): The direction of top and bottom layers. 0: x, 1: y, 2: z

        """
        if bt == "t":
            l1, l2 = (-1, -2)
        else:
            l1, l2 = (0, 1)

        l = self.lattice.abc[axis]
        layers = self.sort_sites_in_layers(tol=tol, axis=axis)
        l_dist = abs(layers[l1][0].coords[axis] - layers[l2][0].coords[axis])
        l_vector = [1, 1]
        l_vector.insert(axis, (l - l_dist) / l)
        new_lat = Lattice(self.lattice.matrix * np.array(l_vector)[:, None])

        layers.pop(l1)
        sites = reduce(lambda x, y: np.concatenate((x, y), axis=0), layers)
        new_sites = []
        l_dist = 0 if bt == "t" else l_dist
        l_vector = [0, 0]
        l_vector.insert(axis, l_dist)
        for i in sites:
            new_sites.append(
                PeriodicSite(i.specie,
                             i.coords - l_vector,
                             new_lat,
                             coords_are_cartesian=True))
        self._sites = new_sites
        self._lattice = new_lat
Exemplo n.º 12
0
    def test2(self):
        l = Lattice.cubic(100)
        s1 = PeriodicSite('Li', [99.5, 0, 1.1], l, coords_are_cartesian=True)
        s2 = PeriodicSite('Sn', [99.5, 1, 0], l, coords_are_cartesian=True)
        s3 = PeriodicSite('Li', [0.5, 0, 0], l, coords_are_cartesian=True)
        s4 = PeriodicSite('Li', [59.5, 0, 1.1], l, coords_are_cartesian=True)
        s5 = PeriodicSite('Sn', [59.5, 1, 0], l, coords_are_cartesian=True)
        s6 = PeriodicSite('Li', [60.5, 0, 0], l, coords_are_cartesian=True)
        s = Structure.from_sites([s1, s2, s3, s4, s5, s6])
        coords = np.array(s.cart_coords)[:, None, :]
        cd = CoordData(coords, s)
        gtc = GaussianTripletColumns(rrange=np.arange(1, 1.1, 1), c=0.5)
        f = gtc.make(cd)
        self.assertAlmostEqual(f[9, 0], 0)
        self.assertAlmostEqual(f[10, 1], -0.36030969)
        self.assertAlmostEqual(f[11, 1], 0.79268132)
        self.assertAlmostEqual(f[12, 4], -0.64481206)
        self.assertAlmostEqual(f[13, 4], 1.36543144)

        self.assertAlmostEqual(np.sum(f), 0)
Exemplo n.º 13
0
 def structure_from_occu(self, occu):
     sites = []
     for b, o, s in zip(self.bits, occu, self.supercell):
         if b[o] != 'Vacancy':
             sites.append(PeriodicSite(b[o], s.frac_coords, self.supercell.lattice))
     return Structure.from_sites(sites)
Exemplo n.º 14
0
def get_structure_graph_scene(
    self,
    origin=None,
    draw_image_atoms=True,
    bonded_sites_outside_unit_cell=True,
    hide_incomplete_edges=False,
    incomplete_edge_length_scale=0.3,
    color_edges_by_edge_weight=True,
    edge_weight_color_scale="coolwarm",
    explicitly_calculate_polyhedra_hull=False,
    legend: Optional[Legend] = None,
) -> Scene:

    origin = origin or list(
        -self.structure.lattice.get_cartesian_coords([0.5, 0.5, 0.5]))

    legend = legend or Legend(self.structure)

    primitives = defaultdict(list)

    sites_to_draw = self._get_sites_to_draw(
        draw_image_atoms=draw_image_atoms,
        bonded_sites_outside_unit_cell=bonded_sites_outside_unit_cell,
    )

    color_edges = False
    if color_edges_by_edge_weight:

        weights = [e[2].get("weight") for e in self.graph.edges(data=True)]
        weights = np.array([w for w in weights if w])

        if any(weights):

            cmap = get_cmap(edge_weight_color_scale)

            # try to keep color scheme symmetric around 0
            weight_max = max([abs(min(weights)), max(weights)])
            weight_min = -weight_max

            def get_weight_color(weight):
                if not weight:
                    weight = 0
                x = (weight - weight_min) / (weight_max - weight_min)
                return "#{:02x}{:02x}{:02x}".format(
                    *[int(c * 255) for c in cmap(x)[0:3]])

            color_edges = True

    for (idx, jimage) in sites_to_draw:

        site = self.structure[idx]
        if jimage != (0, 0, 0):
            connected_sites = self.get_connected_sites(idx, jimage=jimage)
            site = PeriodicSite(
                site.species,
                np.add(site.frac_coords, jimage),
                site.lattice,
                properties=site.properties,
            )
        else:
            connected_sites = self.get_connected_sites(idx)

        connected_sites = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) in sites_to_draw
        ]
        connected_sites_not_drawn = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) not in sites_to_draw
        ]

        if color_edges:

            connected_sites_colors = [
                get_weight_color(cs.weight) for cs in connected_sites
            ]
            connected_sites_not_drawn_colors = [
                get_weight_color(cs.weight) for cs in connected_sites_not_drawn
            ]

        else:

            connected_sites_colors = None
            connected_sites_not_drawn_colors = None

        site_scene = site.get_scene(
            connected_sites=connected_sites,
            connected_sites_not_drawn=connected_sites_not_drawn,
            hide_incomplete_edges=hide_incomplete_edges,
            incomplete_edge_length_scale=incomplete_edge_length_scale,
            connected_sites_colors=connected_sites_colors,
            connected_sites_not_drawn_colors=connected_sites_not_drawn_colors,
            explicitly_calculate_polyhedra_hull=
            explicitly_calculate_polyhedra_hull,
            legend=legend,
        )
        for scene in site_scene.contents:
            primitives[scene.name] += scene.contents

    primitives["unit_cell"].append(self.structure.lattice.get_scene())

    return Scene(
        name=self.structure.composition.reduced_formula,
        origin=origin,
        contents=[
            Scene(name=k, contents=v, origin=origin)
            for k, v in primitives.items()
        ],
    )
Exemplo n.º 15
0
def generate_supercells(
    bulk_structure, 
    grid_size = 4, 
    supercell = (2, 2, 2), 
    method = 'grid', 
    positions=None
):
    """
    This is a wrapper to various methods to generate different interstitial impurities.
    
    Parameters
    ----------
    bulk_structure : Structure object
        A unitcell (magnetic or not) structure in form of Pymatgen Structure object 
    grid_size : int
        A grid size in all lattice directions to generate uniform 
        grid for interstitial impurities implemented by Pietro Bonfa. Default=4.
    supercell : tuple, numpy.ndarray
        Supercell size in a, b and c direction. Default = (2, 2, 2)
    method : str
        The method to generate interstial impurities. Default='grid'
    positions : None
        A numpy.ndarray of muon positions if `method="manual"`.
    
    Returns
    -------
    structure_list : list
        A list of supercell structure containing interstitial impurities
    """

    #magnetic_structure = CollinearMagneticStructureAnalyzer(bulk_structure, make_primitive=False)
    #if magnetic_structure.is_magnetic:
    #    #spin_bulk_structure = magnetic_structure.get_structure_with_spin()
    #    spin_bulk_structure =
    #    spin_bulk_structure.make_supercell(supercell)
    site_properties_preservation = bulk_structure.copy()
    site_properties_preservation.make_supercell(supercell)

    structure_list = []

    ## Manually set ?
    if method == 'manual':
        if positions is None:
            raise ValueError('Position must be specified in manual mode!')
        r = []
        for position in positions:
            defect_site = PeriodicSite("H", position, bulk_structure.lattice, coords_are_cartesian=False)
            r.append(Interstitial(bulk_structure, defect_site, charge=0.))
    elif method == 'tess':
        r = []
        for position in tess_interstitials(bulk_structure):
            defect_site = PeriodicSite("H", position, bulk_structure.lattice, coords_are_cartesian=False)
            r.append(Interstitial(bulk_structure, defect_site, charge=0.))
    elif method == 'infit':
        r = list(InterstitialGenerator( bulk_structure, 'H'))
    elif method == 'grid':
        r = []
        for position in generate_uniform_grid(bulk_structure, grid_size):
            defect_site = PeriodicSite("H", position, bulk_structure.lattice, coords_are_cartesian=False)
            r.append(Interstitial(bulk_structure, defect_site, charge=0.))
    else:
        r = list(VoronoiInterstitialGenerator( bulk_structure, 'H'))

    for i,v in enumerate(r):
        struct=v.generate_defect_structure(supercell=supercell)


        ## Preserve magnetic structure
        #if (magnetic_structure.is_magnetic):
        #    spins = np.zeros(struct.num_sites)
        #    # TODO: check non collinear...
        #    for site1 in spin_bulk_structure:
        #        for i, site2 in enumerate(struct):
        #            if np.allclose(site1.coords, site2.coords, atol = site2.position_atol):
        #                spins[i] = site1.specie.spin
        #                break
        #
        #    struct.add_spin_by_site(spins)

        for site1 in site_properties_preservation:
            for i, site2 in enumerate(struct):
                if np.allclose(site1.coords, site2.coords, atol = site2.position_atol):
                    #spins[i] = site1.specie.spin
                    struct[i].properties = site1.properties
                    break

        # Remove symmetry
        if method != 'manual':
            # Here we assume, manual muon site are perturb.
            # Performs a random perturbation of the sites in the structure 
            # to break symmetries. A distance of 1e-4 Angs. surely does nothing
            # However we can perturb the muon site with a random vector with
            # 0.1 Angs. distance
            struct.perturb(distance=0.0001)
            struct.translate_sites(-1, 0.1 * np.random.random(3), frac_coords=False)           
        if struct.is_valid():
            structure_list.append(struct)
    return structure_list
Exemplo n.º 16
0
def get_structure_graph_scene(
    self,
    origin=None,
    draw_image_atoms=True,
    bonded_sites_outside_unit_cell=True,
    hide_incomplete_edges=False,
    incomplete_edge_length_scale=0.3,
    color_edges_by_edge_weight=True,
    edge_weight_color_scale="coolwarm",
    explicitly_calculate_polyhedra_hull=False,
    legend: Optional[Legend] = None,
    group_by_symmetry: bool = True,
) -> Scene:

    origin = origin or list(
        -self.structure.lattice.get_cartesian_coords([0.5, 0.5, 0.5]))

    legend = legend or Legend(self.structure)

    primitives = defaultdict(list)

    sites_to_draw = self._get_sites_to_draw(
        draw_image_atoms=draw_image_atoms,
        bonded_sites_outside_unit_cell=bonded_sites_outside_unit_cell,
    )

    color_edges = False
    if color_edges_by_edge_weight:

        weights = [e[2].get("weight") for e in self.graph.edges(data=True)]
        weights = np.array([w for w in weights if w])

        if any(weights):

            cmap = get_cmap(edge_weight_color_scale)

            # try to keep color scheme symmetric around 0
            weight_max = max([abs(min(weights)), max(weights)])
            weight_min = -weight_max

            def get_weight_color(weight):
                if not weight:
                    weight = 0
                x = (weight - weight_min) / (weight_max - weight_min)
                return "#{:02x}{:02x}{:02x}".format(
                    *[int(c * 255) for c in cmap(x)[0:3]])

            color_edges = True

    idx_to_wyckoff = {}
    if group_by_symmetry:
        sga = SpacegroupAnalyzer(self.structure)
        struct_sym = sga.get_symmetrized_structure()
        for equiv_idxs, wyckoff in zip(struct_sym.equivalent_indices,
                                       struct_sym.wyckoff_symbols):
            for idx in equiv_idxs:
                idx_to_wyckoff[idx] = wyckoff

    for (idx, jimage) in sites_to_draw:

        site = self.structure[idx]
        if jimage != (0, 0, 0):
            connected_sites = self.get_connected_sites(idx, jimage=jimage)
            site = PeriodicSite(
                site.species,
                np.add(site.frac_coords, jimage),
                site.lattice,
                properties=site.properties,
            )
        else:
            connected_sites = self.get_connected_sites(idx)

        connected_sites = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) in sites_to_draw
        ]
        connected_sites_not_drawn = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) not in sites_to_draw
        ]

        if color_edges:

            connected_sites_colors = [
                get_weight_color(cs.weight) for cs in connected_sites
            ]
            connected_sites_not_drawn_colors = [
                get_weight_color(cs.weight) for cs in connected_sites_not_drawn
            ]

        else:

            connected_sites_colors = None
            connected_sites_not_drawn_colors = None

        site_scene = site.get_scene(
            connected_sites=connected_sites,
            connected_sites_not_drawn=connected_sites_not_drawn,
            hide_incomplete_edges=hide_incomplete_edges,
            incomplete_edge_length_scale=incomplete_edge_length_scale,
            connected_sites_colors=connected_sites_colors,
            connected_sites_not_drawn_colors=connected_sites_not_drawn_colors,
            explicitly_calculate_polyhedra_hull=
            explicitly_calculate_polyhedra_hull,
            legend=legend,
        )
        for scene in site_scene.contents:
            if group_by_symmetry and scene.name == "atoms" and idx in idx_to_wyckoff:
                # will rename to e.g. atoms_N_4e
                scene.name = f"atoms_{site_scene.name}_{idx_to_wyckoff[idx]}"
                # this is a proof-of-concept to demonstrate hover labels, could create label
                # automatically from site properties instead
                scene.contents[
                    0].tooltip = f"{site_scene.name} ({idx_to_wyckoff[idx]})"
            primitives[scene.name] += scene.contents

    primitives["unit_cell"].append(self.structure.lattice.get_scene())

    return Scene(
        name="StructureGraph",
        origin=origin,
        contents=[
            Scene(name=k, contents=v, origin=origin)
            for k, v in primitives.items()
        ],
    )
Exemplo n.º 17
0
def get_structure_graph_scene(
    self,
    origin=(0, 0, 0),
    draw_image_atoms=True,
    bonded_sites_outside_unit_cell=True,
    hide_incomplete_bonds=False,
    explicitly_calculate_polyhedra_hull=False,
) -> Scene:

    primitives = defaultdict(list)

    sites_to_draw = self._get_sites_to_draw(
        draw_image_atoms=draw_image_atoms,
        bonded_sites_outside_unit_cell=bonded_sites_outside_unit_cell,
    )

    for (idx, jimage) in sites_to_draw:

        site = self.structure[idx]
        if jimage != (0, 0, 0):
            connected_sites = self.get_connected_sites(idx, jimage=jimage)
            site = PeriodicSite(
                site.species,
                np.add(site.frac_coords, jimage),
                site.lattice,
                properties=site.properties,
            )
        else:
            connected_sites = self.get_connected_sites(idx)

        true_number_of_connected_sites = len(connected_sites)
        connected_sites_being_drawn = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) in sites_to_draw
        ]
        number_of_connected_sites_drawn = len(connected_sites_being_drawn)
        all_connected_sites_present = (
            true_number_of_connected_sites == number_of_connected_sites_drawn)
        if hide_incomplete_bonds:
            # only draw bonds if the destination site is also being drawn
            connected_sites = connected_sites_being_drawn

        site_scene = site.get_scene(
            connected_sites=connected_sites,
            all_connected_sites_present=all_connected_sites_present,
            origin=origin,
            explicitly_calculate_polyhedra_hull=
            explicitly_calculate_polyhedra_hull,
        )
        for scene in site_scene.contents:
            primitives[scene.name] += scene.contents

    # we are here ...
    # select polyhedra
    # split by atom type at center
    # see if any intersect, if yes split further
    # order sets, with each choice, go to add second set etc if don't intersect
    # they intersect if centre atom forms vertex of another atom (caveat: centre atom may not actually be inside polyhedra! not checking for this, add todo)
    # def _set_intersects() ->bool:
    # def _split_set() ->List: (by type, then..?)
    # def _order_sets()... pick 1, ask can add 2? etc

    primitives["unit_cell"].append(
        self.structure.lattice.get_scene(origin=origin))

    return Scene(
        name=self.structure.composition.reduced_formula,
        contents=[Scene(name=k, contents=v) for k, v in primitives.items()],
    )
Exemplo n.º 18
0
def get_all_neighbors_and_image(structure, r, include_index=False):

    """
    Modified from `pymatgen 
    <http://pymatgen.org/_modules/pymatgen/core/structure.html#IStructure.get_all_neighbors>`_ 
    to return image (used for mapping to supercell), and to use the f2py wrapped
    OpenMP dist subroutine to get the distances (smaller memory footprint and faster
    than numpy).

    Get neighbours for each atom in the unit cell, out to a distance r
    Returns a list of list of neighbors for each site in structure.
    Use this method if you are planning on looping over all sites in the
    crystal. If you only want neighbors for a particular site, use the
    method get_neighbors as it may not have to build such a large supercell
    However if you are looping over all sites in the crystal, this method
    is more efficient since it only performs one pass over a large enough
    supercell to contain all possible atoms out to a distance r.
    The return type is a [(site, dist) ...] since most of the time,
    subsequent processing requires the distance.

    
    Args:
        - r (float): Radius of sphere.
        - include_index (bool): Whether to include the non-supercell site
        - in the returned data

    Returns:
        - A list of a list of nearest neighbors for each site, i.e., 
        [[(site, dist, index, image) ...], ..]. Index only supplied if include_index = True.
        The index is the index of the site in the original (non-supercell)
        structure. This is needed for ewaldmatrix by keeping track of which
        sites contribute to the ewald sum.


    """
    recp_len = np.array(structure.lattice.reciprocal_lattice.abc)
    maxr = np.ceil((r + 0.15) * recp_len / (2 * math.pi))
    nmin = np.floor(np.min(structure.frac_coords, axis=0)) - maxr
    nmax = np.ceil(np.max(structure.frac_coords, axis=0)) + maxr

    all_ranges = [np.arange(x, y) for x, y in zip(nmin, nmax)]

    latt = structure._lattice
    neighbors = [list() for i in range(len(structure._sites))]
    all_fcoords = np.mod(structure.frac_coords, 1)
    coords_in_cell = latt.get_cartesian_coords(all_fcoords)
    site_coords = structure.cart_coords

    indices = np.arange(len(structure))
    for image in itertools.product(*all_ranges):
        coords = latt.get_cartesian_coords(image) + coords_in_cell
        all_dists = dist.dist(coords, site_coords, len(coords))
        all_within_r = np.bitwise_and(all_dists <= r, all_dists > 1e-8)

        for (j, d, within_r) in zip(indices, all_dists, all_within_r):
            nnsite = PeriodicSite(
                structure[j].specie,
                coords[j],
                latt,
                properties=structure[j].properties,
                coords_are_cartesian=True,
            )
            for i in indices[within_r]:
                item = (nnsite, d[i], j, image) if include_index else (nnsite, d[i])
                neighbors[i].append(item)
    return neighbors
Exemplo n.º 19
0
    def trialstep(self, spch_config, energy_now):

        e0 = energy_now

        structure = spch_config.structure.copy()
        structure_Osite = spch_config.structure.copy()
        structure_Osite.remove_species(["Pt", "Zr"])
        base_Osite = spch_config.Osite_struct.copy()

        # base_Osite.append("He", [0,0,0])
        # base_Osite.append("He", [0.4,0.5,0])
        # base_Osite.append("He", [0.3, 0.2, 0.4])
        # Osite.append("He", [0,0,0])
        # Osite.append("He", [0.4,0.5,0])
        # Osite.append("He", [0.3, 0.2, 0.4])
        # Figure out where the vacancies are by comparing with base_structure
        # filled_sites = self.matcher_site.get_mapping(base_Osite,
        #                                             Osite)
        # if not filled_sites.any():
        #    print("something went wrong at matching")
        #    sys.exit(1)
        # vac_struct = base_Osite
        # vac_struct.remove_sites(filled_sites)
        # Make sure the correct number of vacancies have been detected
        # assert len(vac_struct)==int(spch_config.N_Ovac*len(spch_config.Osite_struct))
        # choose one vacancy and one O atom randomly and flip
        # Osites = structure.indices_from_symbol("O")
        # O_flip = rand.choice(Osites)
        # del structure[O_flip]

        # choose one O atom and move it
        Osites = structure.indices_from_symbol("O")
        O_flip = rand.choice(Osites)
        del structure[O_flip]

        ntrial = 0
        while True:
            ntrial += 1
            Omove_candidate = PeriodicSite(
                "O",
                [
                    rand.random(),
                    rand.random(),
                    rand.uniform(spch_config.ZrO2boxZ[0], spch_config.ZrO2boxZ[1]),
                ],
                structure[0].lattice,
            )
            okflag = True
            for site in structure:
                if site.distance_and_image(Omove_candidate)[0] < 1.5:
                    okflag = False
                    break

            if okflag:
                break

        print("It took ", ntrial, " trials to find space for O")
        print(Omove_candidate.frac_coords)

        structure.append(
            "O", Omove_candidate.frac_coords, properties={"velocities": [0, 0, 0]}
        )
        # print(vac_flip.frac_coords)
        # structure.append("O", vac_candidate.frac_coords,properties={"velocities":[0]})
        # structure.to(fmt="poscar", filename="POSCAR.1")

        # Backup structure of previous step
        structure0 = spch_config.structure
        spch_config.structure = structure

        # do vasp calculation on structure
        e1 = self.energy(spch_config)

        # return old spch structure
        spch_config.structure = structure0

        # Simply pass new structure in dconfig to be used by newconfig():
        dconfig = structure

        dE = e1 - e0

        return dconfig, dE
Exemplo n.º 20
0
def get_structure_graph_scene(
    self,
    origin=(0, 0, 0),
    draw_image_atoms=True,
    bonded_sites_outside_unit_cell=True,
    hide_incomplete_edges=False,
    incomplete_edge_length_scale=0.3,
    color_edges_by_edge_weight=True,
    edge_weight_color_scale="coolwarm",
    explicitly_calculate_polyhedra_hull=False,
) -> Scene:

    primitives = defaultdict(list)

    sites_to_draw = self._get_sites_to_draw(
        draw_image_atoms=draw_image_atoms,
        bonded_sites_outside_unit_cell=bonded_sites_outside_unit_cell,
    )

    color_edges = False
    if color_edges_by_edge_weight:

        weights = [e[2].get("weight") for e in self.graph.edges(data=True)]
        weights = np.array([w for w in weights if w])

        if any(weights):

            cmap = get_cmap(edge_weight_color_scale)

            # try to keep color scheme symmetric around 0
            weight_max = max([abs(min(weights)), max(weights)])
            weight_min = -weight_max

            def get_weight_color(weight):
                if not weight:
                    weight = 0
                x = (weight - weight_min) / (weight_max - weight_min)
                return "#{:02x}{:02x}{:02x}".format(
                    *[int(c * 255) for c in cmap(x)[0:3]])

            color_edges = True

    for (idx, jimage) in sites_to_draw:

        site = self.structure[idx]
        if jimage != (0, 0, 0):
            connected_sites = self.get_connected_sites(idx, jimage=jimage)
            site = PeriodicSite(
                site.species,
                np.add(site.frac_coords, jimage),
                site.lattice,
                properties=site.properties,
            )
        else:
            connected_sites = self.get_connected_sites(idx)

        connected_sites = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) in sites_to_draw
        ]
        connected_sites_not_drawn = [
            cs for cs in connected_sites
            if (cs.index, cs.jimage) not in sites_to_draw
        ]

        if color_edges:

            connected_sites_colors = [
                get_weight_color(cs.weight) for cs in connected_sites
            ]
            connected_sites_not_drawn_colors = [
                get_weight_color(cs.weight) for cs in connected_sites_not_drawn
            ]

        else:

            connected_sites_colors = None
            connected_sites_not_drawn_colors = None

        site_scene = site.get_scene(
            connected_sites=connected_sites,
            connected_sites_not_drawn=connected_sites_not_drawn,
            hide_incomplete_edges=hide_incomplete_edges,
            incomplete_edge_length_scale=incomplete_edge_length_scale,
            connected_sites_colors=connected_sites_colors,
            connected_sites_not_drawn_colors=connected_sites_not_drawn_colors,
            origin=origin,
            explicitly_calculate_polyhedra_hull=
            explicitly_calculate_polyhedra_hull,
        )
        for scene in site_scene.contents:
            primitives[scene.name] += scene.contents

    # we are here ...
    # select polyhedra
    # split by atom type at center
    # see if any intersect, if yes split further
    # order sets, with each choice, go to add second set etc if don't intersect
    # they intersect if centre atom forms vertex of another atom (caveat: centre atom may not actually be inside polyhedra! not checking for this, add todo)
    # def _set_intersects() ->bool:
    # def _split_set() ->List: (by type, then..?)
    # def _order_sets()... pick 1, ask can add 2? etc

    primitives["unit_cell"].append(
        self.structure.lattice.get_scene(origin=origin))

    return Scene(
        name=self.structure.composition.reduced_formula,
        contents=[Scene(name=k, contents=v) for k, v in primitives.items()],
    )
Exemplo n.º 21
0
def folded_coords(site: PeriodicSite, center: GenCoords) -> GenCoords:
    _, image = site.distance_and_image_from_frac_coords(center)
    return tuple(site.frac_coords - image)
structure = Poscar.from_file('POSCAR_unit').structure
default_inputs = DefaultInputs(structure)
incar_settings = default_inputs.get_incar_default(xc='PBE')
incar_settings['LVTOT'] = '.TRUE.'
kpoints = Kpoints.gamma_automatic(kpts=(2, 2, 2))

supercell_size = 3
structure.make_supercell(supercell_size)

structure_pure = structure.copy()

for el in charge_states_dict:
    structure = structure_pure.copy()
    for s in structure.sites:
        if s.species_string == 'Na':
            defect_site = PeriodicSite(el, s.frac_coords, s.lattice)
            break

    substitution = Substitution(structure, defect_site)
    defect_site_coords = defect_site.frac_coords

    structure = substitution.generate_defect_structure()
    structure.get_sorted_structure()

    for charge in charge_states_dict[el]:
        path = os.path.join(os.getcwd(), f'{el}-substitution',
                            f'Charged{charge}')

        default_inputs = DefaultInputs(structure)
        potcar_symbols = []
        for s in default_inputs.potcar_symbols:
Exemplo n.º 23
0
def end_point_wf(mp_id, pair_index, image_num, moving_cation, col):
    """

    :param col: collection name
    :param mp_id: mp_id in the db_scripts
    :param pair_index: pair_index in the db_scripts
    :param image_num: index number of the image on the path from the db_scripts
    :param moving_cation: pymatgen.Element object, represeting the moving cation, e.g. Element('Mg')
    :return:
    """
    MyDB.db_access().connect()
    collection = MyDB.db_access().collection(col)

    doc = collection.find_one({'mp-id': mp_id, 'pair_index': pair_index})

    # Calculation that is already successful
    if 'MEP_energy' in doc.keys() and ("image_{}".format(image_num)
                                       in doc['MEP_energy']):
        if doc['MEP_energy']['image_{}'.format(
                image_num)]['status'] == 'success':
            return
        else:
            # Calculation that has halted halfway due to errors
            if 'CONTCAR_struct' in doc['MEP_energy']['image_{}'.format(
                    image_num)].keys():
                struct = Structure.from_dict(doc["MEP_energy"][
                    "image_{}".format(image_num)]["CONTCAR_struct"])
            # Calculation that has not been run before
            else:
                struct = Structure.from_dict(doc['gamma_structure'])
                cation_site = PeriodicSite.from_dict(doc['path'][image_num])
                struct.insert(0,
                              cation_site.specie,
                              cation_site.frac_coords,
                              properties=doc['path'][image_num]['properties'])
    else:
        struct = Structure.from_dict(doc['gamma_structure'])
        cation_site = PeriodicSite.from_dict(doc['path'][image_num])
        struct.insert(0,
                      cation_site.specie,
                      cation_site.frac_coords,
                      properties=doc['path'][image_num]['properties'])

    task1 = WritePointRunInput(structure=struct.as_dict(),
                               moving_cation=moving_cation.as_dict())
    task2 = PointCustodianRun(handlers='all')
    task3 = PointRunAnalyze()

    fw = Firework(
        [task1, task2, task3],
        spec={
            "mp_id": mp_id,
            "pair_index": pair_index,
            "image_num": image_num,
            "collection": col,
            "_queueadapter": {
                'nnodes': 128,
                'walltime': '10:00:00',
                'queue': 'Q.JCESR',
                'job_name': "{}_{}".format(doc["pretty_formula"], image_num)
            }
        })

    wf_list = [fw]
    wf_depend = {}
    wf = Workflow(wf_list, wf_depend)

    MyDB.db_access().close()
    return wf