Source code for asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy

#!/usr/bin/env python
'''
Calculates the monovacancy formation energy from a bulk structure

Author: mkphuthi@github.com
'''

from typing import Dict, Sequence, Optional
import logging
from asimtools.calculators import load_calc
from asimtools.asimmodules.geometry_optimization.atom_relax import atom_relax
from asimtools.asimmodules.geometry_optimization.optimize import optimize
from asimtools.utils import (
    get_atoms,
)

[docs] def vacancy_formation_energy( calculator: Dict, image: Dict, vacancy_index: int = 0, atom_relax_args: Optional[Dict] = None, optimize_args: Optional[Dict] = None, repeat: Optional[Sequence] = (1,1,1) ) -> Dict: """Calculates the monovacancy formation energy from a bulk structure :param calculator: Calculator specification, see :func:`asimtools.calculators.load_calc` :type calculator: Dict :param image: Image specification, see :func:`asimtools.utils.get_atoms` :type image: Dict :param vacancy_index: Index of atom to remove, defaults to 0 :type vacancy_index: int, optional :param atom_relax_args: Args to pass to :func:`asimtools.asimmodules.geometry_optimization.atom_relax.atom_relax`, this applies if you do not want to optimize the cell at all defaults to None :type atom_relax_args: Optional[Dict], optional :param optimize_args: Args to pass to :func:`asimtools.asimmodules.geometry_optimization.optimize.optimize`, this applies if you want to optimize both the cell and positions defaults to None :type optimize_args: Optional[Dict], optional :param repeat: Repeat to apply to image to create supercell, defaults to None :type repeat: Optional[Sequence], optional :return: Empty dictionary :rtype: Dict """ calc = load_calc(calculator=calculator) bulk = get_atoms(**image).repeat(repeat) bulk.calc = calc vacant = bulk.copy() del vacant[vacancy_index] try: bulk_e = calc.get_potential_energy(bulk) logging.info('Finished bulk calculation') except ValueError: logging.error("Failed to calculate energy of bulk structure, " "see calculator output") raise bulk.write('bulk_image_output.xyz') if atom_relax_args is not None: try: relax_results = atom_relax( calculator=calculator, image={'atoms': vacant}, optimizer=atom_relax_args.get('optimizer', 'BFGS'), properties=('energy','forces'), fmax=atom_relax_args.get('fmax', 0.01), prefix=f'vacant_relaxed', ) logging.info('Relaxed vacant structure') except ValueError: logging.error("Failed to calculate energy of bulk structure, " "see calculator output") raise else: try: relax_results = optimize( calculator=calculator, image={'atoms': vacant}, # optimizer=optimize_args.get('optimizer', 'BFGS'), # fmax=atom_relax_args.get('fmax', 0.003), # prefix=f'vacant_optimized', **optimize_args, ) logging.info('Relaxed vacant structure') except ValueError: logging.error("Failed to calculate energy of bulk structure, " "see calculator output") raise vacant_e = relax_results['energy'] vac_form_e = vacant_e - (len(vacant) / len(bulk) * bulk_e) res_dict = {} res_dict['bulk_e'] = float(bulk_e) res_dict['vacant_e'] = float(vacant_e) res_dict['bulk_n'] = len(bulk) res_dict['vfe'] = float(vac_form_e) results = {'vfe': res_dict} return results