示例#1
0
    def setUp(self):
        self.cscl = Structure.from_spacegroup("Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]])
        self.Fe = Structure.from_spacegroup("Im-3m", Lattice.cubic(2.82), ["Fe"], [[0, 0, 0]])
        mglatt = Lattice.from_parameters(3.2, 3.2, 5.13, 90, 90, 120)
        self.Mg = Structure(mglatt, ["Mg", "Mg"], [[1 / 3, 2 / 3, 1 / 4], [2 / 3, 1 / 3, 3 / 4]])
        self.lifepo4 = self.get_structure("LiFePO4")
        self.tei = Structure.from_file(get_path("icsd_TeI.cif"), primitive=False)
        self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"), primitive=False)

        self.p1 = Structure(
            Lattice.from_parameters(3, 4, 5, 31, 43, 50),
            ["H", "He"],
            [[0, 0, 0], [0.1, 0.2, 0.3]],
        )
        self.graphite = self.get_structure("Graphite")
        self.trigBi = Structure(
            Lattice.from_parameters(3, 3, 10, 90, 90, 120),
            ["Bi", "Bi", "Bi", "Bi", "Bi", "Bi"],
            [
                [0.3333, 0.6666, 0.39945113],
                [0.0000, 0.0000, 0.26721554],
                [0.0000, 0.0000, 0.73278446],
                [0.6666, 0.3333, 0.60054887],
                [0.6666, 0.3333, 0.06611779],
                [0.3333, 0.6666, 0.93388221],
            ],
        )
示例#2
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, 4.0, 10.0, 3.0, 1.0, 2.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, 1.1304420998572722)
     self.assertEqual(list(img), [0, -1, -1])
示例#3
0
 def _identical(a, b, c, alpha, beta, gamma):
     mat1 = Lattice.from_parameters(a, b, c, alpha, beta, gamma,
                                    False).matrix
     mat2 = Lattice.from_parameters(a, b, c, alpha, beta, gamma,
                                    True).matrix
     # self.assertArrayAlmostEqual(mat1, mat2)
     return ((mat1 - mat2)**2).sum() < 1e-6
示例#4
0
    def get_lattice_quanta(self, convert_to_muC_per_cm2=True, all_in_polar=True):
        """
        Returns the dipole / polarization quanta along a, b, and c for
        all structures.
        """
        lattices = [s.lattice for s in self.structures]
        volumes = np.array([s.lattice.volume for s in self.structures])

        L = len(self.structures)

        e_to_muC = -1.6021766e-13
        cm2_to_A2 = 1e16
        units = 1.0 / np.array(volumes)
        units *= e_to_muC * cm2_to_A2

        # convert polarizations and lattice lengths prior to adjustment
        if convert_to_muC_per_cm2 and not all_in_polar:
            # adjust lattices
            for i in range(L):
                lattice = lattices[i]
                l = lattice.lengths
                a = lattice.angles
                lattices[i] = Lattice.from_parameters(*(np.array(l) * units.ravel()[i]), *a)
        elif convert_to_muC_per_cm2 and all_in_polar:
            for i in range(L):
                lattice = lattices[-1]
                l = lattice.lengths
                a = lattice.angles
                lattices[i] = Lattice.from_parameters(*(np.array(l) * units.ravel()[-1]), *a)

        quanta = np.array([np.array(l.lengths) for l in lattices])

        return quanta
示例#5
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])
示例#6
0
    def test_get_niggli_reduced_lattice(self):
        latt = Lattice.from_parameters(
            3, 5.196, 2, 103 + 55 / 60, 109 + 28 / 60, 134 + 53 / 60
        )
        reduced_cell = latt.get_niggli_reduced_lattice()
        abc = reduced_cell.lengths
        angles = reduced_cell.angles
        self.assertAlmostEqual(abc[0], 2, 3)
        self.assertAlmostEqual(abc[1], 3, 3)
        self.assertAlmostEqual(abc[2], 3, 3)
        self.assertAlmostEqual(angles[0], 116.382855225, 3)
        self.assertAlmostEqual(angles[1], 94.769790287999996, 3)
        self.assertAlmostEqual(angles[2], 109.466666667, 3)

        mat = [[5.0, 0, 0], [0, 5.0, 0], [5.0, 0, 5.0]]
        latt = Lattice(np.dot([[1, 1, 1], [1, 1, 0], [0, 1, 1]], mat))
        reduced_cell = latt.get_niggli_reduced_lattice()
        abc = reduced_cell.lengths
        angles = reduced_cell.angles
        for l in abc:
            self.assertAlmostEqual(l, 5, 3)
        for a in angles:
            self.assertAlmostEqual(a, 90, 3)

        latt = Lattice(
            [
                1.432950,
                0.827314,
                4.751000,
                -1.432950,
                0.827314,
                4.751000,
                0.0,
                -1.654628,
                4.751000,
            ]
        )
        # ans = [[-1.432950, -2.481942, 0.0],
        #       [-2.8659, 0.0, 0.0],
        #       [-1.432950, -0.827314, -4.751000]]
        ans = [
            [-1.43295, -2.481942, 0.0],
            [-2.8659, 0.0, 0.0],
            [-1.43295, -0.827314, -4.751],
        ]
        self.assertArrayAlmostEqual(latt.get_niggli_reduced_lattice().matrix, ans)

        latt = Lattice.from_parameters(
            7.365450, 6.199506, 5.353878, 75.542191, 81.181757, 156.396627
        )
        ans = [
            [2.578932, 0.826965, 0.000000],
            [-0.831059, 2.067413, 1.547813],
            [-0.458407, -2.480895, 1.129126],
        ]
        self.assertArrayAlmostEqual(
            latt.get_niggli_reduced_lattice().matrix, np.array(ans), 5
        )
示例#7
0
        def make_new_lattice(lattice, afac=0.1, alphafac=2):
            """make new lattice with small modification

            Parameters
            ----------
            lattice: Structure.lattice
                lattice information
            afac: float
                a factor for lattice length modification
            alphafac: float
                a factor for lattice angle modification

            Returns
            -------
            Structure.lattice
                new structure with small modification
            """

            r = np.random.rand(6)
            a = lattice.a + r[0] * afac
            b = lattice.b + r[1] * afac
            c = lattice.c + r[2] * afac
            alpha = lattice.alpha + r[3] * alphafac
            beta = lattice.beta + r[4] * alphafac
            gamma = lattice.gamma + r[5] * alphafac

            new_lattice = Lattice.from_parameters(a, b, c, alpha, beta, gamma)
            return new_lattice
