Source code for custodian.feff.handlers

# coding: utf-8

"""
This module implements specific error handler for FEFF runs.
"""


import logging
import re

from pymatgen.io.feff.sets import FEFFDictSet

from custodian.custodian import ErrorHandler
from custodian.feff.interpreter import FeffModder
from custodian.utils import backup

__author__ = "Chen Zheng"
__copyright__ = "Copyright 2012, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Chen Zheng"
__email__ = "chz022@ucsd.edu"
__date__ = "Oct 18, 2017"

FEFF_BACKUP_FILES = [
    "ATOMS",
    "HEADER",
    "PARAMETERS",
    "POTENTIALS",
    "feff.inp",
    "*.cif",
    "pot.bin",
]

logger = logging.getLogger(__name__)


[docs]class UnconvergedErrorHandler(ErrorHandler): """ Correct the unconverged error of FEFF's SCF calculation. """ is_monitor = False def __init__(self, output_filename="log1.dat"): """ Initializes the handler with the output file to check Args: output_filename (str): Filename for the log1.dat file. log1.dat file contains the SCF calculation convergence information. Change this only if it is different from the default (unlikely). """ self.output_filename = output_filename
[docs] def check(self): """ If the FEFF run does not converge, the check will return "TRUE" """ return self._notconverge_check()
def _notconverge_check(self): # Process the output file and get converge information not_converge_pattern = re.compile("Convergence not reached.*") converge_pattern = re.compile("Convergence reached.*") for _, line in enumerate(open(self.output_filename)): if len(not_converge_pattern.findall(line)) > 0: return True if len(converge_pattern.findall(line)) > 0: return False return None
[docs] def correct(self): """ Perform the corrections. """ backup(FEFF_BACKUP_FILES) feff_input = FEFFDictSet.from_directory(".") scf_values = feff_input.tags.get("SCF") nscmt = scf_values[2] ca = scf_values[3] nmix = scf_values[4] actions = [] # Add RESTART card to PARAMETERS if "RESTART" not in feff_input.tags: actions.append({"dict": "PARAMETERS", "action": {"_set": {"RESTART": []}}}) if nscmt < 100 and ca == 0.2: scf_values[2] = 100 scf_values[4] = 3 # Set nmix = 3 actions.append( {"dict": "PARAMETERS", "action": {"_set": {"SCF": scf_values}}} ) FeffModder().apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} if nscmt == 100 and nmix == 3 and ca > 0.01: # Reduce the convergence accelerator factor scf_values[3] = round(ca / 2, 2) actions.append( {"dict": "PARAMETERS", "action": {"_set": {"SCF": scf_values}}} ) FeffModder().apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} if nmix == 3 and ca == 0.01: # Set ca = 0.05 and set nmix scf_values[3] = 0.05 scf_values[4] = 5 actions.append( {"dict": "PARAMETERS", "action": {"_set": {"SCF": scf_values}}} ) FeffModder().apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} if nmix == 5 and ca == 0.05: # Set ca = 0.05 and set nmix scf_values[3] = 0.05 scf_values[4] = 10 actions.append( {"dict": "PARAMETERS", "action": {"_set": {"SCF": scf_values}}} ) FeffModder().apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} if nmix == 10 and ca < 0.2: # loop through ca with nmix = 10 scf_values[3] = round(ca * 2, 2) actions.append( {"dict": "PARAMETERS", "action": {"_set": {"SCF": scf_values}}} ) FeffModder().apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} # Unfixable error. Just return None for actions. return {"errors": ["Non-converging job"], "actions": None}