コード例 #1
0
    def load_from_outcar(self, path, structure, mode):
        """
    This function reads atom positions, unit cell, forces and stress tensor from the VASP
    OUTCAR file
    path: 
    structure: 
    """
        if mode == 'scf':
            filename = os.path.join(path, 'OUTCAR')
            self.name = filename.split('/')[-2]
        elif mode == 'nscf':
            filename = os.path.join(path, 'nscf_SOC/OUTCAR')
            self.name = filename.split('/')[-3]
        else:
            raise Exception(
                f"Calculation mode {mode} is wrong. Must be scf or nscf")

        if os.access(filename, os.R_OK):
            outcar = Outcar(filename)
        else:
            raise Exception("Missing OUTCAR file in {}".format(filename))

        print(self.name)

        # ATOMIC PROPERTIES
        self.num_atoms = int(
            structure.composition.num_atoms)  # total number of atoms
        self.atoms_frac = structure.frac_coords  # fraction coordinates
        self.atoms_cart = structure.cart_coords  # cartesian coordinates
        self.num_per_type = [
            int(x) for x in structure.composition.get_el_amt_dict().values()
        ]  # number of atoms per type
        self.species = [x.symbol for x in structure.species
                        ]  # list with atomic symbols for each specie
        self.pomass = [
            Element(x.symbol).atomic_mass for x in structure.species
        ]  # list with atomic masses for each specie
        self.charges = [x['tot'] for x in outcar.charge]  # list with charges

        # read zval dict and create a mapping
        outcar.read_pseudo_zval()
        zval_dict = outcar.zval_dict
        self.zvals = [zval_dict[x.symbol] for x in structure.species]

        # UNIT CELL
        self.unit_cell = structure.lattice.matrix  # unit cell
        self.recip_cell = structure.lattice.inv_matrix  # inverse unit cell
        self.volume = structure.lattice.volume

        # total energy in eV
        self.energy = outcar.final_energy
        # atomic positions read from Outcar
        self.atoms = np.array(
            outcar.read_table_pattern(
                header_pattern=r"\sPOSITION\s+TOTAL-FORCE \(eV/Angst\)\n\s-+",
                row_pattern=
                r"\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+",
                footer_pattern=r"\s--+",
                postprocess=lambda x: float(x),
                last_one_only=False)[0])
        # forces acting on atoms from Outcar
        self.forces = np.array(
            outcar.read_table_pattern(
                header_pattern=r"\sPOSITION\s+TOTAL-FORCE \(eV/Angst\)\n\s-+",
                row_pattern=
                r"\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)",
                footer_pattern=r"\s--+",
                postprocess=lambda x: float(x),
                last_one_only=False)[0])

        # READ STRESS: (XX, YY, ZZ, XY, YZ, ZX) and convert values to array
        outcar.read_pattern(
            {
                'stress':
                r"in kB\s+([\.\-\d]+)\s+([\.\-\d]+)\s+([\.\-\d]+)\s+([\.\-\d]+)\s+([\.\-\d]+)\s+([\.\-\d]+)"
            },
            terminate_on_match=False,
            postprocess=float)
        stress = outcar.data.get("stress")[0]
        self.stress = np.array([[stress[0], stress[3], stress[5]],
                                [stress[3], stress[1], stress[4]],
                                [stress[5], stress[4], stress[2]]])
        # Conversion from kbar to ev/A^3.
        self.stress *= KBAR_TO_EVA3
        # MAGNETIZATION and its PROJECTION ON EVERY ATOM
        try:
            # non-collinear
            outcar.read_pattern(
                {
                    'total_mag':
                    r"number of electron\s+\S+\s+magnetization\s+([\.\-\d]+)\s+([\.\-\d]+)\s+([\.\-\d]+)\s"
                },
                terminate_on_match=False,
                postprocess=float)
            self.__magnetization = outcar.data.get("total_mag")[-1]

            self.proj_magn = np.array([
                mag['tot'].moment for mag in outcar.magnetization
            ])  # 2-D array
        except:
            # collinear
            outcar.read_pattern(
                {
                    'total_mag':
                    r"number of electron\s+\S+\s+magnetization\s+("
                    r"\S+)"
                },
                terminate_on_match=False,
                postprocess=float)
            self.__magnetization = np.zeros(3)
            self.__magnetization[2] = outcar.data.get("total_mag")[-1][0]

            self.proj_magn = np.zeros((self.num_atoms, 3))
            for i in range(self.num_atoms):
                self.proj_magn[i,
                               2] = outcar.magnetization[i]['tot']  # 2-D array

        # NOTE: sum of magnetization projected on atoms differs from the total magnetization
        self.proj_magn_sum = np.sum(self.proj_magn, axis=0)
        self.get__magnetization()

        # POLARIZATION
        self.load_polarization(path)
        self.fileID = filename