Intermidiate Tutorial#

In this tutorial you will learn how to define the non-analytical constants for the Data types presented in the previous tutorial.

Polar insulators#

The phonon band structure of bulk polar insulators, which we define to be insulators with different atomic species (e.g. AlAs, BaTiO3), needs extra quantities to be interpolated correctly around the gamma point. These quantities are the so called non-analytical constants. They are composed by two tensors:

  1. Dielectric tensor: this is the high-frequency dielectric tensor of the material, \(\epsilon^{\infty}_{ij}\).

  2. Born effective charges tensor: these are effective charges of the nuclei, usually expressed in unit of charge \(e\), \(Z^{*}_{I,ij}\)

The indices \(i\) and \(j\) refer to the three Cartesian axes, while \(I\) is the atomic index.

Important

The tensors \(Z^{*}_{I,ij}\) are not symmetric with the exchange of \(i\) and \(j\)!

Convention

In Phonopy and aiida-phonopy, the convention for \(Z^{*}_{I,ij}\) indices is as follow:

  1. Atomic index.

  2. Polarization index.

  3. Atomic displacement index.

Let’s show this with AlAs. On the same lines of the basic tutorial, we define PreProcessData:

# ================= IMPORTS ======================== #
from local_module import load_temp_profile
from aiida.plugins import DataFactory, CalculationFactory
from aiida.orm import load_code, Dict
# If you download this file, you can run it with your own profile.
# Put these lines instead:
# from aiida import load_profile
# load_profile()
load_temp_profile(
    name="intermidiate-tutorial",
    add_computer=True,
    add_phonopy_code=True,
)

StructureData = DataFactory("core.structure")
PreProcessData = DataFactory("phonopy.preprocess")
PhonopyData = DataFactory("phonopy.phonopy")
PhonopyCalculation = CalculationFactory("phonopy.phonopy")
# ============== STRUCTURE DATA ==================== #
a = 2.839
cell = [[0,a,a],[a,0,a],[a,a,0]]
structure = StructureData(cell=cell)
structure.append_atom(position=(0,0,0), symbols="Al")
structure.append_atom(position=(0.5*a,0.5*a,0.5*a), symbols="As")
# ============= PREPROCESS DATA ==================== #
supercell_matrix = [[-1,1,1],[1,-1,1],[1,1,-1]] # standard cell 8 atoms
preprocess_data =  PreProcessData(structure=structure, supercell_matrix=supercell_matrix)

We could go through and compute the forces for the displaced structure. The result would be:

dict_of_forces = {
    "forces_1": 
    [
        [-0.0988347466,    0.0000000000,    0.0000000000],
        [-0.0200237511,    0.0000000000,    0.0000000000],
        [ 0.0135502277,    0.0000000000,    0.0000000000],
        [ 0.0135502277,    0.0000000000,    0.0000000000],
        [ 0.0230530248,    0.0183687320,    0.0183687320],
        [ 0.0230530248,   -0.0183687320,   -0.0183687320],
        [ 0.0228262535,    0.0179280450,   -0.0179280450],
        [ 0.0228262535,   -0.0179280450,    0.0179280450],
    ],
    "forces_2": 
    [
        [ 0.0228136551,    0.0179285592,    0.0179285592],
        [ 0.0228136551,   -0.0179285592,   -0.0179285592],
        [ 0.0230645948,   -0.0183682178,    0.0183682178],
        [ 0.0230645948,    0.0183682178,   -0.0183682178],
        [-0.1025024252,    0.0000000000,    0.0000000000],
        [-0.0044662632,    0.0000000000,    0.0000000000],
        [ 0.0076060944,    0.0000000000,    0.0000000000],
        [ 0.0076060944,    0.0000000000,    0.0000000000],
    ]
}

phonopy_data =  PhonopyData(preprocess_data=preprocess_data)
phonopy_data.set_forces(dict_of_forces=dict_of_forces)

We may want to try to compute the band structure of the phonons directly.

builder = PhonopyCalculation.get_builder()
builder.code = load_code("phonopy@local_direct") # WARNING! You may redefine this
builder.phonopy_data = phonopy_data
builder.parameters = Dict({"band":"auto"})

Submit the calculation.

from aiida.engine import run_get_node

results, node = run_get_node(builder)
print("These are the final results:")
results
These are the final results:
{'output_parameters': <Dict: uuid: eac7a1c8-04a9-4171-888a-2a83025f53fd (pk: 7)>,
 'phonon_bands': <BandsData: uuid: 17beda26-a889-4f86-b638-1e19e7b9d57e (pk: 8)>,
 'remote_folder': <RemoteData: uuid: 5d65f3e9-a296-41a1-a63e-deddf8ef9f14 (pk: 5)>,
 'retrieved': <FolderData: uuid: 65931787-eb29-4a42-a7f2-4ff66d5163e6 (pk: 6)>}

Check the phonon dispersion.

node.outputs.phonon_bands.show_mpl()
_images/7f9173b63e0da05d195d4c6d4568cfe3d0d441e25594b0a6d7b6370013cfe900.png

It looks fine, isn’t it?

Actually, there is a subtle discrepancy. If one would compare this with experiments, a phonon mode seems to miss at \(\Gamma\)! Try to answer the following question before continuing the tutorial.

Let’s now add the non-analytical contribution (NAC). Imagine we have already computed such quantities.

phonopy_data_nac = phonopy_data.clone() # the `phonopy_data` is now immutable in AiiDA!

born_charges = [
    [
        [+2.1576, 0, 0], 
        [0, +2.1576, 0], 
        [0, 0, +2.1576]
    ],
    [
        [-2.1576, 0, 0],
        [0, -2.1576, 0],
        [0, 0, -2.1576]
    ],
]

dielectric = [
    [9.4626, 0, 0],
    [0, 9.4626, 0],
    [0, 0, 9.4626],
]

phonopy_data_nac.set_born_charges(born_charges)
phonopy_data_nac.set_dielectric(dielectric)

Does it have the NAC now? Let’s ask!

phonopy_data_nac.has_nac_parameters()
True

Hurray!

Now we can recompute the band structure and see if something changes.

builder.phonopy_data = phonopy_data_nac

results, node = run_get_node(builder)
node.outputs.phonon_bands.show_mpl()
_images/c611b64d1999881aca98e5168ea9e28e192fd566e5bdb03c06152e1bb98a7130.png

A huge splitting at \(\Gamma\) appeared! This is often referred to as LO-TO splitting.

If you want to learn more features, continue with the next tutorial.