def setUp(self):
        self.unitcell_dir = self.TEST_FILES_DIR / "MgAl2Se4_unitcell"

        self.unitcell = UnitcellCalcResults(band_edge=None,
                                            static_dielectric_tensor=None,
                                            ionic_dielectric_tensor=None,
                                            total_dos=None,
                                            volume=None)
Пример #2
0
    def setUp(self):
        """ """
        filename = (self.TEST_FILES_DIR / "defects" / "MgO" / "unitcell.json")
        self.unitcell = UnitcellCalcResults.load_json(filename)

        filename = ["defects", "MgO", "perfect", "dft_results.json"]
        self.perfect = self.get_object_by_name(SupercellCalcResults.load_json,
                                               filename)

        defect_dirs = ["Va_O1_0", "Va_O1_1", "Va_O1_2", "Va_Mg1_-2"]
        defects = []
        for dd in defect_dirs:
            filename = ["defects", "MgO", dd, "defect.json"]
            defects.append(self.get_object_by_name(Defect.load_json, filename))

        # temporary insert values
        filename = ["defects", "MgO", "cpd.json"]
        self.chem_pot = self.get_object_by_name(ChemPotDiag.load_json,
                                                filename)
        self.chem_pot_label = "A"

        self.defect_energies = \
            DefectEnergies.from_objects(unitcell=self.unitcell,
                                        perfect=self.perfect,
                                        defects=defects,
                                        chem_pot=self.chem_pot,
                                        chem_pot_label=self.chem_pot_label,
                                        system="MgO")
Пример #3
0
    def setUp(self):
        filename = (self.TEST_FILES_DIR / "defects" / "MgO" / "unitcell.json")
        unitcell = UnitcellCalcResults.load_json(filename)

        filename = ["defects", "MgO", "perfect", "dft_results.json"]
        perfect = self.get_object_by_name(SupercellCalcResults.load_json,
                                          filename)

        structure = perfect.final_structure
        dielectric_tensor = unitcell.total_dielectric_tensor

        ewald = Ewald.from_optimization(structure,
                                        dielectric_tensor,
                                        prod_cutoff_fwhm=20)

        filename = ["defects", "MgO", "Va_O1_2", "dft_results.json"]
        defect = self.get_object_by_name(SupercellCalcResults.load_json,
                                         filename)

        filename = ["defects", "MgO", "Va_O1_2", "defect_entry.json"]
        defect_entry = self.get_object_by_name(DefectEntry.load_json, filename)

        self.correction = \
            ExtendedFnvCorrection.compute_correction(
                defect_entry=defect_entry,
                defect_dft=defect,
                perfect_dft=perfect,
                dielectric_tensor=unitcell.total_dielectric_tensor,
                ewald=ewald)

        self.correction.manually_added_correction_energy = 0.1
Пример #4
0
    def setUp(self):
        self.defect_energies = {"Va_O1": {}, "Va_Mg1": {}}

        self.defect_energies["Va_O1"][0] = \
            DefectEnergy(defect_energy=4.0,
                         annotation=None,
                         multiplicity=1,
                         magnetization=0.0,
                         convergence=True,
                         shallow=False)
        self.defect_energies["Va_O1"][1] = \
            DefectEnergy(3.0, None, 1, 1.0, True, False)
        self.defect_energies["Va_O1"][2] = \
            DefectEnergy(1.0, None, 2, 1.0, True, False)
        self.defect_energies["Va_Mg1"][-2] = \
            DefectEnergy(4.0, None, 1, 0.0, True, False)
        energies = np.linspace(-1, 11, num=121).tolist()
        # Dos is halved at the boundaries.
        # dos -> 0.5 at -0.2, 0, 10, and 10.2, and 1 at -0.1 and 10.1
        dos = [0.0] * 8 + [0.5] + [1.0] + [0.5] + [0.0] * 99 + [0.5] + [1.0] + \
              [0.5] + [0.0] * 8
        total_dos = [dos, energies]

        self.unitcell = UnitcellCalcResults(band_edge=[0, 10],
                                            static_dielectric_tensor=None,
                                            ionic_dielectric_tensor=None,
                                            total_dos=total_dos,
                                            volume=100)

        self.unitcell_no_band_edge = \
            UnitcellCalcResults(band_edge=None,
                                static_dielectric_tensor=None,
                                ionic_dielectric_tensor=None,
                                total_dos=total_dos,
                                volume=100)

        self.defect_concentration = \
            DefectConcentration.from_calc_results(self.defect_energies,
                                                  self.unitcell)

        self.defect_concentration.calc_equilibrium_concentration(
            temperature=10000, verbose=False)
        self.defect_concentration.calc_quenched_equilibrium_concentration(
            temperature=298, verbose=False)
