From 911fafef6ab15a4b763602b4ed354fcf83e07b59 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 13:53:17 +0200 Subject: [PATCH 01/11] BLD: Bump qmflows to >=0.12 --- nanoqm/schedule/scheduleCP2K.py | 8 ++++---- nanoqm/workflows/initialization.py | 15 ++++----------- nanoqm/workflows/input_validation.py | 2 +- nanoqm/workflows/templates.py | 2 +- nanoqm/workflows/workflow_coop.py | 2 +- nanoqm/workflows/workflow_ipr.py | 2 +- setup.py | 2 +- test/test_absorption_spectrum.py | 4 ---- test/test_initialization.py | 3 --- test/test_input_validation.py | 2 +- test/test_multipole.py | 3 ++- test/utilsTest.py | 2 +- test_requirements.txt | 2 +- 13 files changed, 18 insertions(+), 31 deletions(-) diff --git a/nanoqm/schedule/scheduleCP2K.py b/nanoqm/schedule/scheduleCP2K.py index 943e59020..5df35f00f 100644 --- a/nanoqm/schedule/scheduleCP2K.py +++ b/nanoqm/schedule/scheduleCP2K.py @@ -23,8 +23,8 @@ from noodles import schedule # Workflow Engine from qmflows import Settings, cp2k, templates -from qmflows.packages.cp2k_package import CP2K, CP2K_Result -from qmflows.parsers.xyzParser import string_to_plams_Molecule +from qmflows.packages import CP2K, CP2K_Result +from qmflows.parsers import string_to_plams_Molecule from qmflows.type_hints import PromisedObject # Starting logger @@ -95,7 +95,7 @@ def prepare_cp2k_settings( @schedule def prepare_job_cp2k( settings: Settings, dict_input: Dict[str, Any], guess_job: PromisedObject) -> CP2K: - """Generate a :class:`qmflows.packages.cp2k_packages.CP2K` job. + """Generate a :class:`qmflows.packages.CP2K` job. Parameters ---------- @@ -108,7 +108,7 @@ def prepare_job_cp2k( Returns ------- - :class:`qmflows.packages.cp2k_package.CP2K` + :class:`qmflows.packages.CP2K` job to run """ diff --git a/nanoqm/workflows/initialization.py b/nanoqm/workflows/initialization.py index d9dc037e7..7a62aef19 100644 --- a/nanoqm/workflows/initialization.py +++ b/nanoqm/workflows/initialization.py @@ -37,7 +37,7 @@ from packaging.version import Version from qmflows.common import AtomBasisKey from qmflows.parsers import parse_string_xyz -from qmflows.parsers.cp2KParser import readCp2KBasis +from qmflows.parsers.cp2k import read_cp2k_basis from qmflows.type_hints import PathLike from .. import __version__ @@ -117,8 +117,6 @@ def save_basis_to_hdf5(config: DictConfig) -> None: store_cp2k_basis(config.path_hdf5, path) -_QMFLOWS_VERSION = Version(qmflows.__version__) -_QMFLOWS_0_11_3 = Version("0.11.3") _NANO_QMFLOWS_0_13_0 = Version("0.13.0") _BASIS_PATH_PATTERN = re.compile(r"/cp2k/basis/([a-z]+)/([^/]+)/(coefficients|exponents)") @@ -155,14 +153,9 @@ def store_cp2k_basis(path_hdf5: PathLike, path_basis: PathLike) -> None: if Version(f.attrs.get("__version__", "0.0.0")) < _NANO_QMFLOWS_0_13_0: _convert_legacy_basis(f) - if _QMFLOWS_VERSION >= _QMFLOWS_0_11_3: - keys, vals = readCp2KBasis(path_basis, allow_multiple_exponents=True) - node_paths_exponents = [_join(xs, str(xs.exponent_set), "exponents") for xs in keys] - node_paths_coefficients = [_join(xs, str(xs.exponent_set), "coefficients") for xs in keys] - else: - keys, vals = readCp2KBasis(path_basis) - node_paths_exponents = [_join(xs, "0", "exponents") for xs in keys] - node_paths_coefficients = [_join(xs, "0", "coefficients") for xs in keys] + keys, vals = read_cp2k_basis(path_basis, allow_multiple_exponents=True) + node_paths_exponents = [_join(xs, str(xs.exponent_set), "exponents") for xs in keys] + node_paths_coefficients = [_join(xs, str(xs.exponent_set), "coefficients") for xs in keys] exponents = [xs.exponents for xs in vals] coefficients = [xs.coefficients for xs in vals] diff --git a/nanoqm/workflows/input_validation.py b/nanoqm/workflows/input_validation.py index f3ff25c7c..b0bde7bcc 100644 --- a/nanoqm/workflows/input_validation.py +++ b/nanoqm/workflows/input_validation.py @@ -21,7 +21,7 @@ from schema import SchemaError from scm.plams import Molecule -from qmflows.settings import Settings +from qmflows import Settings from qmflows.type_hints import PathLike from ..common import DictConfig, UniqueSafeLoader, valence_electrons diff --git a/nanoqm/workflows/templates.py b/nanoqm/workflows/templates.py index 6dc97dcfd..7ccd6ef3d 100644 --- a/nanoqm/workflows/templates.py +++ b/nanoqm/workflows/templates.py @@ -16,7 +16,7 @@ import yaml from scm.plams import Molecule -from qmflows.settings import Settings +from qmflows import Settings from qmflows.type_hints import PathLike from nanoqm.common import UniqueSafeLoader, valence_electrons, aux_fit from typing import Any, Dict, Iterable, FrozenSet diff --git a/nanoqm/workflows/workflow_coop.py b/nanoqm/workflows/workflow_coop.py index c6db2ff2f..b0b42e583 100644 --- a/nanoqm/workflows/workflow_coop.py +++ b/nanoqm/workflows/workflow_coop.py @@ -17,7 +17,7 @@ import numpy as np -from qmflows.parsers.xyzParser import readXYZ +from qmflows.parsers import readXYZ from ..common import (DictConfig, MolXYZ, h2ev, number_spherical_functions_per_atom, retrieve_hdf5_data) diff --git a/nanoqm/workflows/workflow_ipr.py b/nanoqm/workflows/workflow_ipr.py index 0098c6439..72478aa49 100644 --- a/nanoqm/workflows/workflow_ipr.py +++ b/nanoqm/workflows/workflow_ipr.py @@ -14,7 +14,7 @@ import numpy as np from scipy.linalg import sqrtm -from qmflows.parsers.xyzParser import readXYZ +from qmflows.parsers import readXYZ from ..common import (DictConfig, h2ev, number_spherical_functions_per_atom, retrieve_hdf5_data) diff --git a/setup.py b/setup.py index 9a8a24a9d..ef3674138 100644 --- a/setup.py +++ b/setup.py @@ -170,7 +170,7 @@ def build_extensions(self) -> None: 'schema', 'pyyaml>=5.1', 'plams>=1.5.1', - 'qmflows>=0.11.2', + 'qmflows>=0.12.0', 'packaging>=1.16.8', 'Nano-Utils>=2.0.0', ], diff --git a/test/test_absorption_spectrum.py b/test/test_absorption_spectrum.py index ac991ea8c..bd034476b 100644 --- a/test/test_absorption_spectrum.py +++ b/test/test_absorption_spectrum.py @@ -7,7 +7,6 @@ import pytest import qmflows import numpy as np -from packaging.version import Version from nanoqm.common import retrieve_hdf5_data from nanoqm.workflows import workflow_stddft from nanoqm.workflows.input_validation import process_input @@ -36,9 +35,6 @@ def test( approx: str, ) -> None: """Compute the oscillator strenght and check the results.""" - if project == "He" and (Version(qmflows.__version__) < Version("0.11.3")): - pytest.skip("Requires QMFlows >= 0.11.3") - name += f"-{approx}" path_original_hdf5 = PATH_TEST / f'{project}.hdf5' shutil.copy(path_original_hdf5, tmp_path) diff --git a/test/test_initialization.py b/test/test_initialization.py index 54f848472..a2eba1239 100644 --- a/test/test_initialization.py +++ b/test/test_initialization.py @@ -12,7 +12,6 @@ import yaml from nanoutils import RecursiveKeysView from assertionlib import assertion -from packaging.version import Version from nanoqm.common import UniqueSafeLoader, DictConfig from nanoqm.workflows.initialization import initialize, save_basis_to_hdf5 @@ -71,8 +70,6 @@ def get_input( tmp_path: Path, ) -> tuple[DictConfig, set[str]]: name, basis_file_name = request.param - if name == "ADMM" and (Version(qmflows.__version__) < Version("0.11.3")): - pytest.xfail("Basis sets consisting of multiple subsets require qmflows >=0.11.3") # COnstruct the settings hdf5_file = tmp_path / f"{name}.hdf5" diff --git a/test/test_input_validation.py b/test/test_input_validation.py index 6c5e1c96c..10435574b 100644 --- a/test/test_input_validation.py +++ b/test/test_input_validation.py @@ -6,7 +6,7 @@ import pytest from qmflows import cp2k, run from qmflows.type_hints import PathLike -from qmflows.packages.cp2k_package import CP2K_Result +from qmflows.packages import CP2K_Result from scm import plams import nanoqm diff --git a/test/test_multipole.py b/test/test_multipole.py index 269952955..d4d2217ba 100644 --- a/test/test_multipole.py +++ b/test/test_multipole.py @@ -5,9 +5,10 @@ import numpy as np from assertionlib import assertion +from qmflows.parsers import readXYZ + from nanoqm.integrals.multipole_matrices import compute_matrix_multipole from nanoqm.workflows.input_validation import process_input -from qmflows.parsers.xyzParser import readXYZ from .utilsTest import PATH_TEST diff --git a/test/utilsTest.py b/test/utilsTest.py index 756db4a16..4e2592db1 100644 --- a/test/utilsTest.py +++ b/test/utilsTest.py @@ -11,7 +11,7 @@ import h5py import pkg_resources as pkg -from qmflows.packages.packages import Result +from qmflows.packages import Result __all__ = [ "PATH_NANOQM", diff --git a/test_requirements.txt b/test_requirements.txt index aec636e86..5e79cda12 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -17,6 +17,6 @@ scipy schema pyyaml>=5.1 plams>=1.5.1 -qmflows>=0.11.2 +qmflows>=0.12.0 packaging>=1.16.8 Nano-Utils>=2.0.0 From ab3b169e6cf5cd119a271b8460e770564783abd3 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 14:05:02 +0200 Subject: [PATCH 02/11] ENH: Add a named tuple with the nano-qmflows version --- nanoqm/__init__.py | 1 + nanoqm/_version_info.py | 11 +++++++++++ test/test_version.py | 12 +++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 nanoqm/_version_info.py diff --git a/nanoqm/__init__.py b/nanoqm/__init__.py index a0799396f..cc1ae19a2 100644 --- a/nanoqm/__init__.py +++ b/nanoqm/__init__.py @@ -3,6 +3,7 @@ chemical (QM) packages.""" from ._version import __version__ as __version__ +from ._version_info import version_info as version_info from .analysis import ( autocorrelate, dephasing, convolute, func_conv, gauss_function, diff --git a/nanoqm/_version_info.py b/nanoqm/_version_info.py new file mode 100644 index 000000000..141dcc10d --- /dev/null +++ b/nanoqm/_version_info.py @@ -0,0 +1,11 @@ +"""The Nano-QMFlows version tuple.""" + +from nanoutils import VersionInfo +from packaging.version import Version + +from ._version import __version__ + +__all__ = ["version_info"] + +VERSION = Version(__version__) +version_info = VersionInfo._make(VERSION.release[:3]) diff --git a/test/test_version.py b/test/test_version.py index e4c8f3b78..b3c3ba215 100644 --- a/test/test_version.py +++ b/test/test_version.py @@ -1,7 +1,17 @@ +import pytest from packaging.version import Version +from assertionlib import assertion + import nanoqm def test_version() -> None: """Check that the nano-qmflows version is PEP 440 compliant.""" - assert Version(nanoqm.__version__) + assertion.assert_(Version, nanoqm.__version__) + + +@pytest.mark.parametrize("name", ["major", "minor", "micro"]) +def test_version_info(name: str) -> None: + attr = getattr(nanoqm.version_info, name) + assertion.isinstance(attr, int) + assertion.ge(attr, 0) From ac0f45c5df4f42f185e64a4ee95384f360f79fd7 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 14:05:52 +0200 Subject: [PATCH 03/11] ENH: Add a single central Nano-QMFlows logger --- conftest.py | 10 ++ nanoqm/__init__.py | 1 + nanoqm/_logger.py | 79 +++++++++++++ nanoqm/integrals/multipole_matrices.py | 4 +- nanoqm/schedule/components.py | 5 +- nanoqm/schedule/scheduleCP2K.py | 4 +- nanoqm/schedule/scheduleCoupling.py | 6 +- nanoqm/workflows/initialization.py | 111 ++++++++----------- nanoqm/workflows/input_validation.py | 6 +- nanoqm/workflows/orbitals_type.py | 5 +- nanoqm/workflows/run_workflow.py | 4 +- nanoqm/workflows/tools.py | 9 +- nanoqm/workflows/workflow_coop.py | 9 +- nanoqm/workflows/workflow_coupling.py | 5 +- nanoqm/workflows/workflow_ipr.py | 8 +- nanoqm/workflows/workflow_single_points.py | 5 +- nanoqm/workflows/workflow_stddft_spectrum.py | 5 +- scripts/qmflows/coordination_ldos.py | 17 +-- 18 files changed, 159 insertions(+), 134 deletions(-) create mode 100644 nanoqm/_logger.py diff --git a/conftest.py b/conftest.py index 991a03b1f..756b96da7 100644 --- a/conftest.py +++ b/conftest.py @@ -5,6 +5,7 @@ from collections.abc import Generator import pytest +from nanoqm._logger import logger, stdout_handler @pytest.fixture(autouse=True, scope="function") @@ -17,3 +18,12 @@ def cleunup_files() -> Generator[None, None, None]: os.remove("input_parameters.yml") if os.path.isdir("overlaps"): shutil.rmtree("overlaps") + + +@pytest.fixture(autouse=True, scope="session") +def prepare_logger() -> Generator[None, None, None]: + """Remove the logging output to stdout while running tests.""" + assert stdout_handler in logger.handlers + logger.removeHandler(stdout_handler) + yield None + logger.addHandler(stdout_handler) diff --git a/nanoqm/__init__.py b/nanoqm/__init__.py index cc1ae19a2..0f5c0975f 100644 --- a/nanoqm/__init__.py +++ b/nanoqm/__init__.py @@ -4,6 +4,7 @@ from ._version import __version__ as __version__ from ._version_info import version_info as version_info +from ._logger import logger as logger from .analysis import ( autocorrelate, dephasing, convolute, func_conv, gauss_function, diff --git a/nanoqm/_logger.py b/nanoqm/_logger.py new file mode 100644 index 000000000..b827981c3 --- /dev/null +++ b/nanoqm/_logger.py @@ -0,0 +1,79 @@ +"""The Nano-QMFlows logger.""" + +from __future__ import annotations + +import os +import sys +import types +import logging +import contextlib +from typing import ClassVar + +from qmflows.type_hints import PathLike + +__all__ = ["logger", "stdout_handler", "EnableFileHandler"] + +#: The Nano-QMFlows logger. +logger = logging.getLogger("nanoqm") +logger.setLevel(logging.DEBUG) + +qmflows_logger = logging.getLogger("qmflows") +noodles_logger = logging.getLogger("noodles") +noodles_logger.setLevel(logging.WARNING) + +#: The Nano-QMFlows stdout handler. +stdout_handler = logging.StreamHandler(stream=sys.stdout) +stdout_handler.setLevel(logging.DEBUG) +stdout_handler.setFormatter(logging.Formatter( + fmt='[%(asctime)s] %(levelname)s: %(message)s', + datefmt='%H:%M:%S', +)) +logger.addHandler(stdout_handler) + + +class EnableFileHandler(contextlib.ContextDecorator): + """Add a file handler to the noodles, qmflows and nanoqm loggers. + + Attributes + ---------- + handler : logging.FileHandler + The relevant titular handler. + + """ + + __slots__ = ("handler",) + + LOGGERS: ClassVar = (logger, qmflows_logger, noodles_logger) + + def __init__(self, path: PathLike) -> None: + """Initialize the context manager. + + Parameters + ---------- + path : path-like object + Path to the log file. + + """ + self.handler = logging.FileHandler(os.fsdecode(path)) + self.handler.setLevel(logging.DEBUG) + self.handler.setFormatter(logging.Formatter( + fmt='%(asctime)s---%(levelname)s\n%(message)s\n', + datefmt='%H:%M:%S', + )) + + def __enter__(self) -> None: + """Add the file handler.""" + for logger in self.LOGGERS: + if self.handler not in logger.handlers: + logger.addHandler(self.handler) + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + exc_traceback: types.TracebackType | None, + ) -> None: + """Remove the file handler.""" + for logger in self.LOGGERS: + if self.handler in logger.handlers: + logger.removeHandler(self.handler) diff --git a/nanoqm/integrals/multipole_matrices.py b/nanoqm/integrals/multipole_matrices.py index 26e72bcbb..d1ed387af 100644 --- a/nanoqm/integrals/multipole_matrices.py +++ b/nanoqm/integrals/multipole_matrices.py @@ -18,7 +18,6 @@ from __future__ import annotations -import logging import os import uuid from os.path import join @@ -29,6 +28,7 @@ from compute_integrals import compute_integrals_multipole from qmflows.common import AtomXYZ +from .. import logger from ..common import (DictConfig, is_data_in_hdf5, retrieve_hdf5_data, store_arrays_in_hdf5, tuplesXYZ_to_plams) @@ -36,8 +36,6 @@ from numpy.typing import NDArray from numpy import float64 as f8 -logger = logging.getLogger(__name__) - def get_multipole_matrix(config: DictConfig, inp: DictConfig, multipole: str) -> NDArray[f8]: """Retrieve the `multipole` number `i` from the trajectory. Otherwise compute it. diff --git a/nanoqm/schedule/components.py b/nanoqm/schedule/components.py index ec8c9d798..b3f80dd03 100644 --- a/nanoqm/schedule/components.py +++ b/nanoqm/schedule/components.py @@ -12,7 +12,6 @@ "split_file_geometries"] import fnmatch -import logging import os from collections import defaultdict from os.path import join @@ -25,13 +24,11 @@ from qmflows.type_hints import PathLike, PromisedObject from qmflows.warnings_qmflows import SCF_Convergence_Warning +from .. import logger from ..common import (DictConfig, Matrix, is_data_in_hdf5, read_cell_parameters_as_array, store_arrays_in_hdf5) from .scheduleCP2K import prepare_job_cp2k -# Starting logger -logger = logging.getLogger(__name__) - #: Molecular orbitals from both restricted and unrestricted calculations OrbitalType = Union[InfoMO, Tuple[InfoMO, InfoMO]] diff --git a/nanoqm/schedule/scheduleCP2K.py b/nanoqm/schedule/scheduleCP2K.py index 5df35f00f..f99ac01ce 100644 --- a/nanoqm/schedule/scheduleCP2K.py +++ b/nanoqm/schedule/scheduleCP2K.py @@ -15,7 +15,6 @@ from __future__ import annotations import fnmatch -import logging import os from os.path import join from pathlib import Path @@ -27,8 +26,7 @@ from qmflows.parsers import string_to_plams_Molecule from qmflows.type_hints import PromisedObject -# Starting logger -logger = logging.getLogger(__name__) +from .. import logger def try_to_read_wf(path_dir: str | os.PathLike[str]) -> str: diff --git a/nanoqm/schedule/scheduleCoupling.py b/nanoqm/schedule/scheduleCoupling.py index 36314d4b3..bd0387708 100644 --- a/nanoqm/schedule/scheduleCoupling.py +++ b/nanoqm/schedule/scheduleCoupling.py @@ -21,10 +21,8 @@ from __future__ import annotations -import logging import os from os.path import join -# Types hint from typing import List, Tuple, TYPE_CHECKING import numpy as np @@ -32,6 +30,7 @@ from scipy.optimize import linear_sum_assignment from qmflows.parsers import parse_string_xyz +from .. import logger from ..common import (DictConfig, Matrix, MolXYZ, Tensor3D, Vector, hbar, femtosec2au, h2ev, is_data_in_hdf5, retrieve_hdf5_data, store_arrays_in_hdf5) @@ -44,9 +43,6 @@ if TYPE_CHECKING: import numpy.typing as npt -# Starting logger -logger = logging.getLogger(__name__) - __all__ = ["calculate_overlap", "lazy_couplings", "write_hamiltonians"] diff --git a/nanoqm/workflows/initialization.py b/nanoqm/workflows/initialization.py index 7a62aef19..3d45852e5 100644 --- a/nanoqm/workflows/initialization.py +++ b/nanoqm/workflows/initialization.py @@ -20,7 +20,6 @@ import re import fnmatch import getpass -import logging import os import subprocess import tempfile @@ -40,15 +39,13 @@ from qmflows.parsers.cp2k import read_cp2k_basis from qmflows.type_hints import PathLike -from .. import __version__ +from .. import logger, __version__, __path__ as nanoqm_path +from .._logger import EnableFileHandler from ..common import (BasisFormats, DictConfig, Matrix, change_mol_units, is_data_in_hdf5, retrieve_hdf5_data, store_arrays_in_hdf5) from ..schedule.components import create_point_folder, split_file_geometries -# Starting logger -logger = logging.getLogger(__name__) - def initialize(config: DictConfig) -> DictConfig: """Initialize all the data required to schedule the workflows. @@ -59,46 +56,50 @@ def initialize(config: DictConfig) -> DictConfig: Input to run the workflow. """ - log_config(config) - - # Scratch folder - scratch_path = create_path_option(config["scratch_path"]) - if scratch_path is None: - scratch_path = Path(tempfile.gettempdir()) / \ - getpass.getuser() / config.project_name - logger.warning( - f"path to scratch was not defined, using: {scratch_path}") - config['workdir'] = scratch_path - - # If the directory does not exist create it - if not scratch_path.exists(): - scratch_path.mkdir(parents=True) - - # Touch HDF5 if it doesn't exists - if not os.path.exists(config.path_hdf5): - Path(config.path_hdf5).touch() - - # all_geometries type :: [String] - geometries = split_file_geometries(config["path_traj_xyz"]) - config['geometries'] = geometries - - # Create a folder for each point the the dynamics - enumerate_from = config["enumerate_from"] - len_geometries = len(geometries) - config["folders"] = create_point_folder( - scratch_path, len_geometries, enumerate_from) - - config['calc_new_wf_guess_on_points'] = guesses_to_compute( - config['calculate_guesses'], enumerate_from, len_geometries) - - # Generate a list of tuples containing the atomic label - # and the coordinates to generate the primitive CGFs - atoms = parse_string_xyz(geometries[0]) - if 'angstrom' in config["geometry_units"].lower(): - atoms = change_mol_units(atoms) - - # Save Basis to HDF5 - save_basis_to_hdf5(config) + with EnableFileHandler(f'{config.project_name}.log'): + logger.info(f"Using nano-qmflows version: {qmflows.__version__} ") + logger.info(f"nano-qmflows path is: {nanoqm_path[0]}") + logger.info(f"Working directory is: {os.path.abspath('.')}") + logger.info(f"Data will be stored in HDF5 file: {config.path_hdf5}") + + # Scratch folder + scratch_path = create_path_option(config["scratch_path"]) + if scratch_path is None: + scratch_path = ( + Path(tempfile.gettempdir()) / getpass.getuser() / config.project_name + ) + logger.warning(f"path to scratch was not defined, using: {scratch_path}") + config['workdir'] = scratch_path + + # If the directory does not exist create it + if not scratch_path.exists(): + scratch_path.mkdir(parents=True) + + # Touch HDF5 if it doesn't exists + if not os.path.exists(config.path_hdf5): + Path(config.path_hdf5).touch() + + # all_geometries type :: [String] + geometries = split_file_geometries(config["path_traj_xyz"]) + config['geometries'] = geometries + + # Create a folder for each point the the dynamics + enumerate_from = config["enumerate_from"] + len_geometries = len(geometries) + config["folders"] = create_point_folder( + scratch_path, len_geometries, enumerate_from) + + config['calc_new_wf_guess_on_points'] = guesses_to_compute( + config['calculate_guesses'], enumerate_from, len_geometries) + + # Generate a list of tuples containing the atomic label + # and the coordinates to generate the primitive CGFs + atoms = parse_string_xyz(geometries[0]) + if 'angstrom' in config["geometry_units"].lower(): + atoms = change_mol_units(atoms) + + # Save Basis to HDF5 + save_basis_to_hdf5(config) return config @@ -244,26 +245,6 @@ def split_trajectory(path: str | Path, nblocks: int, pathOut: str | os.PathLike[ return fnmatch.filter(os.listdir(), "chunk_xyz_?") -def log_config(config: DictConfig) -> None: - """Print initial configuration.""" - workdir = os.path.abspath('.') - file_log = f'{config.project_name}.log' - logging.basicConfig(filename=file_log, level=logging.DEBUG, - format='%(asctime)s---%(levelname)s\n%(message)s\n', - datefmt='[%I:%M:%S]') - logging.getLogger("noodles").setLevel(logging.WARNING) - handler = logging.StreamHandler() - handler.terminator = "" - - version = pkg_resources.get_distribution('nano-qmflows').version - path = pkg_resources.resource_filename('nanoqm', '') - - logger.info(f"Using nano-qmflows version: {version} ") - logger.info(f"nano-qmflows path is: {path}") - logger.info(f"Working directory is: {workdir}") - logger.info(f"Data will be stored in HDF5 file: {config.path_hdf5}") - - def create_path_option(path: str | os.PathLike[str]) -> Path | None: """Create a Path object or return None if path is None.""" return Path(path) if path is not None else None diff --git a/nanoqm/workflows/input_validation.py b/nanoqm/workflows/input_validation.py index b0bde7bcc..a2db1ede9 100644 --- a/nanoqm/workflows/input_validation.py +++ b/nanoqm/workflows/input_validation.py @@ -10,7 +10,7 @@ .. autofunction:: process_input """ -import logging + import os import warnings from os.path import join @@ -24,6 +24,7 @@ from qmflows import Settings from qmflows.type_hints import PathLike +from .. import logger from ..common import DictConfig, UniqueSafeLoader, valence_electrons from .schemas import (schema_absorption_spectrum, schema_coop, schema_cp2k_general_settings, @@ -34,9 +35,6 @@ schema_single_points) from .templates import create_settings_from_template -logger = logging.getLogger(__name__) - - schema_workflows = { 'absorption_spectrum': schema_absorption_spectrum, 'derivative_couplings': schema_derivative_couplings, diff --git a/nanoqm/workflows/orbitals_type.py b/nanoqm/workflows/orbitals_type.py index de0d6f180..6af3d416a 100644 --- a/nanoqm/workflows/orbitals_type.py +++ b/nanoqm/workflows/orbitals_type.py @@ -1,17 +1,14 @@ """Module to run restricted and unrestricted calculations.""" -import logging from typing import Any, Callable from noodles import gather from qmflows import run +from .. import logger from ..common import DictConfig from .initialization import initialize -# Starting logger -logger = logging.getLogger(__name__) - def select_orbitals_type( config: DictConfig, workflow: Callable[[DictConfig], Any]) -> Any: diff --git a/nanoqm/workflows/run_workflow.py b/nanoqm/workflows/run_workflow.py index 258542778..93ebe3599 100755 --- a/nanoqm/workflows/run_workflow.py +++ b/nanoqm/workflows/run_workflow.py @@ -14,11 +14,11 @@ """ import argparse -import logging import os import yaml +from .. import logger from ..common import UniqueSafeLoader from .input_validation import process_input from .workflow_coop import workflow_crystal_orbital_overlap_population @@ -27,8 +27,6 @@ from .workflow_single_points import workflow_single_points from .workflow_stddft_spectrum import workflow_stddft -logger = logging.getLogger(__name__) - msg = "run_workflow.py -i input.yml" parser = argparse.ArgumentParser(description=msg) diff --git a/nanoqm/workflows/tools.py b/nanoqm/workflows/tools.py index 411e687f8..62dd14422 100644 --- a/nanoqm/workflows/tools.py +++ b/nanoqm/workflows/tools.py @@ -1,11 +1,8 @@ """Common utilities use by the workflows.""" +from .. import logger from ..common import DictConfig, is_data_in_hdf5 from .workflow_single_points import workflow_single_points -import logging - -# Starting logger -LOGGER = logging.getLogger(__name__) def compute_single_point_eigenvalues_coefficients(config: DictConfig): @@ -18,9 +15,9 @@ def compute_single_point_eigenvalues_coefficients(config: DictConfig): node_paths = (node_path_coefficients, node_path_eigenvalues) if all(is_data_in_hdf5(config.path_hdf5, x) for x in node_paths): - LOGGER.info("Coefficients and eigenvalues already in hdf5.") + logger.info("Coefficients and eigenvalues already in hdf5.") else: # Call the single point workflow to calculate the eigenvalues and # coefficients - LOGGER.info("Starting single point calculation.") + logger.info("Starting single point calculation.") workflow_single_points(config) diff --git a/nanoqm/workflows/workflow_coop.py b/nanoqm/workflows/workflow_coop.py index b0b42e583..cf826e294 100644 --- a/nanoqm/workflows/workflow_coop.py +++ b/nanoqm/workflows/workflow_coop.py @@ -12,13 +12,13 @@ __all__ = ['workflow_crystal_orbital_overlap_population'] -import logging from typing import Tuple, TYPE_CHECKING import numpy as np from qmflows.parsers import readXYZ +from .. import logger from ..common import (DictConfig, MolXYZ, h2ev, number_spherical_functions_per_atom, retrieve_hdf5_data) from ..integrals.multipole_matrices import compute_matrix_multipole @@ -29,9 +29,6 @@ from numpy.typing import NDArray from numpy import float64 as f8, int64 as i8 -# Starting logger -LOGGER = logging.getLogger(__name__) - def workflow_crystal_orbital_overlap_population(config: DictConfig) -> NDArray[f8]: """Compute the Crystal Orbital Overlap Population.""" @@ -43,7 +40,7 @@ def workflow_crystal_orbital_overlap_population(config: DictConfig) -> NDArray[f compute_single_point_eigenvalues_coefficients(config) # Logger info - LOGGER.info("Starting COOP calculation.") + logger.info("Starting COOP calculation.") # Get eigenvalues and coefficients from hdf5 atomic_orbitals, energies = get_eigenvalues_coefficients(config) @@ -68,7 +65,7 @@ def workflow_crystal_orbital_overlap_population(config: DictConfig) -> NDArray[f # Lastly, we save the COOP as a txt-file result_coop = print_coop(energies, coop) - LOGGER.info("COOP calculation completed.") + logger.info("COOP calculation completed.") return result_coop diff --git a/nanoqm/workflows/workflow_coupling.py b/nanoqm/workflows/workflow_coupling.py index fa44d3880..b474ae25f 100644 --- a/nanoqm/workflows/workflow_coupling.py +++ b/nanoqm/workflows/workflow_coupling.py @@ -14,7 +14,6 @@ __all__ = ['workflow_derivative_couplings'] -import logging import os from os.path import join from typing import List, Tuple, Union @@ -23,15 +22,13 @@ from noodles.interface import PromisedObject from qmflows.type_hints import PathLike +from .. import logger from ..common import DictConfig from ..schedule.components import calculate_mos from ..schedule.scheduleCoupling import (calculate_overlap, lazy_couplings, write_hamiltonians) from .orbitals_type import select_orbitals_type -# Starting logger -logger = logging.getLogger(__name__) - #: Type defining the derivative couplings calculation ResultPaths = Tuple[List[str], List[str]] diff --git a/nanoqm/workflows/workflow_ipr.py b/nanoqm/workflows/workflow_ipr.py index 72478aa49..246b452a5 100644 --- a/nanoqm/workflows/workflow_ipr.py +++ b/nanoqm/workflows/workflow_ipr.py @@ -9,22 +9,18 @@ """ __all__ = ['workflow_ipr'] -import logging - import numpy as np from scipy.linalg import sqrtm from qmflows.parsers import readXYZ +from .. import logger from ..common import (DictConfig, h2ev, number_spherical_functions_per_atom, retrieve_hdf5_data) from ..integrals.multipole_matrices import compute_matrix_multipole from .initialization import initialize from .tools import compute_single_point_eigenvalues_coefficients -# Starting logger -LOGGER = logging.getLogger(__name__) - def workflow_ipr(config: DictConfig) -> np.ndarray: """Compute the Inverse Participation Ratio main function.""" @@ -35,7 +31,7 @@ def workflow_ipr(config: DictConfig) -> np.ndarray: compute_single_point_eigenvalues_coefficients(config) # Logger info - LOGGER.info("Starting IPR calculation.") + logger.info("Starting IPR calculation.") # Get eigenvalues and coefficients from hdf5 node_path_coefficients = 'coefficients/point_0/' diff --git a/nanoqm/workflows/workflow_single_points.py b/nanoqm/workflows/workflow_single_points.py index bcd7a6fb0..eea3e5d20 100644 --- a/nanoqm/workflows/workflow_single_points.py +++ b/nanoqm/workflows/workflow_single_points.py @@ -11,19 +11,16 @@ __all__ = ['workflow_single_points'] -import logging from typing import List from qmflows import run from qmflows.packages import Result +from .. import logger from ..common import DictConfig from ..schedule.components import calculate_mos from .initialization import initialize -# Starting logger -logger = logging.getLogger(__name__) - def workflow_single_points(config: DictConfig) -> Result: """Perform single point calculations for a given trajectory. diff --git a/nanoqm/workflows/workflow_stddft_spectrum.py b/nanoqm/workflows/workflow_stddft_spectrum.py index 26dce92e2..b56dbbb4e 100644 --- a/nanoqm/workflows/workflow_stddft_spectrum.py +++ b/nanoqm/workflows/workflow_stddft_spectrum.py @@ -12,7 +12,6 @@ __all__ = ['workflow_stddft'] -import logging from os.path import join from typing import Tuple, TYPE_CHECKING @@ -24,6 +23,7 @@ from qmflows.parsers import parse_string_xyz from qmflows.type_hints import PathLike +from .. import logger from ..common import (DictConfig, angs2au, change_mol_units, h2ev, hardness, is_data_in_hdf5, number_spherical_functions_per_atom, retrieve_hdf5_data, store_arrays_in_hdf5, xc) @@ -35,9 +35,6 @@ from numpy.typing import NDArray from numpy import float64 as f8 -# Starting logger -logger = logging.getLogger(__name__) - def workflow_stddft(config: DictConfig) -> None: """Compute the excited states using simplified TDDFT. diff --git a/scripts/qmflows/coordination_ldos.py b/scripts/qmflows/coordination_ldos.py index 41b0109d8..ffee09211 100644 --- a/scripts/qmflows/coordination_ldos.py +++ b/scripts/qmflows/coordination_ldos.py @@ -1,9 +1,9 @@ #!/usr/bin/env python """Performs a molecular optimization using CP2K and prints local PDOS projected on subsets of atoms based on the atom type and coordination number.""" + import argparse import itertools -import logging import os from typing import Dict, List @@ -12,28 +12,18 @@ from qmflows import Settings, cp2k, run, templates from scm.plams import Molecule +from nanoqm import logger +from nanoqm._logger import EnableFileHandler from nanoqm.workflows.templates import generate_kinds #: A nested dictonary NestedDict = Dict[str, Dict[int, List[int]]] -# Starting logger -logger = logging.getLogger(__name__) - names = ("Ac", "MA") molecules = {name: Molecule(f"{name}.xyz") for name in names} -def set_logger(): - """Set logging default behaviour.""" - file_log = 'output.log' - logging.basicConfig(filename=file_log, level=logging.DEBUG, - format='%(asctime)s---%(levelname)s\n%(message)s\n', - datefmt='[%I:%M:%S]') - logging.getLogger("noodles").setLevel(logging.WARNING) - - def create_cp2k_settings(mol: Molecule) -> Settings: """Create CP2K general settings.""" # Set path for basis set @@ -147,6 +137,7 @@ def store_coordination(coord: NestedDict, name: str, path_results: str): f.write(t) +@EnableFileHandler("output.log") def main(workdir: str): set_logger() From 1ced1c2a1c0f33fca9f0e15053434de58abdb3e4 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 14:12:22 +0200 Subject: [PATCH 04/11] TYP: Install `pyparsing` >=3.0.8 when running mypy --- .github/workflows/pythonapp.yml | 2 +- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index 3e608b126..f472cabce 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -167,7 +167,7 @@ jobs: python-version: "3.10" - name: Install linters - run: pip install pydocstyle pycodestyle mypy qmflows "numpy>=1.21" types-pyyaml types-pkg_resources types-setuptools + run: pip install pydocstyle pycodestyle mypy qmflows "numpy>=1.21" types-pyyaml types-pkg_resources types-setuptools "pyparsing>=3.0.8" - name: Python info run: | diff --git a/pyproject.toml b/pyproject.toml index ceb6f190c..27297ebc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,6 @@ module = [ "scm.plams.*", "h5py.*", "scipy.*", - "pyparsing.*", "noodles.*", "schema.*", "mendeleev.*", From cfab630c4b8633b7b6d8c1bd889fc93d4668a70a Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 14:13:01 +0200 Subject: [PATCH 05/11] MAINT: Move the `compute_integrals` extension module to the `nanoqm` namespace --- docs/conf.py | 2 +- {libint => nanoqm}/compute_integrals.pyi | 0 nanoqm/integrals/multipole_matrices.py | 2 +- nanoqm/integrals/nonAdiabaticCoupling.py | 3 +-- pyproject.toml | 2 -- setup.py | 2 +- 6 files changed, 4 insertions(+), 7 deletions(-) rename {libint => nanoqm}/compute_integrals.pyi (100%) diff --git a/docs/conf.py b/docs/conf.py index 75004ac2a..e25522b77 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -210,7 +210,7 @@ autodoc_mock_imports = [ 'h5py', 'qmflows', - 'compute_integrals', + 'nanoqm.compute_integrals', 'mendeleev', 'scm', 'noodles', diff --git a/libint/compute_integrals.pyi b/nanoqm/compute_integrals.pyi similarity index 100% rename from libint/compute_integrals.pyi rename to nanoqm/compute_integrals.pyi diff --git a/nanoqm/integrals/multipole_matrices.py b/nanoqm/integrals/multipole_matrices.py index d1ed387af..fb0c0910a 100644 --- a/nanoqm/integrals/multipole_matrices.py +++ b/nanoqm/integrals/multipole_matrices.py @@ -25,12 +25,12 @@ from typing import List, Union, TYPE_CHECKING import numpy as np -from compute_integrals import compute_integrals_multipole from qmflows.common import AtomXYZ from .. import logger from ..common import (DictConfig, is_data_in_hdf5, retrieve_hdf5_data, store_arrays_in_hdf5, tuplesXYZ_to_plams) +from ..compute_integrals import compute_integrals_multipole if TYPE_CHECKING: from numpy.typing import NDArray diff --git a/nanoqm/integrals/nonAdiabaticCoupling.py b/nanoqm/integrals/nonAdiabaticCoupling.py index 7c508b67a..ca05818a4 100644 --- a/nanoqm/integrals/nonAdiabaticCoupling.py +++ b/nanoqm/integrals/nonAdiabaticCoupling.py @@ -35,10 +35,9 @@ import numpy as np -from compute_integrals import compute_integrals_couplings - from ..common import (DictConfig, Matrix, MolXYZ, Tensor3D, retrieve_hdf5_data, tuplesXYZ_to_plams) +from ..compute_integrals import compute_integrals_couplings def calculate_couplings_3points( diff --git a/pyproject.toml b/pyproject.toml index 27297ebc8..22ddd16be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,8 +4,6 @@ requires = ['Cython', 'setuptools>=48.0', 'wheel', 'pybind11>=2.2.4'] [tool.mypy] plugins = "numpy.typing.mypy_plugin" -mypy_path = "libint" -files = ["nanoqm", "libint"] show_error_codes = true [[tool.mypy.overrides]] diff --git a/setup.py b/setup.py index ef3674138..07e1c3267 100644 --- a/setup.py +++ b/setup.py @@ -120,7 +120,7 @@ def build_extensions(self) -> None: conda_include = join(conda_prefix, 'include') conda_lib = join(conda_prefix, 'lib') ext_pybind = Extension( - 'compute_integrals', + 'nanoqm.compute_integrals', sources=['libint/compute_integrals.cc'], include_dirs=[ # Path to pybind11 headers From 0c06490f2d676c6f87943907cc18a2c16f58a3a7 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 14:14:10 +0200 Subject: [PATCH 06/11] TST: Promote `QMFlows_Warning` warnings to exceptions --- setup.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.cfg b/setup.cfg index c219f774e..515ddd99b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,9 @@ max-line-length = 100 testpaths = test addopts = --tb=short --cov --cov-report xml --cov-report term --cov-report html --cache-clear -s --pdbcls=IPython.terminal.debugger:TerminalPdb markers = slow: A marker for slow tests requiring external quantum-chemical packages. +filterwarnings = + error::qmflows.warnings_qmflows.QMFlows_Warning + ignore:Generic keyword '_pytestfixturefunction' not implemented for package \w+:qmflows.warnings_qmflows.Key_Warning # Define `python setup.py build_sphinx` [build_sphinx] From db8775546c6c87778fea0185fefc6bc8b4452ec5 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 16:56:18 +0200 Subject: [PATCH 07/11] MAINT: Get rid of stray `print` calls --- libint/compute_integrals.cc | 39 +++++++++++++++----- nanoqm/compute_integrals.pyi | 4 ++ nanoqm/integrals/multipole_matrices.py | 6 ++- nanoqm/integrals/nonAdiabaticCoupling.py | 7 +++- nanoqm/workflows/input_validation.py | 2 +- nanoqm/workflows/workflow_stddft_spectrum.py | 1 - scripts/hamiltonians/plot_spectra.py | 9 +++-- scripts/pyxaid/plot_spectra_pyxaid.py | 5 ++- scripts/qmflows/dos_cp2k.py | 3 +- scripts/qmflows/opt_anion_cp2k.py | 4 +- scripts/qmflows/opt_cation_cp2k.py | 4 +- scripts/qmflows/opt_cp2k.py | 3 +- scripts/qmflows/plot_dos.py | 6 ++- scripts/qmflows/removeHDF5folders.py | 3 +- scripts/qmflows/remove_mos_hdf5.py | 4 +- scripts/reenumerate.py | 5 ++- test/test_cpk2_error_call.py | 4 +- test/test_distribute.py | 9 ++--- test/test_workflow_IPR.py | 11 ++---- test/test_workflow_coop.py | 11 ++---- test/test_workflow_single_points.py | 2 - 21 files changed, 88 insertions(+), 54 deletions(-) diff --git a/libint/compute_integrals.cc b/libint/compute_integrals.cc index 42abd9b30..1709c0aa1 100644 --- a/libint/compute_integrals.cc +++ b/libint/compute_integrals.cc @@ -82,20 +82,33 @@ template void parallel_do(Lambda &lambda) { * \brief Set the number of thread to use */ void set_nthread() { - +#if defined(_OPENMP) using libint2::nthreads; nthreads = std::thread::hardware_concurrency(); - -#if defined(_OPENMP) omp_set_num_threads(nthreads); #endif - std::cout << "Will scale over " << nthreads -#if defined(_OPENMP) - << " OpenMP" -#else - << " C++11" -#endif - << " threads" << std::endl; +} + +/** + * \brief Get the number of threads and the thread type as a 2-tuple + */ +int get_thread_count() { + using libint2::nthreads; + return std::thread::hardware_concurrency(); +} + +/** + * \brief Get the type of threads + */ +string get_thread_type() { + string ret; + + #if defined(_OPENMP) + ret = "OpenMP"; + #else + ret = "C++11"; + #endif + return ret; } /** @@ -551,4 +564,10 @@ PYBIND11_MODULE(compute_integrals, m) { m.def("compute_integrals_multipole", &compute_integrals_multipole, py::return_value_policy::reference_internal); + + m.def("get_thread_count", &get_thread_count, + py::return_value_policy::reference_internal); + + m.def("get_thread_type", &get_thread_type, + py::return_value_policy::reference_internal); } diff --git a/nanoqm/compute_integrals.pyi b/nanoqm/compute_integrals.pyi index 49e6c8ec8..229829ad4 100644 --- a/nanoqm/compute_integrals.pyi +++ b/nanoqm/compute_integrals.pyi @@ -14,3 +14,7 @@ def compute_integrals_multipole( __basis_name: str, __multipole: str, ) -> npt.NDArray[np.float64]: ... + +def get_thread_count() -> int: ... + +def get_thread_type() -> str: ... diff --git a/nanoqm/integrals/multipole_matrices.py b/nanoqm/integrals/multipole_matrices.py index fb0c0910a..b96ee0907 100644 --- a/nanoqm/integrals/multipole_matrices.py +++ b/nanoqm/integrals/multipole_matrices.py @@ -30,7 +30,7 @@ from .. import logger from ..common import (DictConfig, is_data_in_hdf5, retrieve_hdf5_data, store_arrays_in_hdf5, tuplesXYZ_to_plams) -from ..compute_integrals import compute_integrals_multipole +from ..compute_integrals import compute_integrals_multipole, get_thread_count, get_thread_type if TYPE_CHECKING: from numpy.typing import NDArray @@ -112,6 +112,9 @@ def compute_matrix_multipole( # name of the basis set basis_name = config["cp2k_general_settings"]["basis"] + thread_count = get_thread_count() + thread_type = get_thread_type() + logger.info(f"Will scale over {thread_count} {thread_type} threads") if multipole == 'overlap': matrix_multipole = compute_integrals_multipole( @@ -127,7 +130,6 @@ def compute_matrix_multipole( elif multipole == 'quadrupole': # The tensor contains the overlap + {xx, xy, xz, yy, yz, zz} quadrupole matrices - print("super_matrix: ", path, path_hdf5, basis_name, multipole) super_matrix = compute_integrals_multipole( path, path_hdf5, basis_name, multipole) dim = super_matrix.shape[1] diff --git a/nanoqm/integrals/nonAdiabaticCoupling.py b/nanoqm/integrals/nonAdiabaticCoupling.py index ca05818a4..2dd1c24e6 100644 --- a/nanoqm/integrals/nonAdiabaticCoupling.py +++ b/nanoqm/integrals/nonAdiabaticCoupling.py @@ -35,9 +35,10 @@ import numpy as np +from .. import logger from ..common import (DictConfig, Matrix, MolXYZ, Tensor3D, retrieve_hdf5_data, tuplesXYZ_to_plams) -from ..compute_integrals import compute_integrals_couplings +from ..compute_integrals import compute_integrals_couplings, get_thread_count, get_thread_type def calculate_couplings_3points( @@ -238,6 +239,10 @@ def calcOverlapMtx(config: DictConfig, molecules: Tuple[MolXYZ, MolXYZ]) -> Matr mol_j.write(path_j) basis_name = config["cp2k_general_settings"]["basis"] + + thread_count = get_thread_count() + thread_type = get_thread_type() + logger.info(f"Will scale over {thread_count} {thread_type} threads") try: integrals = compute_integrals_couplings( path_i, path_j, config["path_hdf5"], basis_name) diff --git a/nanoqm/workflows/input_validation.py b/nanoqm/workflows/input_validation.py index a2db1ede9..8d1374e45 100644 --- a/nanoqm/workflows/input_validation.py +++ b/nanoqm/workflows/input_validation.py @@ -80,7 +80,7 @@ def process_input(input_file: PathLike, workflow_name: str) -> DictConfig: except SchemaError as e: msg = f"There was an error in the input yaml provided:\n{e}" - print(msg) + logger.warning(msg) raise diff --git a/nanoqm/workflows/workflow_stddft_spectrum.py b/nanoqm/workflows/workflow_stddft_spectrum.py index b56dbbb4e..ffef8e20c 100644 --- a/nanoqm/workflows/workflow_stddft_spectrum.py +++ b/nanoqm/workflows/workflow_stddft_spectrum.py @@ -496,7 +496,6 @@ def compute_MNOK_integrals(mol, xc_dft): n_atoms = len(mol) r_ab = get_r_ab(mol) hardness_vec = np.stack([hardness(m[0]) for m in mol]).reshape(n_atoms, 1) - print("hardness: ", [m[0].capitalize() for m in mol]) hard = np.add(hardness_vec, hardness_vec.T) beta = xc(xc_dft)['beta1'] + xc(xc_dft)['ax'] * xc(xc_dft)['beta2'] alpha = xc(xc_dft)['alpha1'] + xc(xc_dft)['ax'] * xc(xc_dft)['alpha2'] diff --git a/scripts/hamiltonians/plot_spectra.py b/scripts/hamiltonians/plot_spectra.py index 3a940aa0e..c598b6ebe 100755 --- a/scripts/hamiltonians/plot_spectra.py +++ b/scripts/hamiltonians/plot_spectra.py @@ -28,6 +28,7 @@ import matplotlib.pyplot as plt import numpy as np +from nanoqm import logger from nanoqm.analysis import (autocorrelate, dephasing, read_couplings, read_energies, spectral_density) from nanoqm.common import fs_to_nm @@ -78,11 +79,11 @@ def plot_stuff(ens, coupls, acf, sd, deph, rate, s1, s2, ts, wsd, wdeph, dt): # ax5.plot(sd[:, 1, 0], sd[:, 0, 0], c='r') # ax5.plot(sd[:, 1, 1], sd[:, 0, 1], c='b') ax5.plot(sd[:, 1, 2], sd[:, 0, 2], c='g') - print(f'The dephasing time is : {rate:f} fs') - print(f'The homogenous line broadening is : {1 / rate * fs_to_nm:f} nm') + logger.info(f'The dephasing time is : {rate:f} fs') + logger.info(f'The homogenous line broadening is : {1 / rate * fs_to_nm:f} nm') # Conversion 1 fs = 4.13567 eV lb = 1 / rate * 4.13567 - print(f'The homogenous line broadening is : {lb:f} eV') + logger.info(f'The homogenous line broadening is : {lb:f} eV') ax6 = plt.subplot(322) ax6.set_xlabel('Time (fs)') @@ -90,7 +91,7 @@ def plot_stuff(ens, coupls, acf, sd, deph, rate, s1, s2, ts, wsd, wdeph, dt): ax6.plot(dim_x, coupls[:, s1, s2], c='b') av_coupl = np.average(abs(coupls[:, s1, s2])) ax6.axhline(av_coupl, c="black") - print(f'The average coupling strength is : {av_coupl:f} meV') + logger.info(f'The average coupling strength is : {av_coupl:f} meV') fileName = "MOs.png" plt.savefig(fileName, format='png', dpi=300) diff --git a/scripts/pyxaid/plot_spectra_pyxaid.py b/scripts/pyxaid/plot_spectra_pyxaid.py index baf4426c3..d6d1e39b4 100755 --- a/scripts/pyxaid/plot_spectra_pyxaid.py +++ b/scripts/pyxaid/plot_spectra_pyxaid.py @@ -29,6 +29,7 @@ import numpy as np from matplotlib import interactive +from nanoqm import logger from nanoqm.analysis import autocorrelate, dephasing, spectral_density from nanoqm.common import fs_to_nm @@ -79,9 +80,9 @@ def plot_stuff(ens, acf, sd, deph, rate, s1, s2, dt, wsd, wdeph): plt.xlim(0, wdeph) plt.plot(dim_x, deph[:, 0], c='r') plt.plot(dim_x, deph[:, 1], c='b') - print(f'The dephasing time is : {rate:f} fs') + logger.info(f'The dephasing time is : {rate:f} fs') line_broadening = 1 / rate * fs_to_nm - print(f'The homogenous line broadening is : {line_broadening:f} nm') + logger.info(f'The homogenous line broadening is : {line_broadening:f} nm') interactive(True) plt.show() diff --git a/scripts/qmflows/dos_cp2k.py b/scripts/qmflows/dos_cp2k.py index 01cb35134..f856daef3 100755 --- a/scripts/qmflows/dos_cp2k.py +++ b/scripts/qmflows/dos_cp2k.py @@ -15,6 +15,7 @@ import os from os.path import join +from nanoqm import logger from qmflows import cp2k, run, templates from scm.plams import Molecule @@ -54,7 +55,7 @@ def main(file_xyz, cell, restart, basis, basis_folder): # Output the results # ====================== - print(result.energy) + logger.info(result.energy) def read_cmd_line(parser): diff --git a/scripts/qmflows/opt_anion_cp2k.py b/scripts/qmflows/opt_anion_cp2k.py index 82dc86257..0a4d83c4a 100755 --- a/scripts/qmflows/opt_anion_cp2k.py +++ b/scripts/qmflows/opt_anion_cp2k.py @@ -18,6 +18,8 @@ from os.path import join import os +from nanoqm import logger + def main(file_xyz, cell, restart, basis, basis_folder): """Define which systems need to be calculated.""" @@ -49,7 +51,7 @@ def main(file_xyz, cell, restart, basis, basis_folder): # Output the results # ====================== - print(result.energy) + logger.info(result.energy) def read_cmd_line(parser): diff --git a/scripts/qmflows/opt_cation_cp2k.py b/scripts/qmflows/opt_cation_cp2k.py index 153bdba1b..6da675509 100755 --- a/scripts/qmflows/opt_cation_cp2k.py +++ b/scripts/qmflows/opt_cation_cp2k.py @@ -19,6 +19,8 @@ from os.path import join import os +from nanoqm import logger + def main(file_xyz, cell, restart, basis, basis_folder): """Define which systems need to be calculated.""" @@ -50,7 +52,7 @@ def main(file_xyz, cell, restart, basis, basis_folder): # Output the results # ====================== - print(result.energy) + logger.info(result.energy) def read_cmd_line(parser): diff --git a/scripts/qmflows/opt_cp2k.py b/scripts/qmflows/opt_cp2k.py index 17918a08f..6955ddf02 100755 --- a/scripts/qmflows/opt_cp2k.py +++ b/scripts/qmflows/opt_cp2k.py @@ -18,6 +18,7 @@ from qmflows import cp2k, run, templates from scm.plams import Molecule +from nanoqm import logger def main(file_xyz, cell, restart, basis, basis_folder): @@ -47,7 +48,7 @@ def main(file_xyz, cell, restart, basis, basis_folder): # Output the results # ====================== - print(result.energy) + logger.info(result.energy) def read_cmd_line(parser): diff --git a/scripts/qmflows/plot_dos.py b/scripts/qmflows/plot_dos.py index fc70b7fed..97cb9df94 100755 --- a/scripts/qmflows/plot_dos.py +++ b/scripts/qmflows/plot_dos.py @@ -20,6 +20,8 @@ import numpy as np from matplotlib import interactive +from nanoqm import logger + def readatom(filename): # In the first line in column 6, the atom is defined @@ -92,7 +94,7 @@ def main(group, emin, emax): files = sorted(glob.glob('*-k*.pdos')) # Define the atom type for each DOS file legends = [readatom(files[i]) for i in range(len(files))] - print(files, legends) + logger.info(files, legends) # MO energies energies = np.loadtxt(files[0], usecols=1) # Convert energies to eV @@ -103,7 +105,7 @@ def main(group, emin, emax): lumo_indx = lumos_indx[0][0] homo_indx = lumo_indx - 1 hl_gap = (energies[lumo_indx] - energies[homo_indx]) - print(f'The homo-lumo gap is: {hl_gap} eV') + logger.info(f'The homo-lumo gap is: {hl_gap} eV') # Read Files with PDOS info xs = [np.loadtxt(files[i]) for i in range(len(files))] diff --git a/scripts/qmflows/removeHDF5folders.py b/scripts/qmflows/removeHDF5folders.py index 99f28ab28..2ab94d549 100644 --- a/scripts/qmflows/removeHDF5folders.py +++ b/scripts/qmflows/removeHDF5folders.py @@ -3,6 +3,7 @@ from os.path import join import h5py +from nanoqm import logger def main(path_hdf5: str, remove_overlaps: bool): @@ -20,7 +21,7 @@ def main(path_hdf5: str, remove_overlaps: bool): paths_css = list(filter(lambda x: 'coupling' in x, f5.keys())) paths = paths_css + paths_overlaps_corrected + path_swaps + paths_overlaps for p in (p for p in paths if p in f5): - print("removing: ", p) + logger.info("removing: ", p) del f5[p] diff --git a/scripts/qmflows/remove_mos_hdf5.py b/scripts/qmflows/remove_mos_hdf5.py index 54808485f..5ddc46701 100644 --- a/scripts/qmflows/remove_mos_hdf5.py +++ b/scripts/qmflows/remove_mos_hdf5.py @@ -5,6 +5,8 @@ import h5py import numpy as np +from nanoqm import logger + def main(project_name, path_hdf5, indices, overlap_flag, mo_flag): @@ -27,7 +29,7 @@ def main(project_name, path_hdf5, indices, overlap_flag, mo_flag): with h5py.File(path_hdf5, 'r+') as f5: for p in paths: if p in f5: - print("removing: ", p) + logger.info("removing: ", p) del f5[p] diff --git a/scripts/reenumerate.py b/scripts/reenumerate.py index 32200c08a..747c7268e 100644 --- a/scripts/reenumerate.py +++ b/scripts/reenumerate.py @@ -7,6 +7,7 @@ import h5py +from nanoqm import logger from nanoqm.workflows.distribute_jobs import compute_number_of_geometries msg = "reenumerate.py -n name_project -d directory" @@ -17,7 +18,7 @@ parser.add_argument('-d', help="work directory", default='.') -def create_new_group_names(groups: Iterable[str], index: str) -> List[str]: +def create_new_group_names(groups: Iterable[str], index: int) -> List[str]: """Create new names using index for groups.""" new_names = [] for g in groups: @@ -48,7 +49,7 @@ def rename_groups_in_hdf5(path_hdf5: Path, project: str, index: int) -> None: def reenumerate(project: str, folder_and_hdf5: Tuple[str, str], acc: int) -> int: """Reenumerate hdf5 files in folder using acc.""" folder, hdf5 = folder_and_hdf5 - print(f"Renaming {hdf5} by adding {acc} to the index") + logger.info(f"Renaming {hdf5} by adding {acc} to the index") rename_groups_in_hdf5(Path(hdf5), project, acc) # Count the number of geometries in the chunk diff --git a/test/test_cpk2_error_call.py b/test/test_cpk2_error_call.py index b516e115c..f48f08981 100644 --- a/test/test_cpk2_error_call.py +++ b/test/test_cpk2_error_call.py @@ -3,6 +3,7 @@ from pathlib import Path import pytest +from assertionlib import assertion from nanoqm.schedule.scheduleCP2K import try_to_read_wf @@ -16,5 +17,4 @@ def test_cp2k_call_error(tmp_path: Path): try_to_read_wf(tmp_path) error = info.value.args[0] - print(error) - assert "CP2K error" in error + assertion.contains(error, "CP2K error") diff --git a/test/test_distribute.py b/test/test_distribute.py index 641e3053a..0be8aff63 100644 --- a/test/test_distribute.py +++ b/test/test_distribute.py @@ -33,15 +33,14 @@ def check_scripts() -> None: # Check that the files are created correctly files = ["launch.sh", "chunk_xyz*", "input.yml"] - for p in paths: - p = Path(p) + for _p in paths: + p = Path(_p) for f in files: try: next(p.glob(f)) except StopIteration: - msg = f"There is not file: {f}" - print(msg) - raise RuntimeError(msg) + msg = f"There is no such file: {f!r}" + raise RuntimeError(msg) from None def remove_chunk_folder() -> None: diff --git a/test/test_workflow_IPR.py b/test/test_workflow_IPR.py index 1ec4d3fa2..3fccf0338 100644 --- a/test/test_workflow_IPR.py +++ b/test/test_workflow_IPR.py @@ -3,8 +3,7 @@ import shutil import sys from os.path import join - -from qmflows.type_hints import PathLike +from pathlib import Path from nanoqm.workflows.input_validation import process_input from nanoqm.workflows.workflow_ipr import workflow_ipr @@ -12,7 +11,7 @@ from .utilsTest import PATH_TEST -def test_workflow_IPR(tmp_path: PathLike) -> None: +def test_workflow_IPR(tmp_path: Path) -> None: """Test the Inverse Participation Ratio workflow.""" file_path = PATH_TEST / 'input_test_IPR.yml' config = process_input(file_path, 'ipr_calculation') @@ -24,7 +23,5 @@ def test_workflow_IPR(tmp_path: PathLike) -> None: try: workflow_ipr(config) os.remove("IPR.txt") - except BaseException: - print("scratch_path: ", tmp_path) - print("Unexpected error:", sys.exc_info()[0]) - raise + except Exception as ex: + raise AssertionError(f"Unxpected error for scratch_path {tmp_path!r}") from ex diff --git a/test/test_workflow_coop.py b/test/test_workflow_coop.py index 8c9d74571..729457eaf 100644 --- a/test/test_workflow_coop.py +++ b/test/test_workflow_coop.py @@ -2,10 +2,9 @@ import os import shutil import sys +from pathlib import Path from os.path import join -from qmflows.type_hints import PathLike - from nanoqm.workflows.input_validation import process_input from nanoqm.workflows.workflow_coop import \ workflow_crystal_orbital_overlap_population @@ -13,7 +12,7 @@ from .utilsTest import PATH_TEST -def test_workflow_coop(tmp_path: PathLike) -> None: +def test_workflow_coop(tmp_path: Path) -> None: """Test the Crystal Orbital Overlap Population workflow.""" file_path = PATH_TEST / 'input_test_coop.yml' config = process_input(file_path, 'coop_calculation') @@ -25,7 +24,5 @@ def test_workflow_coop(tmp_path: PathLike) -> None: try: workflow_crystal_orbital_overlap_population(config) os.remove("COOP.txt") - except BaseException: - print("scratch_path: ", tmp_path) - print("Unexpected error:", sys.exc_info()[0]) - raise + except Exception as ex: + raise AssertionError(f"Unxpected error for scratch_path {tmp_path!r}") from ex diff --git a/test/test_workflow_single_points.py b/test/test_workflow_single_points.py index bd3921e60..25b5e823f 100644 --- a/test/test_workflow_single_points.py +++ b/test/test_workflow_single_points.py @@ -22,8 +22,6 @@ def run_single_point(tmp_path: Path, input_file: str): Path(tmp_hdf5).touch() try: path_orbitals, path_energies = workflow_single_points(config) - print("path_orbitals: ", path_orbitals) - print("path_energies: ", path_energies) if config["compute_orbitals"]: assertion.truth(is_data_in_hdf5(tmp_hdf5, path_orbitals[0])) finally: From 35008dc57f99a5ab8f3ca60ca434784476fb0a6c Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Wed, 13 Apr 2022 17:30:51 +0200 Subject: [PATCH 08/11] TST: Add `ipython` to the test requirements --- setup.py | 1 + test_requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/setup.py b/setup.py index 07e1c3267..c4b59d281 100644 --- a/setup.py +++ b/setup.py @@ -186,6 +186,7 @@ def build_extensions(self) -> None: 'pytest-mock', 'Cython', 'setuptools', + 'ipython', ], 'doc': ['sphinx>=2.1', 'sphinx-autodoc-typehints', 'sphinx_rtd_theme', 'nbsphinx'] }, diff --git a/test_requirements.txt b/test_requirements.txt index 5e79cda12..d8530f96a 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -6,6 +6,7 @@ pytest-cov pytest-mock Cython setuptools +ipython # Runtime dependencies h5py From 5a006f493df2703213c0c328027a56aeb771b5da Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 14 Apr 2022 11:49:03 +0200 Subject: [PATCH 09/11] BUG: Fix the exponent vector not being properly sliced for basis sets with multiple exponent sets --- libint/compute_integrals.cc | 58 +++++++++++++++++--------------- libint/include/namd.hpp | 4 +-- test/test_files/test_files.hdf5 | Bin 84256 -> 84256 bytes 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/libint/compute_integrals.cc b/libint/compute_integrals.cc index 1709c0aa1..82a834c49 100644 --- a/libint/compute_integrals.cc +++ b/libint/compute_integrals.cc @@ -300,13 +300,9 @@ std::vector compute_multipoles( CP2K_Basis_Atom read_basis_from_hdf5(const string &path_file, const string &symbol, const string &basis) { - std::vector> coefficients; - std::vector exponents; - std::vector format; - - libint2::svector small_exp; + libint2::svector> small_exp; libint2::svector> small_coef; - libint2::svector small_fmt; + libint2::svector> small_fmt; try { // Open an existing HDF5 File @@ -323,6 +319,10 @@ CP2K_Basis_Atom read_basis_from_hdf5(const string &path_file, // only a single set of exponents, but there are exception such // as BASIS_ADMM_MOLOPT for (const auto &name : dset_names) { + std::vector> coefficients; + std::vector exponents; + std::vector format; + const string path_coefficients = root + "/" + name + "/coefficients"; const string path_exponents = root + "/" + name + "/exponents"; @@ -336,14 +336,16 @@ CP2K_Basis_Atom read_basis_from_hdf5(const string &path_file, dataset_es.read(exponents); attr.read(format); - // Move data to small vectors and keep extending them as iteration - // over `dset_names` continues - std::move(exponents.begin(), exponents.end(), std::back_inserter(small_exp)); + // Move data to small vectors and keep appending or extending them as + // iteration over `dset_names` continues + libint2::svector small_exp_1d; + std::move(exponents.begin(), exponents.end(), std::back_inserter(small_exp_1d)); + small_exp.push_back(small_exp_1d); for (const auto &v : coefficients) { - libint2::svector small; - std::move(v.begin(), v.end(), std::back_inserter(small)); - small_coef.push_back(small); + libint2::svector small_coef_1d; + std::move(v.begin(), v.end(), std::back_inserter(small_coef_1d)); + small_coef.push_back(small_coef_1d); } // The CP2K basis format is defined by a vector of integers, for each atom. @@ -362,15 +364,12 @@ CP2K_Basis_Atom read_basis_from_hdf5(const string &path_file, // Note: Elements 4 and onwards define the number of contracted for each // angular momentum quantum number (all prior elements are disgarded). int l, i; + libint2::svector small_fmt_1d; for (i=4, l=format[1]; i != static_cast(format.size()); i++, l++) { int count = format[i]; - small_fmt.push_back(CP2K_Contractions{l, count}); + small_fmt_1d.push_back({l, count}); } - - // Clear the temp vectors for the next iteration cycle - coefficients.clear(); - exponents.clear(); - format.clear(); + small_fmt.push_back(small_fmt_1d); } } catch (HighFive::Exception &err) { // catch and print any HDF5 error @@ -418,18 +417,23 @@ create_map_symbols_basis(const string &path_hdf5, */ libint2::svector create_shells_for_atom(const CP2K_Basis_Atom &data, const Atom &atom) { - libint2::svector basis_format = data.basis_format; libint2::svector shells; + libint2::svector exponents; + libint2::svector basis_format; int acc = 0; - for (auto contractions : basis_format) { - for (int i = 0; i < contractions.count; i++) { - shells.push_back({ - data.exponents, - {{contractions.l, true, data.coefficients[acc]}}, // compute integrals in sphericals - {{atom.x, atom.y, atom.z}} // Atomic Coordinates - }); - acc += 1; + for (int i = 0; i != static_cast(data.exponents.size()); i++) { + exponents = data.exponents[i]; + basis_format = data.basis_format[i]; + for (auto contractions : basis_format) { + for (int j = 0; j < contractions.count; j++) { + shells.push_back({ + exponents, + {{contractions.l, true, data.coefficients[acc]}}, // compute integrals in sphericals + {{atom.x, atom.y, atom.z}} // Atomic Coordinates + }); + acc += 1; + } } } return shells; diff --git a/libint/include/namd.hpp b/libint/include/namd.hpp index 81effc7b4..5ea3ff12e 100644 --- a/libint/include/namd.hpp +++ b/libint/include/namd.hpp @@ -57,8 +57,8 @@ struct CP2K_Basis_Atom { // Contains the basis specificationf for a given atom std::string symbol; libint2::svector> coefficients; - libint2::svector exponents; - libint2::svector basis_format; + libint2::svector> exponents; + libint2::svector> basis_format; }; // Map from atomic_number to symbol diff --git a/test/test_files/test_files.hdf5 b/test/test_files/test_files.hdf5 index bc5385948704743698de9b8fe8face732189faea..d4c367b7097619ba3a2633a561707bca358cb778 100644 GIT binary patch delta 336 zcmZ25iFLsw)(tH;MQ-IN+cO{m5P$N7dg;mUUyDzE_gZ4|y=OuauRnaXLsA1~if|a( lPu!@%0g{8TMKo}!gXu-6b--h$1d^Ewn+0ySxTc%oHkrYlSWrnJ8mD naiazYNDjgl(ZHn+rWc{sK?0ZBi5n%5%v9JcaJwaED0=_^9l215 From a4f2933c76c5f2c7273c1dfa49877e02f8b816cf Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 14 Apr 2022 12:01:54 +0200 Subject: [PATCH 10/11] MAINT: Remove usage of `pkg_resources` as `setuptools` is not a runtime dependency --- .github/workflows/pythonapp.yml | 2 +- nanoqm/common.py | 11 ++++++----- nanoqm/workflows/initialization.py | 1 - scripts/qmflows/coordination_ldos.py | 7 +++---- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index f472cabce..508db945b 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -167,7 +167,7 @@ jobs: python-version: "3.10" - name: Install linters - run: pip install pydocstyle pycodestyle mypy qmflows "numpy>=1.21" types-pyyaml types-pkg_resources types-setuptools "pyparsing>=3.0.8" + run: pip install pydocstyle pycodestyle mypy qmflows "numpy>=1.21" types-pyyaml types-setuptools "pyparsing>=3.0.8" - name: Python info run: | diff --git a/nanoqm/common.py b/nanoqm/common.py index 401c0442f..d617db9ac 100644 --- a/nanoqm/common.py +++ b/nanoqm/common.py @@ -32,11 +32,11 @@ import os import json -from itertools import chain, repeat +from itertools import chain +from pathlib import Path from typing import (Any, Dict, Iterable, List, Mapping, NamedTuple, Tuple, Sequence, overload, TypeVar, TYPE_CHECKING, Iterator) -import pkg_resources as pkg import h5py import mendeleev import numpy as np @@ -46,15 +46,16 @@ from scm.plams import Atom, Molecule from qmflows.yaml_utils import UniqueSafeLoader +from . import __path__ as nanoqm_path if TYPE_CHECKING: import numpy.typing as npt _T = TypeVar("_T") -_path_valence_electrons = pkg.resource_filename( - "nanoqm", "basis/valence_electrons.json") -_path_aux_fit = pkg.resource_filename("nanoqm", "basis/aux_fit.json") + +_path_valence_electrons = Path(nanoqm_path[0]) / "basis" / "valence_electrons.json" +_path_aux_fit = Path(nanoqm_path[0]) / "basis" / "aux_fit.json" with open(_path_valence_electrons, 'r') as f1, open(_path_aux_fit, 'r') as f2: valence_electrons: "dict[str, int]" = json.load(f1) diff --git a/nanoqm/workflows/initialization.py b/nanoqm/workflows/initialization.py index 3d45852e5..92f582967 100644 --- a/nanoqm/workflows/initialization.py +++ b/nanoqm/workflows/initialization.py @@ -30,7 +30,6 @@ import h5py import numpy as np -import pkg_resources import qmflows from nanoutils import RecursiveItemsView from packaging.version import Version diff --git a/scripts/qmflows/coordination_ldos.py b/scripts/qmflows/coordination_ldos.py index ffee09211..1b0a41a94 100644 --- a/scripts/qmflows/coordination_ldos.py +++ b/scripts/qmflows/coordination_ldos.py @@ -7,12 +7,11 @@ import os from typing import Dict, List -import pkg_resources from nanoCAT.recipes import coordination_number from qmflows import Settings, cp2k, run, templates from scm.plams import Molecule -from nanoqm import logger +from nanoqm import logger, __path__ as nanoqm_path from nanoqm._logger import EnableFileHandler from nanoqm.workflows.templates import generate_kinds @@ -27,8 +26,8 @@ def create_cp2k_settings(mol: Molecule) -> Settings: """Create CP2K general settings.""" # Set path for basis set - path_basis = pkg_resources.resource_filename("nanoqm", "basis/BASIS_MOLOPT") - path_potential = pkg_resources.resource_filename("nanoqm", "basis/GTH_POTENTIALS") + path_basis = os.path.join(nanoqm_path[0], "basis", "BASIS_MOLOPT") + path_potential = os.path.join(nanoqm_path[0], "basis", "GTH_POTENTIALS") # Settings specifics s = Settings() From 009777b3aaed15a083bfccbc7657840e90439432 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Tue, 19 Apr 2022 13:43:20 +0200 Subject: [PATCH 11/11] TST: Use a less strict tolerance for single-precision floating point comparisons --- test/test_coupling.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_coupling.py b/test/test_coupling.py index 5c0e45872..30911dc4a 100644 --- a/test/test_coupling.py +++ b/test/test_coupling.py @@ -107,8 +107,8 @@ def create_paths(keyword: str) -> list: with h5py.File(PATH_TEST / "test_files.hdf5", "r") as f: ref_couplings = f[f"test_coupling/TestCoupling/{name}/couplings"][...] ref_overlaps = f[f"test_coupling/TestCoupling/{name}/overlaps"][...] - np.testing.assert_allclose(couplings, ref_couplings, rtol=0, atol=1e-7) - np.testing.assert_allclose(overlaps, ref_overlaps, rtol=0, atol=1e-7) + np.testing.assert_allclose(couplings, ref_couplings, rtol=0, atol=1e-06) + np.testing.assert_allclose(overlaps, ref_overlaps, rtol=0, atol=1e-06) def test_hamiltonians(self, output: CouplingsOutput) -> None: if len(output.hamiltonians) == 1: @@ -137,5 +137,5 @@ def _test_hamiltonians(self, hamiltonians: Sequence[str], name: str, suffix: str with h5py.File(PATH_TEST / "test_files.hdf5", "r") as f: ref_energies = f[f"test_coupling/TestCoupling/{name}/txt_energies"][...] ref_couplings = f[f"test_coupling/TestCoupling/{name}/txt_couplings"][...] - np.testing.assert_allclose(energies, ref_energies, rtol=0, atol=1e-7) - np.testing.assert_allclose(couplings, ref_couplings, rtol=0, atol=1e-7) + np.testing.assert_allclose(energies, ref_energies, rtol=0, atol=1e-06) + np.testing.assert_allclose(couplings, ref_couplings, rtol=0, atol=1e-06)