예제 #1
0
    def from_dict(cls, d):
        """
        Args:
            d (dict): A dict with all data for a band structure symm line
                object.

        Returns:
            A BandStructureSymmLine object
        """
        try:
            # Strip the label to recover initial string (see trick used in as_dict to handle $ chars)
            labels_dict = {k.strip(): v for k, v in d["labels_dict"].items()}
            projections = {}
            structure = None
            if d.get("projections"):
                if isinstance(d["projections"]["1"][0][0], dict):
                    raise ValueError("Old band structure dict format detected!")
                structure = Structure.from_dict(d["structure"])
                projections = {
                    Spin(int(spin)): np.array(v) for spin, v in d["projections"].items()
                }

            return LobsterBandStructureSymmLine(
                d["kpoints"],
                {Spin(int(k)): d["bands"][k] for k in d["bands"]},
                Lattice(d["lattice_rec"]["matrix"]),
                d["efermi"],
                labels_dict,
                structure=structure,
                projections=projections,
            )
        except Exception:
            warnings.warn(
                "Trying from_dict failed. Now we are trying the old "
                "format. Please convert your BS dicts to the new "
                "format. The old format will be retired in pymatgen "
                "5.0."
            )
            return LobsterBandStructureSymmLine.from_old_dict(d)
예제 #2
0
    def apply_operation(self, symmop):
        """
        Apply a symmetry operation to the structure and return the new
        structure. The lattice is operated by the rotation matrix only.
        Coords are operated in full and then transformed to the new lattice.

        Args:
            symmop:
                Symmetry operation to apply.
        """
        self._lattice = Lattice(
            [symmop.apply_rotation_only(row) for row in self._lattice.matrix])

        def operate_site(site):
            new_cart = symmop.operate(site.coords)
            new_frac = self._lattice.get_fractional_coords(new_cart)
            return PeriodicSite(site.species_and_occu,
                                new_frac,
                                self._lattice,
                                properties=site.properties)

        self._sites = map(operate_site, self._sites)
    def test_apply_transformation(self):
        t = OxidationStateRemovalTransformation()
        coords = []
        coords.append([0, 0, 0])
        coords.append([0.75, 0.75, 0.75])
        coords.append([0.5, 0.5, 0.5])
        coords.append([0.25, 0.25, 0.25])
        lattice = Lattice([
            [3.8401979337, 0.00, 0.00],
            [1.9200989668, 3.3257101909, 0.00],
            [0.00, -2.2171384943, 3.1355090603],
        ])
        struct = Structure(lattice, ["Li+", "Li+", "O2-", "O2-"], coords)
        s = t.apply_transformation(struct)
        self.assertEqual(s[0].species_string, "Li")
        self.assertEqual(s[2].species_string, "O")

        d = t.as_dict()
        self.assertEqual(
            type(OxidationStateRemovalTransformation.from_dict(d)),
            OxidationStateRemovalTransformation,
        )
예제 #4
0
    def get_displacements(self):
        """
        Return the initial structure and displacements for each time step.
        Used to interface witht the DiffusionAnalyzer.

        Returns:
            Structure object, numpy array of displacements
        """
        lattice = Lattice([[self.box_lengths[0], 0, 0],
                           [0, self.box_lengths[1], 0],
                           [0, 0, self.box_lengths[2]]])
        mass_to_symbol = dict(
            (round(y["Atomic mass"], 1), x) for x, y in _pt_data.items())
        unique_atomic_masses = np.array(self.lammps_data.atomic_masses)[:, 1]
        frac_coords = []
        for step in range(self.timesteps.size):
            begin = step * self.natoms
            end = (step + 1) * self.natoms
            mol_vector_structured = \
                self.trajectory[begin:end][:][["x", "y", "z"]]
            new_shape = mol_vector_structured.shape + (-1,)
            mol_vector = mol_vector_structured.view(np.float64).reshape(
                new_shape)
            coords = mol_vector.copy()
            if step == 0:
                species = [
                    mass_to_symbol[round(unique_atomic_masses[atype - 1], 1)]
                    for atype in self.trajectory[begin:end][:]["atom_type"]]
                mol = Molecule(species, coords)
                structure = mol.get_boxed_structure(*self.box_lengths)
            step_frac_coords = [lattice.get_fractional_coords(crd)
                                for crd in coords]
            frac_coords.append(np.array(step_frac_coords)[:, None])
        frac_coords = np.concatenate(frac_coords, axis=1)
        dp = frac_coords[:, 1:] - frac_coords[:, :-1]
        dp = dp - np.round(dp)
        f_disp = np.cumsum(dp, axis=1)
        disp = lattice.get_cartesian_coords(f_disp)
        return structure, disp
예제 #5
0
    def test_get_distance_and_image_strict(self):
        for count in range(10):
            lengths = [np.random.randint(1, 100) for i in range(3)]
            lattice = [np.random.rand(3) * lengths[i]
                               for i in range(3)]
            lattice = Lattice(np.array(lattice))

            f1 = np.random.rand(3)
            f2 = np.random.rand(3)

            scope = list(range(-3, 4))
            min_image_dist = (float("inf"), None)
            for image in itertools.product(scope, scope, scope):
                cart = lattice.get_cartesian_coords(f1 - (f2 + image))
                dist = np.dot(cart, cart) ** 0.5
                if dist < min_image_dist[0]:
                    min_image_dist = (dist, image)

            pmg_result = lattice.get_distance_and_image(f1, f2)
            self.assertGreaterEqual(min_image_dist[0] + 1e-7, pmg_result[0])
            if abs(min_image_dist[0] - pmg_result[0]) < 1e-12:
                self.assertArrayAlmostEqual(min_image_dist[1], pmg_result[1])
