Source code for sisl.io.siesta.times

# 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/.
from __future__ import annotations

import numpy as np
import xarray as xr

from sisl._array import arrayd, arrayi
from sisl._internal import set_module

from ..sile import add_sile, sile_fh_open
from .sile import SileSiesta

__all__ = ["timesSileSiesta"]


@set_module("sisl.io.siesta")
class timesSileSiesta(SileSiesta):
    """Time information from the Siesta run

    The timings are stored in either the ``TIMES`` or
    the ``<SystemLabel>.times`` files.
    """

    _info_attributes_ = [
        dict(
            name="processors",
            searcher=r"^timer: Number of nodes",
            parser=lambda attr, instance, match: int(match.string.split()[-1]),
            not_found="error",
        ),
        dict(
            name="threads",
            searcher=r"^timer: Number of threads per node",
            parser=lambda attr, instance, match: int(match.string.split()[-1]),
            default=1,
            not_found="info",
        ),
        dict(
            name="processor_reference",
            searcher=r"^timer: Times refer to node",
            parser=lambda attr, instance, match: int(match.string.split()[-1]),
            not_found="error",
        ),
        dict(
            name="wall_clock",
            searcher=r"^timer: Total elapsed wall-clock",
            parser=lambda attr, instance, match: float(match.string.split()[-1]),
            not_found="error",
        ),
    ]

[docs] @sile_fh_open(True) def read_data(self) -> xarray.DataArray: r"""Returns data associated with the times file Returns ------- times : xarray.DataArray containing timings. """ rl = self.readline # first line is empty rl() line = rl() # Number of nodes line = rl() # Busiest calculating line = rl() # Times refer to node line = rl() # Total elapsed line = rl() # CPU times for _ in range(4): rl() self.step_to("Program") # header rl() # now we read content routines = [] calls = [] comm = [] times = [] imbalance = [] while len(cols := rl().split()) > 1: if cols[0] == "MPI": break routines.append(cols[0]) calls.append(cols[1]) comm.append(cols[2]) times.append(cols[4]) imbalance.append(cols[6]) def ar(ar): return ar.reshape(1, -1) dims = ["parallel", "routine"] data = arrayd([calls, comm, times, imbalance]).T data_vars = dict( calls=(dims, ar(arrayi(calls))), comm=(dims, ar(arrayd(comm))), time=(dims, ar(arrayd(times))), imbalance=(dims, ar(arrayd(imbalance))), ) coords = dict( processors=("parallel", [self.info.processors]), threads=("parallel", [self.info.threads]), routine=routines, ) data = xr.Dataset( data_vars=data_vars, coords=coords, attrs=dict(file=f"{self!s}", unit="s") ) data = data.set_index(parallel=["processors", "threads"]) return data
# This will both allow TIMES + siesta.times add_sile("TIMES", timesSileSiesta, case=False, gzip=True)