示例#8
0
    def compile_crystal(datarow, flavor='pmg'):
        """
        Helper method for representing the MPDS crystal structures in two flavors:
        either as a Pymatgen Structure object, or as an ASE Atoms object.

        Attention! These two flavors are not compatible, e.g.
        primitive vs. crystallographic cell is defaulted,
        atoms wrapped or non-wrapped into the unit cell etc.

        Note, that the crystal structures are not retrieved by default,
        so one needs to specify the fields while retrieval:
            - cell_abc
            - sg_n
            - setting
            - basis_noneq
            - els_noneq
        e.g. like this: {'S':['cell_abc', 'sg_n', 'setting', 'basis_noneq', 'els_noneq']}
        NB. occupancies are not considered.

        Args:
            datarow: (list) Required data to construct crystal structure:
                [cell_abc, sg_n, setting, basis_noneq, els_noneq]
            flavor: (str) Either "pmg", or "ase"

        Returns:
            - if flavor is pmg, returns Pymatgen Structure object
            - if flavor is ase, returns ASE Atoms object
        """
        if not datarow or not datarow[-1]:
            return None

        cell_abc, sg_n, setting, basis_noneq, els_noneq = \
            datarow[-5], int(datarow[-4]), datarow[-3], datarow[-2], datarow[-1]

        if flavor == 'pmg':
            return Structure.from_spacegroup(
                sg_n,
                Lattice.from_parameters(*cell_abc),
                els_noneq,
                basis_noneq
            )

        elif flavor == 'ase' and use_ase:
            atom_data = []
            setting = 2 if setting == '2' else 1

            for num, i in enumerate(basis_noneq):
                atom_data.append(Atom(els_noneq[num], tuple(i)))

            return crystal(
                atom_data,
                spacegroup=sg_n,
                cellpar=cell_abc,
                primitive_cell=True,
                setting=setting,
                onduplicates='replace'
            )

        else:
            raise APIError("Crystal structure treatment unavailable")
示例#9
0
def get_high_accuracy_voronoi_nodes(structure, rad_dict, probe_rad=0.1):
    """
    Analyze the void space in the input structure using high accuracy
    voronoi decomposition.
    Calls Zeo++ for Voronoi decomposition.

    Args:
        structure: pymatgen.core.structure.Structure
        rad_dict (optional): Dictionary of radii of elements in structure.
            If not given, Zeo++ default values are used.
            Note: Zeo++ uses atomic radii of elements.
            For ionic structures, pass rad_dict with ionic radii
        probe_rad (optional): Sampling probe radius in Angstroms.
            Default is 0.1 A

    Returns:
        voronoi nodes as pymatgen.core.structure.Strucutre within the
        unit cell defined by the lattice of input structure
        voronoi face centers as pymatgen.core.structure.Strucutre within the
        unit cell defined by the lattice of input structure
    """

    with ScratchDir("."):
        name = "temp_zeo1"
        zeo_inp_filename = name + ".cssr"
        ZeoCssr(structure).write_file(zeo_inp_filename)
        rad_flag = True
        rad_file = name + ".rad"
        with open(rad_file, "w+") as fp:
            for el in rad_dict.keys():
                print(f"{el} {rad_dict[el].real}", file=fp)

        atmnet = AtomNetwork.read_from_CSSR(zeo_inp_filename, rad_flag=rad_flag, rad_file=rad_file)
        # vornet, vor_edge_centers, vor_face_centers = \
        #        atmnet.perform_voronoi_decomposition()
        red_ha_vornet = prune_voronoi_network_close_node(atmnet)
        # generate_simplified_highaccuracy_voronoi_network(atmnet)
        # get_nearest_largest_diameter_highaccuracy_vornode(atmnet)
        red_ha_vornet.analyze_writeto_XYZ(name, probe_rad, atmnet)
        voro_out_filename = name + "_voro.xyz"
        voro_node_mol = ZeoVoronoiXYZ.from_file(voro_out_filename).molecule

    species = ["X"] * len(voro_node_mol.sites)
    coords = []
    prop = []
    for site in voro_node_mol.sites:
        coords.append(list(site.coords))
        prop.append(site.properties["voronoi_radius"])

    lattice = Lattice.from_parameters(*structure.lattice.parameters)
    vor_node_struct = Structure(
        lattice,
        species,
        coords,
        coords_are_cartesian=True,
        to_unit_cell=True,
        site_properties={"voronoi_radius": prop},
    )

    return vor_node_struct
示例#10
0
    def test_pbc_shortest_vectors(self):
        fcoords = np.array([
            [0.3, 0.3, 0.5],
            [0.1, 0.1, 0.3],
            [0.9, 0.9, 0.8],
            [0.1, 0.0, 0.5],
            [0.9, 0.7, 0.0],
        ])
        lattice = Lattice.from_parameters(8, 8, 4, 90, 76, 58)
        expected = np.array([
            [0.000, 3.015, 4.072, 3.519, 3.245],
            [3.015, 0.000, 3.207, 1.131, 4.453],
            [4.072, 3.207, 0.000, 2.251, 1.788],
            [3.519, 1.131, 2.251, 0.000, 3.852],
        ])

        vectors = pbc_shortest_vectors(lattice, fcoords[:-1], fcoords)
        dists = np.sum(vectors**2, axis=-1)**0.5
        self.assertArrayAlmostEqual(dists, expected, 3)

        # now try with small loop threshold
        from pymatgen.util import coord

        prev_threshold = coord.LOOP_THRESHOLD
        coord.LOOP_THRESHOLD = 0

        vectors = pbc_shortest_vectors(lattice, fcoords[:-1], fcoords)
        dists = np.sum(vectors**2, axis=-1)**0.5
        self.assertArrayAlmostEqual(dists, expected, 3)

        coord.LOOP_THRESHOLD = prev_threshold
示例#11
0
 def output(self,job_record):
   """ Collect relaxed geometry from output."""
   if os.path.isfile('autogen.d12.o'):
     f = open('autogen.d12.o', 'r')
     lines = f.readlines()
     for li,line in enumerate(lines):
       if 'FINAL OPTIMIZED GEOMETRY' in line:
         lattice_params = [float(v) for v in lines[li+6].split()]
         lattice = Lattice.from_parameters(
           lattice_params[0],
           lattice_params[1],
           lattice_params[2],
           lattice_params[3],
           lattice_params[4],
           lattice_params[5])
         idx = li+11
         species = []
         coords = []
         while len(lines[idx].strip()) != 0:
           species.append(int(lines[idx].split()[2])-200)
           coords.append([float(v) for v in lines[idx].split()[4:7]])
           idx += 1
         coords = np.asarray(coords)
         job_record['dft']['relaxed_cif'] = str(
           CifWriter(Structure(lattice=lattice,species=species,coords=coords))
           )
         break
   job_record = AbstractRunCrystal.output(self, job_record)
   return job_record
示例#12
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!")
示例#13
0
    def test_find_all_mappings(self):
        m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]])
        latt = Lattice(m)

        op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, -1, 3], 40)
        rot = op.rotation_matrix
        scale = np.array([[0, 2, 0], [1, 1, 0], [0, 0, 1]])

        latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T)

        for (aligned_out, rot_out, scale_out) in latt.find_all_mappings(latt2):
            self.assertArrayAlmostEqual(np.inner(latt2.matrix, rot_out),
                                        aligned_out.matrix, 5)
            self.assertArrayAlmostEqual(np.dot(scale_out, latt.matrix),
                                        aligned_out.matrix)
            self.assertArrayAlmostEqual(aligned_out.parameters,
                                        latt2.parameters)
            self.assertFalse(
                np.allclose(aligned_out.parameters, latt.parameters))

        latt = Lattice.orthorhombic(9, 9, 5)
        self.assertEqual(len(list(latt.find_all_mappings(latt))), 16)

        # catch the singular matrix error
        latt = Lattice.from_parameters(1, 1, 1, 10, 10, 10)
        for l, _, _ in latt.find_all_mappings(latt, ltol=0.05, atol=11):
            self.assertTrue(isinstance(l, Lattice))