예제 #6
0
 def test_static_methods(self):
     lengths_c = [3.840198, 3.84019885, 3.8401976]
     angles_c = [119.99998575, 90, 60.00000728]
     mat_c = [[3.840198, 0.000000, 0.0000], [1.920099, 3.325710, 0.000000],
              [0.000000, -2.217138, 3.135509]]
     # should give the lengths and angles above
     newlatt = Lattice(mat_c)
     lengths = newlatt.lengths
     angles = newlatt.angles
     for i in range(0, 3):
         self.assertAlmostEqual(lengths[i], lengths_c[i], 5,
                                "Lengths incorrect!")
         self.assertAlmostEqual(angles[i], angles_c[i], 5,
                                "Angles incorrect!")
     latt = Lattice.from_parameters(*lengths, *angles)
     lengths = latt.lengths
     angles = latt.angles
     for i in range(0, 3):
         self.assertAlmostEqual(lengths[i], lengths_c[i], 5,
                                "Lengths incorrect!")
         self.assertAlmostEqual(angles[i], angles_c[i], 5,
                                "Angles incorrect!")
예제 #7
0
    def test_kpath_generation(self):
        triclinic = [1, 2]
        monoclinic = range(3, 16)
        orthorhombic = range(16, 75)
        tetragonal = range(75, 143)
        rhombohedral = range(143, 168)
        hexagonal = range(168, 195)
        cubic = range(195, 231)

        species = ["K", "La", "Ti"]
        coords = [[0.345, 5, 0.77298], [0.1345, 5.1, 0.77298], [0.7, 0.8, 0.9]]
        for i in range(230):
            sg_num = i + 1
            if sg_num in triclinic:
                lattice = Lattice(
                    [
                        [3.0233057319441246, 1, 0],
                        [0, 7.9850357844548681, 1],
                        [0, 1.2, 8.1136762279561818],
                    ]
                )
            elif sg_num in monoclinic:
                lattice = Lattice.monoclinic(2, 9, 1, 99)
            elif sg_num in orthorhombic:
                lattice = Lattice.orthorhombic(2, 9, 1)
            elif sg_num in tetragonal:
                lattice = Lattice.tetragonal(2, 9)
            elif sg_num in rhombohedral:
                lattice = Lattice.hexagonal(2, 95)
            elif sg_num in hexagonal:
                lattice = Lattice.hexagonal(2, 9)
            elif sg_num in cubic:
                lattice = Lattice.cubic(2)

            struct = Structure.from_spacegroup(sg_num, lattice, species, coords)

            # Throws error if something doesn't work, causing test to fail.
            kpath = HighSymmKpath(struct, path_type="all")
            kpoints = kpath.get_kpoints()
예제 #8
0
    def from_old_dict(cls, d):
        """
        Args:
            d (dict): A dict with all data for a band structure symm line
                object.
        Returns:
            A BandStructureSymmLine object
        """
        # Strip the label to recover initial string (see trick used in as_dict to handle $ chars)
        labels_dict = {k.strip(): v for k, v in d['labels_dict'].items()}
        projections = {}
        structure = None
        if 'projections' in d and len(d['projections']) != 0:
            structure = Structure.from_dict(d['structure'])
            projections = {}
            for spin in d['projections']:
                dd = []
                for i in range(len(d['projections'][spin])):
                    ddd = []
                    for j in range(len(d['projections'][spin][i])):
                        dddd = []
                        for k in range(len(d['projections'][spin][i][j])):
                            ddddd = []
                            orb = Orbital(k).name
                            for l in range(len(d['projections'][spin][i][j][
                                                   orb])):
                                ddddd.append(d['projections'][spin][i][j][
                                                orb][l])
                            dddd.append(np.array(ddddd))
                        ddd.append(np.array(dddd))
                    dd.append(np.array(ddd))
                projections[Spin(int(spin))] = np.array(dd)

        return BandStructureSymmLine(
            d['kpoints'], {Spin(int(k)): d['bands'][k]
                           for k in d['bands']},
            Lattice(d['lattice_rec']['matrix']), d['efermi'],
            labels_dict, structure=structure, projections=projections)
