This first part is only needed as we have to mock FHI-aims here as we cannot run it directly in a jupyter notebook:
import warnings
from mock_aims import TEST_DIR, mock_aims
ref_paths = {
"Relaxation calculation": "phonon-relax-si",
"phonon static aims 1/1": "phonon-disp-si",
"SCF Calculation": "phonon-energy-si",
"phonon static aims anharmonicity quant. 1/1": "anharm-si-full",
}
Phonon Workflow Tutorial with FHI-aims¶
This tutorial has been written based on the VASP version.
Background¶
The Phonon workflow is based on the finite displacement approach as implemented in Phonopy.
If you want to read more about Phonopy, please read Togo’s paper: https://doi.org/10.7566/JPSJ.92.012001
Let’s run the workflow¶
Now, we load a structure and other important functions and classes for running the phonon workflow.
from jobflow import JobStore, run_locally
from maggma.stores import MemoryStore
from pymatgen.core import SETTINGS, Structure
from atomate2.aims.flows.phonons import PhononMaker
warnings.filterwarnings("ignore")
job_store = JobStore(MemoryStore(), additional_stores={"data": MemoryStore()})
si_structure = Structure.from_file(TEST_DIR / "structures" / "Si_diamond.cif")
SETTINGS["AIMS_SPECIES_DIR"] = TEST_DIR / "../aims/species_dir/tight"
Then one can use the PhononMaker
to generate a Flow
. For testing here, we are choosing a very small supercell length (min_length
). Ideally, a larger cell should be chosen. For non-metallic systems with more than one element, one might need to add the non-analytical term correction considering very long-ranging forces by computing the BORN
charges with the born_maker
. Of course, the structure should also be relaxed in advance with the bulk_relax_maker
. Please make sure this is done very accurately. For FHI-aims a born_maker
still needs to be implemented.
phonon_maker = PhononMaker(
min_length=3.0,
generate_frequencies_eigenvectors_kwargs={"tstep": 100},
create_thermal_displacements=True,
store_force_constants=True,
born_maker=None,
use_symmetrized_structure="primitive",
)
flow = phonon_maker.make(si_structure)
The phonon run will first perform a bulk relaxation, then the displacements are generated and run.
flow.draw_graph().show()
We now run the flow with run_locally
. We mock the run here. Normally, you would simply use run_locally
without the with mock_aims
with mock_aims(ref_paths=ref_paths) as mf:
run_locally(
flow,
create_folders=True,
ensure_success=True,
raise_immediately=True,
store=job_store,
)
from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine
from pymatgen.phonon.dos import PhononDos
from pymatgen.phonon.plotter import PhononBSPlotter, PhononDosPlotter
job_store.connect()
result = job_store.query_one(
{"name": "generate_frequencies_eigenvectors"},
load=True,
sort={"completed_at": -1}, # to get the latest computation
)
ph_bs = PhononBandStructureSymmLine.from_dict(
result["output"]["phonon_bandstructure"]
) # get pymatgen bandstructure object
ph_dos = PhononDos.from_dict(
result["output"]["phonon_dos"]
) # get pymatgen phonon dos object
# initialize dos plotter and visualize dos plot
dos_plot = PhononDosPlotter()
dos_plot.add_dos(label="a", dos=ph_dos)
dos_plot.get_plot()
# initialize Phonon bandstructure plotter and visualize band structure plot
bs_plot = PhononBSPlotter(bs=ph_bs)
bs_plot.get_plot()
One can run the same workflow with a forcefield or VASP as well.
Anharmonicity Quantification¶
Now that we have a phonon calculation completed, we can quantify the anharmonicty (\(\sigma^A\)) using the method first proposed in this paper: Phys. Rev. Materials 4, 083809 DOI: https://doi.org/10.1103/PhysRevMaterials.4.083809
from atomate2.aims.flows.anharmonicity import AnharmonicityMaker
from atomate2.common.schemas.phonons import PhononBSDOSDoc
anharm_quant_maker = AnharmonicityMaker(phonon_maker=phonon_maker)
phonon_doc = PhononBSDOSDoc(**result["output"])
anharm_flow = anharm_quant_maker.make_from_phonon_doc(
phonon_doc=phonon_doc,
one_shot_approx=False,
seed=1234,
)
with mock_aims(ref_paths=ref_paths) as mf:
run_locally(
anharm_flow,
create_folders=True,
ensure_success=True,
raise_immediately=True,
store=job_store,
)
result_anharm = job_store.query_one(
{"name": "get_sigmas"},
load=True,
sort={"completed_at": -1}, # to get the latest computation
)
print(f"The estimated anharmonicity is {result_anharm['output']['full']}") # noqa: T201
We can also use the oneshot method to approximate \(\sigma^A\)
anharm_os_flow = anharm_quant_maker.make_from_phonon_doc(
phonon_doc=phonon_doc,
one_shot_approx=True,
seed=1234,
)
ref_paths = {
"Relaxation calculation": "phonon-relax-si",
"phonon static aims 1/1": "phonon-disp-si",
"SCF Calculation": "phonon-energy-si",
"phonon static aims anharmonicity quant. 1/1": "anharm-os-si",
}
with mock_aims(ref_paths=ref_paths) as mf:
run_locally(
anharm_os_flow,
create_folders=True,
ensure_success=True,
raise_immediately=True,
store=job_store,
)
result_anharm = job_store.query_one(
{"name": "get_sigmas"},
load=True,
sort={"completed_at": -1}, # to get the latest computation
)
print(f"The estimated one-shot anharmonicity is {result_anharm['output']['one-shot']}") # noqa: T201