示例#14
0
 def test_selling_dist(self):
     # verification process described here: https://github.com/materialsproject/pymatgen/pull/1888#issuecomment-818072164
     np.testing.assert_(Lattice.selling_dist(Lattice.cubic(5), Lattice.cubic(5)) == 0)
     hex_lattice = Lattice.hexagonal(5, 8)
     triclinic_lattice = Lattice.from_parameters(4, 10, 11, 100, 110, 80)
     np.testing.assert_allclose(Lattice.selling_dist(hex_lattice, triclinic_lattice), 76, rtol=0.1)
     np.testing.assert_allclose(
         Lattice.selling_dist(Lattice.tetragonal(10, 12), Lattice.tetragonal(10.1, 11.9)),
         3.7,
         rtol=0.1,
     )
     np.testing.assert_allclose(
         Lattice.selling_dist(Lattice.cubic(5), Lattice.from_parameters(8, 10, 12, 80, 90, 95)),
         115.6,
         rtol=0.1,
     )
示例#15
0
    def scale_slots(
        self, scales: Tuple[float, float, float] = (1.0, 1.0, 1.0)) -> None:
        """
        Applies in-place a scaling along cell vectors of the slots contines in
        the topology.
        TODO: rename scales to three a, b, c parameters for clarity

        Parameters
        ----------
        scales : Tuple[float, float, float], optional
            the cell vector lengths to apply, by default (1.0, 1.0, 1.0)
        """
        alpha, beta, gamma = self.cell.angles
        a, b, c = scales
        scaled_cell = Lattice.from_parameters(a, b, c, alpha, beta, gamma)
        scaled_slots = []
        for slot in self.slots:
            scaled_slot = copy.deepcopy(slot)
            fract_coords = self.cell.get_fractional_coords(
                slot.atoms.cart_coords)
            scaled_coords = scaled_cell.get_cartesian_coords(fract_coords)
            scaled_slot.atoms = Molecule(
                slot.atoms.species,
                scaled_coords,
                site_properties=slot.atoms.site_properties)
            scaled_slots.append(scaled_slot)
        self.slots = scaled_slots
        self.cell = scaled_cell
        return None
示例#16
0
 def test_get_all_distances(self):
     fcoords = np.array([
         [0.3, 0.3, 0.5],
         [0.1, 0.1, 0.3],
         [0.9, 0.9, 0.8],
         [0.1, 0.0, 0.5],
         [0.9, 0.7, 0.0],
     ])
     lattice = Lattice.from_parameters(8, 8, 4, 90, 76, 58)
     expected = np.array([
         [0.000, 3.015, 4.072, 3.519, 3.245],
         [3.015, 0.000, 3.207, 1.131, 4.453],
         [4.072, 3.207, 0.000, 2.251, 1.788],
         [3.519, 1.131, 2.251, 0.000, 3.852],
         [3.245, 4.453, 1.788, 3.852, 0.000],
     ])
     output = lattice.get_all_distances(fcoords, fcoords)
     self.assertArrayAlmostEqual(output, expected, 3)
     # test just one input point
     output2 = lattice.get_all_distances(fcoords[0], fcoords)
     self.assertArrayAlmostEqual(output2, [expected[0]], 2)
     # test distance when initial points are not in unit cell
     f1 = [0, 0, 17]
     f2 = [0, 0, 10]
     self.assertEqual(lattice.get_all_distances(f1, f2)[0, 0], 0)
示例#17
0
    def get_boxed_structure(self, a, b, c):
        """
        Creates a Structure from a Molecule by putting the Molecule in a box.
        Useful for creating Structure for calculating molecules using periodic
        codes.

        Args:
            a:
                a-lattice parameter.
            b:
                b-lattice parameter.
            c:
                c-lattice parameter.

        Returns:
            Structure containing molecule in a box.
        """
        coords = np.array(self.cart_coords)
        x_range = max(coords[:, 0]) - min(coords[:, 0])
        y_range = max(coords[:, 1]) - min(coords[:, 1])
        z_range = max(coords[:, 2]) - min(coords[:, 2])
        if a <= x_range or b <= y_range or c <= z_range:
            raise ValueError("Box is not big enough to contain Molecule.")
        lattice = Lattice.from_parameters(a, b, c, 90, 90, 90)
        return Structure(lattice, self.species, self.cart_coords,
                         coords_are_cartesian=True,
                         site_properties=self.site_properties)
示例#18
0
    def make_random_lattice(self, constraints, random):
        """
        Returns a random lattice that satisfies the constraints on maximum and
        minimum lengths and angles.

        Args:
            constraints: the Constraints of the search

            random: a copy of Python's built in PRNG
        """

        # make three random lattice vectors that satisfy the length constraints
        a = constraints.min_lattice_length + random.random() * (
            constraints.max_lattice_length - constraints.min_lattice_length)
        b = constraints.min_lattice_length + random.random() * (
            constraints.max_lattice_length - constraints.min_lattice_length)
        c = constraints.min_lattice_length + random.random() * (
            constraints.max_lattice_length - constraints.min_lattice_length)

        # make three random lattice angles that satisfy the angle constraints
        alpha = constraints.min_lattice_angle + random.random() * (
            constraints.max_lattice_angle - constraints.min_lattice_angle)
        beta = constraints.min_lattice_angle + random.random() * (
            constraints.max_lattice_angle - constraints.min_lattice_angle)
        gamma = constraints.min_lattice_angle + random.random() * (
            constraints.max_lattice_angle - constraints.min_lattice_angle)

        # build the random lattice
        return Lattice.from_parameters(a, b, c, alpha, beta, gamma)
示例#19
0
文件: cssr.py 项目: zooks97/pymatgen
    def from_string(string):
        """
        Reads a string representation to a Cssr object.

        Args:
            string (str): A string representation of a CSSR.

        Returns:
            Cssr object.
        """
        lines = string.split("\n")
        toks = lines[0].split()
        lengths = [float(i) for i in toks]
        toks = lines[1].split()
        angles = [float(i) for i in toks[0:3]]
        latt = Lattice.from_parameters(*lengths, *angles)
        sp = []
        coords = []
        for l in lines[4:]:
            m = re.match(
                r"\d+\s+(\w+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)",
                l.strip())
            if m:
                sp.append(m.group(1))
                coords.append([float(m.group(i)) for i in range(2, 5)])
        return Cssr(Structure(latt, sp, coords))