예제 #9
0
    def get_structures_from_trajectory(self):
        """
        Convert the coordinates in each time step to a structure(boxed molecule).
        Used to construct DiffusionAnalyzer object.

        Returns:
            list of Structure objects
        """
        lattice = Lattice([[self.box_lengths[0], 0, 0],
                           [0, self.box_lengths[1], 0],
                           [0, 0, self.box_lengths[2]]])
        structures = []
        mass_to_symbol = dict(
            (round(y["Atomic mass"], 1), x) for x, y in _pt_data.items())
        unique_atomic_masses = np.array(self.lammps_data.atomic_masses)[:, 1]
        for step in range(self.timesteps.size):
            begin = step * self.natoms
            end = (step + 1) * self.natoms
            mol_vector_structured = \
                self.trajectory[begin:end][:][["x", "y", "z"]]
            new_shape = mol_vector_structured.shape + (-1, )
            mol_vector = mol_vector_structured.view(
                np.float64).reshape(new_shape)
            coords = mol_vector.copy()
            species = [
                mass_to_symbol[round(unique_atomic_masses[atype - 1], 1)]
                for atype in self.trajectory[begin:end][:]["atom_type"]
            ]
            try:
                structure = Structure(lattice,
                                      species,
                                      coords,
                                      coords_are_cartesian=True)
            except ValueError as error:
                print("Error: '{}' at timestep {} in the trajectory".format(
                    error, int(self.timesteps[step])))
            structures.append(structure)
        return structures
    def test_apply_transformation(self):
        t = OrderDisorderedStructureTransformation()
        coords = list()
        coords.append([0, 0, 0])
        coords.append([0.75, 0.75, 0.75])
        coords.append([0.5, 0.5, 0.5])
        coords.append([0.25, 0.25, 0.25])
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])

        struct = Structure(lattice, [{"Si4+":0.5, "O2-": 0.25, "P5+": 0.25},
                                     {"Si4+":0.5, "O2-": 0.25, "P5+": 0.25},
                                     {"Si4+":0.5, "O2-": 0.25, "P5+": 0.25},
                                     {"Si4+":0.5, "O2-": 0.25, "P5+": 0.25}],
                           coords)
        output = t.apply_transformation(struct, return_ranked_list=50)
        self.assertEqual(len(output), 12)
        self.assertIsInstance(output[0]['structure'], Structure)

        struct = Structure(lattice, [{"Si4+": 0.5}, {"Si4+": 0.5},
                                     {"P5+": 0.5, "O2-": 0.5},
                                     {"P5+": 0.5, "O2-": 0.5}],
                           coords)
        output = t.apply_transformation(struct, return_ranked_list=50)
        self.assertIsInstance(output, list)
        self.assertEqual(len(output), 4)
        self.assertEqual(t.lowest_energy_structure, output[0]['structure'])

        struct = Structure(lattice, [{"Si4+":0.5}, {"Si4+":0.5}, {"O2-": 0.5},
                                     {"O2-": 0.5}], coords)
        allstructs = t.apply_transformation(struct, 50)
        self.assertEqual(len(allstructs), 4)

        struct = Structure(lattice, [{"Si4+": 0.333}, {"Si4+": 0.333},
                                     {"Si4+": 0.333}, "O2-"], coords)
        allstructs = t.apply_transformation(struct, 50)
        self.assertEqual(len(allstructs), 3)
예제 #11
0
    def from_dict(cls, d):
        """
        Create from dict.

        Args:
            A dict with all data for a band structure object.

        Returns:
            A BandStructure object
        """
        labels_dict = d['labels_dict']
        projections = {}
        structure = None
        if 'structure' in d:
            structure = Structure.from_dict(d['structure'])
        if 'projections' in d and len(d['projections']) != 0:
            projections = {
                Spin.from_int(int(spin)):
                [[{
                    Orbital.from_string(orb): [
                        d['projections'][spin][i][j][orb][k]
                        for k in range(len(d['projections'][spin][i][j][orb]))
                    ]
                    for orb in d['projections'][spin][i][j]
                } for j in range(len(d['projections'][spin][i]))]
                 for i in range(len(d['projections'][spin]))]
                for spin in d['projections']
            }

        return BandStructure(
            d['kpoints'],
            {Spin.from_int(int(k)): d['bands'][k]
             for k in d['bands']},
            Lattice(d['lattice_rec']['matrix']),
            d['efermi'],
            labels_dict,
            structure=structure,
            projections=projections)
예제 #12
0
    def from_dict(cls, d):
        """

        Args:
            d (dict): Dict representation

        Returns:
            GruneisenPhononBandStructure: Phonon band structure with Grueneisen parameters.

        """

        lattice_rec = Lattice(d["lattice_rec"]["matrix"])
        eigendisplacements = np.array(d["eigendisplacements"]["real"]) + np.array(d["eigendisplacements"]["imag"]) * 1j
        structure = Structure.from_dict(d["structure"]) if "structure" in d else None
        return cls(
            qpoints=d["qpoints"],
            frequencies=np.array(d["bands"]),
            gruneisenparameters=np.array(d["gruneisen"]),
            lattice=lattice_rec,
            eigendisplacements=eigendisplacements,
            labels_dict=d["labels_dict"],
            structure=structure,
        )
