예제 #1
0
    def test_merge_sites(self):
        species = [{'Ag': 0.5}, {'Cl': 0.25}, {'Cl': 0.1},
                   {'Ag': 0.5}, {'F': 0.15}, {'F': 0.1}]
        coords = [[0, 0, 0], [0.5, 0.5, 0.5], [0.5, 0.5, 0.5],
                  [0, 0, 0], [0.5, 0.5, 1.501], [0.5, 0.5, 1.501]]
        s = Structure(Lattice.cubic(1), species, coords)
        s.merge_sites(mode="s")
        self.assertEqual(s[0].specie.symbol, 'Ag')
        self.assertEqual(s[1].species_and_occu,
                         Composition({'Cl': 0.35, 'F': 0.25}))
        self.assertArrayAlmostEqual(s[1].frac_coords, [.5, .5, .5005])

        # Test for TaS2 with spacegroup 166 in 160 setting.
        l = Lattice.from_lengths_and_angles([3.374351, 3.374351, 20.308941],
                                            [90.000000, 90.000000, 120.000000])
        species = ["Ta", "S", "S"]
        coords = [[0.000000, 0.000000, 0.944333], [0.333333, 0.666667, 0.353424],
                  [0.666667, 0.333333, 0.535243]]
        tas2 = Structure.from_spacegroup(160, l, species, coords)
        assert len(tas2) == 13
        tas2.merge_sites(mode="d")
        assert len(tas2) == 9

        l = Lattice.from_lengths_and_angles([3.587776, 3.587776, 19.622793],
                                            [90.000000, 90.000000, 120.000000])
        species = ["Na", "V", "S", "S"]
        coords = [[0.333333, 0.666667, 0.165000], [0.000000, 0.000000, 0.998333],
                  [0.333333, 0.666667, 0.399394], [0.666667, 0.333333, 0.597273]]
        navs2 = Structure.from_spacegroup(160, l, species, coords)
        assert len(navs2) == 18
        navs2.merge_sites(mode="d")
        assert len(navs2) == 12
예제 #2
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, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    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, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.ravel()[-1], a)

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

        return quanta
예제 #3
0
    def _cart_dists(self, s1, s2, l1, l2, mask):
        """
        Finds the cartesian distances normalized by (V/Natom) ^ 1/3
        between s1 and s2 on the average lattice of l1 and l2
        s1 and s2 are lists of fractional coordinates. Minimizes the
        RMS distance of the matching with an additional translation
        (but doesn't change the mapping)
        returns distances, fractional_translation vector
        """
        #create the average lattice
        avg_params = (np.array(l1.lengths_and_angles) +
                      np.array(l2.lengths_and_angles)) / 2
        avg_lattice = Lattice.from_lengths_and_angles(*avg_params)
        norm_length = (avg_lattice.volume / len(s1)) ** (1 / 3)
        mask_val = 1e20 * norm_length * self.stol

        all_d_2 = np.zeros([len(s1), len(s1)])
        vec_matrix = np.zeros([len(s1), len(s1), 3])

        vecs = pbc_shortest_vectors(avg_lattice, s2, s1)
        vec_matrix[:len(s2)] = vecs
        vec_matrix[mask] = mask_val
        d_2 = (np.sum(vecs ** 2, axis=-1))
        all_d_2[:len(s2)] = d_2
        all_d_2[mask] = mask_val

        lin = LinearAssignment(all_d_2)
        inds = np.arange(len(s2))
        shortest_vecs = vec_matrix[inds, lin.solution[:len(s2)], :]
        translation = np.average(shortest_vecs, axis=0)
        f_translation = avg_lattice.get_fractional_coords(translation)
        shortest_distances = np.sum((shortest_vecs - translation) ** 2,
                                    -1) ** 0.5
        return shortest_distances / norm_length, f_translation
예제 #4
0
파일: cif.py 프로젝트: dcossey014/pymatgen
    def get_lattice(
        self, data, length_strings=("a", "b", "c"), angle_strings=("alpha", "beta", "gamma"), lattice_type=None
    ):
        """
        Generate the lattice from the provided lattice parameters. In
        the absence of all six lattice parameters, the crystal system
        and necessary parameters are parsed
        """
        try:

            lengths = [str2float(data["_cell_length_" + i]) for i in length_strings]
            angles = [str2float(data["_cell_angle_" + i]) for i in angle_strings]
            if not lattice_type:
                return Lattice.from_lengths_and_angles(lengths, angles)

            else:
                return getattr(Lattice, lattice_type)(*(lengths + angles))

        except KeyError:
            # Missing Key search for cell setting
            for lattice_lable in ["_symmetry_cell_setting", "_space_group_crystal_system"]:
                if data.data.get(lattice_lable):
                    lattice_type = data.data.get(lattice_lable).lower()
                    try:

                        required_args = getargspec(getattr(Lattice, lattice_type)).args

                        lengths = (l for l in length_strings if l in required_args)
                        angles = (a for a in angle_strings if a in required_args)
                        return self.get_lattice(data, lengths, angles, lattice_type=lattice_type)
                    except AttributeError as exc:
                        warnings.warn(exc)

                else:
                    return None
예제 #5
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.lengths_and_angles, latt2.lengths_and_angles)
            self.assertFalse(np.allclose(aligned_out.lengths_and_angles,
                                         latt.lengths_and_angles))

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

        #catch the singular matrix error
        latt = Lattice.from_lengths_and_angles([1,1,1], [10,10,10])
        for l, _, _ in latt.find_all_mappings(latt, ltol=0.05, atol=11):
            self.assertTrue(isinstance(l, Lattice))
예제 #6
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=["tet", "oct", "tetoct"],
         op_targets=[1.0, 1.0, 1.0],
         op_threshs=[0.5, 0.5, 0.5],
         dl=0.4,
         fac_max_radius=2.5,
         drel_overlap=0.5,
         write_timings=False,
     )
예제 #7
0
    def test_interpolate_lattice(self):
        coords = list()
        coords.append([0, 0, 0])
        coords.append([0.75, 0.5, 0.75])
        struct = IStructure(self.lattice, ["Si"] * 2, coords)
        coords2 = list()
        coords2.append([0, 0, 0])
        coords2.append([0.5, 0.5, 0.5])
        l2 = Lattice.from_lengths_and_angles([3,4,4], [100,100,70])
        struct2 = IStructure(l2, ["Si"] * 2, coords2)
        int_s = struct.interpolate(struct2, 2, interpolate_lattices=True)
        self.assertArrayAlmostEqual(struct.lattice.abc,
                                    int_s[0].lattice.abc)
        self.assertArrayAlmostEqual(struct.lattice.angles,
                                    int_s[0].lattice.angles)
        self.assertArrayAlmostEqual(struct2.lattice.abc,
                                    int_s[2].lattice.abc)
        self.assertArrayAlmostEqual(struct2.lattice.angles,
                                    int_s[2].lattice.angles)
        int_angles = [110.3976469, 94.5359731, 64.5165856]
        self.assertArrayAlmostEqual(int_angles,
                                    int_s[1].lattice.angles)

        # Assert that volume is monotonic
        self.assertTrue(struct2.lattice.volume >= int_s[1].lattice.volume)
        self.assertTrue(int_s[1].lattice.volume >= struct.lattice.volume)