示例#20
0
    def compile_crystal(datarow, flavor='pmg'):
        """
        Helper method for representing the MPDS crystal structures in two flavors:
        either as a Pymatgen Structure object, or as an ASE Atoms object.

        Attention! These two flavors are not compatible, e.g.
        primitive vs. crystallographic cell is defaulted,
        atoms wrapped or non-wrapped into the unit cell etc.

        Note, that the crystal structures are not retrieved by default,
        so one needs to specify the fields while retrieval:
            - cell_abc
            - sg_n
            - setting
            - basis_noneq
            - els_noneq
        e.g. like this: {'S':['cell_abc', 'sg_n', 'setting', 'basis_noneq', 'els_noneq']}
        NB. occupancies are not considered.

        Args:
            datarow: (list) Required data to construct crystal structure:
                [cell_abc, sg_n, setting, basis_noneq, els_noneq]
            flavor: (str) Either "pmg", or "ase"

        Returns:
            - if flavor is pmg, returns Pymatgen Structure object
            - if flavor is ase, returns ASE Atoms object
        """
        if not datarow or not datarow[-1]:
            return None

        cell_abc, sg_n, setting, basis_noneq, els_noneq = \
            datarow[-5], int(datarow[-4]), datarow[-3], datarow[-2], datarow[-1]

        if flavor == 'pmg':
            return Structure.from_spacegroup(
                sg_n,
                Lattice.from_parameters(*cell_abc),
                els_noneq,
                basis_noneq
            )

        elif flavor == 'ase' and use_ase:
            atom_data = []
            setting = 2 if setting == '2' else 1

            for num, i in enumerate(basis_noneq):
                atom_data.append(Atom(els_noneq[num], tuple(i)))

            return crystal(
                atom_data,
                spacegroup=sg_n,
                cellpar=cell_abc,
                primitive_cell=True,
                setting=setting,
                onduplicates='replace'
            )

        else:
            raise APIError("Crystal structure treatment unavailable")
示例#21
0
    def from_string(header_str):
        """
        Reads Header string and returns Header object if header was
        generated by pymatgen.
        Note: Checks to see if generated by pymatgen, if not it is impossible
            to generate structure object so it is not possible to generate
            header object and routine ends

        Args:
            header_str: pymatgen generated feff.inp header

        Returns:
            Structure object.
        """
        lines = tuple(clean_lines(header_str.split("\n"), False))
        comment1 = lines[0]
        feffpmg = comment1.find("pymatgen")
        if feffpmg == -1:
            feffpmg = False
        if feffpmg:
            comment2 = " ".join(lines[1].split()[2:])

            source = " ".join(lines[2].split()[2:])
            basis_vec = lines[6].split(":")[-1].split()
            # a, b, c
            a = float(basis_vec[0])
            b = float(basis_vec[1])
            c = float(basis_vec[2])
            lengths = [a, b, c]
            # alpha, beta, gamma
            basis_ang = lines[7].split(":")[-1].split()
            alpha = float(basis_ang[0])
            beta = float(basis_ang[1])
            gamma = float(basis_ang[2])
            angles = [alpha, beta, gamma]

            lattice = Lattice.from_parameters(*lengths, *angles)

            natoms = int(lines[8].split(":")[-1].split()[0])

            atomic_symbols = []
            for i in range(9, 9 + natoms):
                atomic_symbols.append(lines[i].split()[2])

            # read the atomic coordinates
            coords = []
            for i in range(natoms):
                toks = lines[i + 9].split()
                coords.append([float(s) for s in toks[3:]])

            struct = Structure(lattice, atomic_symbols, coords, False, False,
                               False)

            h = Header(struct, source, comment2)

            return h

        raise ValueError(
            "Header not generated by pymatgen, cannot return header object")
示例#22
0
def topology_from_string(cgd: str,
                         spacegroups: Dict[str, int]) -> Tuple[str, Structure]:
    lines = cgd.splitlines()
    lines = [l[2:].split() for l in lines if len(l) > 2]
    elements = []
    xyz = []
    is_2D = False
    # might benefit from new case syntax in 3.10
    for l in lines:
        if l[0].startswith("NAME"):
            name = l[1].strip()
        elif l[0].startswith("GROUP"):
            groupname = l[1].strip()
            if groupname not in spacegroups.keys():
                return groupname, None
            sg = spacegroups[groupname]
        elif l[0].startswith("CELL"):
            parameters = [float(p) for p in l[1:]]
            if len(parameters) == 3:
                # 2D net, only one angle and two vectors.
                # need to be completed up to 6 parameters
                parameters = parameters[0:2] + [10.0, 90.0, 90.0
                                                ] + parameters[2:]
                is_2D = True
            lattice = Lattice.from_parameters(*parameters)
        elif l[0].startswith("NODE"):
            elements.append(get_el_sp(int(l[2])))
            xyz.append(numpy.array(l[3:], dtype=float))
        elif l[0].startswith("EDGE_CENTER"):
            # add a linear connector, represented by He
            elements.append(get_el_sp(int(2)))
            xyz.append(numpy.array(l[1:], dtype=float))
        elif l[0].startswith("EDGE"):
            # now we append some dummies
            s = int((len(l) - 1) / 2)
            midl = int((len(l) + 1) / 2)
            x0 = numpy.array(l[1:midl], dtype=float).reshape(-1, 1)
            x1 = numpy.array(l[midl:], dtype=float).reshape(-1, 1)
            xx = numpy.concatenate([x0, x1], axis=1).T
            com = xx.mean(axis=0)
            xx -= com
            xx = xx.dot(numpy.eye(s) * 0.5)
            xx += com
            dummy_element = get_el_sp("X")
            xyz += [xx[0], xx[1]]
            elements += [dummy_element, dummy_element]
    # concatenate the coordinates
    xyz = numpy.stack(xyz, axis=0)
    if is_2D:
        # node coordinates need to be padded
        xyz = numpy.pad(xyz, ((0, 0), (0, 1)), 'constant', constant_values=0.0)
    # generate the crystal
    topology = Structure.from_spacegroup(sg=sg,
                                         lattice=lattice,
                                         species=elements,
                                         coords=xyz)
    # remove any duplicate sites
    topology.merge_sites(tol=1e-3, mode="delete")
    return name, topology
示例#23
0
    def _get_structure_from_spcgrp(self):
        if 'A' not in self.lattice:
            raise AssertionError()
        if 'B' not in self.lattice:
            logging.info('Lattice vector B not given, assume equal to A')
            self.lattice['B'] = self.lattice['A']
        if 'C' not in self.lattice:
            logging.info('Lattice vector C not given, assume equal to A')
            self.lattice['C'] = self.lattice['C']
        if 'ALPHA' not in self.lattice:
            logging.info('Lattice angle ALPHA not given, assume right-angle')
            self.lattice['ALPHA'] = 90
        if 'BETA' not in self.lattice:
            logging.info('Lattice angle BETA not given, assume right-angle')
            self.lattice['BETA'] = 90
        if 'GAMMA' not in self.lattice:
            try:
                spcgrp_number = int(self.lattice['SPCGRP'])
            except ValueError:
                spcgrp_number = 0
            if (167 < spcgrp_number < 195):
                logging.info('Lattice angle GAMMA not given, '
                             'hexagonal space group, assume 120')
                self.lattice['GAMMA'] = 120
            else:
                logging.info('Lattice angle GAMMA not given, '
                             'assume right-angle')
                self.lattice['GAMMA'] = 90

        if self.cartesian:
            logging.info("Warning: Cartesian positions used without "
                         "explicit lattice vectors")

        if 'UNITS' not in self.lattice or self.lattice['UNITS'] is None:
            if self.ignore_units:
                pass
            else:
                for length in ('A', 'B', 'C'):
                    self.lattice[length] *= _bohr_to_angstrom

        if 'ALAT' not in self.lattice:
            raise AssertionError()
        for length in ('A', 'B', 'C'):
            self.lattice[length] *= self.lattice['ALAT']

        lattice = Lattice.from_parameters(self.lattice['A'], self.lattice['B'],
                                          self.lattice['C'],
                                          self.lattice['ALPHA'],
                                          self.lattice['BETA'],
                                          self.lattice['GAMMA'])

        species, coords = self._get_species_coords()

        return Structure.from_spacegroup(self.lattice['SPCGRP'],
                                         lattice,
                                         species,
                                         coords,
                                         coords_are_cartesian=self.cartesian,
                                         tol=self.tol)