예제 #13
0
 def test_get_vector_along_lattice_directions(self):
     lattice_mat = np.array(
         [[0.5, 0.0, 0.0], [0.5, np.sqrt(3) / 2.0, 0.0], [0.0, 0.0, 1.0]]
     )
     lattice = Lattice(lattice_mat)
     cart_coord = np.array([0.5, np.sqrt(3) / 4.0, 0.5])
     latt_coord = np.array([0.25, 0.5, 0.5])
     from_direct = lattice.get_fractional_coords(cart_coord) * lattice.lengths
     self.assertArrayAlmostEqual(
         lattice.get_vector_along_lattice_directions(cart_coord), from_direct
     )
     self.assertArrayAlmostEqual(
         lattice.get_vector_along_lattice_directions(cart_coord), latt_coord
     )
     self.assertArrayEqual(
         lattice.get_vector_along_lattice_directions(cart_coord).shape, [3,]
     )
     self.assertArrayEqual(
         lattice.get_vector_along_lattice_directions(
             cart_coord.reshape([1, 3])
         ).shape,
         [1, 3],
     )
    def test_apply_transformation(self):
        t = ChargeBalanceTransformation("Li+")
        coords = []
        coords.append([0, 0, 0])
        coords.append([0.375, 0.375, 0.375])
        coords.append([0.5, 0.5, 0.5])
        coords.append([0.875, 0.875, 0.875])
        coords.append([0.125, 0.125, 0.125])
        coords.append([0.25, 0.25, 0.25])
        coords.append([0.625, 0.625, 0.625])
        coords.append([0.75, 0.75, 0.75])

        lattice = Lattice(
            [
                [3.8401979337, 0.00, 0.00],
                [1.9200989668, 3.3257101909, 0.00],
                [0.00, -2.2171384943, 3.1355090603],
            ]
        )
        struct = Structure(lattice, ["Li+", "Li+", "Li+", "Li+", "Li+", "Li+", "O2-", "O2-"], coords)
        s = t.apply_transformation(struct)

        self.assertAlmostEqual(s.charge, 0, 5)
예제 #15
0
 def test_fractional_substitution(self):
     t = SubstitutionTransformation({
         "Li+": "Na+",
         "O2-": {
             "S2-": 0.5,
             "Se2-": 0.5
         }
     })
     # test the to and from dict on the nested dictionary
     t = SubstitutionTransformation.from_dict(t.as_dict())
     coords = []
     coords.append([0, 0, 0])
     coords.append([0.75, 0.75, 0.75])
     coords.append([0.5, 0.5, 0.5])
     coords.append([0.25, 0.25, 0.25])
     lattice = Lattice([
         [3.8401979337, 0.00, 0.00],
         [1.9200989668, 3.3257101909, 0.00],
         [0.00, -2.2171384943, 3.1355090603],
     ])
     struct = Structure(lattice, ["Li+", "Li+", "O2-", "O2-"], coords)
     s = t.apply_transformation(struct)
     self.assertEqual(s.composition.formula, "Na2 Se1 S1")
예제 #16
0
 def test_distance_and_image(self):
     other_site = PeriodicSite("Fe", np.array([1, 1, 1]), self.lattice)
     (distance, image) = self.site.distance_and_image(other_site)
     self.assertAlmostEqual(distance, 6.22494979899, 5)
     self.assertTrue(([-1, -1, -1] == image).all())
     (distance, image) = self.site.distance_and_image(other_site, [1, 0, 0])
     self.assertAlmostEqual(distance, 19.461500456028563, 5)
     # Test that old and new distance algo give the same ans for
     # "standard lattices"
     lattice = Lattice(np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))
     site1 = PeriodicSite("Fe", np.array([0.01, 0.02, 0.03]), lattice)
     site2 = PeriodicSite("Fe", np.array([0.99, 0.98, 0.97]), lattice)
     self.assertAlmostEqual(
         get_distance_and_image_old(site1, site2)[0],
         site1.distance_and_image(site2)[0],
     )
     lattice = Lattice.from_parameters(1, 0.01, 1, 10, 10, 10)
     site1 = PeriodicSite("Fe", np.array([0.01, 0.02, 0.03]), lattice)
     site2 = PeriodicSite("Fe", np.array([0.99, 0.98, 0.97]), lattice)
     self.assertTrue(get_distance_and_image_old(site1, site2)[0] > site1.distance_and_image(site2)[0])
     site2 = PeriodicSite("Fe", np.random.rand(3), lattice)
     (dist_old, jimage_old) = get_distance_and_image_old(site1, site2)
     (dist_new, jimage_new) = site1.distance_and_image(site2)
     self.assertTrue(
         dist_old - dist_new > -1e-8,
         "New distance algo should give smaller answers!",
     )
     self.assertFalse(
         (abs(dist_old - dist_new) < 1e-8) ^ (jimage_old == jimage_new).all(),
         "If old dist == new dist, images must be the same!",
     )
     latt = Lattice.from_parameters(3.0, 3.1, 10.0, 2.96, 2.0, 1.0)
     site = PeriodicSite("Fe", [0.1, 0.1, 0.1], latt)
     site2 = PeriodicSite("Fe", [0.99, 0.99, 0.99], latt)
     (dist, img) = site.distance_and_image(site2)
     self.assertAlmostEqual(dist, 0.15495358379511573)
     self.assertEqual(list(img), [-11, 6, 0])
def lammps_lattice(structure):
    """
    Imposes transformation for non-orthorobic cell for LAMMPS to read cell_lengths and tilt_factors, creates a new pymatgen structure object with the new transformation and associated forces.
    
    Args:
        structure (obj): A pymatgen structural object created from a POSCAR, with forces from an OUTCAR included as site properties.
    
    Returns:
        cell_lengths (np.array): Lengths of each cell direction.
        tilt_factors (np.array): Tilt factors of the cell.
        new_structure (obj): A pymatgen structural object created from the transformed matrix structure, with forces included as site properties.
    """
    a, b, c = structure.lattice.matrix
    if np.cross(a, b).dot(c) < 0:
        raise ValueError(
            'This is a left-hand coordinate system. Lammps requires a right-hand coordinate system.'
        )
    else:
        abc = abc_matrix(a, b, c)
        #         abc[0,1] = 0.00
        #         abc[0,2] = 0.00
        #         abc[1,2] = 0.00
        new_lattice = Lattice(abc)
        cell_lengths = np.array([abc[0, 0], abc[1, 1], abc[2, 2]])
        tilt_factors = np.array([abc[0, 1], abc[0, 2], abc[1, 2]])
        new_base = new_basis(abc, structure.lattice)

        new_coords = apply_new_basis(new_base, structure.cart_coords.T)
        new_forces = apply_new_basis(
            new_base,
            np.array(structure.site_properties['forces']).T)
        new_structure = Structure(new_lattice,
                                  structure.species,
                                  new_coords,
                                  coords_are_cartesian=True,
                                  site_properties={'forces': new_forces})
    return cell_lengths, tilt_factors, new_structure
