Source code for pymatgen.analysis.diffusion.neb.io
# Copyright (c) Materials Virtual Lab.
# Distributed under the terms of the BSD License.
"""Generate input fields for NEB calculations."""
from __future__ import annotations
import copy
from pymatgen.core import Structure
from pymatgen.io.vasp.sets import MITNEBSet, MITRelaxSet
__author__ = "Austen"
[docs]
class MVLCINEBEndPointSet(MITRelaxSet):
    """Class for writing NEB end points relaxation inputs."""
    def __init__(self, structure, **kwargs):
        r"""
        Args:
            structure: Structure
            **kwargs: Keyword args supported by VaspInputSets.
        """
        user_incar_settings = kwargs.get("user_incar_settings", {})
        defaults = {
            "ISIF": 2,
            "EDIFF": 5e-5,
            "EDIFFG": -0.02,
            "ISMEAR": 0,
            "ISYM": 0,
            "LCHARG": False,
            "LDAU": False,
            "NELMIN": 4,
        }
        if user_incar_settings != {}:
            defaults.update(user_incar_settings)
        kwargs["user_incar_settings"] = defaults
        super().__init__(structure, **kwargs) 
[docs]
class MVLCINEBSet(MITNEBSet):
    """
    MAVRL-tested settings for CI-NEB calculations. Note that these parameters
    requires the VTST modification of VASP from the Henkelman group. See
    http://theory.cm.utexas.edu/vtsttools/.
    """
    def __init__(self, structures, **kwargs):
        r"""
        Args:
            structures: Input structures.
            **kwargs: Keyword args supported by VaspInputSets.
        """
        user_incar_settings = kwargs.get("user_incar_settings", {})
        # CI-NEB settings
        defaults = {
            "EDIFF": 5e-5,
            "EDIFFG": -0.02,
            "IBRION": 3,
            "ICHAIN": 0,
            "IOPT": 1,
            "ISIF": 2,
            "ISMEAR": 0,
            "ISPIN": 2,
            "LCHARG": False,
            "LCLIMB": True,
            "LDAU": False,
            "LORBIT": 0,
            "NSW": 200,
            "POTIM": 0,
            "SPRING": -5,
        }
        if user_incar_settings != {}:
            defaults.update(user_incar_settings)
        kwargs["user_incar_settings"] = defaults
        super().__init__(structures, **kwargs) 
[docs]
def get_endpoints_from_index(structure, site_indices):
    """
    This class reads in one perfect structure and the two endpoint structures
    are generated using site_indices.
    Args:
        structure (Structure): A perfect structure.
        site_indices (list of int): a two-element list indicating site indices.
    Returns:
        endpoints (list of Structure): a two-element list of two endpoints
                                        Structure object.
    """
    if len(site_indices) != 2 or len(set(site_indices)) != 2:
        raise ValueError("Invalid indices!")
    if structure[site_indices[0]].specie != structure[site_indices[1]].specie:
        raise ValueError("The site indices must be associated with identical species!")
    s = structure.copy()
    sites = s.sites
    # Move hopping atoms to the beginning of species index.
    init_site = sites[site_indices[0]]
    final_site = sites[site_indices[1]]
    sites.remove(init_site)
    sites.remove(final_site)
    init_sites = copy.deepcopy(sites)
    final_sites = copy.deepcopy(sites)
    init_sites.insert(0, final_site)
    final_sites.insert(0, init_site)
    s_0 = Structure.from_sites(init_sites)
    s_1 = Structure.from_sites(final_sites)
    return [s_0, s_1] 
[docs]
def get_endpoint_dist(ep_0, ep_1):
    """
    Calculate a list of site distances between two endpoints, assuming periodic
    boundary conditions.
    Args:
        ep_0 (Structure): the first endpoint structure.
        ep_1 (Structure): the second endpoint structure.
    Returns:
        dist (list): a list of distances between two structures.
    """
    ep_0.remove_oxidation_states()
    ep_1.remove_oxidation_states()
    assert ep_0.species == ep_1.species, "Formula mismatch!"
    assert ep_0.lattice.abc == ep_0.lattice.abc, "Lattice mismatch!"
    distances = []
    for site0, site1 in zip(ep_0, ep_1):
        fc = (site0.frac_coords, site1.frac_coords)
        d = ep_0.lattice.get_distance_and_image(fc[0], fc[1])[0]
        distances.append(d)
    return distances