示例#24
0
    def test_pbc_shortest_vectors(self):
        fcoords = np.array(
            [
                [0.3, 0.3, 0.5],
                [0.1, 0.1, 0.3],
                [0.9, 0.9, 0.8],
                [0.1, 0.0, 0.5],
                [0.9, 0.7, 0.0],
            ]
        )
        lattice = Lattice.from_parameters(8, 8, 4, 90, 76, 58)
        expected = np.array(
            [
                [0.000, 3.015, 4.072, 3.519, 3.245],
                [3.015, 0.000, 3.207, 1.131, 4.453],
                [4.072, 3.207, 0.000, 2.251, 1.788],
                [3.519, 1.131, 2.251, 0.000, 3.852],
            ]
        )

        vectors = coord.pbc_shortest_vectors(lattice, fcoords[:-1], fcoords)
        dists = np.sum(vectors**2, axis=-1) ** 0.5
        self.assertArrayAlmostEqual(dists, expected, 3)

        prev_threshold = coord.LOOP_THRESHOLD
        coord.LOOP_THRESHOLD = 0

        vectors = coord.pbc_shortest_vectors(lattice, fcoords[:-1], fcoords)
        dists = np.sum(vectors**2, axis=-1) ** 0.5
        self.assertArrayAlmostEqual(dists, expected, 3)

        coord.LOOP_THRESHOLD = prev_threshold

        lattice_pbc = Lattice.from_parameters(8, 8, 4, 90, 76, 58, pbc=(True, True, False))
        expected_pbc = np.array(
            [
                [0.000, 3.015, 4.072, 3.519, 4.089],
                [3.015, 0.000, 3.207, 1.131, 4.453],
                [4.072, 3.207, 0.000, 2.251, 3.578],
                [3.519, 1.131, 2.251, 0.000, 4.235],
            ]
        )
        vectors = coord.pbc_shortest_vectors(lattice_pbc, fcoords[:-1], fcoords)
        dists = np.sum(vectors**2, axis=-1) ** 0.5
        self.assertArrayAlmostEqual(dists, expected_pbc, 3)
示例#25
0
 def reorient_axis(self) -> None:
     """
     Change the orientation of the lattice vector so that:
     a points along the x-axis, b is in the xy-plane, c is in the positive-z halve of space
     """
     args = (
         self.structure.lattice.abc + self.structure.lattice.angles
     )  # type:  Tuple[float, float, float, float, float, float]
     self.structure.lattice = Lattice.from_parameters(*args, vesta=True)
示例#26
0
    def setUp(self):
        self.cscl = self.get_structure("CsCl")
        self.lifepo4 = self.get_structure("LiFePO4")
        self.tei = Structure.from_file(get_path("icsd_TeI.cif"),
                                       primitive=False)
        self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"),
                                          primitive=False)

        self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50),
                            ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]])
示例#27
0
    def setUp(self):
        self.cscl = self.get_structure("CsCl")
        self.lifepo4 = self.get_structure("LiFePO4")
        self.tei = Structure.from_file(get_path("icsd_TeI.cif"),
                                       primitive=False)
        self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"),
                                          primitive=False)

        self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50),
                            ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]])
示例#28
0
    def test_from_structure_NPT(self):

        coords1 = np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]])
        coords2 = np.array([[0.0, 0.0, 0.0], [0.6, 0.6, 0.6]])
        coords3 = np.array([[0.0, 0.0, 0.0], [0.7, 0.7, 0.7]])
        lattice1 = Lattice.from_parameters(a=2.0,
                                           b=2.0,
                                           c=2.0,
                                           alpha=90,
                                           beta=90,
                                           gamma=90)
        lattice2 = Lattice.from_parameters(a=2.1,
                                           b=2.1,
                                           c=2.1,
                                           alpha=90,
                                           beta=90,
                                           gamma=90)
        lattice3 = Lattice.from_parameters(a=2.0,
                                           b=2.0,
                                           c=2.0,
                                           alpha=90,
                                           beta=90,
                                           gamma=90)
        s1 = Structure(coords=coords1, lattice=lattice1, species=["F", "Li"])
        s2 = Structure(coords=coords2, lattice=lattice2, species=["F", "Li"])
        s3 = Structure(coords=coords3, lattice=lattice3, species=["F", "Li"])
        structures = [s1, s2, s3]
        d = DiffusionAnalyzer.from_structures(
            structures,
            specie="Li",
            temperature=500.0,
            time_step=2.0,
            step_skip=1,
            smoothed=None,
        )
        self.assertArrayAlmostEqual(
            d.disp[1],
            np.array([[0.0, 0.0, 0.0], [0.21, 0.21, 0.21], [0.40, 0.40,
                                                            0.40]]),
        )
 def test_process_entry_ozonide(self):
     el_li = Element("Li")
     el_o = Element("O")
     elts = [el_li, el_o, el_o, el_o]
     latt = Lattice.from_parameters(3.999911, 3.999911, 3.999911, 133.847504, 102.228244, 95.477342)
     coords = [[0.513004, 0.513004, 1.000000],
               [0.017616, 0.017616, 0.000000], 
               [0.649993, 0.874790, 0.775203], 
               [0.099587, 0.874790, 0.224797]]
     struct = Structure(latt, elts, coords)
     lio3_entry = ComputedStructureEntry(struct, -19.20762604)
     lio3_entry_corrected = self.compat.process_entry(lio3_entry)
     self.assertEqual(lio3_entry_corrected, None)
示例#30
0
    def setUp(self):
        self.cscl = Structure.from_spacegroup(
            "Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]])

        self.lifepo4 = self.get_structure("LiFePO4")
        self.tei = Structure.from_file(get_path("icsd_TeI.cif"),
                                       primitive=False)
        self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"),
                                          primitive=False)

        self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50),
                            ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]])
        self.graphite = self.get_structure("Graphite")
示例#31
0
    def setUp(self):
        self.cscl = Structure.from_spacegroup("Pm-3m", Lattice.cubic(4.2),
                                              ["Cs", "Cl"],
                                              [[0, 0, 0], [0.5, 0.5, 0.5]])

        self.lifepo4 = self.get_structure("LiFePO4")
        self.tei = Structure.from_file(get_path("icsd_TeI.cif"),
                                       primitive=False)
        self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"),
                                          primitive=False)

        self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50),
                            ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]])
        self.graphite = self.get_structure("Graphite")