Пример #5
0
def parse_eigenvalues(args):
    unitcell = UnitcellCalcResults.load_json(args.unitcell)

    # TODO: Modify here to run w/o correction
    logger.info(f"parsing directory {args.defect_dir}...")
    defect = Defect.load_json(Path(args.defect_dir) / "defect.json")

    defect_eigenvalues = DefectEigenvalue.from_files(unitcell=unitcell,
                                                     defect=defect)

    defect_eigenvalues.plot(y_range=args.y_range,
                            title=args.title,
                            filename=args.save_file)
class UnitcellDftResultsTest(PydefectTest):
    def setUp(self):
        self.unitcell_dir = self.TEST_FILES_DIR / "MgAl2Se4_unitcell"

        self.unitcell = UnitcellCalcResults(band_edge=None,
                                            static_dielectric_tensor=None,
                                            ionic_dielectric_tensor=None,
                                            total_dos=None,
                                            volume=None)

    def test_print(self):
        print(self.unitcell)

    def test_static_dielectric_tensor(self):
        self.unitcell.set_static_dielectric_tensor_from_vasp(
            directory_path=self.unitcell_dir, outcar_name="dielectric_OUTCAR")

        expected = \
            [[51.24297, 0., 0.], [0., 51.24299, -0.], [0., -0., 19.32937]]
        actual = self.unitcell.static_dielectric_tensor
        self.assertArrayAlmostEqual(expected, actual, 5)

    def test_ionic_dielectric_tensor(self):
        self.unitcell.set_ionic_dielectric_tensor_from_vasp(
            directory_path=self.unitcell_dir, outcar_name="dielectric_OUTCAR")
        expected = [[8.71950e+01, 0.00000e+00, 0.00000e+00],
                    [0.00000e+00, 8.71942e+01, -6.70000e-05],
                    [0.00000e+00, -6.70000e-05, 5.04341e+00]]
        actual = self.unitcell.ionic_dielectric_tensor
        self.assertArrayAlmostEqual(expected, actual, 4)

    def test_band_edge(self):
        self.unitcell.set_band_edge_from_vasp(directory_path=self.unitcell_dir,
                                              vasprun_name="band_vasprun.xml",
                                              outcar_name="dielectric_OUTCAR")
        expected = [3.127, 4.197]
        actual = self.unitcell.band_edge
        self.assertArrayAlmostEqual(expected, actual, 3)

    def test_total_dos(self):
        self.unitcell.set_total_dos_and_volume_from_vasp(
            directory_path=self.unitcell_dir, vasprun_name="dos_vasprun.xml")
        expected = 168.72742284380834
        actual = self.unitcell.volume
        self.assertEqual(expected, actual)

    def test_msonable(self):
        self.assertMSONable(self.unitcell)