예제 #8
0
파일: cssr.py 프로젝트: albalu/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_lengths_and_angles(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))
예제 #9
0
def get_voronoi_nodes(structure, rad_dict=None, probe_rad=0.1):
    """
    Analyze the void space in the input structure using 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
    """

    temp_dir = tempfile.mkdtemp()
    current_dir = os.getcwd()
    name = "temp_zeo1"
    zeo_inp_filename = name + ".cssr"
    os.chdir(temp_dir)
    ZeoCssr(structure).write_file(zeo_inp_filename)
    rad_file = None
    rad_flag = False

    if rad_dict:
        rad_file = name + ".rad"
        rad_flag = True
        with open(rad_file, 'w+') as fp:
            for el in rad_dict.keys():
                print >>fp, "{} {}".format(el, rad_dict[el].real)

    atmnet = AtomNetwork.read_from_CSSR(zeo_inp_filename, rad_flag=rad_flag, rad_file=rad_file)
    vornet = atmnet.perform_voronoi_decomposition()
    vornet.analyze_writeto_XYZ(name, probe_rad, atmnet)
    voronoi_out_filename = name + '_voro.xyz'
    voronoi_node_mol = ZeoVoronoiXYZ.from_file(voronoi_out_filename).molecule
    #print voronoi_node_mol
    species = ["X"] * len(voronoi_node_mol.sites)
    coords = []
    prop = []
    for site in voronoi_node_mol.sites:
        coords.append(list(site.coords))
        prop.append(site.properties['voronoi_radius'])

    lattice = Lattice.from_lengths_and_angles(
        structure.lattice.abc, structure.lattice.angles
    )
    voronoi_node_struct = Structure(
        lattice, species, coords, coords_are_cartesian=True,
        site_properties={"voronoi_radius": prop}
    )

    os.chdir(current_dir)
    shutil.rmtree(temp_dir)

    return voronoi_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_lengths_and_angles([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_utils
        prev_threshold = coord_utils.LOOP_THRESHOLD
        coord_utils.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_utils.LOOP_THRESHOLD = prev_threshold
예제 #11
0
파일: zeopp.py 프로젝트: gpetretto/pymatgen
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("{} {}".format(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_lengths_and_angles(
        structure.lattice.abc, structure.lattice.angles)
    vor_node_struct = Structure(
        lattice, species, coords, coords_are_cartesian=True,
        to_unit_cell=True, site_properties={"voronoi_radius": prop})

    return vor_node_struct
예제 #12
0
    def from_string(header_str):
        """
        Reads Header string and returns Header object if header was
        generated by pymatgen.

        Args:
            header_str:
                pymatgen generated feff.inp header

        Returns:
            structure object.
        """
        lines = tuple(clean_lines(header_str.split("\n"), False))
        comment = lines[0]
        feffpmg = comment.find("pymatgen")

        if feffpmg > 0:
            source = lines[1].split()[2]
            natoms = int(lines[7].split()[2])
            basis_vec = lines[5].split()

            a = float(basis_vec[2])
            b = float(basis_vec[3])
            c = float(basis_vec[4])

            lengths = [a, b, c]
            basis_ang = lines[6].split()

            alpha = float(basis_ang[2])
            beta = float(basis_ang[3])
            gamma = float(basis_ang[4])
            angles = [alpha, beta, gamma]

            lattice = Lattice.from_lengths_and_angles(lengths, angles)
            atomic_symbols = []

            for i in xrange(8, 8 + natoms):
                atomic_symbols.append(lines[i].split()[2])

            # read the atomic coordinates
            coords = []

            for i in xrange(natoms):
                toks = lines[i + 8].split()
                coords.append([float(s) for s in toks[3:]])

            struct_fromfile = Structure(lattice, atomic_symbols, coords, False,
                                        False, False)
            struct_fromfile.compound = lines[3].split()[2]

            h = Header(struct_fromfile, comment)
            h.set_source(source)

            return h
        else:
            return "Header not generated by pymatgen, " \
                   "cannot return header object"
예제 #13
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)
예제 #14
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_lengths_and_angles([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)
예제 #15
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)
예제 #16
0
파일: resio.py 프로젝트: muhrin/SPLpy
    def from_string(data):
        """
        Reads a Res from a string.

        Args:
            data (str): String containing Res data.

        Returns:
            Res object.
        """
        abc = []
        ang = []
        sp = []
        coords = []
        info = dict()
        coord_patt = re.compile(
            "(\w+)\s+([0-9]+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)"
        )
        lines = data.splitlines()
        line_no = 0
        while line_no < len(lines):
            line = lines[line_no]
            tokens = line.split()
            if tokens:
                if tokens[0] == 'TITL':
                    try:
                        info = Res.parse_title(line)
                    except ValueError:
                        info = dict()
                elif tokens[0] == 'CELL' and len(tokens) == 8:
                    abc = map(float, tokens[2:5])
                    ang = map(float, tokens[5:8])
                elif tokens[0] == 'SFAC':
                    for atom_line in lines[line_no:]:
                        if line.strip() == 'END':
                            break
                        else:
                            match = coord_patt.search(atom_line)
                            if match:
                                sp.append(match.group(1))  # 1-indexed
                                coords.append(map(float, match.groups()[2:5]))  # 0-indexed
                        line_no += 1  # Make sure the global is updated
            line_no += 1

        return Res(Structure(Lattice.from_lengths_and_angles(abc, ang), sp, coords), info.get('name'),
                   info.get('pressure'), info.get('energy'), info.get('spacegroup'), info.get('times_found'))
예제 #17
0
 def test_interpolate_lattice(self):
     coords = list()
     coords.append([0, 0, 0])
     coords.append([0.75, 0.5, 0.75])
     struct = IStructure(self.lattice, ["Si"] * 2, coords)
     coords2 = list()
     coords2.append([0, 0, 0])
     coords2.append([0.5, 0.5, 0.5])
     l2 = Lattice.from_lengths_and_angles([3, 4, 4], [100, 100, 70])
     struct2 = IStructure(l2, ["Si"] * 2, coords2)
     int_s = struct.interpolate(struct2, 2, interpolate_lattices=True)
     self.assertArrayAlmostEqual(struct.lattice.abc, int_s[0].lattice.abc)
     self.assertArrayAlmostEqual(struct.lattice.angles, int_s[0].lattice.angles)
     self.assertArrayAlmostEqual(struct2.lattice.abc, int_s[2].lattice.abc)
     self.assertArrayAlmostEqual(struct2.lattice.angles, int_s[2].lattice.angles)
     int_angles = [(a + struct2.lattice.angles[i]) / 2 for i, a in enumerate(struct.lattice.angles)]
     self.assertArrayAlmostEqual(int_angles, int_s[1].lattice.angles)
예제 #18
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_lengths_and_angles([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)
예제 #19
0
    def _cmp_cartesian_struct(self, s1, s2, l1, l2):
        """
        Once a fit is found, a rms minimizing fit is done to
        ensure the fit is correct. To do this,

        1) The structures are placed into an average lattice
        2) All sites are shifted by the mean
            displacement vector between matched sites.
        3) calculate distances
        4) return rms distance normalized by (V/Natom) ^ 1/3
            and the maximum distance found
        """
        nsites = sum(map(len, s1))

        avg_params = (np.array(l1.lengths_and_angles) +
                      np.array(l2.lengths_and_angles)) / 2

        avg_lattice = Lattice.from_lengths_and_angles(avg_params[0],
                                                      avg_params[1])
        dist = np.zeros([nsites, nsites]) + 100 * nsites
        vec_matrix = np.zeros([nsites, nsites, 3])
        i = 0
        for s1_coords, s2_coords in zip(s1, s2):
            j = len(s1_coords)
            vecs = pbc_shortest_vectors(avg_lattice, s1_coords, s2_coords)
            distances = (np.sum(vecs**2, axis=-1))**0.5
            dist[i:i + j, i:i + j] = distances
            vec_matrix[i:i + j, i:i + j] = vecs
            i += j
        lin = LinearAssignment(dist)
        inds = np.arange(nsites)

        shortest_vecs = vec_matrix[inds, lin.solution, :]
        shortest_vec_square = np.sum(
            (shortest_vecs - np.average(shortest_vecs, axis=0))**2, -1)

        norm_length = (avg_lattice.volume / nsites)**(1 / 3)

        rms = np.average(shortest_vec_square)**0.5 / norm_length

        max_dist = np.max(shortest_vec_square)**0.5 / norm_length

        return rms, max_dist
예제 #20
0
    def _cart_dists(self, s1, s2, l1, l2, mask):
        """
        Finds the cartesian distances normalized by (V/Natom) ^ 1/3
        between two structures on the average lattice of l1 and l2
        s_superset and s_subset are lists of fractional coordinates.
        Minimizes the RMS distance of the matching with an additional
        translation (but doesn't change the mapping)
        returns distances, fractional_translation vector
        """
        #ensure that we always calculate distances from the subset
        #to the superset
        if len(s1) > len(s2):
            s_superset, s_subset, mult = s1, s2, 1
        else:
            s_superset, s_subset, mult = s2, s1, -1
            mask = mask.T
        #create the average lattice
        avg_params = (np.array(l1.lengths_and_angles) +
                      np.array(l2.lengths_and_angles)) / 2
        avg_lattice = Lattice.from_lengths_and_angles(*avg_params)
        norm_length = (avg_lattice.volume / len(s_superset)) ** (1 / 3)
        mask_val = 1e20 * norm_length * self.stol

        all_d_2 = np.zeros([len(s_superset), len(s_superset)])
        vec_matrix = np.zeros([len(s_superset), len(s_superset), 3])

        #vectors from subset to superset
        #1st index subset, 2nd index superset
        vecs = pbc_shortest_vectors(avg_lattice, s_subset, s_superset)
        vec_matrix[:len(s_subset), :len(s_superset)] = vecs
        vec_matrix[mask] = mask_val
        d_2 = (np.sum(vecs ** 2, axis=-1))
        all_d_2[:len(s_subset), :len(s_superset)] = d_2
        all_d_2[mask] = mask_val
        lin = LinearAssignment(all_d_2)
        inds = np.arange(len(s_subset))
        #shortest vectors from the subset to the superset
        shortest_vecs = vec_matrix[inds, lin.solution[:len(s_subset)], :]
        translation = np.average(shortest_vecs, axis=0)
        f_translation = avg_lattice.get_fractional_coords(translation)
        shortest_distances = np.sum((shortest_vecs - translation) ** 2,
                                    -1) ** 0.5
        return shortest_distances / norm_length, f_translation * mult
예제 #21
0
    def _cmp_cartesian_struct(self, s1, s2, l1, l2):
        """
        Once a fit is found, a rms minimizing fit is done to
        ensure the fit is correct. To do this,

        1) The structures are placed into an average lattice
        2) All sites are shifted by the mean
            displacement vector between matched sites.
        3) calculate distances
        4) return rms distance normalized by (V/Natom) ^ 1/3
            and the maximum distance found
        """
        nsites = sum(map(len, s1))

        avg_params = (np.array(l1.lengths_and_angles) +
                      np.array(l2.lengths_and_angles)) / 2

        avg_lattice = Lattice.from_lengths_and_angles(avg_params[0],
                                                      avg_params[1])
        dist = np.zeros([nsites, nsites]) + 100 * nsites
        vec_matrix = np.zeros([nsites, nsites, 3])
        i = 0
        for s1_coords, s2_coords in zip(s1, s2):
            j = len(s1_coords)
            vecs = pbc_shortest_vectors(avg_lattice, s1_coords, s2_coords)
            distances = (np.sum(vecs ** 2, axis=-1)) ** 0.5
            dist[i: i + j, i: i + j] = distances
            vec_matrix[i: i + j, i: i + j] = vecs
            i += j
        lin = LinearAssignment(dist)
        inds = np.arange(nsites)

        shortest_vecs = vec_matrix[inds, lin.solution, :]
        shortest_vec_square = np.sum(
            (shortest_vecs - np.average(shortest_vecs, axis=0)) ** 2, -1)

        norm_length = (avg_lattice.volume / nsites) ** (1 / 3)

        rms = np.average(shortest_vec_square) ** 0.5 / norm_length

        max_dist = np.max(shortest_vec_square) ** 0.5 / norm_length

        return rms, max_dist
예제 #22
0
    def _cart_dists(self, s1, s2, l1, l2, mask):
        """
        Finds the cartesian distances normalized by (V/Natom) ^ 1/3
        between two structures on the average lattice of l1 and l2
        s_superset and s_subset are lists of fractional coordinates.
        Minimizes the RMS distance of the matching with an additional
        translation (but doesn't change the mapping)
        returns distances, fractional_translation vector
        """
        #ensure that we always calculate distances from the subset
        #to the superset
        if len(s1) > len(s2):
            s_superset, s_subset, mult = s1, s2, 1
        else:
            s_superset, s_subset, mult = s2, s1, -1
            mask = mask.T
        #create the average lattice
        avg_params = (np.array(l1.lengths_and_angles) +
                      np.array(l2.lengths_and_angles)) / 2
        avg_lattice = Lattice.from_lengths_and_angles(*avg_params)
        norm_length = (avg_lattice.volume / len(s_superset))**(1 / 3)
        mask_val = 1e20 * norm_length * self.stol

        all_d_2 = np.zeros([len(s_superset), len(s_superset)])
        vec_matrix = np.zeros([len(s_superset), len(s_superset), 3])

        #vectors from subset to superset
        #1st index subset, 2nd index superset
        vecs = pbc_shortest_vectors(avg_lattice, s_subset, s_superset)
        vec_matrix[:len(s_subset), :len(s_superset)] = vecs
        vec_matrix[mask] = mask_val
        d_2 = (np.sum(vecs**2, axis=-1))
        all_d_2[:len(s_subset), :len(s_superset)] = d_2
        all_d_2[mask] = mask_val
        lin = LinearAssignment(all_d_2)
        inds = np.arange(len(s_subset))
        #shortest vectors from the subset to the superset
        shortest_vecs = vec_matrix[inds, lin.solution[:len(s_subset)], :]
        translation = np.average(shortest_vecs, axis=0)
        f_translation = avg_lattice.get_fractional_coords(translation)
        shortest_distances = np.sum((shortest_vecs - translation)**2, -1)**0.5
        return shortest_distances / norm_length, f_translation * mult
예제 #23
0
파일: cif.py 프로젝트: ProkillerJ/pymatgen
    def get_lattice(self, data, length_strings=("a", "b", "c"),
                    angle_strings=("alpha", "beta", "gamma"),
                    lattice_type=None):
        """
        Generate the lattice from the provided lattice parameters. In
        the absence of all six lattice parameters, the crystal system
        and necessary parameters are parsed
        """
        try:

            lengths = [str2float(data["_cell_length_" + i])
                       for i in length_strings]
            angles = [str2float(data["_cell_angle_" + i])
                      for i in angle_strings]
            if not lattice_type:
                return Lattice.from_lengths_and_angles(lengths, angles)

            else:
                return getattr(Lattice, lattice_type)(*(lengths + angles))

        except KeyError:
            # Missing Key search for cell setting
            for lattice_lable in ["_symmetry_cell_setting",
                                  "_space_group_crystal_system"]:
                if data.data.get(lattice_lable):
                    lattice_type = data.data.get(lattice_lable).lower()
                    try:

                        required_args = getargspec(
                            getattr(Lattice, lattice_type)).args

                        lengths = (l for l in length_strings
                                   if l in required_args)
                        angles = (a for a in angle_strings
                                  if a in required_args)
                        return self.get_lattice(data, lengths, angles,
                                                lattice_type=lattice_type)
                    except AttributeError as exc:
                        warnings.warn(exc)

                else:
                    return None
예제 #24
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=["tet", "oct"],
                                           op_threshs=[0.3, 0.5],
                                           dl=0.4,
                                           doverlap=1.0,
                                           facmaxdl=1.01)
예제 #25
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, angles) = newlatt.lengths_and_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!")
     (lengths, angles) = \
         Lattice.from_lengths_and_angles(lengths, angles).lengths_and_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!")
예제 #26
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, angles) = newlatt.lengths_and_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!")
     (lengths, angles) = \
         Lattice.from_lengths_and_angles(lengths, angles).lengths_and_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!")
예제 #27
0
 def test_interpolate_lattice(self):
     coords = list()
     coords.append([0, 0, 0])
     coords.append([0.75, 0.5, 0.75])
     struct = IStructure(self.lattice, ["Si"] * 2, coords)
     coords2 = list()
     coords2.append([0, 0, 0])
     coords2.append([0.5, 0.5, 0.5])
     l2 = Lattice.from_lengths_and_angles([3, 4, 4], [100, 100, 70])
     struct2 = IStructure(l2, ["Si"] * 2, coords2)
     int_s = struct.interpolate(struct2, 2, interpolate_lattices=True)
     self.assertArrayAlmostEqual(struct.lattice.abc, int_s[0].lattice.abc)
     self.assertArrayAlmostEqual(struct.lattice.angles,
                                 int_s[0].lattice.angles)
     self.assertArrayAlmostEqual(struct2.lattice.abc, int_s[2].lattice.abc)
     self.assertArrayAlmostEqual(struct2.lattice.angles,
                                 int_s[2].lattice.angles)
     int_angles = [(a + struct2.lattice.angles[i]) / 2
                   for i, a in enumerate(struct.lattice.angles)]
     self.assertArrayAlmostEqual(int_angles, int_s[1].lattice.angles)
예제 #28
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_lengths_and_angles([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)
예제 #29
0
    def test_interpolate_lattice(self):
        coords = list()
        coords.append([0, 0, 0])
        coords.append([0.75, 0.5, 0.75])
        struct = IStructure(self.lattice, ["Si"] * 2, coords)
        coords2 = list()
        coords2.append([0, 0, 0])
        coords2.append([0.5, 0.5, 0.5])
        l2 = Lattice.from_lengths_and_angles([3, 4, 4], [100, 100, 70])
        struct2 = IStructure(l2, ["Si"] * 2, coords2)
        int_s = struct.interpolate(struct2, 2, interpolate_lattices=True)
        self.assertArrayAlmostEqual(struct.lattice.abc, int_s[0].lattice.abc)
        self.assertArrayAlmostEqual(struct.lattice.angles,
                                    int_s[0].lattice.angles)
        self.assertArrayAlmostEqual(struct2.lattice.abc, int_s[2].lattice.abc)
        self.assertArrayAlmostEqual(struct2.lattice.angles,
                                    int_s[2].lattice.angles)
        int_angles = [110.3976469, 94.5359731, 64.5165856]
        self.assertArrayAlmostEqual(int_angles, int_s[1].lattice.angles)

        # Assert that volume is monotonic
        self.assertTrue(struct2.lattice.volume >= int_s[1].lattice.volume)
        self.assertTrue(int_s[1].lattice.volume >= struct.lattice.volume)
예제 #30
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_lengths_and_angles([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
예제 #31
0
파일: zeoio.py 프로젝트: bkappes/pymatgen
    def from_string(string):
        """ 
        Reads a string representation to a ZeoCssr object.

        Args:
            string:
                A string representation of a ZeoCSSR.

        Returns:
            ZeoCssr object.
        """
        lines = string.split("\n")
        toks = lines[0].split()
        lengths = map(float, toks)
        toks = lines[1].split()
        angles = map(float, toks[0:3])
        # Zeo++ takes x-axis along a and pymatgen takes z-axis along c
        a = lengths.pop(-1)
        lengths.insert(0, a)
        alpha = angles.pop(-1)
        angles.insert(0, alpha)
        latt = Lattice.from_lengths_and_angles(lengths, angles)
        sp = []
        coords = []
        chrg = []
        for l in lines[4:]:
            m = re.match(
                "\d+\s+(\w+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)\s+" +
                "([0-9\-\.]+)\s+(?:0\s+){8}([0-9\-\.]+)", l.strip())
            if m:
                sp.append(m.group(1))
                #coords.append([float(m.group(i)) for i in xrange(2, 5)])
                # Zeo++ takes x-axis along a and pymatgen takes z-axis along c
                coords.append([float(m.group(i)) for i in [3, 4, 2]])
                chrg.append(m.group(5))
        return ZeoCssr(
            Structure(latt, sp, coords, site_properties={'charge': chrg}))
예제 #32
0
파일: zeoio.py 프로젝트: akashneo/pymatgen
    def from_string(string):
        """ 
        Reads a string representation to a ZeoCssr object.

        Args:
            string:
                A string representation of a ZeoCSSR.

        Returns:
            ZeoCssr object.
        """
        lines = string.split("\n")
        toks = lines[0].split()
        lengths = map(float, toks)
        toks = lines[1].split()
        angles = map(float, toks[0:3])
        # Zeo++ takes x-axis along a and pymatgen takes z-axis along c
        a = lengths.pop(-1)
        lengths.insert(0, a)
        alpha = angles.pop(-1)
        angles.insert(0, alpha)
        latt = Lattice.from_lengths_and_angles(lengths, angles)
        sp = []
        coords = []
        chrg = []
        for l in lines[4:]:
            m = re.match("\d+\s+(\w+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)\s+" +
                         "([0-9\-\.]+)\s+(?:0\s+){8}([0-9\-\.]+)", l.strip())
            if m:
                sp.append(m.group(1))
                #coords.append([float(m.group(i)) for i in xrange(2, 5)])
                # Zeo++ takes x-axis along a and pymatgen takes z-axis along c
                coords.append([float(m.group(i)) for i in [3, 4, 2]])
                chrg.append(m.group(5))
        return ZeoCssr(
            Structure(latt, sp, coords, site_properties={'charge': chrg})
        )
예제 #33
0
    def get_same_branch_polarization_data(self, convert_to_muC_per_cm2=False):
        """
        Get same branch dipole moment (convert_to_muC_per_cm2=False)
        or polarization for given polarization data (convert_to_muC_per_cm2=True).

        Polarization is a lattice vector, meaning it is only defined modulo the
        quantum of polarization:

            P = P_0 + \\sum_i \\frac{n_i e R_i}{\\Omega}

        where n_i is an integer, e is the charge of the electron in microCoulombs,
        R_i is a lattice vector, and \\Omega is the unit cell volume in cm**3
        (giving polarization units of microCoulomb per centimeter**2).

        The quantum of the dipole moment in electron Angstroms (as given by VASP) is:

            \\sum_i n_i e R_i

        where e, the electron charge, is 1 and R_i is a lattice vector, and n_i is an integer.

        Given N polarization calculations in order from nonpolar to polar, this algorithm
        minimizes the distance between adjacent polarization images. To do this, it
        constructs a polarization lattice for each polarization calculation using the
        pymatgen.core.structure class and calls the get_nearest_site method to find the
        image of a given polarization lattice vector that is closest to the previous polarization
        lattice vector image.

        convert_to_muC_per_cm2: convert polarization from electron * Angstroms to
            microCoulomb per centimeter**2
        """

        p_elec, p_ion = self.get_pelecs_and_pions()
        p_tot = p_elec + p_ion
        p_tot = np.matrix(p_tot)

        lattices = [s.lattice for s in self.structures]
        volumes = np.matrix([s.lattice.volume for s in self.structures])

        L = len(p_elec)

        # convert polarizations and lattice lengths prior to adjustment
        if convert_to_muC_per_cm2:
            e_to_muC = -1.6021766e-13
            cm2_to_A2 = 1e16
            units = 1.0 / np.matrix(volumes)
            units *= e_to_muC * cm2_to_A2
            # Convert the total polarization
            p_tot = np.multiply(units.T, p_tot)
            # adjust lattices
            for i in range(L):
                lattice = lattices[i]
                l, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.A1[i], a)

        d_structs = []
        sites = []

        for i in range(L):
            l = lattices[i]
            frac_coord = np.divide(np.matrix(p_tot[i]),
                                   np.matrix([l.a, l.b, l.c]))
            d = PolarizationLattice(l, ["C"], [np.matrix(frac_coord).A1])
            d_structs.append(d)
            site = d[0]
            if i == 0:
                # Adjust nonpolar polarization to be closest to zero.
                # This is compatible with both a polarization of zero or a half quantum.
                prev_site = [0, 0, 0]
            else:
                prev_site = sites[-1].coords
            new_site = d.get_nearest_site(prev_site, site)
            sites.append(new_site[0])

        adjust_pol = []
        for s, d in zip(sites, d_structs):
            l = d.lattice
            adjust_pol.append(
                np.multiply(s.frac_coords, np.matrix([l.a, l.b, l.c])).A1)
        adjust_pol = np.matrix(adjust_pol)

        return adjust_pol
예제 #34
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)
def get_voronoi_percolate_nodes(structure, rad_dict=None, probe_rad=0.1):
    """
    This function is used to get voronoi percolate nodes. Different from get_percolated_node_edge,
    the vor_accessible_node_struct returned by this one does not contain neighbor information. So if you need
    neighboring information of each accessible node, you may use get_percolated_node_edge function.
    Args:
        structure (Structure): Structure object for analysis
        rad_dict (dict): optional, dictionary of radii of elements in structures.
            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:

    Returns:
        vor_node_struct, vor_accessible_node_struct, vor_edgecenter_struct, vor_facecenter_struct (Structure):


    """
    with ScratchDir('.'):
        name = "temp_zeo2"
        zeo_inp_filename = name + ".cssr"
        ZeoCssr(structure).write_file(zeo_inp_filename)
        rad_file = None
        rad_flag = False
        if rad_dict:
            rad_file = name + ".rad"
            rad_flag = True
            with open(rad_file, 'w+') as fp:
                for el in rad_dict.keys():
                    fp.write("{} {}\n".format(el, rad_dict[el].real))

        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()
        vornet.analyze_writeto_XYZ(name, probe_rad, atmnet)
        voro_out_filename = name + '_voro.xyz'
        voro_node_mol = ZeoVoronoiXYZ.from_file(name + '_voro.xyz').molecule
        voro_accessible_node_mol = ZeoVoronoiXYZ.from_file(
            name + '_voro_accessible.xyz').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_lengths_and_angles(structure.lattice.abc,
                                              structure.lattice.angles)
    vor_node_struct = Structure(lattice,
                                species,
                                coords,
                                coords_are_cartesian=True,
                                to_unit_cell=False,
                                site_properties={"voronoi_radius": prop})

    # percolate node struct
    species = ["X"] * len(voro_accessible_node_mol.sites)
    coords = []
    prop = []
    for site in voro_accessible_node_mol.sites:
        coords.append(list(site.coords))
        prop.append(site.properties['voronoi_radius'])

    lattice = Lattice.from_lengths_and_angles(structure.lattice.abc,
                                              structure.lattice.angles)
    vor_accessible_node_struct = Structure(
        lattice,
        species,
        coords,
        coords_are_cartesian=True,
        to_unit_cell=False,
        site_properties={"voronoi_radius": prop})

    # PMG-Zeo c<->a transformation for voronoi face centers
    rot_face_centers = [(center[1], center[2], center[0])
                        for center in vor_face_centers]
    rot_edge_centers = [(center[1], center[2], center[0])
                        for center in vor_edge_centers]

    species = ["X"] * len(rot_face_centers)
    prop = [0.0] * len(rot_face_centers)  # Vor radius not evaluated for fc
    vor_facecenter_struct_origin = Structure(
        lattice,
        species,
        rot_face_centers,
        coords_are_cartesian=True,
        to_unit_cell=False,
        site_properties={"voronoi_radius": prop})
    vor_facecenter_struct = Structure.from_sites(
        list(set([i for i in vor_facecenter_struct_origin])))
    species = ["X"] * len(rot_edge_centers)
    prop = [0.0] * len(rot_edge_centers)  # Vor radius not evaluated for fc
    vor_edgecenter_struct_origin = Structure(
        lattice,
        species,
        rot_edge_centers,
        coords_are_cartesian=True,
        to_unit_cell=False,
        site_properties={"voronoi_radius": prop})
    vor_edgecenter_struct = Structure.from_sites(
        list(set([i for i in vor_edgecenter_struct_origin])))
    return vor_node_struct, vor_accessible_node_struct, vor_edgecenter_struct, vor_facecenter_struct
예제 #36
0
    def get_same_branch_polarization_data(self, convert_to_muC_per_cm2=False):
        """
        Get same branch dipole moment (convert_to_muC_per_cm2=False)
        or polarization for given polarization data (convert_to_muC_per_cm2=True).

        Polarization is a lattice vector, meaning it is only defined modulo the
        quantum of polarization:

            P = P_0 + \\sum_i \\frac{n_i e R_i}{\\Omega}

        where n_i is an integer, e is the charge of the electron in microCoulombs,
        R_i is a lattice vector, and \\Omega is the unit cell volume in cm**3
        (giving polarization units of microCoulomb per centimeter**2).

        The quantum of the dipole moment in electron Angstroms (as given by VASP) is:

            \\sum_i n_i e R_i

        where e, the electron charge, is 1 and R_i is a lattice vector, and n_i is an integer.

        Given N polarization calculations in order from nonpolar to polar, this algorithm
        minimizes the distance between adjacent polarization images. To do this, it
        constructs a polarization lattice for each polarization calculation using the
        pymatgen.core.structure class and calls the get_nearest_site method to find the
        image of a given polarization lattice vector that is closest to the previous polarization
        lattice vector image.

        convert_to_muC_per_cm2: convert polarization from electron * Angstroms to
            microCoulomb per centimeter**2
        """

        p_elec, p_ion = self.get_pelecs_and_pions()
        p_tot = p_elec + p_ion
        p_tot = np.matrix(p_tot)

        lattices = [s.lattice for s in self.structures]
        volumes = np.matrix([s.lattice.volume for s in self.structures])

        L = len(p_elec)

        # convert polarizations and lattice lengths prior to adjustment
        if convert_to_muC_per_cm2:
            e_to_muC = -1.6021766e-13
            cm2_to_A2 = 1e16
            units = 1.0 / np.matrix(volumes)
            units *= e_to_muC * cm2_to_A2
            # Convert the total polarization
            p_tot = np.multiply(units.T, p_tot)
            # adjust lattices
            for i in range(L):
                lattice = lattices[i]
                l, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.A1[i], a)

        d_structs = []
        sites = []

        for i in range(L):
            l = lattices[i]
            frac_coord = np.divide(np.matrix(p_tot[i]),
                                   np.matrix([l.a, l.b, l.c]))
            d = PolarizationLattice(l, ["C"], [np.matrix(frac_coord).A1])
            d_structs.append(d)
            site = d[0]
            if i == 0:
                # Adjust nonpolar polarization to be closest to zero.
                # This is compatible with both a polarization of zero or a half quantum.
                prev_site = [0, 0, 0]
            else:
                prev_site = sites[-1].coords
            new_site = d.get_nearest_site(prev_site, site)
            sites.append(new_site[0])

        adjust_pol = []
        for s, d in zip(sites, d_structs):
            l = d.lattice
            adjust_pol.append(
                np.multiply(s.frac_coords, np.matrix([l.a, l.b, l.c])).A1)
        adjust_pol = np.matrix(adjust_pol)

        return adjust_pol
예제 #37
0
    def _get_structure(self, data, primitive):
        """
        Generate structure from part of the cif.
        """
        lengths = [float_from_str(data["_cell_length_" + i])
                   for i in ["a", "b", "c"]]
        angles = [float_from_str(data["_cell_angle_" + i])
                  for i in ["alpha", "beta", "gamma"]]
        lattice = Lattice.from_lengths_and_angles(lengths, angles)
        try:
            sympos = data["_symmetry_equiv_pos_as_xyz"]
        except KeyError:
            try:
                sympos = data["_symmetry_equiv_pos_as_xyz_"]
            except KeyError:
                warnings.warn("No _symmetry_equiv_pos_as_xyz type key found. "
                              "Defaulting to P1.")
                sympos = ['x, y, z']
        self.symmetry_operations = parse_symmetry_operations(sympos)

        def parse_symbol(sym):
            m = re.search("([A-Z][a-z]*)", sym)
            if m:
                return m.group(1)
            return ""

        try:
            oxi_states = {data["_atom_type_symbol"][i]:
                          float_from_str(data["_atom_type_oxidation_number"][i])
                          for i in xrange(len(data["_atom_type_symbol"]))}
        except (ValueError, KeyError):
            oxi_states = None

        coord_to_species = OrderedDict()

        for i in xrange(len(data["_atom_site_type_symbol"])):
            symbol = parse_symbol(data["_atom_site_type_symbol"][i])
            if oxi_states is not None:
                el = Specie(symbol,
                            oxi_states[data["_atom_site_type_symbol"][i]])
            else:
                el = Element(symbol)
            x = float_from_str(data["_atom_site_fract_x"][i])
            y = float_from_str(data["_atom_site_fract_y"][i])
            z = float_from_str(data["_atom_site_fract_z"][i])
            try:
                occu = float_from_str(data["_atom_site_occupancy"][i])
            except (KeyError, ValueError):
                occu = 1
            if occu > 0:
                coord = (x, y, z)
                if coord not in coord_to_species:
                    coord_to_species[coord] = {el: occu}
                else:
                    coord_to_species[coord][el] = occu

        allspecies = []
        allcoords = []

        for coord, species in coord_to_species.items():
            coords = self._unique_coords(coord)
            allcoords.extend(coords)
            allspecies.extend(len(coords) * [species])

        #rescale occupancies if necessary
        for species in allspecies:
            totaloccu = sum(species.values())
            if  1 < totaloccu <= self._occupancy_tolerance:
                for key, value in species.iteritems():
                    species[key] = value / totaloccu

        struct = Structure(lattice, allspecies, allcoords)
        if primitive:
            struct = struct.get_primitive_structure()
        return struct.get_sorted_structure()
예제 #38
0
 def av_lat(l1, l2):
     params = (np.array(l1.lengths_and_angles) +
               np.array(l2.lengths_and_angles)) / 2
     return Lattice.from_lengths_and_angles(*params)
예제 #39
0
    def from_string(header_str):
        """
        Reads Header string and returns Header object if header was
        generated by pymatgen.

        Args:
            header_str: pymatgen generated feff.inp header

        Returns:
            Structure object.
        """
        # 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

        lines = tuple(clean_lines(header_str.split("\n"), False))
        comment1 = lines[0]
        feffpmg = comment1.find("pymatgen")

        if feffpmg > 0:
            comment2 = ' '.join(lines[1].split()[2:])

            #This sec section gets information to create structure object

            source = ' '.join(lines[2].split()[2:])
            natoms = int(lines[8].split()[2])
            basis_vec = lines[6].split()

            a = float(basis_vec[2])
            b = float(basis_vec[3])
            c = float(basis_vec[4])

            lengths = [a, b, c]
            basis_ang = lines[7].split()

            alpha = float(basis_ang[2])
            beta = float(basis_ang[3])
            gamma = float(basis_ang[4])
            angles = [alpha, beta, gamma]

            lattice = Lattice.from_lengths_and_angles(lengths, angles)
            atomic_symbols = []

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

            # read the atomic coordinates
            coords = []

            for i in xrange(natoms):
                toks = lines[i + 9].split()
                coords.append([float(s) for s in toks[3:]])

            #Structure object is now generated and Header object returned

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

            h = Header(struct_fromfile, source, comment2)

            return h
        else:
            return "Header not generated by pymatgen, " \
                   "cannot return header object"
예제 #40
0
 def av_lat(l1, l2):
     params = (np.array(l1.lengths_and_angles) +
               np.array(l2.lengths_and_angles)) / 2
     return Lattice.from_lengths_and_angles(*params)
예제 #41
0
    def structure(self):
        # Get lattice vectors
        if "lattice_cart" in self.blocks:
            lattice_cart = self.blocks["lattice_cart"].values
            if lattice_cart[0][0].lower() in ("ang", "nm", "cm", "m", "bohr",
                                              "a0"):
                unit = lattice_cart[0][0].lower()
                vectors = lattice_cart[1:]
            else:
                unit = "ang"
                vectors = lattice_cart
            vectors = np.array([list(map(float, row)) for row in vectors])
            if vectors.shape != (3, 3):
                raise ValueError("lattice_cart should contain a 3x3 matrix")

            vectors *= to_angstrom[unit]
            lattice = Lattice(vectors)
        elif "lattice_abc" in self.blocks:
            lattice_abc = self.blocks["lattice_abc"].values
            if lattice_abc[0][0].lower() in ("ang", "nm", "cm", "m", "bohr",
                                             "a0"):
                unit = lattice_abc[0][0].lower()
                lengths_and_angles = lattice_abc[1:]
            else:
                unit = "ang"
                lengths_and_angles = lattice_abc[1:]
            if len(lengths_and_angles) != 2:
                raise ValueError("lattice_abc should have two rows")
            lengths_and_angles = [
                list(map(float, row)) for row in lengths_and_angles
            ]
            lengths_and_angles[0] = [
                x * to_angstrom[unit] for x in lengths_and_angles[0]
            ]
            lattice = Lattice.from_lengths_and_angles(*lengths_and_angles)
        else:
            raise ValueError("Couldn't find a lattice in cell file")

        if "positions_frac" in self.blocks:
            elements_coords = [(row[0], list(map(float, row[1:4])))
                               for row in self.blocks["positions_frac"].values]
            elements, coords = zip(*elements_coords)
            return Structure(lattice,
                             elements,
                             coords,
                             coords_are_cartesian=False)
        elif "positions_abs" in self.blocks:
            positions_abs = self.blocks["positions_abs"].values
            if positions_abs[0][0].lower() in ("ang", "nm", "cm", "m", "bohr",
                                               "a0"):
                unit = positions_abs[0][0].lower()
                positions_abs = positions_abs[1:]
            else:
                unit = "ang"
            elements_coords = [(row[0], list(map(float, row[1:4])))
                               for row in positions_abs]
            elements, coords = zip(*elements_coords)
            return Structure(lattice,
                             elements,
                             coords,
                             coords_are_cartesian=True)
        else:
            raise ValueError("Couldn't find any atom positions in cell file")
예제 #42
0
파일: cifio.py 프로젝트: chenweis/pymatgen
    def _get_structure(self, data, primitive):
        """
        Generate structure from part of the cif.
        """
        spacegroup = data['_symmetry_space_group_name_H-M']

        if len(spacegroup) == 0:
            latt_type = "P"
        else:
            latt_type = spacegroup[0]
        lengths = [float_from_string(data['_cell_length_' + i]) for i in ['a', 'b', 'c']]
        angles = [float_from_string(data['_cell_angle_' + i]) for i in ['alpha', 'beta', 'gamma']]
        lattice = Lattice.from_lengths_and_angles(lengths, angles)
        primlattice = lattice.get_primitive_lattice(latt_type)
        try:
            sympos = data['_symmetry_equiv_pos_as_xyz']
        except:
            try:
                sympos = data['_symmetry_equiv_pos_as_xyz_']
            except:
                warnings.warn("No _symmetry_equiv_pos_as_xyz type key found. Defaulting to P1.")
                sympos
        def parse_symbol(sym):
            m = re.search("([A-Z][a-z]*)", sym)
            if m:
                return m.group(1)
            return ''

        #oxi_states = None
        try:
            oxi_states = dict()
            for i in xrange(len(data['_atom_type_symbol'])):
                oxi_states[data['_atom_type_symbol'][i]] = float_from_string(data['_atom_type_oxidation_number'][i])
        except:
            oxi_states = None

        coord_to_species = OrderedDict()

        for i in xrange(len(data['_atom_site_type_symbol'])):
            symbol = parse_symbol(data['_atom_site_type_symbol'][i])
            if oxi_states != None:
                el = Specie(symbol, oxi_states[data['_atom_site_type_symbol'][i]])
            else:
                el = Element(symbol)
            x = float_from_string(data['_atom_site_fract_x'][i])
            y = float_from_string(data['_atom_site_fract_y'][i])
            z = float_from_string(data['_atom_site_fract_z'][i])
            try:
                occu = float_from_string(data['_atom_site_occupancy'][i])
            except:
                occu = 1
            coord = (x, y, z)
            if coord not in coord_to_species:
                coord_to_species[coord] = {el:occu}
            else:
                coord_to_species[coord][el] = occu

        allspecies = list()
        allcoords = list()

        for coord, species in coord_to_species.items():
            coords = self._unique_coords(coord, sympos, primitive, lattice, primlattice)
            allcoords.extend(coords)
            allspecies.extend(len(coords) * [species])

        if primitive:
            return Structure(primlattice, allspecies, allcoords).get_sorted_structure()
        else:
            return Structure(lattice, allspecies, allcoords).get_sorted_structure()
예제 #43
0
def get_high_accuracy_voronoi_nodes_alt(structure, rad_dict, probe_rad=0.1):
    """
    Function to replace high_accuracy_voronoi_nodes function. In testing
    mode.
    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.
            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 >>fp, "{} {}".format(el, rad_dict[el].real)

        atmnet = AtomNetwork.read_from_CSSR(
                zeo_inp_filename, rad_flag=rad_flag, rad_file=rad_file)
        vornet, voronoi_face_centers = atmnet.perform_voronoi_decomposition()
        red_ha_vornet = \
                generate_simplified_highaccuracy_voronoi_network(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_lengths_and_angles(
        structure.lattice.abc, structure.lattice.angles)
    voronoi_node_struct = Structure(
        lattice, species, coords, coords_are_cartesian=True,
        to_unit_cell=True, site_properties={"voronoi_radius": prop})


    #PMG-Zeo c<->a transformation for voronoi face centers
    rot_face_centers = [(center[1],center[2],center[0]) for center in 
                        voronoi_face_centers]
    species = ["X"] * len(rot_face_centers)
    # Voronoi radius not evaluated for fc. Fix in future versions
    prop = [0.0] * len(rot_face_centers)  
    voronoi_facecenter_struct = Structure(
        lattice, species, rot_face_centers, coords_are_cartesian=True,
        to_unit_cell=True, site_properties={"voronoi_radius": prop})

    return voronoi_node_struct, voronoi_facecenter_struct
예제 #44
0
    def from_string(header_str):
        """
        Reads Header string and returns Header object if header was
        generated by pymatgen.

        Args:
            header_str: pymatgen generated feff.inp header

        Returns:
            Structure object.
        """
        # 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

        lines = tuple(clean_lines(header_str.split("\n"), False))
        comment1 = lines[0]
        feffpmg = comment1.find("pymatgen")

        if feffpmg > 0:
            comment2 = ' '.join(lines[1].split()[2:])

            #This sec section gets information to create structure object

            source = ' '.join(lines[2].split()[2:])
            natoms = int(lines[8].split()[2])
            basis_vec = lines[6].split()

            a = float(basis_vec[2])
            b = float(basis_vec[3])
            c = float(basis_vec[4])

            lengths = [a, b, c]
            basis_ang = lines[7].split()

            alpha = float(basis_ang[2])
            beta = float(basis_ang[3])
            gamma = float(basis_ang[4])
            angles = [alpha, beta, gamma]

            lattice = Lattice.from_lengths_and_angles(lengths, angles)
            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:]])

            #Structure object is now generated and Header object returned

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

            h = Header(struct_fromfile, source, comment2)

            return h
        else:
            return "Header not generated by pymatgen, " \
                   "cannot return header object"
예제 #45
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("{} {}".format(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_lengths_and_angles(structure.lattice.abc,
                                              structure.lattice.angles)
    vor_node_struct = Structure(lattice,
                                species,
                                coords,
                                coords_are_cartesian=True,
                                to_unit_cell=True,
                                site_properties={"voronoi_radius": prop})

    return vor_node_struct
예제 #46
0
def get_voronoi_nodes(structure, rad_dict=None, probe_rad=0.1):
    """
    Analyze the void space in the input structure using 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_file = None
        rad_flag = False

        if rad_dict:
            rad_file = name + ".rad"
            rad_flag = True
            with open(rad_file, 'w+') as fp:
                for el in rad_dict.keys():
                    fp.write("{} {}\n".format(el, rad_dict[el].real))

        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()
        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_lengths_and_angles(
        structure.lattice.abc, structure.lattice.angles)
    vor_node_struct = Structure(
        lattice, species, coords, coords_are_cartesian=True,
        to_unit_cell=True, site_properties={"voronoi_radius": prop})

    # PMG-Zeo c<->a transformation for voronoi face centers
    rot_face_centers = [(center[1], center[2], center[0]) for center in
                        vor_face_centers]
    rot_edge_centers = [(center[1], center[2], center[0]) for center in
                        vor_edge_centers]

    species = ["X"] * len(rot_face_centers)
    prop = [0.0] * len(rot_face_centers)  # Vor radius not evaluated for fc
    vor_facecenter_struct = Structure(
        lattice, species, rot_face_centers, coords_are_cartesian=True,
        to_unit_cell=True, site_properties={"voronoi_radius": prop})

    species = ["X"] * len(rot_edge_centers)
    prop = [0.0] * len(rot_edge_centers)  # Vor radius not evaluated for fc
    vor_edgecenter_struct = Structure(
        lattice, species, rot_edge_centers, coords_are_cartesian=True,
        to_unit_cell=True, site_properties={"voronoi_radius": prop})

    return vor_node_struct, vor_edgecenter_struct, vor_facecenter_struct
def get_voronoi_node_edge(structure, rad_dict, write_nt2_file=False):
    """
    This function obtain the voronoi nodes and the edge information with 0 probe radius. It will contain neighboring
    information of each nodes.
    !!!Notice the nt2 file change the xyz to zxy. Thus the result need rotate. What a strange setting!!!
    Args:
        structure: orginal Structure
        rad_dict: {'Na':10,...}
    Returns:
        Structure: the voronoi node structure. For each site, there are voronoi_radius, neighbor_atoms, neighbor_nodes
            in the properties. 
            The neighbor_nodes in the format : [[node_No,channel_size,node_image]...] node image is list of int, 
                not array
            The neighbor_atoms in the format: [1,2,3,4] the number is the sequence number of sites in structure. So 
            take care of the structure, don't do any change on the sequence order.
    """
    with ScratchDir('.'):
        name = "temp_zeo3"
        cssr_file = name + ".cssr"
        rad_file = name + ".rad"
        mass_file = name + ".mass"
        out_file = name + ".nt2"
        cssr = ZeoCssr(structure)
        with open(cssr_file, 'w+') as fp:
            fp.write(str(cssr))
        # CifWriter(structure).write_file(cif_file) the xyz need to rotate to zxy, so just use existing ZeoCssr
        # rad_file
        with open(rad_file, 'w+') as fp:
            for el in rad_dict.keys():
                fp.write("{} {}\n".format(el, rad_dict[el].real))
        # mass_file
        struct_element_set = set(structure.composition.elements)
        with open(mass_file, 'w+') as fp:
            for el in struct_element_set:
                fp.write("{} {}\n".format(el, float(el.atomic_mass)))
        bashcmd = "network -r {} -mass {} -nt2 {} {}".format(
            rad_file, mass_file, out_file, cssr_file)
        process = subprocess.Popen(bashcmd.split(), stdout=subprocess.PIPE)
        zeo_plus_plus_output = process.communicate()[0]
        with open(out_file, 'r') as fp:
            nt2_file = fp.readlines()
    if write_nt2_file != False:
        with open(write_nt2_file, 'w+') as fp:
            for i in nt2_file:
                fp.write(i)
    node_info_string_list = nt2_file[1:nt2_file.index('\n')]
    edge_info_string_list = nt2_file[nt2_file.index('\n') + 2:]

    # node info string to Structure object
    species = ["X"] * len(node_info_string_list)
    coords = []
    voronoi_radius = []
    neighbor_atoms_num = [
    ]  # the four closest atoms, the number corresponding to the sequence number in structure
    neighbor_nodes = [list() for _ in range(len(node_info_string_list))]
    # the connected neighbor voronoi nodes, [node_No,channel_size,node_image], node image: [-1,0,0]
    # means the actual connected neighbor will have a transition in -a direction.
    # final_frac_coords = node_frac_coords+node_image

    for site in node_info_string_list:
        coords_temp = map(float, site.split()[1:4])
        coords.append([coords_temp[1], coords_temp[2], coords_temp[0]])
        voronoi_radius.append(float(site.split()[4]))
        neighbor_atoms_num.append(map(int, site.split()[5:]))

    for neighbor in edge_info_string_list:
        valid_info = neighbor.split()
        valid_info.pop(1)  # there is a arrow in the output string
        image_temp = map(int, valid_info[3:6])
        valid_info = [
            int(valid_info[0]),
            int(valid_info[1]),
            float(valid_info[2]),
            [image_temp[1], image_temp[2], image_temp[0]]
        ]
        neighbor_nodes[valid_info[0]].append(copy.deepcopy(valid_info[1:]))
    lattice = Lattice.from_lengths_and_angles(structure.lattice.abc,
                                              structure.lattice.angles)
    vor_node_struct = Structure(lattice,
                                species,
                                coords,
                                coords_are_cartesian=True,
                                to_unit_cell=False,
                                site_properties={
                                    "voronoi_radius": voronoi_radius,
                                    "neighbor_atoms": neighbor_atoms_num,
                                    "neighbor_nodes": neighbor_nodes
                                })  # notice, to_unit_cell must be False,
    # or the image of neighbor_nodes need change
    return vor_node_struct
예제 #48
0
    def structure(self):
        # Get lattice vectors
        if 'lattice_cart' in self.blocks:
            lattice_cart = self.blocks['lattice_cart'].values
            if lattice_cart[0][0].lower() in ('ang', 'nm', 'cm', 'm', 'bohr',
                                              'a0'):
                unit = lattice_cart[0][0].lower()
                vectors = lattice_cart[1:]
            else:
                unit = 'ang'
                vectors = lattice_cart
            vectors = np.array([list(map(float, row)) for row in vectors])
            if vectors.shape != (3, 3):
                raise ValueError('lattice_cart should contain a 3x3 matrix')

            vectors *= to_angstrom[unit]
            lattice = Lattice(vectors)
        elif 'lattice_abc' in self.blocks:
            lattice_abc = self.blocks['lattice_abc'].values
            if lattice_abc[0][0].lower() in ('ang', 'nm', 'cm', 'm', 'bohr',
                                             'a0'):
                unit = lattice_abc[0][0].lower()
                lengths_and_angles = lattice_abc[1:]
            else:
                unit = 'ang'
                lengths_and_angles = lattice_abc[1:]
            if len(lengths_and_angles) != 2:
                raise ValueError('lattice_abc should have two rows')
            lengths_and_angles = [
                list(map(float, row)) for row in lengths_and_angles
            ]
            lengths_and_angles[0] = [
                x * to_angstrom[unit] for x in lengths_and_angles[0]
            ]
            lattice = Lattice.from_lengths_and_angles(*lengths_and_angles)
        else:
            raise ValueError("Couldn't find a lattice in cell file")

        if 'positions_frac' in self.blocks:
            elements_coords = [(row[0], list(map(float, row[1:4])))
                               for row in self.blocks['positions_frac'].values]
            elements, coords = zip(*elements_coords)
            return Structure(lattice,
                             elements,
                             coords,
                             coords_are_cartesian=False)
        elif 'positions_abs' in self.blocks:
            positions_abs = self.blocks['positions_abs'].values
            if positions_abs[0][0].lower() in ('ang', 'nm', 'cm', 'm', 'bohr',
                                               'a0'):
                unit = positions_abs[0][0].lower()
                positions_abs = positions_abs[1:]
            else:
                unit = 'ang'
            elements_coords = [(row[0], list(map(float, row[1:4])))
                               for row in positions_abs]
            elements, coords = zip(*elements_coords)
            return Structure(lattice,
                             elements,
                             coords,
                             coords_are_cartesian=True)
        else:
            raise ValueError("Couldn't find any atom positions in cell file")
예제 #49
0
파일: cifio.py 프로젝트: paulfons/pymatgen
    def _get_structure(self, data, primitive):
        """
        Generate structure from part of the cif.
        """
        lengths = [
            str2float(data["_cell_length_" + i]) for i in ["a", "b", "c"]
        ]
        angles = [
            str2float(data["_cell_angle_" + i])
            for i in ["alpha", "beta", "gamma"]
        ]
        lattice = Lattice.from_lengths_and_angles(lengths, angles)
        try:
            sympos = data["_symmetry_equiv_pos_as_xyz"]
        except KeyError:
            try:
                sympos = data["_symmetry_equiv_pos_as_xyz_"]
            except KeyError:
                warnings.warn("No _symmetry_equiv_pos_as_xyz type key found. "
                              "Defaulting to P1.")
                sympos = ['x, y, z']
        self.symmetry_operations = [SymmOp.from_xyz_string(s) for s in sympos]

        def parse_symbol(sym):
            # capitalization conventions are not strictly followed, eg Cu will be CU
            m = re.search("([A-Za-z]*)", sym)
            if m:
                return m.group(1)[:2].capitalize()
            return ""

        try:
            oxi_states = {
                data["_atom_type_symbol"][i]:
                str2float(data["_atom_type_oxidation_number"][i])
                for i in range(len(data["_atom_type_symbol"]))
            }
        except (ValueError, KeyError):
            oxi_states = None

        coord_to_species = OrderedDict()
        for i in range(len(data["_atom_site_label"])):
            symbol = parse_symbol(data["_atom_site_label"][i])

            # make sure symbol was properly parsed from _atom_site_label
            # otherwise get it from _atom_site_type_symbol
            try:
                Element(symbol)
            except KeyError:
                symbol = parse_symbol(data["_atom_site_type_symbol"][i])

            if oxi_states is not None:
                # sometimes the site doesn't have the type_symbol.
                # we then hope the type_symbol can be parsed from the label
                if "_atom_site_type_symbol" in data.data.keys():
                    k = data["_atom_site_type_symbol"][i]
                else:
                    k = symbol
                el = Specie(symbol, oxi_states[k])
            else:
                el = Element(symbol)
            x = str2float(data["_atom_site_fract_x"][i])
            y = str2float(data["_atom_site_fract_y"][i])
            z = str2float(data["_atom_site_fract_z"][i])
            try:
                occu = str2float(data["_atom_site_occupancy"][i])
            except (KeyError, ValueError):
                occu = 1
            if occu > 0:
                coord = (x, y, z)
                if coord not in coord_to_species:
                    coord_to_species[coord] = {el: occu}
                else:
                    coord_to_species[coord][el] = occu

        allspecies = []
        allcoords = []

        for coord, species in coord_to_species.items():
            coords = self._unique_coords(coord)
            allcoords.extend(coords)
            allspecies.extend(len(coords) * [species])

        #rescale occupancies if necessary
        for species in allspecies:
            totaloccu = sum(species.values())
            if 1 < totaloccu <= self._occupancy_tolerance:
                for key, value in six.iteritems(species):
                    species[key] = value / totaloccu

        struct = Structure(lattice, allspecies, allcoords)
        if primitive:
            struct = struct.get_primitive_structure().get_reduced_structure()
        return struct.get_sorted_structure()
예제 #50
0
def get_high_accuracy_voronoi_nodes_alt(structure, rad_dict, probe_rad=0.1):
    """
    Function to replace high_accuracy_voronoi_nodes function. In testing
    mode.
    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.
            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 >> fp, "{} {}".format(el, rad_dict[el].real)

        atmnet = AtomNetwork.read_from_CSSR(zeo_inp_filename,
                                            rad_flag=rad_flag,
                                            rad_file=rad_file)
        vornet, voronoi_face_centers = atmnet.perform_voronoi_decomposition()
        red_ha_vornet = \
                generate_simplified_highaccuracy_voronoi_network(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_lengths_and_angles(structure.lattice.abc,
                                              structure.lattice.angles)
    voronoi_node_struct = Structure(lattice,
                                    species,
                                    coords,
                                    coords_are_cartesian=True,
                                    to_unit_cell=True,
                                    site_properties={"voronoi_radius": prop})

    #PMG-Zeo c<->a transformation for voronoi face centers
    rot_face_centers = [(center[1], center[2], center[0])
                        for center in voronoi_face_centers]
    species = ["X"] * len(rot_face_centers)
    # Voronoi radius not evaluated for fc. Fix in future versions
    prop = [0.0] * len(rot_face_centers)
    voronoi_facecenter_struct = Structure(
        lattice,
        species,
        rot_face_centers,
        coords_are_cartesian=True,
        to_unit_cell=True,
        site_properties={"voronoi_radius": prop})

    return voronoi_node_struct, voronoi_facecenter_struct
예제 #51
0
    def get_same_branch_polarization_data(self, convert_to_muC_per_cm2=True, all_in_polar=True):
        """
        Get same branch dipole moment (convert_to_muC_per_cm2=False)
        or polarization for given polarization data (convert_to_muC_per_cm2=True).

        Polarization is a lattice vector, meaning it is only defined modulo the
        quantum of polarization:

            P = P_0 + \\sum_i \\frac{n_i e R_i}{\\Omega}

        where n_i is an integer, e is the charge of the electron in microCoulombs,
        R_i is a lattice vector, and \\Omega is the unit cell volume in cm**3
        (giving polarization units of microCoulomb per centimeter**2).

        The quantum of the dipole moment in electron Angstroms (as given by VASP) is:

            \\sum_i n_i e R_i

        where e, the electron charge, is 1 and R_i is a lattice vector, and n_i is an integer.

        Given N polarization calculations in order from nonpolar to polar, this algorithm
        minimizes the distance between adjacent polarization images. To do this, it
        constructs a polarization lattice for each polarization calculation using the
        pymatgen.core.structure class and calls the get_nearest_site method to find the
        image of a given polarization lattice vector that is closest to the previous polarization
        lattice vector image.

        Note, using convert_to_muC_per_cm2=True and all_in_polar=True calculates the "proper
        polarization" (meaning the change in polarization does not depend on the choice of
        polarization branch) while convert_to_muC_per_cm2=True and all_in_polar=False calculates
        the "improper polarization" (meaning the change in polarization does depend on the choice
        of branch). As one might guess from the names. We recommend calculating the "proper
        polarization".

        convert_to_muC_per_cm2: convert polarization from electron * Angstroms to
            microCoulomb per centimeter**2
        all_in_polar: convert polarization to be in polar (final structure) polarization lattice
        """

        p_elec, p_ion = self.get_pelecs_and_pions()
        p_tot = p_elec + p_ion
        p_tot = np.array(p_tot)

        lattices = [s.lattice for s in self.structures]
        volumes = np.array([s.lattice.volume for s in self.structures])

        L = len(p_elec)

        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:
            # Convert the total polarization
            p_tot = np.multiply(units.T[:, np.newaxis], p_tot)
            # adjust lattices
            for i in range(L):
                lattice = lattices[i]
                l, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.ravel()[i], a)
        #  convert polarizations to polar lattice
        elif convert_to_muC_per_cm2 and all_in_polar:
            abc = [lattice.abc for lattice in lattices]
            abc = np.array(abc)  # [N, 3]
            p_tot /= abc  # e * Angstroms to e
            p_tot *= abc[-1] / volumes[-1] * e_to_muC * cm2_to_A2  # to muC / cm^2
            for i in range(L):
                lattice = lattices[-1]  # Use polar lattice
                l, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.ravel()[-1], a)  # Use polar units (volume)


        d_structs = []
        sites = []
        for i in range(L):
            l = lattices[i]
            frac_coord = np.divide(np.array([p_tot[i]]),
                                   np.array([l.a, l.b, l.c]))
            d = PolarizationLattice(l, ["C"], [np.array(frac_coord).ravel()])
            d_structs.append(d)
            site = d[0]
            if i == 0:
                # Adjust nonpolar polarization to be closest to zero.
                # This is compatible with both a polarization of zero or a half quantum.
                prev_site = [0, 0, 0]
            else:
                prev_site = sites[-1].coords
            new_site = d.get_nearest_site(prev_site, site)
            sites.append(new_site[0])

        adjust_pol = []
        for s, d in zip(sites, d_structs):
            l = d.lattice
            adjust_pol.append(
                np.multiply(s.frac_coords, np.array([l.a, l.b, l.c])).ravel())
        adjust_pol = np.array(adjust_pol)

        return adjust_pol
예제 #52
0
    def get_same_branch_polarization_data(self,
                                          convert_to_muC_per_cm2=True,
                                          all_in_polar=True):
        """
        Get same branch dipole moment (convert_to_muC_per_cm2=False)
        or polarization for given polarization data (convert_to_muC_per_cm2=True).

        Polarization is a lattice vector, meaning it is only defined modulo the
        quantum of polarization:

            P = P_0 + \\sum_i \\frac{n_i e R_i}{\\Omega}

        where n_i is an integer, e is the charge of the electron in microCoulombs,
        R_i is a lattice vector, and \\Omega is the unit cell volume in cm**3
        (giving polarization units of microCoulomb per centimeter**2).

        The quantum of the dipole moment in electron Angstroms (as given by VASP) is:

            \\sum_i n_i e R_i

        where e, the electron charge, is 1 and R_i is a lattice vector, and n_i is an integer.

        Given N polarization calculations in order from nonpolar to polar, this algorithm
        minimizes the distance between adjacent polarization images. To do this, it
        constructs a polarization lattice for each polarization calculation using the
        pymatgen.core.structure class and calls the get_nearest_site method to find the
        image of a given polarization lattice vector that is closest to the previous polarization
        lattice vector image.

        Note, using convert_to_muC_per_cm2=True and all_in_polar=True calculates the "proper
        polarization" (meaning the change in polarization does not depend on the choice of
        polarization branch) while convert_to_muC_per_cm2=True and all_in_polar=False calculates
        the "improper polarization" (meaning the change in polarization does depend on the choice
        of branch). As one might guess from the names. We recommend calculating the "proper
        polarization".

        convert_to_muC_per_cm2: convert polarization from electron * Angstroms to
            microCoulomb per centimeter**2
        all_in_polar: convert polarization to be in polar (final structure) polarization lattice
        """

        p_elec, p_ion = self.get_pelecs_and_pions()
        p_tot = p_elec + p_ion
        p_tot = np.array(p_tot)

        lattices = [s.lattice for s in self.structures]
        volumes = np.array([s.lattice.volume for s in self.structures])

        L = len(p_elec)

        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:
            # Convert the total polarization
            p_tot = np.multiply(units.T[:, np.newaxis], p_tot)
            # adjust lattices
            for i in range(L):
                lattice = lattices[i]
                l, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.ravel()[i], a)
        #  convert polarizations to polar lattice
        elif convert_to_muC_per_cm2 and all_in_polar:
            abc = [lattice.abc for lattice in lattices]
            abc = np.array(abc)  # [N, 3]
            p_tot /= abc  # e * Angstroms to e
            p_tot *= abc[-1] / volumes[
                -1] * e_to_muC * cm2_to_A2  # to muC / cm^2
            for i in range(L):
                lattice = lattices[-1]  # Use polar lattice
                l, a = lattice.lengths_and_angles
                lattices[i] = Lattice.from_lengths_and_angles(
                    np.array(l) * units.ravel()[-1],
                    a)  # Use polar units (volume)

        d_structs = []
        sites = []
        for i in range(L):
            l = lattices[i]
            frac_coord = np.divide(np.array([p_tot[i]]),
                                   np.array([l.a, l.b, l.c]))
            d = PolarizationLattice(l, ["C"], [np.array(frac_coord).ravel()])
            d_structs.append(d)
            site = d[0]
            if i == 0:
                # Adjust nonpolar polarization to be closest to zero.
                # This is compatible with both a polarization of zero or a half quantum.
                prev_site = [0, 0, 0]
            else:
                prev_site = sites[-1].coords
            new_site = d.get_nearest_site(prev_site, site)
            sites.append(new_site[0])

        adjust_pol = []
        for s, d in zip(sites, d_structs):
            l = d.lattice
            adjust_pol.append(
                np.multiply(s.frac_coords, np.array([l.a, l.b, l.c])).ravel())
        adjust_pol = np.array(adjust_pol)

        return adjust_pol
예제 #53
0
    def _get_structure(self, data, primitive):
        """
        Generate structure from part of the cif.
        """
        lengths = [
            str2float(data["_cell_length_" + i]) for i in ["a", "b", "c"]
        ]
        angles = [
            str2float(data["_cell_angle_" + i])
            for i in ["alpha", "beta", "gamma"]
        ]
        lattice = Lattice.from_lengths_and_angles(lengths, angles)
        try:
            sympos = data["_symmetry_equiv_pos_as_xyz"]
        except KeyError:
            try:
                sympos = data["_symmetry_equiv_pos_as_xyz_"]
            except KeyError:
                warnings.warn("No _symmetry_equiv_pos_as_xyz type key found. "
                              "Defaulting to P1.")
                sympos = ['x, y, z']
        self.symmetry_operations = parse_symmetry_operations(sympos)

        def parse_symbol(sym):
            m = re.search("([A-Z][a-z]*)", sym)
            if m:
                return m.group(1)
            return ""

        try:
            oxi_states = {
                data["_atom_type_symbol"][i]:
                str2float(data["_atom_type_oxidation_number"][i])
                for i in xrange(len(data["_atom_type_symbol"]))
            }
        except (ValueError, KeyError):
            oxi_states = None

        coord_to_species = OrderedDict()

        for i in xrange(len(data["_atom_site_type_symbol"])):
            symbol = parse_symbol(data["_atom_site_type_symbol"][i])
            if oxi_states is not None:
                el = Specie(symbol,
                            oxi_states[data["_atom_site_type_symbol"][i]])
            else:
                el = Element(symbol)
            x = str2float(data["_atom_site_fract_x"][i])
            y = str2float(data["_atom_site_fract_y"][i])
            z = str2float(data["_atom_site_fract_z"][i])
            try:
                occu = str2float(data["_atom_site_occupancy"][i])
            except (KeyError, ValueError):
                occu = 1
            if occu > 0:
                coord = (x, y, z)
                if coord not in coord_to_species:
                    coord_to_species[coord] = {el: occu}
                else:
                    coord_to_species[coord][el] = occu

        allspecies = []
        allcoords = []

        for coord, species in coord_to_species.items():
            coords = self._unique_coords(coord)
            allcoords.extend(coords)
            allspecies.extend(len(coords) * [species])

        #rescale occupancies if necessary
        for species in allspecies:
            totaloccu = sum(species.values())
            if 1 < totaloccu <= self._occupancy_tolerance:
                for key, value in species.iteritems():
                    species[key] = value / totaloccu

        struct = Structure(lattice, allspecies, allcoords)
        if primitive:
            struct = struct.get_primitive_structure().get_reduced_structure()
        return struct.get_sorted_structure()