示例#32
0
    def test_get_niggli_reduced_lattice(self):
        latt = Lattice.from_parameters(3, 5.196, 2, 103 + 55 / 60,
                                       109 + 28 / 60,
                                       134 + 53 / 60)
        reduced_cell = latt.get_niggli_reduced_lattice()
        abc, angles = reduced_cell.lengths_and_angles
        self.assertAlmostEqual(abc[0], 2, 3)
        self.assertAlmostEqual(abc[1], 3, 3)
        self.assertAlmostEqual(abc[2], 3, 3)
        self.assertAlmostEqual(angles[0], 116.382855225, 3)
        self.assertAlmostEqual(angles[1], 94.769790287999996, 3)
        self.assertAlmostEqual(angles[2], 109.466666667, 3)

        mat = [[5.0, 0, 0], [0, 5.0, 0], [5.0, 0, 5.0]]
        latt = Lattice(np.dot([[1, 1, 1], [1, 1, 0], [0, 1, 1]], mat))
        reduced_cell = latt.get_niggli_reduced_lattice()
        abc, angles = reduced_cell.lengths_and_angles
        for l in abc:
            self.assertAlmostEqual(l, 5, 3)
        for a in angles:
            self.assertAlmostEqual(a, 90, 3)

        latt = Lattice([1.432950, 0.827314, 4.751000, -1.432950, 0.827314,
                        4.751000, 0.0, -1.654628, 4.751000])
        ans = [[-1.432950, -2.481942, 0.0],
               [-2.8659, 0.0, 0.0],
               [-1.432950, -0.827314, -4.751000]]
        self.assertArrayAlmostEqual(latt.get_niggli_reduced_lattice().matrix,
                                    ans)

        latt = Lattice.from_parameters(7.365450, 6.199506, 5.353878,
                                       75.542191, 81.181757, 156.396627)
        ans = [[-2.578932, -0.826965, 0.000000],
               [0.831059, -2.067413, -1.547813],
               [0.458407, 2.480895, -1.129126]]
        self.assertArrayAlmostEqual(latt.get_niggli_reduced_lattice().matrix,
                                    ans, 5)
示例#33
0
    def setUp(self):
        self.cscl = Structure.from_spacegroup(
            "Pm-3m", Lattice.cubic(4.2), ["Cs", "Cl"],
            [[0, 0, 0], [0.5, 0.5, 0.5]])
        self.Fe = Structure.from_spacegroup( \
            "Im-3m", Lattice.cubic(2.82), ["Fe"],
            [[0, 0, 0]])
        self.lifepo4 = self.get_structure("LiFePO4")
        self.tei = Structure.from_file(get_path("icsd_TeI.cif"),
                                       primitive=False)
        self.LiCoO2 = Structure.from_file(get_path("icsd_LiCoO2.cif"),
                                          primitive=False)

        self.p1 = Structure(Lattice.from_parameters(3, 4, 5, 31, 43, 50),
                            ["H", "He"], [[0, 0, 0], [0.1, 0.2, 0.3]])
        self.graphite = self.get_structure("Graphite")
        self.trigBi = Structure(Lattice.from_parameters(3, 3, 10, 90, 90, 120),
                                ["Bi", "Bi", "Bi", "Bi", "Bi", "Bi"],
                                [[0.3333, 0.6666, 0.39945113],
                                 [0.0000, 0.0000, 0.26721554],
                                 [0.0000, 0.0000, 0.73278446],
                                 [0.6666, 0.3333, 0.60054887],
                                 [0.6666, 0.3333, 0.06611779],
                                 [0.3333, 0.6666, 0.93388221]])
示例#34
0
    def test_primitive_positions(self):
        coords = [[0, 0, 0], [0.3, 0.35, 0.45]]
        s = Structure(Lattice.from_parameters(1,2,3,50,66,88), ["Ag"] * 2, coords)

        a = [[-1,2,-3], [3,2,-4], [1,0,-1]]
        b = [[4, 0, 0], [1, 1, 0], [3, 0, 1]]
        c = [[2, 0, 0], [1, 3, 0], [1, 1, 1]]

        for sc_matrix in [c]:
            sc = s.copy()
            sc.make_supercell(sc_matrix)
            prim = sc.get_primitive_structure(0.01)

            self.assertEqual(len(prim), 2)
            self.assertAlmostEqual(prim.distance_matrix[0,1], 1.0203432356739286)
示例#35
0
def test_add_sp_hydrogen():
    """Add H on simplified case with one neighbor"""
    site_b_coord = [0, 0, 0]
    site_a_coord = [0.5, 0, 0]
    lattice = Lattice.from_parameters(1, 1, 1, 90, 90, 90)
    site_a = PeriodicSite(Composition("H"), site_a_coord, lattice)
    site_b = ConnectedSite(
        PeriodicSite(Composition("H"), site_b_coord, lattice))

    hydrogen = add_sp_hydrogen(site_a, [site_b])
    assert len(hydrogen) == 3

    assert np.abs(np.linalg.norm(np.array(site_a_coord) - hydrogen) - 1) < 0.01
    assert np.linalg.norm(hydrogen[1]) < 0.01
    assert np.linalg.norm(hydrogen[2]) < 0.01
 def test_process_entry_hydroxide(self):
     el_li = Element("Li")
     el_o = Element("O")
     el_h = Element("H")
     latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000)
     elts = [el_h, el_h, el_li, el_li, el_o, el_o]
     coords = [[0.000000, 0.500000, 0.413969],
               [0.500000, 0.000000, 0.586031], 
               [0.000000, 0.000000, 0.000000],
               [0.500000, 0.500000, 0.000000],
               [0.000000, 0.500000, 0.192672],
               [0.500000, 0.000000, 0.807328]]
     struct = Structure(latt, elts, coords)
     lioh_entry = ComputedStructureEntry(struct, -29.85285134)
     lioh_entry_corrected = self.compat.process_entry(lioh_entry)
     self.assertAlmostEqual(lioh_entry_corrected.energy, -28.9047, 4)
示例#37
0
 def test_consistency(self):
     """
     when only lengths and angles are given for constructors, the
     internal matrix representation is ambiguous since the lattice rotation
     is not specified.
     This test makes sure that a consistent definition is specified for the
     lattice rotation when using different constructors from lengths angles
     """
     l = [3.840198, 3.84019885, 3.8401976]
     a = [119.99998575, 90, 60.00000728]
     mat1 = Lattice.from_lengths_and_angles(l, a).matrix
     mat2 = Lattice.from_parameters(l[0], l[1], l[2],
                                    a[0], a[1], a[2]).matrix
     for i in range(0, 3):
         for j in range(0, 3):
             self.assertAlmostEqual(mat1[i][j], mat2[i][j], 5)
示例#38
0
 def test_consistency(self):
     """
     when only lengths and angles are given for constructors, the
     internal matrix representation is ambiguous since the lattice rotation
     is not specified.
     This test makes sure that a consistent definition is specified for the
     lattice rotation when using different constructors from lengths angles
     """
     l = [3.840198, 3.84019885, 3.8401976]
     a = [119.99998575, 90, 60.00000728]
     mat1 = Lattice.from_lengths_and_angles(l, a).matrix
     mat2 = Lattice.from_parameters(l[0], l[1], l[2], a[0], a[1],
                                    a[2]).matrix
     for i in range(0, 3):
         for j in range(0, 3):
             self.assertAlmostEqual(mat1[i][j], mat2[i][j], 5)