Пример #7
0
    def setUp(self):
        filename = (self.TEST_FILES_DIR / "defects" / "MgO" / "unitcell.json")
        unitcell = UnitcellCalcResults.load_json(filename)

        filename = ["defects", "MgO", "perfect", "dft_results.json"]
        perfect = self.get_object_by_name(SupercellCalcResults.load_json,
                                          filename)

        structure = perfect.final_structure
        dielectric_tensor = unitcell.total_dielectric_tensor

        self.ewald = Ewald.from_optimization(structure,
                                             dielectric_tensor,
                                             prod_cutoff_fwhm=25)
    def from_calc_results(
            cls,
            defect_energies: dict,
            unitcell: UnitcellCalcResults,
            round_magnetization: bool = False,
            fractional_criterion: float = 0.1) -> "DefectConcentration":
        """Create instance object from DefectEnergies and UnitcellCalcResults.

        Args:
            defect_energies (dict):
                DefectEnergy as a function of name, charge, and annotation.
                energies[name][charge] = DefectEnergy object
            unitcell (UnitcellCalcResults):
                UnitcellDftResults object for volume, band edges and total_dos
            round_magnetization (bool)
                Whether to round the fractional magnetization.
            fractional_criterion (float):
                The criterion to determine if the magnetization is fractional.

        Returns:
            DefectConcentration object.
        """
        defect_energies = deepcopy(defect_energies)

        for name, charge, defect_energy in flatten_dict(defect_energies):
            defect_name = DefectName(name, charge, defect_energy.annotation)
            mag = defect_energy.magnetization
            rounded_mag = round(mag)
            if abs(mag - rounded_mag) > fractional_criterion:
                logger.warning(f"The total_magnetization of {defect_name} "
                               f"is {mag}, and not integer")

                if round_magnetization:
                    logger.warning(f"The magnetization of {defect_name} is "
                                   f"rounded to {rounded_mag}.")
                    defect_energies[name][charge].magnetization = rounded_mag

        for attr in ["volume", "band_edge", "total_dos"]:
            if unitcell.__getattribute__(attr) is None:
                logger.critical(
                    f"{attr} needs to be set for the calculation of"
                    f" carrier/defect concentrations.")
                raise ValueError

        return cls(
            defect_energies=defect_energies,
            volume=unitcell.volume,  # [A^3]
            vbm=unitcell.band_edge[0],
            cbm=unitcell.band_edge[1],
            total_dos=unitcell.total_dos)
Пример #9
0
def vertical_transition_energy(args):

    initial_dir = Path(args.initial_dir)
    initial_calc_results = \
        SupercellCalcResults.load_json(initial_dir / "dft_results.json")
    final_dir = Path(args.dir)
    final_calc_results = \
        SupercellCalcResults.load_json(final_dir / "dft_results.json")
    unitcell = UnitcellCalcResults.load_json(args.unitcell_json)

    if args.print:
        vtec = VerticalTransitionEnergyCorrection.load_json(args.json)
        vtec.plot_potential()
        print(vtec)
        if vtec.additional_charge == 1:
            cbm = unitcell.band_edge[1]
            print(f"CBM position (eV): {cbm}")
            band_edge_related_energy = cbm

        else:
            vbm = unitcell.band_edge[0]
            print(f"VBM position (eV): {vbm}")
            band_edge_related_energy = -vbm

        vte_wo_corr = (final_calc_results.total_energy -
                       initial_calc_results.total_energy +
                       band_edge_related_energy)
        vte = vte_wo_corr + vtec.correction_energy
        print(f"Vertical transition energy w/o correction (eV): {vte_wo_corr}")
        print(f"Vertical transition energy w/  correction (eV): {vte}")
        return

    dielectric_tensor = unitcell.total_dielectric_tensor
    static_dielectric_tensor = unitcell.static_dielectric_tensor

    initial_efnv = \
        ExtendedFnvCorrection.load_json(initial_dir / "correction.json")
    initial_calc_results = \
        SupercellCalcResults.load_json(initial_dir / "dft_results.json")

    final_defect_entry = DefectEntry.load_json(final_dir / "defect_entry.json")

    c = VerticalTransitionEnergyCorrection.from_files(
        dielectric_tensor, static_dielectric_tensor, initial_efnv,
        initial_calc_results, final_defect_entry, final_calc_results)
    c.to_json_file(args.json)
    print(c)
