Source code for aim2dat.io.cp2k.restart

"""
Functions to read the restart file of CP2K.
"""

# Standard library imports
from typing import List, Union
import re

# Third party library imports
import numpy as np

# Internal library imports
from aim2dat.io.base_parser import parse_function, _BasePattern
from aim2dat.io.utils import read_multiple


class _CellPattern(_BasePattern):
    _pattern = r"^\s*&CELL\n(.*\n)*?\s*&END\sCELL"
    _dir_mapping = {"A": 0, "B": 1, "C": 2}

    def process_data(self, output: dict, matches: List[re.Match]):
        output["pbc"] = [True, True, True]
        cell = [None, None, None]
        cell_factors = [1.0, 1.0, 1.0]
        m = matches[-1]
        for line in m.string[m.start() : m.end()].splitlines()[1:-1]:
            line_sp = line.split()
            label = line_sp[0].upper()
            if label in self._dir_mapping:
                cell[self._dir_mapping[label]] = np.array([float(val) for val in line_sp[1:]])
            elif label == "PERIODIC":
                output["pbc"] = [(dir_st in line_sp[1]) for dir_st in ["X", "Y", "Z"]]
            elif label == "MULTIPLE_UNIT_CELL":
                cell_factors = [float(val) for val in line_sp[1:]]
        if all(c0 is not None for c0 in cell):
            output["cell"] = [(c_f * v0).tolist() for c_f, v0 in zip(cell_factors, cell)]


class _CoordPattern(_BasePattern):
    _pattern = r"^\s*&COORD\n(.*\n)*?\s*&END\sCOORD"

    def process_data(self, output: dict, matches: List[re.Match]):
        output["kinds"] = []
        output["positions"] = []
        m = matches[-1]
        for line in m.string[m.start() : m.end()].splitlines()[1:-1]:
            line_sp = line.split()
            output["kinds"].append(line_sp[0])
            pos = []
            for val in line_sp[1:]:
                try:
                    pos.append(float(val))
                except ValueError:
                    pos.append(0.0)
            output["positions"].append(pos)


class _KindPattern(_BasePattern):
    _pattern = r"\s*&KIND\s(?P<kind>\S+)\n(.*\n)*?\s*&END\sKIND"

    def process_data(self, output: dict, matches: List[re.Match]):
        output["kind_info"] = {}
        for m in matches:
            kind = m.groupdict()["kind"]
            element = kind
            for line in m.string[m.start() : m.end()].splitlines()[1:-1]:
                line_sp = line.split()
                if line_sp[0].upper() == "ELEMENT":
                    element = line_sp[1]
                    break
            output["kind_info"][kind] = element


[docs] def read_optimized_structure(folder_path: str) -> Union[dict, List[dict]]: """ Read optimized structures from 'restart'-files. Parameters ---------- folder_path : str Path to the folder containing the CP2K ouput-files. Returns ------- dict or list Dictionary containing the structural information. In case of a farming job a list of dictionaries is returned. In case several calculations have been run in the same folder a nested dictionary is returned. """ from warnings import warn warn( "This function will be removed, please use `read_restart_structure` instead.", DeprecationWarning, 2, ) structures = read_restart_structure(folder_path) if isinstance(structures, list): for strct in structures: strct["symbols"] = strct.pop("elements") else: structures["symbols"] = structures.pop("elements") return structures
[docs] @read_multiple(r".*-1\.restart$", is_read_strct_method=True) def read_restart_structure(folder_path: str) -> Union[dict, List[dict]]: """ Read structures from 'restart'-files. Parameters ---------- folder_path : str Path to the folder containing the CP2K ouput-files. Returns ------- dict or list Dictionary or list of dictionaries containing the structural information. In case of a farming job or several calculations have been run in the same folder, a list of dictionaries is returned. """ structures = [] for file_p, file_n in zip(folder_path["file"], folder_path["file_name"]): proj = file_n.rsplit("-", 1)[0] output = parse_function(file_p, [_CellPattern, _CoordPattern, _KindPattern]) kind_info = output.pop("kind_info") output["elements"] = [kind_info[kind] for kind in output["kinds"]] output["label"] = proj structures.append(output) return structures[0] if len(structures) == 1 else structures