示例#39
0
    def structure(self):
        """
        Transform from LammpsData file to a pymatgen structure object

        Return:
            A pymatgen structure object
        """
        species_map = {}
        for sp in self.atomic_masses:
            for el in Element:
                if abs(el.atomic_mass - sp[1]) < 0.05:
                    species_map[sp[0]] = el
        xhi, yhi, zhi = self.box_size[0][1] - self.box_size[0][0], self.box_size[1][1] - self.box_size[1][0], \
                        self.box_size[2][1] - self.box_size[0][0]
        xy, xz, yz = self.box_tilt if self.box_tilt is not None else [
            0.0, 0.0, 0.0
        ]
        a = xhi
        b = np.sqrt(yhi**2 + xy**2)
        c = np.sqrt(zhi**2 + xz**2 + yz**2)

        gamma = math.degrees(math.acos(xy / b))
        beta = math.degrees(math.acos(xz / c))
        alpha = math.degrees(math.acos((yhi * yz + xy * xz) / b / c))
        lattice = Lattice.from_parameters(a, b, c, alpha, beta, gamma)
        species = []
        coords = []
        for d in self.atoms_data:
            if self.atom_style == 'full':
                if d[3] != 0:
                    species.append(Specie(species_map[d[2]].symbol, d[3]))
                else:
                    species.append(species_map[d[1]])
                coords.append(d[4:7])
            elif self.atom_style == 'charge':
                if d[2] != 0:
                    species.append(Specie(species_map[d[1]].symbol, d[2]))
                else:
                    species.append(species_map[d[1]])
                coords.append(d[3:6])
            elif self.atom_style == 'atomic':
                species.append(species_map[d[1]])
                coords.append(d[2:5])
            else:
                raise RuntimeError('data style not implemented')

        return Structure(lattice, species, coords, coords_are_cartesian=True)
示例#40
0
    def _get_structure(entry, use_web_api=True):
        """
        Extracts structure data from AFLOW CONTCAR file. If the file is unavailable,
        the structure can be reconstituted from different fields in the AFLOW database.
        Can perform web queries to retrieve those fields.

        Args:
            entry (aflow.entries.Entry): entry containing the CONTCAR data as a string in
                the "AEL_elastic_tensor_json" field, or containing the fields 'geometry',
                'species', 'composition', and 'positions_fractional'.
            use_web_api (bool): True allows missing data to be retrieved from the AFLOW API.
                False will raise an exception if the data is missing. Default: True

        Returns:
            pymatgen.core.structure.Structure: a pymatgen structure object
        """
        data_in = entry.raw.get('CONTCAR_relax_vasp')
        contcar = True
        if data_in is None:
            contcar = False

        if contcar:
            try:
                structure = Structure.from_str(data_in, fmt="poscar")
                return structure
            except Exception:
                logger.warning("Parsing structure file for {} failed.".format(entry.auid) +
                               " Generating from material entry")

        if not use_web_api:
            if not all(kw in entry.attributes for kw in ('geometry', 'species',
                                                         'composition', 'positions_fractional')):
                return None

        from pymatgen.core.lattice import Lattice
        # This lazy-loads the data by making an HTTP request for each property it needs
        # if the fields don't exist in the entry
        geometry = entry.geometry
        lattice = Lattice.from_parameters(*geometry)

        elements = list(map(str.strip, entry.species))
        composition = list(entry.composition)
        species = list(chain.from_iterable([elem] * comp for elem, comp in zip(elements, composition)))

        xyz = entry.positions_fractional.tolist()

        return Structure(lattice, species, xyz)
示例#41
0
def test_add_sp3_hydrogens_on_cn1():
    """Test on a toy example with one neighbor on the x axis"""
    site_b_coord = [0, 0, 0]
    site_a_coord = [0.5, 0, 0]

    lattice = Lattice.from_parameters(1, 1, 1, 90, 90, 90)
    site_a = PeriodicSite(Composition("H"), site_a_coord, lattice)
    site_b = ConnectedSite(
        PeriodicSite(Composition("H"), site_b_coord, lattice))

    vectors = add_sp3_hydrogens_on_cn1(site_a, [site_b])

    for vector in vectors:
        assert (np.linalg.norm(vector - np.array(site_a_coord)) - 1) < 0.01
        assert vector[0] > 0.5
        assert vector[1] != 0
        assert vector[2] != 0
示例#42
0
    def test_primitive_positions(self):
        coords = [[0, 0, 0], [0.3, 0.35, 0.45]]
        s = Structure(Lattice.from_parameters(1, 2, 3, 50, 66, 88), ["Ag"] * 2,
                      coords)

        a = [[-1, 2, -3], [3, 2, -4], [1, 0, -1]]
        b = [[4, 0, 0], [1, 1, 0], [3, 0, 1]]
        c = [[2, 0, 0], [1, 3, 0], [1, 1, 1]]

        for sc_matrix in [c]:
            sc = s.copy()
            sc.make_supercell(sc_matrix)
            prim = sc.get_primitive_structure(0.01)

            self.assertEqual(len(prim), 2)
            self.assertAlmostEqual(prim.distance_matrix[0, 1],
                                   1.0203432356739286)
 def test_process_entry_peroxide(self):
     latt = Lattice.from_parameters(3.159597, 3.159572, 7.685205, 89.999884, 89.999674, 60.000510)
     el_li = Element("Li")
     el_o = Element("O")
     elts = [el_li, el_li, el_li, el_li, el_o, el_o, el_o, el_o]
     coords = [[0.666656, 0.666705, 0.750001], 
               [0.333342, 0.333378, 0.250001], 
               [0.000001, 0.000041, 0.500001],
               [0.000001, 0.000021, 0.000001], 
               [0.333347, 0.333332, 0.649191], 
               [0.333322, 0.333353, 0.850803], 
               [0.666666, 0.666686, 0.350813], 
               [0.666665, 0.666684, 0.149189]]
     struct = Structure(latt, elts, coords)
     li2o2_entry = ComputedStructureEntry(struct, -38.80421304)
     li2o2_entry_corrected = self.compat.process_entry(li2o2_entry)
     self.assertAlmostEqual(li2o2_entry_corrected.energy, -37.80087, 4)
示例#44
0
文件: data.py 项目: matk86/pymatgen
    def structure(self):
        """
        Transform from LammpsData file to a pymatgen structure object

        Return:
            A pymatgen structure object
        """
        species_map = {}
        for sp in self.atomic_masses:
            for el in Element:
                if abs(el.atomic_mass - sp[1]) < 0.05:
                    species_map[sp[0]] = el
        xhi, yhi, zhi = self.box_size[0][1] - self.box_size[0][0], self.box_size[1][1] - self.box_size[1][0], \
                        self.box_size[2][1] - self.box_size[0][0]
        xy, xz, yz = self.box_tilt if self.box_tilt is not None else [0.0, 0.0, 0.0]
        a = xhi
        b = np.sqrt(yhi ** 2 + xy ** 2)
        c = np.sqrt(zhi ** 2 + xz ** 2 + yz ** 2)

        gamma = math.degrees(math.acos(xy / b))
        beta = math.degrees(math.acos(xz / c))
        alpha = math.degrees(math.acos((yhi * yz + xy * xz) / b / c))
        lattice = Lattice.from_parameters(a, b, c, alpha, beta, gamma)
        species = []
        coords = []
        for d in self.atoms_data:
            if self.atom_style == 'full':
                if d[3] != 0:
                    species.append(Specie(species_map[d[2]].symbol, d[3]))
                else:
                    species.append(species_map[d[1]])
                coords.append(d[4:7])
            elif self.atom_style == 'charge':
                if d[2] != 0:
                    species.append(Specie(species_map[d[1]].symbol, d[2]))
                else:
                    species.append(species_map[d[1]])
                coords.append(d[3:6])
            elif self.atom_style == 'atomic':
                species.append(species_map[d[1]])
                coords.append(d[2:5])
            else:
                raise RuntimeError('data style not implemented')

        return Structure(lattice, species, coords, coords_are_cartesian=True)