예제 #18
0
 def get_orthogonal_c_slab(self):
     """
     This method returns a Slab where the normal (c lattice vector) is
     "forced" to be exactly orthogonal to the surface a and b lattice
     vectors. **Note that this breaks inherent symmetries in the slab.**
     It should be pointed out that orthogonality is not required to get good
     surface energies, but it can be useful in cases where the slabs are
     subsequently used for postprocessing of some kind, e.g. generating
     GBs or interfaces.
     """
     a, b, c = self.lattice.matrix
     new_c = np.cross(a, b)
     new_c /= np.linalg.norm(new_c)
     new_c = np.dot(c, new_c) * new_c
     new_latt = Lattice([a, b, new_c])
     return Slab(lattice=new_latt,
                 species=self.species,
                 coords=self.cart_coords,
                 miller_index=self.miller_index,
                 oriented_unit_cell=self.oriented_unit_cell,
                 shift=self.shift,
                 scale_factor=self.scale_factor,
                 coords_are_cartesian=True,
                 energy=self.energy)
예제 #19
0
    def from_dict(cls, d):
        """
        Create from dict.

        Args:
            A dict with all data for a band structure object.

        Returns:
            A BandStructure object
        """
        eigenvals = {}
        labels_dict = d['labels_dict']
        projections = {}
        structure = None
        if isinstance(d['bands'].values()[0], dict):
            eigenvals = {
                Spin(int(k)): np.array(d['bands'][k]['data'])
                for k in d['bands']
            }
        else:
            eigenvals = {Spin(int(k)): d['bands'][k] for k in d['bands']}
        if 'structure' in d:
            structure = Structure.from_dict(d['structure'])
        if d.get('projections'):
            projections = {
                Spin(int(spin)): np.array(v)
                for spin, v in d["projections"].items()
            }

        return BandStructure(d['kpoints'],
                             eigenvals,
                             Lattice(d['lattice_rec']['matrix']),
                             d['efermi'],
                             labels_dict,
                             structure=structure,
                             projections=projections)
예제 #20
0
    def from_dict(cls, d):
        """
        Args:
            d (dict): A dict with all data for a band structure symm line
                object.

        Returns:
            A BandStructureSymmLine object
        """
        try:
            # Strip the label to recover initial string (see trick used in as_dict to handle $ chars)
            labels_dict = {k.strip(): v for k, v in d['labels_dict'].items()}
            projections = {}
            structure = None
            if d.get('projections'):
                structure = Structure.from_dict(d['structure'])
                projections = {
                    Spin(int(spin)): np.array(v)
                    for spin, v in d["projections"].items()
                }

            return BandStructureSymmLine(
                d['kpoints'],
                {Spin(int(k)): d['bands'][k]
                 for k in d['bands']},
                Lattice(d['lattice_rec']['matrix']),
                d['efermi'],
                labels_dict,
                structure=structure,
                projections=projections)
        except:
            warnings.warn("Trying from_dict failed. Now we are trying the old "
                          "format. Please convert your BS dicts to the new "
                          "format. The old format will be retired in pymatgen "
                          "5.0.")
            return BandStructureSymmLine.from_old_dict(d)
예제 #21
0
    def from_dict(cls, d):
        """
        Args:
            A dict with all data for a band structure symm line object.

        Returns:
            A BandStructureSymmLine object
        """
        # Strip the label to recover initial string (see trick used in as_dict to handle $ chars)
        labels_dict = {k.strip(): v for k, v in d['labels_dict'].items()}
        projections = {}
        structure = None
        if 'projections' in d and len(d['projections']) != 0:
            structure = Structure.from_dict(d['structure'])
            projections = {
                Spin.from_int(int(spin)):
                [[{
                    Orbital.from_string(orb): [
                        d['projections'][spin][i][j][orb][k]
                        for k in range(len(d['projections'][spin][i][j][orb]))
                    ]
                    for orb in d['projections'][spin][i][j]
                } for j in range(len(d['projections'][spin][i]))]
                 for i in range(len(d['projections'][spin]))]
                for spin in d['projections']
            }

        return BandStructureSymmLine(
            d['kpoints'],
            {Spin.from_int(int(k)): d['bands'][k]
             for k in d['bands']},
            Lattice(d['lattice_rec']['matrix']),
            d['efermi'],
            labels_dict,
            structure=structure,
            projections=projections)
