Exemple #1
0
def gkfo_correction(efnv_correction):
    s1 = PotentialSite(specie="H",
                       distance=1.999,
                       potential=10,
                       pc_potential=None)
    s2 = PotentialSite(specie="He",
                       distance=2.0001,
                       potential=15,
                       pc_potential=2)
    s3 = PotentialSite(specie="He", distance=3.0, potential=20, pc_potential=3)

    return GkfoCorrection(init_efnv_correction=efnv_correction,
                          additional_charge=1,
                          pc_2nd_term=10.0,
                          gkfo_sites=[s1, s2, s3],
                          ave_dielectric_tensor=4.0,
                          ave_electronic_dielectric_tensor=2.0)
Exemple #2
0
def efnv_correction():
    s1 = PotentialSite(specie="H",
                       distance=1.999,
                       potential=1.0,
                       pc_potential=None)
    s2 = PotentialSite(specie="He",
                       distance=2.0001,
                       potential=1.5,
                       pc_potential=0.2)
    s3 = PotentialSite(specie="He",
                       distance=3.0,
                       potential=2.0,
                       pc_potential=0.3)

    return ExtendedFnvCorrection(charge=10,
                                 point_charge_correction=1.0,
                                 defect_region_radius=2.0,
                                 sites=[s1, s2, s3],
                                 defect_coords=(0.0, 0.0, 0.0))
def make_efnv_correction(charge: int,
                         calc_results: CalcResults,
                         perfect_calc_results: CalcResults,
                         dielectric_tensor: np.array,
                         accuracy: float = defaults.ewald_accuracy,
                         unit_conversion: float = 180.95128169876497):
    """
    Notes:
    (1) The formula written in YK2014 need to be divided by 4pi in the SI unit.
    (2) When assuming an element charge locate at the defect_coords and
        angstrom for length, relative dielectric tensor, Multiply
        elementary_charge * 1e10 / epsilon_0 = 180.95128169876497
        to make potential in V.
    """
    if calc_results.structure.lattice != perfect_calc_results.structure.lattice:
        raise SupercellError("The lattice constants for defect and perfect "
                             "models are different")

    structure_analyzer = DefectStructureComparator(
        calc_results.structure, perfect_calc_results.structure)
    defect_coords = structure_analyzer.defect_center_coord
    lattice = calc_results.structure.lattice
    ewald = Ewald(lattice.matrix, dielectric_tensor, accuracy=accuracy)
    point_charge_correction = \
        0.0 if not charge else - ewald.lattice_energy * charge ** 2

    defect_region_radius = calc_max_sphere_radius(lattice.matrix)

    sites = []
    for d, p in structure_analyzer.atom_mapping.items():
        specie = str(calc_results.structure[d].specie)
        frac_coords = calc_results.structure[d].frac_coords
        distance, _ = lattice.get_distance_and_image(defect_coords,
                                                     frac_coords)
        pot = calc_results.potentials[d] - perfect_calc_results.potentials[p]

        coord = calc_results.structure[d].frac_coords
        rel_coord = [x - y for x, y in zip(coord, defect_coords)]
        if distance <= defect_region_radius:
            pc_potential = None
        else:
            if charge == 0:
                pc_potential = 0
            else:
                pc_potential = ewald.atomic_site_potential(rel_coord) * charge
                pc_potential *= unit_conversion

        sites.append(PotentialSite(specie, distance, pot, pc_potential))

    return ExtendedFnvCorrection(
        charge=charge,
        point_charge_correction=point_charge_correction * unit_conversion,
        defect_region_radius=defect_region_radius,
        sites=sites,
        defect_coords=tuple(defect_coords))