示例#45
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.assertAlmostEquals(distance, 6.22494979899, 5)
     self.assertTrue(([-1, -1, -1] == image).all())
     (distance, image) = self.site.distance_and_image(other_site, [1, 0, 0])
     self.assertAlmostEquals(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.assertTrue(site1.distance_and_image_old(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(site1.distance_and_image_old(site2)[0] > site1.distance_and_image(site2)[0])
     site2 = PeriodicSite("Fe", np.random.rand(3), lattice)
     (dist_old, jimage_old) = site1.distance_and_image_old(site2)
     (dist_new, jimage_new) = site1.distance_and_image(site2)
     self.assertTrue(dist_old >= dist_new, "New distance algo should always give smaller answers!")
     self.assertFalse((dist_old == dist_new) ^ (jimage_old == jimage_new).all(), "If old dist == new dist, the images returned must be the same!")
示例#46
0
    def get_relaxed_structure(self, gout):
        #Find the structure lines
        structure_lines = []
        cell_param_lines = []
        #print gout
        output_lines = gout.split("\n")
        no_lines = len(output_lines)
        i = 0
        # Compute the input lattice parameters
        while i < no_lines:
            line = output_lines[i]
            if "Full cell parameters" in line:
                i += 2
                line = output_lines[i]
                a = float(line.split()[8])
                alpha = float(line.split()[11])
                line = output_lines[i + 1]
                b = float(line.split()[8])
                beta = float(line.split()[11])
                line = output_lines[i + 2]
                c = float(line.split()[8])
                gamma = float(line.split()[11])
                i += 3
                break
            elif "Cell parameters" in line:
                i += 2
                line = output_lines[i]
                a = float(line.split()[2])
                alpha = float(line.split()[5])
                line = output_lines[i + 1]
                b = float(line.split()[2])
                beta = float(line.split()[5])
                line = output_lines[i + 2]
                c = float(line.split()[2])
                gamma = float(line.split()[5])
                i += 3
                break
            else:
                i += 1

        while i < no_lines:
            line = output_lines[i]
            if "Final fractional coordinates of atoms" in line:
                # read the site coordinates in the following lines
                i += 6
                line = output_lines[i]
                while line[0:2] != '--':
                    structure_lines.append(line)
                    i += 1
                    line = output_lines[i]
                    # read the cell parameters
                i += 9
                line = output_lines[i]
                if "Final cell parameters" in line:
                    i += 3
                    for del_i in range(6):
                        line = output_lines[i + del_i]
                        cell_param_lines.append(line)

                break
            else:
                i += 1

        #Process the structure lines
        if structure_lines:
            sp = []
            coords = []
            for line in structure_lines:
                fields = line.split()
                if fields[2] == 'c':
                    sp.append(fields[1])
                    coords.append(list(float(x) for x in fields[3:6]))
        else:
            raise IOError("No structure found")

        if cell_param_lines:
            a = float(cell_param_lines[0].split()[1])
            b = float(cell_param_lines[1].split()[1])
            c = float(cell_param_lines[2].split()[1])
            alpha = float(cell_param_lines[3].split()[1])
            beta = float(cell_param_lines[4].split()[1])
            gamma = float(cell_param_lines[5].split()[1])
        latt = Lattice.from_parameters(a, b, c, alpha, beta, gamma)

        return Structure(latt, sp, coords)
示例#47
0
 def _identical(a, b, c, alpha, beta, gamma):
     mat1 = Lattice.from_parameters(a, b, c, alpha, beta, gamma, False).matrix
     mat2 = Lattice.from_parameters(a, b, c, alpha, beta, gamma, True).matrix
     # self.assertArrayAlmostEqual(mat1, mat2)
     return ((mat1 - mat2)**2).sum() < 1e-6
    def test_oxide_type(self):
        el_li = Element("Li")
        el_o = Element("O")
        latt = Lattice([[3.985034, 0.0, 0.0],
                        [0.0, 4.881506, 0.0],
                        [0.0, 0.0, 2.959824]])
        elts = [el_li, el_li, el_o, el_o, el_o, el_o]
        coords = list()
        coords.append([0.500000, 0.500000, 0.500000])
        coords.append([0.0, 0.0, 0.0])
        coords.append([0.632568, 0.085090, 0.500000])
        coords.append([0.367432, 0.914910, 0.500000])
        coords.append([0.132568, 0.414910, 0.000000])
        coords.append([0.867432, 0.585090, 0.000000])
        struct = Structure(latt, elts, coords)
        self.assertEqual(oxide_type(struct, 1.1), "superoxide")
        
        el_li = Element("Li")
        el_o = Element("O")
        elts = [el_li, el_o, el_o, el_o]
        latt = Lattice.from_parameters(3.999911, 3.999911, 3.999911, 133.847504, 102.228244, 95.477342)
        coords = [[0.513004, 0.513004, 1.000000],
                  [0.017616, 0.017616, 0.000000], 
                  [0.649993, 0.874790, 0.775203], 
                  [0.099587, 0.874790, 0.224797]]
        struct = Structure(latt, elts, coords)
        self.assertEqual(oxide_type(struct, 1.1), "ozonide")

        latt = Lattice.from_parameters(3.159597, 3.159572, 7.685205, 89.999884, 89.999674, 60.000510)
        el_li = Element("Li")
        el_o = Element("O")
        elts = [el_li, el_li, el_li, el_li, el_o, el_o, el_o, el_o]
        coords = [[0.666656, 0.666705, 0.750001], 
                  [0.333342, 0.333378, 0.250001], 
                  [0.000001, 0.000041, 0.500001],
                  [0.000001, 0.000021, 0.000001], 
                  [0.333347, 0.333332, 0.649191], 
                  [0.333322, 0.333353, 0.850803], 
                  [0.666666, 0.666686, 0.350813], 
                  [0.666665, 0.666684, 0.149189]]
        struct = Structure(latt, elts, coords)
        self.assertEqual(oxide_type(struct, 1.1), "peroxide")
    
        el_li = Element("Li")
        el_o = Element("O")
        el_h = Element("H")
        latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000)
        elts = [el_h, el_h, el_li, el_li, el_o, el_o]
        coords = [[0.000000, 0.500000, 0.413969],
                  [0.500000, 0.000000, 0.586031], 
                  [0.000000, 0.000000, 0.000000],
                  [0.500000, 0.500000, 0.000000],
                  [0.000000, 0.500000, 0.192672],
                  [0.500000, 0.000000, 0.807328]]
        struct = Structure(latt, elts, coords)
        self.assertEqual(oxide_type(struct, 1.1), "hydroxide")
        
        el_li = Element("Li")
        el_n = Element("N")
        el_h = Element("H")
        latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000)
        elts = [el_h, el_h, el_li, el_li, el_n, el_n]
        coords = [[0.000000, 0.500000, 0.413969],
                  [0.500000, 0.000000, 0.586031], 
                  [0.000000, 0.000000, 0.000000],
                  [0.500000, 0.500000, 0.000000],
                  [0.000000, 0.500000, 0.192672],
                  [0.500000, 0.000000, 0.807328]]
        struct = Structure(latt, elts, coords)
        self.assertEqual(oxide_type(struct, 1.1), "None")