Пример #10
0
def concentration(args):
    defect_energies = DefectEnergies.load_json(args.energies).defect_energies
    unitcell = UnitcellCalcResults.load_json(args.unitcell)

    defect_concentration = DefectConcentration.from_calc_results(
        defect_energies=defect_energies,
        unitcell=unitcell,
        round_magnetization=args.frac_mag_to_one)

    defect_concentration.calc_equilibrium_concentration(
        temperature=args.temperature, verbose=args.verbose)

    defect_concentration.calc_quenched_equilibrium_concentration(
        temperature=args.quenched_temperature, verbose=args.verbose)

    print(defect_concentration)
    defect_concentration.calc_concentrations(args.temperature)
    plt = defect_concentration.plot_carrier_concentrations()
    plt.show()
    def setUp(self) -> None:
        unitcell = UnitcellCalcResults.load_json(parent / "MgO_unitcell.json")
        dielectric_tensor = unitcell.total_dielectric_tensor
        static_dielectric_tensor = unitcell.static_dielectric_tensor
        initial_efnv_cor = ExtendedFnvCorrection.load_json(
            parent / "MgO_Va_O_1_correction.json")
        initial_calc_results = SupercellCalcResults.load_json(
            parent / "MgO_Va_O_1_dft_results.json")
        final_defect_entry = DefectEntry.load_json(
            parent / "MgO_Va_O_1-added_defect_entry.json")
        final_calc_results = SupercellCalcResults.load_json(
            parent / "MgO_Va_O_1-added_dft_results.json")

        self.vertical_correction = \
            VerticalTransitionEnergyCorrection.from_files(
                dielectric_tensor,
                static_dielectric_tensor,
                initial_efnv_cor,
                initial_calc_results,
                final_defect_entry,
                final_calc_results,
                8)
Пример #12
0
def plot_energy(args):

    if args.reload_defects:
        os.remove(args.energies)

    try:
        defect_energies = DefectEnergies.load_json(args.energies)
    except FileNotFoundError:
        unitcell = UnitcellCalcResults.load_json(args.unitcell)
        perfect = SupercellCalcResults.load_json(args.perfect)

        defects_dirs = args.defect_dirs or glob('*[0-9]/')

        defect_list = []
        for d in defects_dirs:
            filename = Path(d) / 'defect.json'
            logger.info(f"parsing directory {filename}...")
            try:
                defect_list.append(Defect.load_json(filename))
            except FileNotFoundError:
                logger.warning(f"Parsing {filename} failed.")
                continue

        chem_pot = ChemPotDiag.load_json(args.chem_pot_json)

        # First construct DefectEnergies class object.
        defect_energies = \
            DefectEnergies.from_objects(unitcell=unitcell,
                                        perfect=perfect,
                                        defects=defect_list,
                                        chem_pot=chem_pot,
                                        chem_pot_label=args.chem_pot_label,
                                        filtering_words=args.filtering,
                                        system=args.name)

    if args.print:
        print(defect_energies)
        return

    defect_energies.to_json_file(filename=args.energies)

    # if args.concentration:
    #     defect_concentration = \
    #         DefectConcentration.from_defect_energies(
    #             energies=energies,
    #             temperature=args.temperature[0],
    #             unitcell=unitcell,
    #             num_sites_filename=args.num_site_file)

    #  #     if len(args.temperature) == 2:
    #         defect_concentration = \
    #             DefectConcentration.from_defect_energies(
    #                 energies=energies,
    #                 temperature=args.temperature[1],
    #                 unitcell=unitcell,
    #                 num_sites_filename=args.num_site_file,
    #                 previous_concentration=defect_concentration)
    # else:
    #         defect_concentration = None

    # plt = defect_energies.plot_energy(filtering_words=args.filtering,
    #                                   x_range=args.x_range,
    #                                   y_range=args.y_range,
    #                                   show_transition_levels=args.show_tl,
    #                                   show_all_energies=args.show_all)
    plt = defect_energies.plot_energy(
        x_range=args.x_range,
        y_range=args.y_range,
        show_transition_levels=args.show_transition_level,
        show_all_energies=args.show_all)

    if args.save_file:
        plt.savefig(args.save_file, format="pdf", transparent=True)
    else:
        plt.show()