Exemple #4
0
def test_make_efnv_correction(mocker):
    mock_perfect = mocker.Mock(spec=CalcResults, autospec=True)
    mock_defect = mocker.Mock(spec=CalcResults, autospec=True)

    mock_perfect.structure = IStructure(Lattice.cubic(10),
                                        species=["H"] + ["He"] * 3 + ["Li"],
                                        coords=[[0, 0, 0], [1 / 2, 1 / 2, 0],
                                                [1 / 2, 0, 1 / 2],
                                                [0, 1 / 2, 1 / 2],
                                                [0, 0, 1 / 2]])
    mock_defect.structure = IStructure(Lattice.cubic(10),
                                       species=["He"] * 3 + ["Li"],
                                       coords=[[1 / 2, 1 / 2, 0],
                                               [1 / 2, 0, 1 / 2],
                                               [0, 1 / 2, 1 / 2],
                                               [0, 0, 1 / 2]])
    mock_perfect.potentials = [3.0, 4.0, 5.0, 6.0, 7.0]
    mock_defect.potentials = [14.0, 25.0, 36.0, 47.0]

    mock_ewald = mocker.patch("pydefect.cli.vasp.make_efnv_correction.Ewald")
    ewald = mocker.Mock()
    ewald.lattice_energy = 1e3
    ewald.atomic_site_potential.return_value = 1e4
    mock_ewald.return_value = ewald

    efnvc = make_efnv_correction(charge=2,
                                 calc_results=mock_defect,
                                 perfect_calc_results=mock_perfect,
                                 dielectric_tensor=np.eye(3))

    unit_conversion = 180.95128169876497

    assert efnvc.charge == 2
    assert efnvc.point_charge_correction == -4e3 * unit_conversion
    assert efnvc.defect_region_radius == 5.0
    assert efnvc.sites == [
        PotentialSite("He", 5 * np.sqrt(2), 10.0, 2e4 * unit_conversion),
        PotentialSite("He", 5 * np.sqrt(2), 20.0, 2e4 * unit_conversion),
        PotentialSite("He", 5 * np.sqrt(2), 30.0, 2e4 * unit_conversion),
        PotentialSite("Li", 5.0, 40.0, None),
    ]
Exemple #5
0
def efnv_cor():
    return ExtendedFnvCorrection(charge=1,
                                 point_charge_correction=0.0,
                                 defect_region_radius=2.8,
                                 sites=[
                                     PotentialSite(specie="H",
                                                   distance=1.0,
                                                   potential=-4,
                                                   pc_potential=None),
                                     PotentialSite(specie="H",
                                                   distance=2.0,
                                                   potential=-3,
                                                   pc_potential=None),
                                     PotentialSite(specie="He",
                                                   distance=3.0,
                                                   potential=-2,
                                                   pc_potential=-3),
                                     PotentialSite(specie="He",
                                                   distance=4.0,
                                                   potential=-1,
                                                   pc_potential=-2)
                                 ],
                                 defect_coords=(0.0, 0.0, 0.0))
def make_gkfo_correction(
        efnv_correction: ExtendedFnvCorrection,
        additional_charge: int,
        final_calc_results: CalcResults,
        initial_calc_results: CalcResults,
        diele_tensor: np.array,
        ion_clamped_diele_tensor: np.array,
        accuracy: float = defaults.ewald_accuracy,
        unit_conversion: float = 180.95128169876497) -> GkfoCorrection:
    assert final_calc_results.structure == initial_calc_results.structure
    assert abs(additional_charge) == 1

    defect_coords = efnv_correction.defect_coords
    lattice = initial_calc_results.structure.lattice
    ewald_ele = Ewald(lattice.matrix,
                      ion_clamped_diele_tensor,
                      accuracy=accuracy)
    defect_region_radius = efnv_correction.defect_region_radius

    pc_2nd_term = -ewald_ele.lattice_energy

    gkfo_sites = []
    for index, site in enumerate(initial_calc_results.structure):
        specie = site.specie
        dist, _ = lattice.get_distance_and_image(site.frac_coords,
                                                 defect_coords)
        pot = (final_calc_results.potentials[index] -
               initial_calc_results.potentials[index])

        rel_coord = [x - y for x, y in zip(site.frac_coords, defect_coords)]
        if dist <= defect_region_radius:
            pc_potential = None
        else:
            pc_potential = (ewald_ele.atomic_site_potential(rel_coord) *
                            additional_charge * unit_conversion)

        gkfo_sites.append(PotentialSite(specie, dist, pot, pc_potential))

    return GkfoCorrection(
        init_efnv_correction=efnv_correction,
        additional_charge=additional_charge,
        pc_2nd_term=pc_2nd_term * unit_conversion,
        gkfo_sites=gkfo_sites,
        ave_dielectric_tensor=np.trace(diele_tensor) / 3,
        ave_electronic_dielectric_tensor=np.trace(ion_clamped_diele_tensor) /
        3)
def test_defect_site_msonable(efnv_correction):
    assert_msonable(
        PotentialSite(specie="H",
                      distance=1.999,
                      potential=1.0,
                      pc_potential=0.1))
def test_defect_site_diff_pot():
    s = PotentialSite("H", distance=1.999, potential=1.0, pc_potential=0.1)
    assert s.diff_pot == 1.0 - 0.1