예제 #22
0
    def from_dict(cls, d):
        """

        Args:
            d: Dict representation

        Returns: PhononBandStructureSummLine

        """
        lattice_rec = Lattice(d["lattice_rec"]["matrix"])
        eigendisplacements = np.array(
            d["eigendisplacements"]["real"]) + np.array(
                d["eigendisplacements"]["imag"]) * 1j
        structure = Structure.from_dict(
            d["structure"]) if "structure" in d else None
        return cls(
            d["qpoints"],
            np.array(d["bands"]),
            lattice_rec,
            d["has_nac"],
            eigendisplacements,
            d["labels_dict"],
            structure=structure,
        )
예제 #23
0
 def setUp(self):
     self.lattice = Lattice([0.5, 0.5, 0, 0, 0.5, 0, 0, 0, 0.4])
예제 #24
0
    def get_ieee_rotation(structure, refine_rotation=True):
        """
        Given a structure associated with a tensor, determines
        the rotation matrix for IEEE conversion according to
        the 1987 IEEE standards.

        Args:
            structure (Structure): a structure associated with the
                tensor to be converted to the IEEE standard
            refine_rotation (bool): whether to refine the rotation
                using SquareTensor.refine_rotation
        """
        # Check conventional setting:
        sga = SpacegroupAnalyzer(structure)
        dataset = sga.get_symmetry_dataset()
        trans_mat = dataset['transformation_matrix']
        conv_latt = Lattice(
            np.transpose(
                np.dot(np.transpose(structure.lattice.matrix),
                       np.linalg.inv(trans_mat))))
        xtal_sys = sga.get_crystal_system()

        vecs = conv_latt.matrix
        lengths = np.array(conv_latt.abc)
        angles = np.array(conv_latt.angles)
        rotation = np.zeros((3, 3))

        # IEEE rules: a,b,c || x1,x2,x3
        if xtal_sys == "cubic":
            rotation = [vecs[i] / lengths[i] for i in range(3)]

        # IEEE rules: a=b in length; c,a || x3, x1
        elif xtal_sys == "tetragonal":
            rotation = np.array([
                vec / mag
                for (mag,
                     vec) in sorted(zip(lengths, vecs), key=lambda x: x[0])
            ])
            if abs(lengths[2] - lengths[1]) < abs(lengths[1] - lengths[0]):
                rotation[0], rotation[2] = rotation[2], rotation[0].copy()
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: c<a<b; c,a || x3,x1
        elif xtal_sys == "orthorhombic":
            rotation = [vec / mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation = np.roll(rotation, 2, axis=0)

        # IEEE rules: c,a || x3,x1, c is threefold axis
        # Note this also includes rhombohedral crystal systems
        elif xtal_sys in ("trigonal", "hexagonal"):
            # find threefold axis:
            tf_index = np.argmin(abs(angles - 120.))
            non_tf_mask = np.logical_not(angles == angles[tf_index])
            rotation[2] = get_uvec(vecs[tf_index])
            rotation[0] = get_uvec(vecs[non_tf_mask][0])
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))

        # IEEE rules: b,c || x2,x3; alpha=beta=90, c<a
        elif xtal_sys == "monoclinic":
            # Find unique axis
            u_index = np.argmax(abs(angles - 90.))
            n_umask = np.logical_not(angles == angles[u_index])
            rotation[1] = get_uvec(vecs[u_index])
            # Shorter of remaining lattice vectors for c axis
            c = [
                vec / mag
                for (mag, vec) in sorted(zip(lengths[n_umask], vecs[n_umask]))
            ][0]
            rotation[2] = np.array(c)
            rotation[0] = np.cross(rotation[1], rotation[2])

        # IEEE rules: c || x3, x2 normal to ac plane
        elif xtal_sys == "triclinic":
            rotation = [vec / mag for (mag, vec) in sorted(zip(lengths, vecs))]
            rotation[1] = get_uvec(np.cross(rotation[2], rotation[0]))
            rotation[0] = np.cross(rotation[1], rotation[2])

        rotation = SquareTensor(rotation)
        if refine_rotation:
            rotation = rotation.refine_rotation()

        return rotation
예제 #25
0
파일: atat.py 프로젝트: mhsiron/pymatgen
    def structure_from_string(data):
        """
        Parses a rndstr.in, lat.in or bestsqs.out file into pymatgen's
        Structure format.

        :param data: contents of a rndstr.in, lat.in or bestsqs.out file
        :return: Structure object
        """

        data = data.splitlines()
        data = [x.split() for x in data if x]  # remove empty lines

        # following specification/terminology given in manual
        if len(data[0]) == 6:  # lattice parameters
            a, b, c, alpha, beta, gamma = map(float, data[0])
            coord_system = Lattice.from_parameters(a, b, c, alpha, beta,
                                                   gamma).matrix
            lattice_vecs = np.array(
                [
                    [data[1][0], data[1][1], data[1][2]],
                    [data[2][0], data[2][1], data[2][2]],
                    [data[3][0], data[3][1], data[3][2]],
                ],
                dtype=float,
            )
            first_species_line = 4
        else:
            coord_system = np.array(
                [
                    [data[0][0], data[0][1], data[0][2]],
                    [data[1][0], data[1][1], data[1][2]],
                    [data[2][0], data[2][1], data[2][2]],
                ],
                dtype=float,
            )
            lattice_vecs = np.array(
                [
                    [data[3][0], data[3][1], data[3][2]],
                    [data[4][0], data[4][1], data[4][2]],
                    [data[5][0], data[5][1], data[5][2]],
                ],
                dtype=float,
            )
            first_species_line = 6

        scaled_matrix = np.matmul(lattice_vecs, coord_system)
        lattice = Lattice(scaled_matrix)

        all_coords = []
        all_species = []
        for l in data[first_species_line:]:

            coords = np.array([l[0], l[1], l[2]], dtype=float)
            scaled_coords = np.matmul(coords, np.linalg.inv(lattice_vecs))
            all_coords.append(scaled_coords)

            species_strs = "".join(
                l[3:])  # join multiple strings back together
            species_strs = species_strs.replace(" ",
                                                "")  # trim any white space
            species_strs = species_strs.split(",")  # comma-delimited

            species = {}

            for species_occ in species_strs:

                # gets a species, occupancy pair
                species_occ = species_occ.split("=")

                if len(species_occ) == 1:
                    # assume occupancy is 1.0
                    species_occ = [species_occ[0], 1.0]

                if "_" in species_occ[0]:
                    # see to_string() method in this file, since , and = are not valid
                    # species names in AT-AT we replace "," with "__" and "=" with "___",
                    # for pymatgen to parse these back correctly we have to replace them back
                    species_occ[0] = (species_occ[0].replace("___",
                                                             "=").replace(
                                                                 "__", ","))

                species[get_el_sp(species_occ[0])] = float(species_occ[1])

            all_species.append(species)

        return Structure(lattice, all_species, all_coords)