Пример #13
0
def efnv_correction(args):
    if args.print:
        print(ExtendedFnvCorrection.load_json(args.json_file))
        return

    dirs = glob('*[0-9]/') if args.dir_all else args.dirs

    if args.plot_potential:
        for directory in dirs:
            d = Path(directory)
            c = ExtendedFnvCorrection.load_json(d / "correction.json")
            c.plot_potential(d / "potential.pdf", args.y_range)
        return

    if args.nocorr:
        for directory in dirs:
            c = ManualCorrection(manual_correction_energy=args.manual)
            c.to_json_file(Path(directory) / "correction.json")
        return

    try:
        ucr = UnitcellCalcResults.load_json(args.unitcell_json)
        dielectric_tensor = ucr.total_dielectric_tensor
    except IOError:
        raise FileNotFoundError("JSON for the unitcell info is not found.")

    try:
        perfect_dft_data = SupercellCalcResults.load_json(args.perfect_json)
    except IOError:
        raise FileNotFoundError("JSON for the perfect supercell is not found.")

    # Ewald parameter related
    if not Path(args.ewald_json).is_file():
        logger.info("optimizing ewald...")
        ewald = Ewald.from_optimization(
            structure=perfect_dft_data.final_structure,
            dielectric_tensor=dielectric_tensor,
            initial_ewald_param=args.ewald_initial_param,
            convergence=args.ewald_convergence,
            prod_cutoff_fwhm=args.ewald_accuracy)
        ewald.to_json_file(args.ewald_json)

    for directory in dirs:
        d = Path(directory)
        json_to_make = d / "correction.json"

        if json_to_make.exists() and not args.force_overwrite:
            logger.warning(f"{json_to_make} already exists, so nothing done.")
            continue

        logger.info(f"correcting {directory} ...")
        entry = DefectEntry.load_json(d / "defect_entry.json")
        try:
            defect_dft_data = \
                SupercellCalcResults.load_json(d / "dft_results.json")
        except IOError:
            logger.warning(f"dft_results.json in {directory} does not exist.")
            continue

        c = ExtendedFnvCorrection. \
            compute_correction(defect_entry=entry,
                               defect_dft=defect_dft_data,
                               perfect_dft=perfect_dft_data,
                               dielectric_tensor=dielectric_tensor,
                               defect_center=args.defect_center,
                               ewald=args.ewald_json)

        c.plot_potential(d / "potential.pdf", args.y_range)
        c.to_json_file(d / "correction.json")
Пример #14
0
def unitcell_calc_results(args):
    if args.print:
        print(UnitcellCalcResults.load_json(filename=args.json_file))
        return

    try:
        dft_results = UnitcellCalcResults.load_json(filename=args.json_file)
    except IOError:
        dft_results = UnitcellCalcResults()

    if args.band_edge_dir:
        try:
            dft_results.set_band_edge_from_vasp(args.band_edge_dir,
                                                vasprun_name=args.vasprun,
                                                outcar_name=args.outcar)
        except IOError:
            raise FileNotFoundError(
                f"{args.band_edge_dir} is not appropriate.")

    if args.static_diele:
        dft_results.static_dielectric_tensor = args.static_diele
    elif args.static_diele_dir:
        try:
            dft_results.set_static_dielectric_tensor_from_vasp(
                args.static_diele_dir, outcar_name=args.outcar)
        except IOError:
            raise FileNotFoundError(args.static_diele_dir,
                                    "is not appropriate.")
        except AttributeError as e:
            logger.error(str(e))

    if args.ionic_diele:
        dft_results.ionic_dielectric_tensor = args.ionic_diele
    elif args.ionic_diele_dir:
        try:
            dft_results.set_ionic_dielectric_tensor_from_vasp(
                args.ionic_diele_dir, outcar_name=args.outcar)
        except IOError:
            raise FileNotFoundError(args.ionic_diele_dir, "not appropriate.")

    if args.total_dos_dir:
        try:
            dft_results.set_total_dos_and_volume_from_vasp(
                args.total_dos_dir, vasprun_name=args.vasprun)
        except IOError:
            raise FileNotFoundError(args.total_dos_dir, "not appropriate.")

    dft_results.to_json_file(args.json_file)
    print(UnitcellCalcResults.load_json(filename=args.json_file))