Source code for sisl.io.orca.txt

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
import numpy as np
from .sile import SileORCA
from ..sile import add_sile, sile_fh_open

from sisl.utils import PropertyDict
from sisl._internal import set_module
from sisl import Geometry
from sisl.unit import units

__all__ = ['txtSileORCA']


@set_module("sisl.io.orca")
class txtSileORCA(SileORCA):
    """ Output from the ORCA property.txt file """

    def _setup(self, *args, **kwargs):
        """ Ensure the class has essential tags """
        super()._setup(*args, **kwargs)
        self._na = None
        self._no = None

    def readline(self, *args, **kwargs):
        line = super().readline(*args, **kwargs)
        if self._na is None and "Number of atoms:"[1:] in line:
            v = line.split()
            self._na = int(v[-1])
        elif self._no is None and "Number of basis functions:"[1:] in line:
            v = line.split()
            self._no = int(v[-1])
        return line

    @property
    @sile_fh_open()
    def na(self):
        """ Number of atoms """
        if self._na is None:
            f = self.step_to("Number of atoms"[1:])
            if f[0]:
                self._na = int(f[1].split()[-1])
            else:
                return None
        return self._na

    @property
    @sile_fh_open()
    def no(self):
        """ Number of orbitals (basis functions) """
        if self._no is None:
            f = self.step_to("Number of basis functions"[1:])
            if f[0]:
                self._no = int(f[1].split()[-1])
            else:
                return None
        return self._no

[docs] @sile_fh_open(True) def read_electrons(self, all=False): """ Read number of electrons (alpha, beta) Parameters ---------- all: bool, optional return electron numbers from all steps (instead of last) Returns ------- ndarray or list of ndarrays : alpha and beta electrons """ def readE(itt): f = self.step_to("Number of Alpha Electrons", allow_reread=False) if f[0]: alpha = float(f[1].split()[-1]) beta = float(next(itt).split()[-1]) else: return None return alpha, beta itt = iter(self) E = [] e = readE(itt) while e is not None: E.append(e) e = readE(itt) if all: return np.array(E) if len(E) > 0: return np.array(E[-1]) return None
[docs] @sile_fh_open(True) def read_energy(self, all=False): """ Reads the energy blocks Parameters ---------- all: bool, optional return a list of dictionaries from each step (instead of the last) Returns ------- PropertyDict : all data (in eV) from the "DFT_Energy" and "VdW_Correction" blocks """ def readE(itt): # read the DFT_Energy block f = self.step_to("$ DFT_Energy", allow_reread=False)[0] if not f: return None next(itt) # description next(itt) # geom. index next(itt) # prop. index line = next(itt) E = PropertyDict() while "----" not in line: v = line.split() value = float(v[-1]) * units('Ha', 'eV') if v[0] == "Exchange": E["exchange"] = value elif v[0] == "Correlation": if v[2] == "NL": E["correlation_nl"] = value else: E["correlation"] = value elif v[0] == "Exchange-Correlation": E["xc"] = value elif v[0] == "Embedding": E["embedding"] = value elif v[1] == "DFT": E["total"] = value line = next(itt) line = next(itt) if "$ VdW_Correction" in line: v = self.step_to("Van der Waals Correction:")[1].split() E["vdw"] = float(v[-1]) * units('Ha', 'eV') return E itt = iter(self) E = [] e = readE(itt) while e is not None: E.append(e) e = readE(itt) if all: return E if len(E) > 0: return E[-1] return None
[docs] @sile_fh_open(True) def read_geometry(self, all=False): """ Reads the geometry from ORCA property.txt file Parameters ---------- all: bool, optional return a list of all geometries instead of the last one Returns ------- geometries: list or Geometry or None if all is False only one geometry will be returned (or None). Otherwise a list of geometries corresponding to each step. """ def readG(itt): # Read the Geometry block f = self.step_to("!GEOMETRY!", allow_reread=False)[0] if not f: return None line = next(itt) na = int(line.split()[-1]) next(itt) # skip Geometry index next(itt) # skip Coordinates line atoms = [] xyz = np.empty([na, 3], np.float64) for ia in range(na): line = next(itt) l = line.split() atoms.append(l[1]) xyz[ia] = l[2:5] return Geometry(xyz, atoms) itt = iter(self) G = [] g = readG(itt) while g is not None: G.append(g) g = readG(itt) if all: return G if len(G) > 0: return G[-1] return None
add_sile('txt', txtSileORCA, gzip=True)