예제 #26
0
def read_data(data=None, ff=None):
    """
    Read LAMMPS data file

    Args:
        data: data file path
        ff: potential.mod/potential information file path
    Returns:
          struct: Structure object
    """
    pot_file = open(ff, "r")
    lines = pot_file.read().splitlines()
    symb = []
    count = 0
    from pymatgen.core.periodic_table import Element

    for i, line in enumerate(lines):
        if "pair_coeff" in line.split():
            sp = line.split()
            print("spsplit", sp, os.getcwd())
            for el in sp:
                try:
                    if Element(el):
                        # if el=='M':
                        #    el='Mo'
                        # count=count+1
                        # if count >4:
                        symb.append(el)
                except:
                    pass
    print("symb=", symb)

    f = open(data, "r")
    lines = f.read().splitlines()
    for i, line in enumerate(lines):
        if "atoms" in line.split():
            natoms = int(line.split()[0])
        if "types" in line.split():
            print(line)
            ntypes = int(line.split()[0])
        if "xlo" in line.split():
            xlo = float(line.split()[0])
            xhi = float(line.split()[1])
        if "ylo" in line.split():
            ylo = float(line.split()[0])
            yhi = float(line.split()[1])
        if "zlo" in line.split():
            zlo = float(line.split()[0])
            zhi = float(line.split()[1])
        if "xy" in line.split():
            xy = float(line.split()[0])
            xz = float(line.split()[1])
            yz = float(line.split()[2])
    if len(symb) != ntypes:
        print("Something wrong in atom type assignment", len(symb), ntypes)
        sys.exit()
    lat = Lattice([[xhi - xlo, 0.0, 0.0], [xy, yhi - ylo, 0.0], [xz, yz, zhi - zlo]])
    typ = np.empty((natoms), dtype="S20")
    x = np.zeros((natoms))
    y = np.zeros((natoms))
    z = np.zeros((natoms))
    q = np.zeros((natoms))
    coords = list()
    for i, line in enumerate(lines):
        if "Atoms" in line.split():
            for j in range(0, natoms):
                # print int(((lines[j+2]).split()[1]))-1
                typ[j] = symb[int(((lines[i + j + 2]).split()[1])) - 1]
                q[j] = (lines[i + j + 2]).split()[2]
                x[j] = (lines[i + j + 2]).split()[3]
                y[j] = (lines[i + j + 2]).split()[4]
                z[j] = (lines[i + j + 2]).split()[5]
                coords.append([x[j], y[j], z[j]])
    f.close()
    # print ("info",(typ),'coo',(coords),'latt',lat)
    pot_file.close()
    typ_sp = [str(i, "utf-8") for i in typ]
    struct = Structure(lat, typ_sp, coords, coords_are_cartesian=True)
    # print struct
    # finder = SpacegroupAnalyzer(struct)
    # num=finder.get_spacegroup_symbol()
    # print(num)
    return struct
예제 #27
0
    def setUp(self):
        self.ref_lat = np.array([[1.59205, -2.757511, 0.0],
                                 [1.59205, 2.757511, 0.0], [0.0, 0.0, 5.1551]])

        self.ref_pmg_lat = Lattice(self.ref_lat)
예제 #28
0
 def test_get_wigner_seitz_cell(self):
     ws_cell = Lattice([[10, 0, 0], [0, 5, 0], [0, 0, 1]])\
         .get_wigner_seitz_cell()
     self.assertEqual(6, len(ws_cell))
     for l in ws_cell[3]:
         self.assertEqual([abs(i) for i in l], [5.0, 2.5, 0.5])
예제 #29
0
 def setUp(self):
     self.silicon = Structure(
         Lattice.from_lengths_and_angles([5.47, 5.47, 5.47],
                                         [90.0, 90.0, 90.0]),
         ["Si", "Si", "Si", "Si", "Si", "Si", "Si", "Si"],
         [[0.000000, 0.000000, 0.500000], [0.750000, 0.750000, 0.750000],
          [0.000000, 0.500000, 1.000000], [0.750000, 0.250000, 0.250000],
          [0.500000, 0.000000, 1.000000], [0.250000, 0.750000, 0.250000],
          [0.500000, 0.500000, 0.500000], [0.250000, 0.250000, 0.750000]],
         validate_proximity=False,
         to_unit_cell=False,
         coords_are_cartesian=False,
         site_properties=None)
     self.smi = StructureMotifInterstitial(
         self.silicon,
         "Si",
         motif_types=["tetrahedral", "octahedral"],
         op_threshs=[0.3, 0.5],
         dl=0.4,
         doverlap=1.0,
         facmaxdl=1.51)
     self.diamond = Structure(
         Lattice([[2.189, 0, 1.264], [0.73, 2.064, 1.264], [0, 0, 2.528]]),
         ["C0+", "C0+"], [[2.554, 1.806, 4.423], [0.365, 0.258, 0.632]],
         validate_proximity=False,
         to_unit_cell=False,
         coords_are_cartesian=True,
         site_properties=None)
     self.nacl = Structure(Lattice([[3.485, 0,
                                     2.012], [1.162, 3.286, 2.012],
                                    [0, 0, 4.025]]), ["Na1+", "Cl1-"],
                           [[0, 0, 0], [2.324, 1.643, 4.025]],
                           validate_proximity=False,
                           to_unit_cell=False,
                           coords_are_cartesian=True,
                           site_properties=None)
     self.cscl = Structure(Lattice([[4.209, 0, 0], [0, 4.209, 0],
                                    [0, 0, 4.209]]), ["Cl1-", "Cs1+"],
                           [[2.105, 2.105, 2.105], [0, 0, 0]],
                           validate_proximity=False,
                           to_unit_cell=False,
                           coords_are_cartesian=True,
                           site_properties=None)
     self.square_pyramid = Structure(Lattice([[100, 0, 0], [0, 100, 0],
                                              [0, 0, 100]]),
                                     ["C", "C", "C", "C", "C", "C"],
                                     [[0, 0, 0], [1, 0, 0], [-1, 0, 0],
                                      [0, 1, 0], [0, -1, 0], [0, 0, 1]],
                                     validate_proximity=False,
                                     to_unit_cell=False,
                                     coords_are_cartesian=True,
                                     site_properties=None)
     self.trigonal_bipyramid = Structure(
         Lattice([[100, 0, 0], [0, 100, 0],
                  [0, 0, 100]]), ["P", "Cl", "Cl", "Cl", "Cl", "Cl"],
         [[0, 0, 0], [0, 0, 2.14], [0, 2.02, 0], [1.74937, -1.01, 0],
          [-1.74937, -1.01, 0], [0, 0, -2.14]],
         validate_proximity=False,
         to_unit_cell=False,
         coords_are_cartesian=True,
         site_properties=None)
예제 #30
0
    def from_string(data):
        """
        Reads the exciting input from a string
        """

        root = ET.fromstring(data)
        speciesnode = root.find('structure').iter('species')
        elements = []
        positions = []
        vectors = []
        lockxyz = []
        # get title
        title_in = str(root.find('title').text)
        # Read elements and coordinates
        for nodes in speciesnode:
            symbol = nodes.get('speciesfile').split('.')[0]
            if len(symbol.split('_')) == 2:
                symbol = symbol.split('_')[0]
            if Element.is_valid_symbol(symbol):
                # Try to recognize the element symbol
                element = symbol
            else:
                raise ValueError("Unknown element!")
            for atom in nodes.iter('atom'):
                x, y, z = atom.get('coord').split()
                positions.append([float(x), float(y), float(z)])
                elements.append(element)
                # Obtain lockxyz for each atom
                if atom.get('lockxyz') is not None:
                    lxyz = []
                    for l in atom.get('lockxyz').split():
                        if l == 'True' or l == 'true':
                            lxyz.append(True)
                        else:
                            lxyz.append(False)
                    lockxyz.append(lxyz)
                else:
                    lockxyz.append([False, False, False])
        # check the atomic positions type
        if 'cartesian' in root.find('structure').attrib.keys():
            if root.find('structure').attrib['cartesian']:
                cartesian = True
                for i in range(len(positions)):
                    for j in range(3):
                        positions[i][
                            j] = positions[i][j] * ExcitingInput.bohr2ang
                print(positions)
        else:
            cartesian = False
        # get the scale attribute
        scale_in = root.find('structure').find('crystal').get('scale')
        if scale_in:
            scale = float(scale_in) * ExcitingInput.bohr2ang
        else:
            scale = ExcitingInput.bohr2ang
        # get the stretch attribute
        stretch_in = root.find('structure').find('crystal').get('stretch')
        if stretch_in:
            stretch = np.array([float(a) for a in stretch_in])
        else:
            stretch = np.array([1.0, 1.0, 1.0])
        # get basis vectors and scale them accordingly
        basisnode = root.find('structure').find('crystal').iter('basevect')
        for vect in basisnode:
            x, y, z = vect.text.split()
            vectors.append([
                float(x) * stretch[0] * scale,
                float(y) * stretch[1] * scale,
                float(z) * stretch[2] * scale
            ])
        # create lattice and structure object
        lattice_in = Lattice(vectors)
        structure_in = Structure(lattice_in,
                                 elements,
                                 positions,
                                 coords_are_cartesian=cartesian)

        return ExcitingInput(structure_in, title_in, lockxyz)