From b22fad16e954fc42bda6574507a1cbdff3d383f8 Mon Sep 17 00:00:00 2001 From: LSMO Date: Tue, 22 Nov 2022 20:24:07 +0100 Subject: [PATCH 1/3] First attempts at fixing CI --- .docker/raspa-code.yml | 5 ++++- Dockerfile | 9 +++++++-- setup.json | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.docker/raspa-code.yml b/.docker/raspa-code.yml index ce79e17..ad37aae 100644 --- a/.docker/raspa-code.yml +++ b/.docker/raspa-code.yml @@ -5,4 +5,7 @@ input_plugin: raspa on_computer: True remote_abs_path: /opt/RASPA2_installed/bin/simulate append_text: -prepend_text: export RASPA2_DIR=/opt/RASPA2_installed/ +prepend_text: | + export RASPA_DIR=/opt/RASPA2_installed/ + export DYLD_LIBRARY_PATH=/opt/RASPA2_installed/lib + export LD_LIBRARY_PATH=/opt/RASPA2_installed/lib diff --git a/Dockerfile b/Dockerfile index e165b36..c58e444 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM aiidateam/aiida-core:latest +FROM aiidateam/aiida-core:1.6.9 # Set HOME, PATH and RASPA_DIR variables: ENV PATH="/opt/RASPA2_installed/bin/:${PATH}" @@ -12,7 +12,7 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* && apt-get update && apt-get in # Download, compile and install RASPA into ~/code folder. WORKDIR /opt/ -RUN git clone --depth 1 --branch v2.0.41 https://github.com/iRASPA/RASPA2.git RASPA2 +RUN git clone --depth 1 --branch v2.0.47 https://github.com/iRASPA/RASPA2.git RASPA2 WORKDIR /opt/RASPA2 RUN rm -rf autom4te.cache RUN mkdir m4 @@ -26,6 +26,11 @@ RUN make install WORKDIR /opt/ +# Grab the raspa data files from the aiida-lsmo-codes repository +RUN git clone https://github.com/lsmo-epfl/aiida-lsmo-codes.git +RUN rsync -av /opt/aiida-lsmo-codes/data/raspa/ /opt/RASPA2_installed +RUN rm -rf aiida-lsmo-codes + # Install coveralls. RUN pip install coveralls diff --git a/setup.json b/setup.json index f416b97..5a6f862 100644 --- a/setup.json +++ b/setup.json @@ -15,7 +15,7 @@ "setup_requires": ["reentry"], "reentry_register": true, "install_requires": [ - "aiida-core>=1.0.0,<3", + "aiida-core>=1.0.0,<2", "pycifrw" ], "entry_points": { From 04b99cf9faade4e8ae3a70fa1e551b2756c768ee Mon Sep 17 00:00:00 2001 From: LSMO Date: Tue, 22 Nov 2022 20:46:42 +0100 Subject: [PATCH 2/3] Specify langauge for docs conf.py --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index dcc2b11..6222fa2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -101,7 +101,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: From 1b833628301caded9eaf55b9d363eb613245910b Mon Sep 17 00:00:00 2001 From: Miriam Pougin Date: Fri, 25 Aug 2023 23:02:59 +0200 Subject: [PATCH 3/3] Add support for `aiida-core==2.X` --- .ci/check_travis_tag.py | 24 - .coveragerc | 2 - .github/workflows/ci.yml | 157 ++--- .github/workflows/run_examples.sh | 7 + .gitignore | 4 +- .pre-commit-config.yaml | 41 +- .style.yapf | 3 - Dockerfile | 7 +- MANIFEST.in | 1 - README.md | 4 +- aiida_raspa/__init__.py | 1 - aiida_raspa/calculations/__init__.py | 219 +++--- aiida_raspa/parsers/__init__.py | 33 +- aiida_raspa/utils/__init__.py | 9 +- aiida_raspa/utils/base_input_generator.py | 37 +- aiida_raspa/utils/base_parser.py | 390 +++++------ aiida_raspa/utils/inspection_tools.py | 12 +- aiida_raspa/workchains/__init__.py | 1 - aiida_raspa/workchains/base.py | 86 ++- conftest.py | 5 +- docs/source/conf.py | 296 ++++---- examples/simple_calculations/example_base.py | 32 +- .../example_base_restart.py | 50 +- .../example_binary_mixture.py | 24 +- ...le_block_pockets_2frameworks_2molecules.py | 63 +- .../example_block_pockets_simple.py | 43 +- .../simple_calculations/example_ff_files.py | 46 +- .../example_framework_box.py | 38 +- .../example_framework_box_restart.py | 36 +- .../example_gemc_single_comp.py | 32 +- .../example_gemc_single_comp_restart.py | 34 +- examples/simple_calculations/example_henry.py | 30 +- .../simple_calculations/example_identity.py | 28 +- .../fixme_base_binary_restart.py | 26 +- .../example_base_restart_timeout.py | 21 +- .../example_base_workchain_gcmc_2comp.py | 26 +- .../example_base_workchain_widom_1comp.py | 24 +- .../example_base_workchain_widom_2comp.py | 26 +- .../too_long_base_workchain_gemc_1comp.py | 27 +- pyproject.toml | 118 +++- setup.json | 55 -- setup.py | 20 - tests/test_input_generator.py | 5 +- tests/test_output_parser.py | 640 +++++++++--------- tests/test_version_agreement.py | 18 - 45 files changed, 1421 insertions(+), 1380 deletions(-) delete mode 100755 .ci/check_travis_tag.py delete mode 100644 .coveragerc create mode 100644 .github/workflows/run_examples.sh delete mode 100644 .style.yapf delete mode 100644 MANIFEST.in delete mode 100644 setup.json delete mode 100644 setup.py delete mode 100644 tests/test_version_agreement.py diff --git a/.ci/check_travis_tag.py b/.ci/check_travis_tag.py deleted file mode 100755 index d87eb2e..0000000 --- a/.ci/check_travis_tag.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# pylint: disable=invalid-name -############################################################################### -# Copyright (c), The AiiDA-CP2K authors. # -# SPDX-License-Identifier: MIT # -# AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k # -# For further information on the license, see the LICENSE.txt file. # -############################################################################### -"""Check travis tag""" - -import os -import sys -import json - -a = os.getenv("TRAVIS_TAG") -with open("setup.json") as fhandle: - b = "v{version}".format(**json.load(fhandle)) - -if not a: - print("TRAVIS_TAG not set") - -elif a != b: - print("ERROR: TRAVIS_TAG and version are inconsistent: '{}' vs '{}'".format(a, b)) - sys.exit(3) diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 08df515..0000000 --- a/.coveragerc +++ /dev/null @@ -1,2 +0,0 @@ -[run] -parallel=True diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7beaa2..9afc90f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,98 +1,103 @@ -name: Continuous Integration +name: CI on: [push, pull_request] jobs: - test-plugin: + tests: + name: Test Suite + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + + - name: Check out repository + uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install python dependencies + run: | + pip install --upgrade pip + pip install -e .[tests] + + - name: Run test suite + run: pytest + + examples: + name: Run examples runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - # see https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache - - name: Cache Docker layers - uses: actions/cache@v2 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- - - - name: Build #and push - uses: docker/build-push-action@v2 - with: - context: . - push: false - load: true - tags: aiida_raspa_test - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new - - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 - - name: Move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache - - - name: Run tests - run: | - export DOCKERID=`docker run -d aiida_raspa_test` - docker exec --tty $DOCKERID wait-for-services - docker logs $DOCKERID - docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'cd /opt/aiida-raspa/ && py.test --cov aiida_raspa --cov-append .' - # see https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables - docker exec --tty --user aiida --env-file <(env | grep GITHUB_) -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} $DOCKERID /bin/bash -l -c 'cd /opt/aiida-raspa/ && coveralls --service=github' + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build #and push + uses: docker/build-push-action@v2 + with: + context: . + push: false + load: true + tags: aiida_raspa_test + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Run examples + run: | # Examples stored and copied from .github/workflows/run_examples.sh + export DOCKERID=`docker run -d aiida_raspa_test` + docker exec --tty $DOCKERID wait-for-services + docker logs $DOCKERID + docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'cd $HOME; bash run_examples.sh' pre-commit: runs-on: ubuntu-latest timeout-minutes: 10 - strategy: - matrix: - python-version: [3.8] + steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install python dependencies - run: | - pip install --upgrade pip - pip install -e .[pre-commit,test,docs] - reentry scan - - name: Run pre-commit - run: | - pre-commit install - pre-commit run --all-files || ( git status --short ; git diff ; exit 1 ) + + - uses: actions/checkout@v3 + + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install python dependencies + run: | + pip install --upgrade pip + pip install -e .[pre-commit,tests,docs] + + - name: Run pre-commit + run: | + pre-commit install + pre-commit run --all-files || ( git status --short ; git diff ; exit 1 ) docs: runs-on: ubuntu-latest timeout-minutes: 10 - strategy: - matrix: - python-version: [3.8] + steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install python dependencies - run: | - pip install --upgrade pip - pip install -e .[docs,test] - reentry scan - - - name: Build docs - run: | - cd docs && make + + - uses: actions/checkout@v3 + + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install python dependencies + run: | + pip install --upgrade pip + pip install -e .[docs] + + - name: Build docs + run: | + make -C docs html diff --git a/.github/workflows/run_examples.sh b/.github/workflows/run_examples.sh new file mode 100644 index 0000000..a88efdf --- /dev/null +++ b/.github/workflows/run_examples.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +verdi run /opt/aiida-raspa/examples/simple_calculations/example_base.py --submit raspa +verdi run /opt/aiida-raspa/examples/simple_calculations/example_base_restart.py --previous_calc 4 --submit raspa +verdi run /opt/aiida-raspa/examples/simple_calculations/example_binary_mixture.py --submit raspa +verdi run /opt/aiida-raspa/examples/simple_calculations/example_block_pockets_2frameworks_2molecules.py --submit raspa +verdi run /opt/aiida-raspa/examples/simple_calculations/example_block_pockets_simple.py --submit raspa diff --git a/.gitignore b/.gitignore index b76a094..0dfe651 100644 --- a/.gitignore +++ b/.gitignore @@ -271,4 +271,6 @@ tags [._]*.un~ # End of https://www.gitignore.io/api/vim,linux,macos,python,pycharm -submit_test \ No newline at end of file +submit_test + +.vscode diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7565b92..5b02839 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,26 +2,25 @@ # pre-commit install repos: -- repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.30.0 - hooks: - # yapf = yet another python formatter - - id: yapf - name: yapf - types: [python] - exclude: > - (?x)^( - docs/.*| - )$ - args: ['-i'] + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort -- repo: local - hooks: - # yapf = yet another python formatter + - repo: https://github.com/psf/black + rev: 23.7.0 + hooks: + - id: black + # It is recommended to specify the latest version of Python + # supported by your project here, or alternatively use + # pre-commit's default_language_version, see + # https://pre-commit.com/#top_level-default_language_version + language_version: python3.10 - # prospector: collection of linters - - id: pylint - language: system - types: [file, python] - name: pylint - entry: pylint + - repo: local + hooks: + - id: pylint + language: system + types: [file, python] + name: pylint + entry: pylint diff --git a/.style.yapf b/.style.yapf deleted file mode 100644 index b3d849f..0000000 --- a/.style.yapf +++ /dev/null @@ -1,3 +0,0 @@ -[style] -based_on_style = google -column_limit = 120 diff --git a/Dockerfile b/Dockerfile index c58e444..26e2cb8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM aiidateam/aiida-core:1.6.9 +FROM aiidateam/aiida-core:2.3.1 # Set HOME, PATH and RASPA_DIR variables: ENV PATH="/opt/RASPA2_installed/bin/:${PATH}" @@ -36,8 +36,11 @@ RUN pip install coveralls # Copy and install aiida-raspa plugin. COPY . aiida-raspa -RUN pip install ./aiida-raspa[pre-commit,test,docs] +RUN pip install -e aiida-raspa[pre-commit,tests,docs] # Install the RASPA code to AiiDA. COPY .docker/opt/add-codes.sh /opt/ COPY .docker/my_init.d/add-codes.sh /etc/my_init.d/50_add-codes.sh + +# COPY the examples test script +COPY .github/workflows/run_examples.sh /home/aiida/run_examples.sh diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index d2ce702..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include setup.json diff --git a/README.md b/README.md index 0526868..443a7e9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -[![Build Status](https://travis-ci.org/yakutovicha/aiida-raspa.svg?branch=develop)](https://travis-ci.org/yakutovicha/aiida-raspa) -[![Coverage Status](https://coveralls.io/repos/github/yakutovicha/aiida-raspa/badge.svg?branch=develop)](https://coveralls.io/github/yakutovicha/aiida-raspa?branch=develop) +![Build Status](https://github.com/lsmo-epfl/aiida-raspa/actions/workflows/ci.yml/badge.svg) [![PyPI version](https://badge.fury.io/py/aiida-raspa.svg)](https://badge.fury.io/py/aiida-raspa) # AiiDA RASPA @@ -10,7 +9,6 @@ Designed to work with with RASPA 2.0.37 or later. # Documentation The documentation for this package can be found on [Read the Docs](https://aiida-raspa.readthedocs.io/en/latest/). - # Installation If you use ``pip``, you can install it as: ``` diff --git a/aiida_raspa/__init__.py b/aiida_raspa/__init__.py index 42a0d49..9dc97d7 100644 --- a/aiida_raspa/__init__.py +++ b/aiida_raspa/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ############################################################################## # Copyright (c), The AiiDA team. All rights reserved. # # This file is part of the AiiDA code. # diff --git a/aiida_raspa/calculations/__init__.py b/aiida_raspa/calculations/__init__.py index a6b6518..91bfc5a 100644 --- a/aiida_raspa/calculations/__init__.py +++ b/aiida_raspa/calculations/__init__.py @@ -1,81 +1,96 @@ -# -*- coding: utf-8 -*- """Raspa input plugin.""" import os +from pathlib import Path from shutil import copyfile, copytree -from aiida.orm import Dict, FolderData, List, RemoteData, SinglefileData from aiida.common import CalcInfo, CodeInfo, InputValidationError -#from aiida.cmdline.utils import echo + +# from aiida.cmdline.utils import echo from aiida.engine import CalcJob +from aiida.orm import Dict, FolderData, List, RemoteData, SinglefileData from aiida.plugins import DataFactory from aiida_raspa.utils import RaspaInput # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("core.cif") # pylint: disable=invalid-name class RaspaCalculation(CalcJob): """This is a RaspaCalculation, subclass of CalcJob, to prepare input for RASPA code. For information on RASPA, refer to: https://github.com/iraspa/raspa2. """ + # Defaults - INPUT_FILE = 'simulation.input' - OUTPUT_FOLDER = 'Output' - RESTART_FOLDER = 'Restart' - PROJECT_NAME = 'aiida' - DEFAULT_PARSER = 'raspa' + INPUT_FILE = "simulation.input" + OUTPUT_FOLDER = "Output" + RESTART_FOLDER = "Restart" + PROJECT_NAME = "aiida" + DEFAULT_PARSER = "raspa" @classmethod def define(cls, spec): super().define(spec) - #Input parameters - spec.input('parameters', valid_type=Dict, required=True, help='Input parameters') - spec.input_namespace('framework', valid_type=CifData, required=False, dynamic=True, help='Input framework(s)') - spec.input_namespace('block_pocket', - valid_type=SinglefileData, - required=False, - dynamic=True, - help='Zeo++ block pocket file') - spec.input_namespace('file', - valid_type=SinglefileData, - required=False, - dynamic=True, - help='Additional input file(s)') - spec.input('settings', valid_type=Dict, required=False, help='Additional input parameters') - spec.input('parent_folder', - valid_type=RemoteData, - required=False, - help='Remote folder used to continue the same simulation stating from the binary restarts.') - spec.input('retrieved_parent_folder', - valid_type=FolderData, - required=False, - help='To use an old calculation as a starting poing for a new one.') - spec.inputs['metadata']['options']['parser_name'].default = cls.DEFAULT_PARSER - spec.inputs['metadata']['options']['resources'].default = { - 'num_machines': 1, - 'num_mpiprocs_per_machine': 1, - 'num_cores_per_mpiproc': 1, + # Input parameters + spec.input("parameters", valid_type=Dict, required=True, help="Input parameters") + spec.input_namespace("framework", valid_type=CifData, required=False, dynamic=True, help="Input framework(s)") + spec.input_namespace( + "block_pocket", valid_type=SinglefileData, required=False, dynamic=True, help="Zeo++ block pocket file" + ) + spec.input_namespace( + "file", valid_type=SinglefileData, required=False, dynamic=True, help="Additional input file(s)" + ) + spec.input("settings", valid_type=Dict, required=False, help="Additional input parameters") + spec.input( + "parent_folder", + valid_type=RemoteData, + required=False, + help="Remote folder used to continue the same simulation stating from the binary restarts.", + ) + spec.input( + "retrieved_parent_folder", + valid_type=FolderData, + required=False, + help="To use an old calculation as a starting poing for a new one.", + validator=cls.validate_retrieved_parent_folder, + ) + spec.inputs["metadata"]["options"]["parser_name"].default = cls.DEFAULT_PARSER + spec.inputs["metadata"]["options"]["resources"].default = { + "num_machines": 1, + "num_mpiprocs_per_machine": 1, + "num_cores_per_mpiproc": 1, } - spec.inputs['metadata']['options']['withmpi'].default = False + spec.inputs["metadata"]["options"]["withmpi"].default = False # Output parameters - spec.output('output_parameters', valid_type=Dict, required=True, help="The results of a calculation") - spec.output('warnings', valid_type=List, required=False, help="Warnings that appeared during the calculation") + spec.output("output_parameters", valid_type=Dict, required=True, help="The results of a calculation") + spec.output("warnings", valid_type=List, required=False, help="Warnings that appeared during the calculation") # Exit codes - spec.exit_code(100, - 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') - spec.exit_code(101, 'ERROR_NO_OUTPUT_FILE', message='The retrieved folder does not contain an output file.') - spec.exit_code(102, - 'ERROR_SIMULATION_DID_NOT_START', - message='The output does not contain "Starting simulation".') - spec.exit_code(500, 'TIMEOUT', message='The calculation could not be completed due to the lack of time.') + spec.exit_code( + 100, "ERROR_NO_RETRIEVED_FOLDER", message="The retrieved folder data node could not be accessed." + ) + spec.exit_code(101, "ERROR_NO_OUTPUT_FILE", message="The retrieved folder does not contain an output file.") + spec.exit_code( + 102, "ERROR_SIMULATION_DID_NOT_START", message='The output does not contain "Starting simulation".' + ) + spec.exit_code(500, "TIMEOUT", message="The calculation could not be completed due to the lack of time.") # Default output node - spec.default_output_node = 'output_parameters' + spec.default_output_node = "output_parameters" + + @staticmethod + def validate_retrieved_parent_folder(value, _): + """Validate the `retrieved_parent_folder` input.""" + + repository = value.base.repository + + if "Restart" not in repository.list_object_names(): + return "Restart was requested but the restart folder was not found in the previous calculation." + for system_path in repository.list_object_names("Restart"): + if len(repository.list_object_names(Path("Restart") / system_path)) != 1: + return "There was more than one file in a system directory of the `Restart` directory." # -------------------------------------------------------------------------- # pylint: disable = too-many-locals @@ -96,64 +111,71 @@ def prepare_for_submission(self, folder): inp = RaspaInput(self.inputs.parameters.get_dict()) # keep order of systems in the extras - self.node.set_extra('system_order', inp.system_order) + self.node.set_extra("system_order", inp.system_order) # handle framework(s) and/or box(es) if "System" in inp.params: self._handle_system_section(inp.params["System"], folder) # handle restart - if 'retrieved_parent_folder' in self.inputs: - self._handle_retrieved_parent_folder(inp, folder) - inp.params['GeneralSettings']['RestartFile'] = True + if "retrieved_parent_folder" in self.inputs: + calcinfo.local_copy_list.extend(self._handle_retrieved_parent_folder(inp)) + inp.params["GeneralSettings"]["RestartFile"] = True # handle binary restart - if 'parent_folder' in self.inputs: - inp.params['GeneralSettings']['ContinueAfterCrash'] = True - calcinfo.remote_copy_list.append((self.inputs.parent_folder.computer.uuid, - os.path.join(self.inputs.parent_folder.get_remote_path(), - 'CrashRestart'), 'CrashRestart')) + if "parent_folder" in self.inputs: + inp.params["GeneralSettings"]["ContinueAfterCrash"] = True + calcinfo.remote_copy_list.append( + ( + self.inputs.parent_folder.computer.uuid, + os.path.join(self.inputs.parent_folder.get_remote_path(), "CrashRestart"), + "CrashRestart", + ) + ) # get settings - if 'settings' in self.inputs: + if "settings" in self.inputs: settings = self.inputs.settings.get_dict() else: settings = {} # write raspa input file - with open(folder.get_abs_path(self.INPUT_FILE), "w") as fobj: + with open(folder.get_abs_path(self.INPUT_FILE), "w", encoding="utf-8") as fobj: fobj.write(inp.render()) # create code info codeinfo = CodeInfo() - codeinfo.cmdline_params = settings.pop('cmdline', []) + [self.INPUT_FILE] + codeinfo.cmdline_params = settings.pop("cmdline", []) + [self.INPUT_FILE] codeinfo.code_uuid = self.inputs.code.uuid calcinfo.stdin_name = self.INPUT_FILE calcinfo.uuid = self.uuid calcinfo.cmdline_params = codeinfo.cmdline_params calcinfo.stdin_name = self.INPUT_FILE - #calcinfo.stdout_name = self.OUTPUT_FILE + # calcinfo.stdout_name = self.OUTPUT_FILE calcinfo.codes_info = [codeinfo] # file lists - if 'file' in self.inputs: + if "file" in self.inputs: for fobj in self.inputs.file.values(): calcinfo.local_copy_list.append((fobj.uuid, fobj.filename, fobj.filename)) # block pockets - if 'block_pocket' in self.inputs: + if "block_pocket" in self.inputs: for name, fobj in self.inputs.block_pocket.items(): - calcinfo.local_copy_list.append((fobj.uuid, fobj.filename, name + '.block')) + calcinfo.local_copy_list.append((fobj.uuid, fobj.filename, name + ".block")) calcinfo.retrieve_list = [self.OUTPUT_FOLDER, self.RESTART_FOLDER] - calcinfo.retrieve_list += settings.pop('additional_retrieve_list', []) + calcinfo.retrieve_list += settings.pop("additional_retrieve_list", []) # check for left over settings if settings: - raise InputValidationError("The following keys have been found " + - "in the settings input node {}, ".format(self.pk) + "but were not understood: " + - ",".join(list(settings.keys()))) + raise InputValidationError( + "The following keys have been found " + + f"in the settings input node {self.pk}, " + + "but were not understood: " + + ",".join(list(settings.keys())) + ) return calcinfo @@ -162,47 +184,52 @@ def _handle_system_section(self, system_dict, folder): for name, sparams in system_dict.items(): if sparams["type"] == "Framework": try: - self.inputs.framework[name].export(folder.get_abs_path(name + '.cif'), fileformat='cif') - except KeyError: + self.inputs.framework[name].export(folder.get_abs_path(name + ".cif"), fileformat="cif") + except KeyError as err: raise InputValidationError( - "You specified '{}' framework in the input dictionary, but did not provide the input " - "framework with the same name".format(name)) - - def _handle_retrieved_parent_folder(self, inp, folder): - """Enable restart from the retrieved folder.""" - if "Restart" not in self.inputs.retrieved_parent_folder._repository.list_object_names(): # pylint: disable=protected-access - raise InputValidationError("Restart was requested but the restart " - "folder was not found in the previos calculation.") + f"You specified '{name}' framework in the input dictionary, but did not provide the input " + "framework with the same name" + ) from err - dest_folder = folder.get_abs_path("RestartInitial") + def _handle_retrieved_parent_folder(self, inp): + """Construct the local copy list from a the `retrieved_parent_folder` input.""" + local_copy_list = [] - # we first copy the whole restart folder - copytree( - os.path.join(self.inputs.retrieved_parent_folder._repository._get_base_folder().abspath, "Restart"), # pylint: disable=protected-access - dest_folder) + parent_folder = self.inputs.retrieved_parent_folder + base_src_path = Path("Restart") + base_dest_path = Path("RestartInitial") - # once this is done, we rename the files to match temperature, pressure and number of unit cells for i_system, system_name in enumerate(inp.system_order): system = inp.params["System"][system_name] - current_folder = folder.get_abs_path("RestartInitial/System_{}".format(i_system)) - content = os.listdir(current_folder) - if len(content) != 1: - raise InputValidationError("Restart folder should contain 1 file only, got {}".format(len(content))) - old_fname = content[0] + system_dir = f"System_{i_system}" + + old_fname = parent_folder.base.repository.list_object_names(base_src_path / system_dir).pop() + if system["type"] == "Box": system_or_box = "Box" (n_x, n_y, n_z) = (1, 1, 1) - if 'ExternalPressure' not in system: - system['ExternalPressure'] = 0 + if "ExternalPressure" not in system: + system["ExternalPressure"] = 0 elif system["type"] == "Framework": system_or_box = system_name try: - (n_x, n_y, n_z) = tuple(map(int, system['UnitCells'].split())) + (n_x, n_y, n_z) = tuple(map(int, system["UnitCells"].split())) except KeyError: (n_x, n_y, n_z) = 1, 1, 1 - external_pressure = system['ExternalPressure'] if 'ExternalPressure' in system else 0 + external_pressure = system["ExternalPressure"] if "ExternalPressure" in system else 0 + + new_fname = ( + f"restart_{system_or_box:s}_{n_x:}.{n_y:d}.{n_z:d}_{system['ExternalTemperature']:f}" + f"_{external_pressure:g}" + ) + + local_copy_list.append( + ( + parent_folder.uuid, + Path(base_src_path, system_dir, old_fname).as_posix(), + Path(base_dest_path, system_dir, new_fname).as_posix(), + ) + ) - new_fname = "restart_{:s}_{:d}.{:d}.{:d}_{:f}_{:g}".format(system_or_box, n_x, n_y, n_z, - system['ExternalTemperature'], external_pressure) - os.rename(os.path.join(current_folder, old_fname), os.path.join(current_folder, new_fname)) + return local_copy_list diff --git a/aiida_raspa/parsers/__init__.py b/aiida_raspa/parsers/__init__.py index 81847cd..fa34c19 100644 --- a/aiida_raspa/parsers/__init__.py +++ b/aiida_raspa/parsers/__init__.py @@ -1,11 +1,12 @@ -# -*- coding: utf-8 -*- """Raspa output parser.""" import os +from pathlib import Path from aiida.common import NotExistent, OutputParsingError from aiida.engine import ExitCode from aiida.orm import Dict, List from aiida.parsers.parser import Parser + from aiida_raspa.utils import parse_base_output # parser @@ -24,34 +25,26 @@ def parse(self, **kwargs): # pylint: disable=too-many-locals return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER output_folder_name = self.node.process_class.OUTPUT_FOLDER - if output_folder_name not in out_folder._repository.list_object_names(): # pylint: disable=protected-access + if output_folder_name not in out_folder.base.repository.list_object_names(): # pylint: disable=protected-access return self.exit_codes.ERROR_NO_OUTPUT_FILE output_parameters = {} warnings = [] - ncomponents = len(self.node.inputs.parameters.get_dict()['Component']) - for system_id, system_name in enumerate(self.node.get_extra('system_order')): + ncomponents = len(self.node.inputs.parameters.get_dict()["Component"]) + for system_id, system_name in enumerate(self.node.get_extra("system_order")): # specify the name for the system - system = "System_{}".format(system_id) - fname = out_folder._repository.list_object_names(os.path.join(output_folder_name, system))[0] # pylint: disable=protected-access - - # get absolute path of the output file - output_abs_path = os.path.join( - out_folder._repository._get_base_folder().abspath, # pylint: disable=protected-access - self.node.process_class.OUTPUT_FOLDER, - system, - fname) + output_dir = Path(output_folder_name) / f"System_{system_id}" + output_filename = out_folder.base.repository.list_object_names(output_dir).pop() + output_contents = out_folder.base.repository.get_object_content(output_dir / output_filename) # Check for possible errors - with open(output_abs_path) as fobj: - content = fobj.read() - if "Starting simulation" not in content: - return self.exit_codes.ERROR_SIMULATION_DID_NOT_START - if "Simulation finished" not in content: - return self.exit_codes.TIMEOUT + if "Starting simulation" not in output_contents: + return self.exit_codes.ERROR_SIMULATION_DID_NOT_START + if "Simulation finished" not in output_contents: + return self.exit_codes.TIMEOUT # parse output parameters and warnings - parsed_parameters, parsed_warnings = parse_base_output(output_abs_path, system_name, ncomponents) + parsed_parameters, parsed_warnings = parse_base_output(output_contents, system_name, ncomponents) output_parameters[system_name] = parsed_parameters warnings += parsed_warnings diff --git a/aiida_raspa/utils/__init__.py b/aiida_raspa/utils/__init__.py index 7aac229..d6d99e9 100644 --- a/aiida_raspa/utils/__init__.py +++ b/aiida_raspa/utils/__init__.py @@ -1,5 +1,8 @@ -# -*- coding: utf-8 -*- """Raspa utils.""" -from .base_parser import parse_base_output from .base_input_generator import RaspaInput -from .inspection_tools import add_write_binary_restart, modify_number_of_cycles, increase_box_lenght +from .base_parser import parse_base_output +from .inspection_tools import ( + add_write_binary_restart, + increase_box_lenght, + modify_number_of_cycles, +) diff --git a/aiida_raspa/utils/base_input_generator.py b/aiida_raspa/utils/base_input_generator.py index d900b86..5115eee 100644 --- a/aiida_raspa/utils/base_input_generator.py +++ b/aiida_raspa/utils/base_input_generator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Basic raspa input generator.""" from copy import deepcopy @@ -12,13 +11,14 @@ class RaspaInput: # pylint: disable=too-few-public-methods """Convert input dictionary into input file""" def __init__(self, params): + """Construct a `RaspaInput` instance.""" self.params = deepcopy(params) # make sure the original object is not modified try: self.system_order = sorted(params["System"].keys()) # we sort the keys to keep the order in the input - except KeyError: - raise KeyError("The input dictionary should contain the System subdictionary.") - except AttributeError: - raise AttributeError("The System subdictionary should be of type dict.") + except KeyError as err: + raise KeyError("The input dictionary should contain the System subdictionary.") from err + except AttributeError as err: + raise AttributeError("The System subdictionary should be of type dict.") from err # file persistent this is essential for the restarts. if not self.system_order: @@ -40,9 +40,9 @@ def render(self): for my_id, name in enumerate(self.system_order): system = section[name] s_type = system.pop("type") - output.append("{} {}".format(s_type, my_id)) + output.append(f"{s_type} {my_id}") if s_type == "Framework": - output.append("{}FrameworkName {}".format(' ' * 3, name)) + output.append(f"{' ' * 3}FrameworkName {name}") self._render_section(output, system, indent=3) # Section Component may contain parameters thar are for several systems @@ -50,14 +50,15 @@ def render(self): # CreateNumberOfMolecules n1, n2 <--- n1 is for system 0, n2 is for system 1 section = params.pop("Component") for my_id, (name, molecule) in enumerate(section.items()): - output.append('Component {} MoleculeName {}'.format(my_id, name)) + output.append(f"Component {my_id} MoleculeName {name}") if "BlockPocketsFileName" in molecule: if isinstance(molecule["BlockPocketsFileName"], dict): try: bps = self._dict_to_ordered_list(molecule["BlockPocketsFileName"]) except KeyError as err: - raise KeyError("You did not provide BlockPocketsFileName parameter for the system '{}'".format( - str(err))) + raise KeyError( + f"You did not provide BlockPocketsFileName parameter for the system '{str(err)}'" + ) from err molecule["BlockPocketsFileName"] = bps molecule["BlockPockets"] = ["yes" if bp else "no" for bp in bps] @@ -68,10 +69,12 @@ def render(self): if isinstance(molecule["CreateNumberOfMolecules"], dict): try: molecule["CreateNumberOfMolecules"] = self._dict_to_ordered_list( - molecule["CreateNumberOfMolecules"]) + molecule["CreateNumberOfMolecules"] + ) except KeyError as err: - raise KeyError("You did not provide CreateNumberOfMolecules parameter for the system {}".format( - str(err))) + raise KeyError( + f"You did not provide CreateNumberOfMolecules parameter for the system {str(err)}" + ) from err for item in ORDERED_ITEMS_COMPONENT_SECTION: if item in molecule: @@ -123,9 +126,9 @@ def _render_item(output, key, val, indent=0): It takes one key-value item and adds to the output file """ if isinstance(val, list): - output.append('{}{} {}'.format(' ' * indent, key, ' '.join(str(p) for p in val))) + output.append(f"{' ' * indent}{key} {' '.join(str(p) for p in val)}") elif isinstance(val, bool): - val_str = 'yes' if val else 'no' - output.append('{}{} {}'.format(' ' * indent, key, val_str)) + val_str = "yes" if val else "no" + output.append(f"{' ' * indent}{key} {val_str}") else: - output.append('{}{} {}'.format(' ' * indent, key, val)) + output.append(f"{' ' * indent}{key} {val}") diff --git a/aiida_raspa/utils/base_parser.py b/aiida_raspa/utils/base_parser.py index 3b4725f..795ba35 100644 --- a/aiida_raspa/utils/base_parser.py +++ b/aiida_raspa/utils/base_parser.py @@ -1,8 +1,6 @@ -# -*- coding: utf-8 -*- """Basic raspa output parser.""" import re - -from math import isnan, isinf +from math import isinf, isnan float_base = float # pylint: disable=invalid-name @@ -12,24 +10,24 @@ def float(number): # pylint: disable=redefined-builtin return number if not any((isnan(number), isinf(number))) else None -KELVIN_TO_KJ_PER_MOL = float(8.314464919 / 1000.0) #exactly the same as Raspa +KELVIN_TO_KJ_PER_MOL = float(8.314464919 / 1000.0) # exactly the same as Raspa # manage block of the first type # -------------------------------------------------------------------------------------------- BLOCK_1_LIST = [ - #("Average temperature:", "temperature", (1, 2, 4), 0), # misleading property! - #("Average Pressure:", "pressure", (1, 2, 4), 0), # misleading property! + # ("Average temperature:", "temperature", (1, 2, 4), 0), # misleading property! + # ("Average Pressure:", "pressure", (1, 2, 4), 0), # misleading property! ("Average Volume:", "cell_volume", (1, 2, 4), 0), ("Average Density:", "adsorbate_density", (1, 2, 4), 0), - #("Average Heat Capacity", "framework_heat_capacity", (1, 2, 4), 0), # misleading property! + # ("Average Heat Capacity", "framework_heat_capacity", (1, 2, 4), 0), # misleading property! ("Enthalpy of adsorption:", "enthalpy_of_adsorption", (1, 4, 3), 4), ("Tail-correction energy:", "tail_correction_energy", (1, 2, 4), 0) - #("Total energy:$", "total_energy", (1, 2, 4), 0), # not important property! + # ("Total energy:$", "total_energy", (1, 2, 4), 0), # not important property! ] # block of box properties. BOX_PROP_LIST = [ - ("Average Box-lengths:", 'box'), + ("Average Box-lengths:", "box"), ] @@ -51,10 +49,10 @@ def parse_block1(flines, result_dict, prop, value=1, unit=2, dev=4): """ for line in flines: - if 'Average' in line: - result_dict[prop + '_average'] = float(line.split()[value]) - result_dict[prop + '_unit'] = re.sub(r"[{}()\[\]]", '', line.split()[unit]) - result_dict[prop + '_dev'] = float(line.split()[dev]) + if "Average" in line: + result_dict[prop + "_average"] = float(line.split()[value]) + result_dict[prop + "_unit"] = re.sub(r"[{}()\[\]]", "", line.split()[unit]) + result_dict[prop + "_dev"] = float(line.split()[dev]) break @@ -69,8 +67,10 @@ def parse_block1(flines, result_dict, prop, value=1, unit=2, dev=4): ("Adsorbate/Adsorbate Coulomb energy:", "ads/ads", "coulomb"), ] -ENERGY_AVERAGE_LIST = [("Average Adsorbate-Adsorbate energy:", "ads/ads"), - ("Average Host-Adsorbate energy:", "host/ads")] +ENERGY_AVERAGE_LIST = [ + ("Average Adsorbate-Adsorbate energy:", "ads/ads"), + ("Average Host-Adsorbate energy:", "host/ads"), +] def parse_block_energy(flines, res_dict, prop): @@ -90,14 +90,14 @@ def parse_block_energy(flines, res_dict, prop): +/- 98.86943 +/- 98.869430 +/- 0.00000 [K] """ for line in flines: - if 'Average' in line: - res_dict["energy_{}_tot_average".format(prop)] = float(line.split()[1]) * KELVIN_TO_KJ_PER_MOL - res_dict["energy_{}_vdw_average".format(prop)] = float(line.split()[5]) * KELVIN_TO_KJ_PER_MOL - res_dict["energy_{}_coulomb_average".format(prop)] = float(line.split()[7]) * KELVIN_TO_KJ_PER_MOL - if '+/-' in line: - res_dict["energy_{}_tot_dev".format(prop)] = float(line.split()[1]) * KELVIN_TO_KJ_PER_MOL - res_dict["energy_{}_vdw_dev".format(prop)] = float(line.split()[3]) * KELVIN_TO_KJ_PER_MOL - res_dict["energy_{}_coulomb_dev".format(prop)] = float(line.split()[5]) * KELVIN_TO_KJ_PER_MOL + if "Average" in line: + res_dict[f"energy_{prop}_tot_average"] = float(line.split()[1]) * KELVIN_TO_KJ_PER_MOL + res_dict[f"energy_{prop}_vdw_average"] = float(line.split()[5]) * KELVIN_TO_KJ_PER_MOL + res_dict[f"energy_{prop}_coulomb_average"] = float(line.split()[7]) * KELVIN_TO_KJ_PER_MOL + if "+/-" in line: + res_dict[f"energy_{prop}_tot_dev"] = float(line.split()[1]) * KELVIN_TO_KJ_PER_MOL + res_dict[f"energy_{prop}_vdw_dev"] = float(line.split()[3]) * KELVIN_TO_KJ_PER_MOL + res_dict[f"energy_{prop}_coulomb_dev"] = float(line.split()[5]) * KELVIN_TO_KJ_PER_MOL return @@ -115,184 +115,188 @@ def parse_lines_with_component(res_components, components, line, prop): """Parse lines that contain components""" # self.logger.info("analysing line: {}".format(line)) for i, component in enumerate(components): - if '[' + component + ']' in line: + if "[" + component + "]" in line: words = line.split() - res_components[i][prop + '_unit'] = re.sub(r'[{}()\[\]]', '', words[-1]) - res_components[i][prop + '_dev'] = float(words[-2]) - res_components[i][prop + '_average'] = float(words[-4]) + res_components[i][prop + "_unit"] = re.sub(r"[{}()\[\]]", "", words[-1]) + res_components[i][prop + "_dev"] = float(words[-2]) + res_components[i][prop + "_average"] = float(words[-4]) # pylint: disable=too-many-locals, too-many-arguments, too-many-statements, too-many-branches -def parse_base_output(output_abs_path, system_name, ncomponents): +def parse_base_output(output_contents, system_name, ncomponents): """Parse RASPA output file: it is divided in different parts, whose start/end is carefully documented.""" warnings = [] res_per_component = [] for i in range(ncomponents): res_per_component.append({}) - result_dict = {'exceeded_walltime': False} - - with open(output_abs_path, "r") as fobj: - - # 1st parsing part: input settings - # -------------------------------- - # from: start of file - # to: "Current (initial full energy) Energy Status" - - icomponent = 0 - component_names = [] - res_cmp = res_per_component[0] - for line in fobj: - if "Component" in line and "molecule)" in line: - component_names.append(line.split()[2][1:-1]) - if "(Adsorbate" in line: - res_cmp['molecule_type'] = 'adsorbate' - elif "(Cation" in line: - res_cmp['molecule_type'] = 'cation' - - # Consider to change it with parse_line() - if "Conversion factor molecules/unit cell -> mol/kg:" in line: - res_cmp['conversion_factor_molec_uc_to_mol_kg'] = float(line.split()[6]) - res_cmp['conversion_factor_molec_uc_to_mol_kg_unit'] = "(mol/kg)/(molec/uc)" - # this line was corrected in Raspa's commit c1ad4de (Nov19), since "gr/gr" should read "mg/g" - if "Conversion factor molecules/unit cell -> gr/gr:" in line \ - or "Conversion factor molecules/unit cell -> mg/g:" in line: - res_cmp['conversion_factor_molec_uc_to_mg_g'] = float(line.split()[6]) - res_cmp['conversion_factor_molec_uc_to_mg_g_unit'] = "(mg/g)/(molec/uc)" - if "Conversion factor molecules/unit cell -> cm^3 STP/gr:" in line: - res_cmp['conversion_factor_molec_uc_to_cm3stp_gr'] = float(line.split()[7]) - res_cmp['conversion_factor_molec_uc_to_cm3stp_gr_unit'] = "(cm^3_STP/gr)/(molec/uc)" - if "Conversion factor molecules/unit cell -> cm^3 STP/cm^3:" in line: - res_cmp['conversion_factor_molec_uc_to_cm3stp_cm3'] = float(line.split()[7]) - res_cmp['conversion_factor_molec_uc_to_cm3stp_cm3_unit'] = "(cm^3_STP/cm^3)/(molec/uc)" - if "MolFraction:" in line: - res_cmp['mol_fraction'] = float(line.split()[1]) - res_cmp['mol_fraction_unit'] = "-" - if "Partial pressure:" in line: - res_cmp['partial_pressure'] = float(line.split()[2]) - res_cmp['partial_pressure_unit'] = "Pa" - if "Partial fugacity:" in line: - res_cmp['partial_fugacity'] = float(line.split()[2]) - res_cmp['partial_fugacity_unit'] = "Pa" - icomponent += 1 - if icomponent < ncomponents: - res_cmp = res_per_component[icomponent] - if "Framework Density" in line: - result_dict['framework_density'] = line.split()[2] - result_dict['framework_density_unit'] = re.sub(r'[{}()\[\]]', '', line.split()[3]) - if "Current (initial full energy) Energy Status" in line: - break - - # 2nd parsing part: initial and final configurations - # -------------------------------------------------- - # from: "Current (initial full energy) Energy Status" - # to: "Average properties of the system" - - reading = 'initial' - result_dict['energy_unit'] = 'kJ/mol' - - for line in fobj: - # Understand if it is the initial or final "Current Energy Status" section - if "Current (full final energy) Energy Status" in line: - reading = 'final' - - # Read the entries of "Current Energy Status" section - if reading: - for parse in ENERGY_CURRENT_LIST: - if parse[0] in line: - result_dict['energy_{}_{}_{}'.format(parse[1], parse[2], - reading)] = float(line.split()[-1]) * KELVIN_TO_KJ_PER_MOL - if parse[1] == "ads/ads" and parse[2] == "coulomb": - reading = None - - if "Average properties of the system" in line: - break - - # 3rd parsing part: average system properties - # -------------------------------------------------- - # from: "Average properties of the system" - # to: "Number of molecules" - - for line in fobj: - for parse in BLOCK_1_LIST: + result_dict = {"exceeded_walltime": False} + + output_contents = iter(output_contents.split("\n")) + + # 1st parsing part: input settings + # -------------------------------- + # from: start of file + # to: "Current (initial full energy) Energy Status" + icomponent = 0 + component_names = [] + res_cmp = res_per_component[0] + + for line in output_contents: + if "Component" in line and "molecule)" in line: + component_names.append(line.split()[2][1:-1]) + if "(Adsorbate" in line: + res_cmp["molecule_type"] = "adsorbate" + elif "(Cation" in line: + res_cmp["molecule_type"] = "cation" + + # Consider to change it with parse_line() + if "Conversion factor molecules/unit cell -> mol/kg:" in line: + res_cmp["conversion_factor_molec_uc_to_mol_kg"] = float(line.split()[6]) + res_cmp["conversion_factor_molec_uc_to_mol_kg_unit"] = "(mol/kg)/(molec/uc)" + # this line was corrected in Raspa's commit c1ad4de (Nov19), since "gr/gr" should read "mg/g" + if ( + "Conversion factor molecules/unit cell -> gr/gr:" in line + or "Conversion factor molecules/unit cell -> mg/g:" in line + ): + res_cmp["conversion_factor_molec_uc_to_mg_g"] = float(line.split()[6]) + res_cmp["conversion_factor_molec_uc_to_mg_g_unit"] = "(mg/g)/(molec/uc)" + if "Conversion factor molecules/unit cell -> cm^3 STP/gr:" in line: + res_cmp["conversion_factor_molec_uc_to_cm3stp_gr"] = float(line.split()[7]) + res_cmp["conversion_factor_molec_uc_to_cm3stp_gr_unit"] = "(cm^3_STP/gr)/(molec/uc)" + if "Conversion factor molecules/unit cell -> cm^3 STP/cm^3:" in line: + res_cmp["conversion_factor_molec_uc_to_cm3stp_cm3"] = float(line.split()[7]) + res_cmp["conversion_factor_molec_uc_to_cm3stp_cm3_unit"] = "(cm^3_STP/cm^3)/(molec/uc)" + if "MolFraction:" in line: + res_cmp["mol_fraction"] = float(line.split()[1]) + res_cmp["mol_fraction_unit"] = "-" + if "Partial pressure:" in line: + res_cmp["partial_pressure"] = float(line.split()[2]) + res_cmp["partial_pressure_unit"] = "Pa" + if "Partial fugacity:" in line: + res_cmp["partial_fugacity"] = float(line.split()[2]) + res_cmp["partial_fugacity_unit"] = "Pa" + icomponent += 1 + if icomponent < ncomponents: + res_cmp = res_per_component[icomponent] + if "Framework Density" in line: + result_dict["framework_density"] = line.split()[2] + result_dict["framework_density_unit"] = re.sub(r"[{}()\[\]]", "", line.split()[3]) + if "Current (initial full energy) Energy Status" in line: + break + + # 2nd parsing part: initial and final configurations + # -------------------------------------------------- + # from: "Current (initial full energy) Energy Status" + # to: "Average properties of the system" + + reading = "initial" + result_dict["energy_unit"] = "kJ/mol" + + for line in output_contents: + # Understand if it is the initial or final "Current Energy Status" section + if "Current (full final energy) Energy Status" in line: + reading = "final" + + # Read the entries of "Current Energy Status" section + if reading: + for parse in ENERGY_CURRENT_LIST: if parse[0] in line: - parse_block1(fobj, result_dict, parse[1], *parse[2]) - # I assume here that properties per component are present furhter in the output file. - # so I need to skip some lines: + result_dict[f"energy_{parse[1]}_{parse[2]}_{reading}"] = ( + float(line.split()[-1]) * KELVIN_TO_KJ_PER_MOL + ) + if parse[1] == "ads/ads" and parse[2] == "coulomb": + reading = None + + if "Average properties of the system" in line: + break + + # 3rd parsing part: average system properties + # -------------------------------------------------- + # from: "Average properties of the system" + # to: "Number of molecules" + + for line in output_contents: + # ("Enthalpy of adsorption:", "enthalpy_of_adsorption", (1, 4, 3), 4), + for parse in BLOCK_1_LIST: + if parse[0] in line: + parse_block1(output_contents, result_dict, parse[1], *parse[2]) + # I assume here that properties per component are present furhter in the output file. + # so I need to skip some lines: + skip_nlines_after = parse[3] + while skip_nlines_after > 0: + line = next(output_contents) + skip_nlines_after -= 1 + for i, cmpnt in enumerate(component_names): + # The order of properties per molecule is the same as the order of molecules in the + # input file. So if component name was not found in the next line, I break the loop + # immidiately as there is no reason to continue it + line = next(output_contents) + if cmpnt in line: + parse_block1(output_contents, res_per_component[i], parse[1], *parse[2]) + else: + break skip_nlines_after = parse[3] while skip_nlines_after > 0: - line = next(fobj) + line = next(output_contents) skip_nlines_after -= 1 - for i, cmpnt in enumerate(component_names): - # The order of properties per molecule is the same as the order of molecules in the - # input file. So if component name was not found in the next line, I break the loop - # immidiately as there is no reason to continue it - line = next(fobj) - if cmpnt in line: - parse_block1(fobj, res_per_component[i], parse[1], *parse[2]) - else: - break - skip_nlines_after = parse[3] - while skip_nlines_after > 0: - line = next(fobj) - skip_nlines_after -= 1 - - continue # no need to perform further checks, propperty has been found already - for parse in ENERGY_AVERAGE_LIST: - if parse[0] in line: - parse_block_energy(fobj, result_dict, prop=parse[1]) - continue # no need to perform further checks, propperty has been found already - for parse in BOX_PROP_LIST: - if parse[0] in line: - # parse three cell vectors - parse_block1(fobj, result_dict, prop='box_ax', value=2, unit=3, dev=5) - parse_block1(fobj, result_dict, prop='box_by', value=2, unit=3, dev=5) - parse_block1(fobj, result_dict, prop='box_cz', value=2, unit=3, dev=5) - # parsee angles between the cell vectors - parse_block1(fobj, result_dict, prop='box_alpha', value=3, unit=4, dev=6) - parse_block1(fobj, result_dict, prop='box_beta', value=3, unit=4, dev=6) - parse_block1(fobj, result_dict, prop='box_gamma', value=3, unit=4, dev=6) - - if "Number of molecules:" in line: - break - - # 4th parsing part: average molecule properties - # -------------------------------------------------- - # from: "Number of molecules" - # to: end of file - - icomponent = 0 - for line in fobj: - # Consider to change it with parse_line? - if 'Average loading absolute [molecules/unit cell]' in line: - res_per_component[icomponent]['loading_absolute_average'] = float(line.split()[5]) - res_per_component[icomponent]['loading_absolute_dev'] = float(line.split()[7]) - res_per_component[icomponent]['loading_absolute_unit'] = 'molecules/unit cell' - elif 'Average loading excess [molecules/unit cell]' in line: - res_per_component[icomponent]['loading_excess_average'] = float(line.split()[5]) - res_per_component[icomponent]['loading_excess_dev'] = float(line.split()[7]) - res_per_component[icomponent]['loading_excess_unit'] = 'molecules/unit cell' - icomponent += 1 - if icomponent >= ncomponents: - break - - for line in fobj: - for to_parse in LINES_WITH_COMPONENT_LIST: - if to_parse[0] in line: - parse_lines_with_component(res_per_component, component_names, line, to_parse[1]) - - # Assigning to None all the quantities that are meaningless if not running a Widom insertion calculation - for res_comp in res_per_component: - for prop in ["henry_coefficient", "widom_rosenbluth_factor", "chemical_potential"]: - if res_comp["{}_dev".format(prop)] == 0.0: - res_comp["{}_average".format(prop)] = None - res_comp["{}_dev".format(prop)] = None - - # The section "Adsorption energy from Widom-insertion" is not showing in the output if no widom is performed - if not "adsorption_energy_widom_average" in res_comp: - res_comp["adsorption_energy_widom_unit"] = "kJ/mol" - res_comp["adsorption_energy_widom_dev"] = None - res_comp["adsorption_energy_widom_average"] = None + + continue # no need to perform further checks, propperty has been found already + for parse in ENERGY_AVERAGE_LIST: + if parse[0] in line: + parse_block_energy(output_contents, result_dict, prop=parse[1]) + continue # no need to perform further checks, propperty has been found already + for parse in BOX_PROP_LIST: + if parse[0] in line: + # parse three cell vectors + parse_block1(output_contents, result_dict, prop="box_ax", value=2, unit=3, dev=5) + parse_block1(output_contents, result_dict, prop="box_by", value=2, unit=3, dev=5) + parse_block1(output_contents, result_dict, prop="box_cz", value=2, unit=3, dev=5) + # parsee angles between the cell vectors + parse_block1(output_contents, result_dict, prop="box_alpha", value=3, unit=4, dev=6) + parse_block1(output_contents, result_dict, prop="box_beta", value=3, unit=4, dev=6) + parse_block1(output_contents, result_dict, prop="box_gamma", value=3, unit=4, dev=6) + + if "Number of molecules:" in line: + break + + # 4th parsing part: average molecule properties + # -------------------------------------------------- + # from: "Number of molecules" + # to: end of file + + icomponent = 0 + for line in output_contents: + # Consider to change it with parse_line? + if "Average loading absolute [molecules/unit cell]" in line: + res_per_component[icomponent]["loading_absolute_average"] = float(line.split()[5]) + res_per_component[icomponent]["loading_absolute_dev"] = float(line.split()[7]) + res_per_component[icomponent]["loading_absolute_unit"] = "molecules/unit cell" + elif "Average loading excess [molecules/unit cell]" in line: + res_per_component[icomponent]["loading_excess_average"] = float(line.split()[5]) + res_per_component[icomponent]["loading_excess_dev"] = float(line.split()[7]) + res_per_component[icomponent]["loading_excess_unit"] = "molecules/unit cell" + icomponent += 1 + if icomponent >= ncomponents: + break + + for line in output_contents: + for to_parse in LINES_WITH_COMPONENT_LIST: + if to_parse[0] in line: + parse_lines_with_component(res_per_component, component_names, line, to_parse[1]) + + # Assigning to None all the quantities that are meaningless if not running a Widom insertion calculation + for res_comp in res_per_component: + for prop in ["henry_coefficient", "widom_rosenbluth_factor", "chemical_potential"]: + if res_comp[f"{prop}_dev"] == 0.0: + res_comp[f"{prop}_average"] = None + res_comp[f"{prop}_dev"] = None + + # The section "Adsorption energy from Widom-insertion" is not showing in the output if no widom is performed + if not "adsorption_energy_widom_average" in res_comp: + res_comp["adsorption_energy_widom_unit"] = "kJ/mol" + res_comp["adsorption_energy_widom_dev"] = None + res_comp["adsorption_energy_widom_average"] = None return_dictionary = {"general": result_dict, "components": {}} @@ -300,10 +304,10 @@ def parse_base_output(output_abs_path, system_name, ncomponents): return_dictionary["components"][name] = value # Parsing all the warning that are printed in the output file, avoiding redoundancy - with open(output_abs_path, "r") as fobj: - for line in fobj: - if "WARNING" in line: - warning_touple = (system_name, line) - if warning_touple not in warnings: - warnings.append(warning_touple) + for line in output_contents: + if "WARNING" in line: + warning_touple = (system_name, line) + if warning_touple not in warnings: + warnings.append(warning_touple) + return return_dictionary, warnings diff --git a/aiida_raspa/utils/inspection_tools.py b/aiida_raspa/utils/inspection_tools.py index 5511b80..26734e6 100644 --- a/aiida_raspa/utils/inspection_tools.py +++ b/aiida_raspa/utils/inspection_tools.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- """RASPA inspection tools""" - from aiida.engine import calcfunction from aiida.orm import Dict @@ -9,7 +7,7 @@ def add_write_binary_restart(input_dict, write_every): final_dict = input_dict.get_dict() final_dict["GeneralSettings"]["WriteBinaryRestartFileEvery"] = write_every - return input_dict if input_dict.get_dict() == final_dict else Dict(dict=final_dict) + return input_dict if input_dict.get_dict() == final_dict else Dict(final_dict) def modify_number_of_cycles(input_dict, additional_init_cycle, additional_prod_cycle): @@ -23,7 +21,7 @@ def modify_number_of_cycles(input_dict, additional_init_cycle, additional_prod_c final_dict["GeneralSettings"]["NumberOfCycles"] += additional_prod_cycle.value # It is a restart job the number of molecules need to be set to zero - for component in final_dict['Component'].values(): + for component in final_dict["Component"].values(): if "CreateNumberOfMolecules" in component: if isinstance(component["CreateNumberOfMolecules"], dict): for number in component["CreateNumberOfMolecules"]: @@ -32,7 +30,7 @@ def modify_number_of_cycles(input_dict, additional_init_cycle, additional_prod_c component["CreateNumberOfMolecules"] = 0 # Return final_dict dict only if it was modified - return input_dict if input_dict.get_dict() == final_dict else Dict(dict=final_dict) + return input_dict if input_dict.get_dict() == final_dict else Dict(final_dict) @calcfunction @@ -46,6 +44,6 @@ def increase_box_lenght(input_dict, box_name, box_length_current): # We do the simulation in cubic box. addition_length = abs(math.ceil(bx_length_old[0] - box_length_current.value)) box_one_length_new = [bx_length_old[i] + addition_length for i in range(3)] - final_dict["System"][box_name.value]["BoxLengths"] = "{} {} {}".format(*box_one_length_new) + final_dict["System"][box_name.value]["BoxLengths"] = " ".join(str(l) for l in box_one_length_new) - return Dict(dict=final_dict) + return Dict(final_dict) diff --git a/aiida_raspa/workchains/__init__.py b/aiida_raspa/workchains/__init__.py index 3bb6a79..50c0ca6 100644 --- a/aiida_raspa/workchains/__init__.py +++ b/aiida_raspa/workchains/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ############################################################################## # Copyright (c), The AiiDA team. All rights reserved. # # This file is part of the AiiDA code. # diff --git a/aiida_raspa/workchains/base.py b/aiida_raspa/workchains/base.py index c679411..28b6f6c 100644 --- a/aiida_raspa/workchains/base.py +++ b/aiida_raspa/workchains/base.py @@ -1,14 +1,22 @@ -# -*- coding: utf-8 -*- """Base work chain to run a RASPA calculation""" from aiida.common import AttributeDict -from aiida.engine import BaseRestartWorkChain, ProcessHandlerReport, process_handler, while_ -from aiida.orm import Int, Str, Float +from aiida.engine import ( + BaseRestartWorkChain, + ProcessHandlerReport, + process_handler, + while_, +) +from aiida.orm import Float, Int, Str from aiida.plugins import CalculationFactory -from aiida_raspa.utils import add_write_binary_restart, modify_number_of_cycles, increase_box_lenght +from aiida_raspa.utils import ( + add_write_binary_restart, + increase_box_lenght, + modify_number_of_cycles, +) -RaspaCalculation = CalculationFactory('raspa') # pylint: disable=invalid-name +RaspaCalculation = CalculationFactory("raspa") # pylint: disable=invalid-name class RaspaBaseWorkChain(BaseRestartWorkChain): @@ -19,7 +27,7 @@ class RaspaBaseWorkChain(BaseRestartWorkChain): @classmethod def define(cls, spec): super().define(spec) - spec.expose_inputs(RaspaCalculation, namespace='raspa') + spec.expose_inputs(RaspaCalculation, namespace="raspa") spec.outline( cls.setup, while_(cls.should_run_process)( @@ -37,7 +45,7 @@ def setup(self): super().setup() - self.ctx.inputs = AttributeDict(self.exposed_inputs(RaspaCalculation, 'raspa')) + self.ctx.inputs = AttributeDict(self.exposed_inputs(RaspaCalculation, "raspa")) if "WriteBinaryRestartFileEvery" not in self.ctx.inputs.parameters["GeneralSettings"]: self.ctx.inputs.parameters = add_write_binary_restart(self.ctx.inputs.parameters, Int(1000)) @@ -48,8 +56,8 @@ def report_error_handled(self, calculation, action): :param action: a string message with the action taken""" arguments = [calculation.process_label, calculation.pk, calculation.exit_status, calculation.exit_message] - self.report('{}<{}> failed with exit status {}: {}'.format(*arguments)) - self.report('Action taken: {}'.format(action)) + self.report("{}<{}> failed with exit status {}: {}".format(*arguments)) + self.report(f"Action taken: {action}") @process_handler(priority=570, exit_codes=RaspaCalculation.exit_codes.TIMEOUT, enabled=True) def handle_timeout(self, calculation): @@ -67,10 +75,10 @@ def check_widom_convergence(self, calculation): additional_cycle = 2000 output_widom = calculation.outputs.output_parameters.get_dict() - structure_label = list(calculation.get_incoming().nested()['framework'].keys())[0] + structure_label = list(calculation.get_incoming().nested()["framework"].keys())[0] conv_stat = [] - for comp in calculation.inputs.parameters['Component']: + for comp in calculation.inputs.parameters["Component"]: kh_average_comp = output_widom[structure_label]["components"][comp]["henry_coefficient_average"] kh_dev_comp = output_widom[structure_label]["components"][comp]["henry_coefficient_dev"] @@ -81,12 +89,11 @@ def check_widom_convergence(self, calculation): conv_stat.append(False) if not all(conv_stat): - self.report("Widom particle insertion calculationulation is NOT converged: repeating with more trials...") - self.ctx.inputs.retrieved_parent_folder = calculation.outputs['retrieved'] - self.ctx.inputs.parameters = modify_number_of_cycles(self.ctx.inputs.parameters, - additional_init_cycle=Int(0), - additional_prod_cycle=Int(additional_cycle)) + self.ctx.inputs.retrieved_parent_folder = calculation.outputs["retrieved"] + self.ctx.inputs.parameters = modify_number_of_cycles( + self.ctx.inputs.parameters, additional_init_cycle=Int(0), additional_prod_cycle=Int(additional_cycle) + ) return ProcessHandlerReport(False) return None @@ -99,11 +106,10 @@ def check_gcmc_convergence(self, calc): additional_prod_cycle = 2000 output_gcmc = calc.outputs.output_parameters.get_dict() - structure_label = list(calc.get_incoming().nested()['framework'].keys())[0] + structure_label = list(calc.get_incoming().nested()["framework"].keys())[0] conv_stat = [] - for comp in calc.inputs.parameters['Component']: - + for comp in calc.inputs.parameters["Component"]: loading_average_comp = output_gcmc[structure_label]["components"][comp]["loading_absolute_average"] loading_dev_comp = output_gcmc[structure_label]["components"][comp]["loading_absolute_dev"] @@ -121,10 +127,12 @@ def check_gcmc_convergence(self, calc): if not all(conv_stat): self.report("GCMC calculation is NOT converged: continuing from restart...") - self.ctx.inputs.retrieved_parent_folder = calc.outputs['retrieved'] - self.ctx.inputs.parameters = modify_number_of_cycles(self.ctx.inputs.parameters, - additional_init_cycle=Int(additional_init_cycle), - additional_prod_cycle=Int(additional_prod_cycle)) + self.ctx.inputs.retrieved_parent_folder = calc.outputs["retrieved"] + self.ctx.inputs.parameters = modify_number_of_cycles( + self.ctx.inputs.parameters, + additional_init_cycle=Int(additional_init_cycle), + additional_prod_cycle=Int(additional_prod_cycle), + ) return ProcessHandlerReport(False) return None @@ -141,11 +149,11 @@ def check_gemc_convergence(self, calc): output_gemc = calc.outputs.output_parameters.get_dict() conv_stat = [] - for comp in calc.inputs.parameters['Component']: - molec_per_box1_comp_average = output_gemc['box_one']["components"][comp]["loading_absolute_average"] - molec_per_box2_comp_average = output_gemc['box_two']["components"][comp]["loading_absolute_average"] - molec_per_box1_comp_dev = output_gemc['box_one']["components"][comp]["loading_absolute_dev"] - molec_per_box2_comp_dev = output_gemc['box_two']["components"][comp]["loading_absolute_dev"] + for comp in calc.inputs.parameters["Component"]: + molec_per_box1_comp_average = output_gemc["box_one"]["components"][comp]["loading_absolute_average"] + molec_per_box2_comp_average = output_gemc["box_two"]["components"][comp]["loading_absolute_average"] + molec_per_box1_comp_dev = output_gemc["box_one"]["components"][comp]["loading_absolute_dev"] + molec_per_box2_comp_dev = output_gemc["box_two"]["components"][comp]["loading_absolute_dev"] error_box1 = round((molec_per_box1_comp_dev / molec_per_box1_comp_average), 2) error_box2 = round((molec_per_box2_comp_dev / molec_per_box2_comp_average), 2) @@ -157,10 +165,12 @@ def check_gemc_convergence(self, calc): if not all(conv_stat): self.report("GEMC calculation is NOT converged: continuing from restart...") - self.ctx.inputs.retrieved_parent_folder = calc.outputs['retrieved'] - self.ctx.inputs.parameters = modify_number_of_cycles(self.ctx.inputs.parameters, - additional_init_cycle=Int(additional_init_cycle), - additional_prod_cycle=Int(additional_prod_cycle)) + self.ctx.inputs.retrieved_parent_folder = calc.outputs["retrieved"] + self.ctx.inputs.parameters = modify_number_of_cycles( + self.ctx.inputs.parameters, + additional_init_cycle=Int(additional_init_cycle), + additional_prod_cycle=Int(additional_prod_cycle), + ) return ProcessHandlerReport(False) return None @@ -170,7 +180,7 @@ def check_gemc_box(self, calc): """Checks whether each simulation box still satisfies minimum image convention.""" output_gemc = calc.outputs.output_parameters.get_dict() - cutoff = calc.inputs.parameters['GeneralSettings']['CutOff'] + cutoff = calc.inputs.parameters["GeneralSettings"]["CutOff"] box_one_stat = [] box_two_stat = [] @@ -194,12 +204,14 @@ def check_gemc_box(self, calc): self.report("GEMC box is NOT converged: repeating with increase box...") # Fixing the issue. if not all(box_one_stat): - self.ctx.inputs.parameters = increase_box_lenght(self.ctx.inputs.parameters, Str("box_one"), - Float(box_one_length_current[0])) + self.ctx.inputs.parameters = increase_box_lenght( + self.ctx.inputs.parameters, Str("box_one"), Float(box_one_length_current[0]) + ) if not all(box_two_stat): - self.ctx.inputs.parameters = increase_box_lenght(self.ctx.inputs.parameters, Str("box_two"), - Float(box_two_length_current[0])) + self.ctx.inputs.parameters = increase_box_lenght( + self.ctx.inputs.parameters, Str("box_two"), Float(box_two_length_current[0]) + ) return ProcessHandlerReport(True) diff --git a/conftest.py b/conftest.py index 355b2d3..3ab1e9c 100644 --- a/conftest.py +++ b/conftest.py @@ -2,9 +2,10 @@ For pytest initialise a test database and profile """ import pytest -pytest_plugins = ['aiida.manage.tests.pytest_fixtures'] # pylint: disable=invalid-name +pytest_plugins = ["aiida.manage.tests.pytest_fixtures"] # pylint: disable=invalid-name -@pytest.fixture(scope='function') + +@pytest.fixture(scope="function") def raspa_code(aiida_local_code_factory): # pylint: disable=unused-argument return aiida_local_code_factory("raspa", "simulate") diff --git a/docs/source/conf.py b/docs/source/conf.py index 6222fa2..e4b4ef7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Sphinx configuration for aiida-raspa This file is execfile()d with the current directory set to its @@ -14,6 +13,7 @@ import os import sys import time + from aiida.manage.configuration import load_documentation_profile # pylint: disable=invalid-name,ungrouped-imports @@ -25,67 +25,61 @@ load_documentation_profile() # If we are not on READTHEDOCS load the Sphinx theme manually -if not os.environ.get('READTHEDOCS', None): +if not os.environ.get("READTHEDOCS", None): import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + html_theme = "sphinx_rtd_theme" + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] -# let's make sure the entry points are up to date -try: - from aiida.plugins.entry_point import ENTRYPOINT_MANAGER as mgr - mgr.scan() -except AttributeError: - # .scan may be no longer availabe if we switch away from reentry - pass import aiida_raspa # pylint: disable=wrong-import-position # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.5' +needs_sphinx = "1.5" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.mathjax', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', - 'sphinxcontrib.contentui', - 'aiida.sphinxext', + "sphinx.ext.autodoc", + "sphinx.ext.mathjax", + "sphinx.ext.intersphinx", + "sphinx.ext.viewcode", + "sphinxcontrib.contentui", + "aiida.sphinxext", ] intersphinx_mapping = { - 'python': ('https://docs.python.org/2.7', None), - 'aiida': ('http://aiida-core.readthedocs.io/en/latest/', None), + "python": ("https://docs.python.org/2.7", None), + "aiida": ("https://aiida.readthedocs.io/projects/aiida-core/en/latest/", None), } # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -#~ master_doc = 'index' -master_doc = 'index' +# ~ master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'aiida-raspa' +project = "aiida-raspa" copyright_first_year = "2019" copyright_owners = "The AiiDA Team" current_year = str(time.localtime().tm_year) -copyright_year_string = current_year if current_year == copyright_first_year else "{}-{}".format( - copyright_first_year, current_year) +copyright_year_string = ( + current_year if current_year == copyright_first_year else f"{copyright_first_year}-{current_year}" +) # pylint: disable=redefined-builtin -copyright = '{}, {}. All rights reserved'.format(copyright_year_string, copyright_owners) +copyright = f"{copyright_year_string}, {copyright_owners}. All rights reserved" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -94,75 +88,75 @@ # The full version, including alpha/beta/rc tags. release = aiida_raspa.__version__ # The short X.Y version. -version = '.'.join(release.split('.')[:2]) +version = ".".join(release.split(".")[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = 'en' +language = "en" # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # exclude_patterns = ['doc.rst'] -#~ exclude_patterns = ['index.rst'] +# ~ exclude_patterns = ['index.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -#~ html_theme = 'basicstrap' +# ~ html_theme = 'basicstrap' ## SET BELOW # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#~ html_theme_options = { -#~ 'inner_theme': True, -#~ 'inner_theme_name': 'bootswatch-darkly', -#~ 'nav_fixed_top': False -#~ } +# ~ html_theme_options = { +# ~ 'inner_theme': True, +# ~ 'inner_theme_name': 'bootswatch-darkly', +# ~ 'nav_fixed_top': False +# ~ } # Add any paths that contain custom themes here, relative to this directory. -#~ html_theme_path = ["."] +# ~ html_theme_path = ["."] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. @@ -176,83 +170,80 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#~ html_show_copyright = False +# ~ html_show_copyright = False # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -html_use_opensearch = 'http://aiida-raspa.readthedocs.io' +html_use_opensearch = "http://aiida-raspa.readthedocs.io" # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -html_search_language = 'en' +html_search_language = "en" # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'aiida-raspa-doc' +htmlhelp_basename = "aiida-raspa-doc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. #'preamble': '', - # Latex figure (float) alignment #'figure_align': 'htbp', } @@ -265,23 +256,23 @@ # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True def run_apidoc(_): @@ -293,38 +284,39 @@ def run_apidoc(_): See also https://github.com/rtfd/readthedocs.org/issues/1139 """ source_dir = os.path.abspath(os.path.dirname(__file__)) - apidoc_dir = os.path.join(source_dir, 'apidoc') - package_dir = os.path.join(source_dir, os.pardir, os.pardir, 'aiida_raspa') + apidoc_dir = os.path.join(source_dir, "apidoc") + package_dir = os.path.join(source_dir, os.pardir, os.pardir, "aiida_raspa") # In #1139, they suggest the route below, but this ended up # calling sphinx-build, not sphinx-apidoc - #from sphinx.apidoc import main - #main([None, '-e', '-o', apidoc_dir, package_dir, '--force']) + # from sphinx.apidoc import main + # main([None, '-e', '-o', apidoc_dir, package_dir, '--force']) import subprocess - cmd_path = 'sphinx-apidoc' - if hasattr(sys, 'real_prefix'): # Check to see if we are in a virtualenv + + cmd_path = "sphinx-apidoc" + if hasattr(sys, "real_prefix"): # Check to see if we are in a virtualenv # If we are, assemble the path manually - cmd_path = os.path.abspath(os.path.join(sys.prefix, 'bin', 'sphinx-apidoc')) + cmd_path = os.path.abspath(os.path.join(sys.prefix, "bin", "sphinx-apidoc")) options = [ - '-o', + "-o", apidoc_dir, package_dir, - '--private', - '--force', - '--no-toc', + "--private", + "--force", + "--no-toc", ] # See https://stackoverflow.com/a/30144019 env = os.environ.copy() - env["SPHINX_APIDOC_OPTIONS"] = 'members,special-members,private-members,undoc-members,show-inheritance' + env["SPHINX_APIDOC_OPTIONS"] = "members,special-members,private-members,undoc-members,show-inheritance" subprocess.check_call([cmd_path] + options, env=env) def setup(app): """Set up documentation.""" - app.connect('builder-inited', run_apidoc) + app.connect("builder-inited", run_apidoc) # -- Options for manual page output --------------------------------------- @@ -335,7 +327,7 @@ def setup(app): # ] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -346,77 +338,77 @@ def setup(app): # ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False # Warnings to ignore when using the -n (nitpicky) option # We should ignore any python built-in exception, for instance nitpick_ignore = [ - ('py:exc', 'ArithmeticError'), - ('py:exc', 'AssertionError'), - ('py:exc', 'AttributeError'), - ('py:exc', 'BaseException'), - ('py:exc', 'BufferError'), - ('py:exc', 'DeprecationWarning'), - ('py:exc', 'EOFError'), - ('py:exc', 'EnvironmentError'), - ('py:exc', 'Exception'), - ('py:exc', 'FloatingPointError'), - ('py:exc', 'FutureWarning'), - ('py:exc', 'GeneratorExit'), - ('py:exc', 'IOError'), - ('py:exc', 'ImportError'), - ('py:exc', 'ImportWarning'), - ('py:exc', 'IndentationError'), - ('py:exc', 'IndexError'), - ('py:exc', 'KeyError'), - ('py:exc', 'KeyboardInterrupt'), - ('py:exc', 'LookupError'), - ('py:exc', 'MemoryError'), - ('py:exc', 'NameError'), - ('py:exc', 'NotImplementedError'), - ('py:exc', 'OSError'), - ('py:exc', 'OverflowError'), - ('py:exc', 'PendingDeprecationWarning'), - ('py:exc', 'ReferenceError'), - ('py:exc', 'RuntimeError'), - ('py:exc', 'RuntimeWarning'), - ('py:exc', 'StandardError'), - ('py:exc', 'StopIteration'), - ('py:exc', 'SyntaxError'), - ('py:exc', 'SyntaxWarning'), - ('py:exc', 'SystemError'), - ('py:exc', 'SystemExit'), - ('py:exc', 'TabError'), - ('py:exc', 'TypeError'), - ('py:exc', 'UnboundLocalError'), - ('py:exc', 'UnicodeDecodeError'), - ('py:exc', 'UnicodeEncodeError'), - ('py:exc', 'UnicodeError'), - ('py:exc', 'UnicodeTranslateError'), - ('py:exc', 'UnicodeWarning'), - ('py:exc', 'UserWarning'), - ('py:exc', 'VMSError'), - ('py:exc', 'ValueError'), - ('py:exc', 'Warning'), - ('py:exc', 'WindowsError'), - ('py:exc', 'ZeroDivisionError'), - ('py:obj', 'str'), - ('py:obj', 'list'), - ('py:obj', 'tuple'), - ('py:obj', 'int'), - ('py:obj', 'float'), - ('py:obj', 'bool'), - ('py:obj', 'Mapping'), - ('py:class', 'list'), - ('py:class', 'tuple'), - ('py:class', 'dict'), + ("py:exc", "ArithmeticError"), + ("py:exc", "AssertionError"), + ("py:exc", "AttributeError"), + ("py:exc", "BaseException"), + ("py:exc", "BufferError"), + ("py:exc", "DeprecationWarning"), + ("py:exc", "EOFError"), + ("py:exc", "EnvironmentError"), + ("py:exc", "Exception"), + ("py:exc", "FloatingPointError"), + ("py:exc", "FutureWarning"), + ("py:exc", "GeneratorExit"), + ("py:exc", "IOError"), + ("py:exc", "ImportError"), + ("py:exc", "ImportWarning"), + ("py:exc", "IndentationError"), + ("py:exc", "IndexError"), + ("py:exc", "KeyError"), + ("py:exc", "KeyboardInterrupt"), + ("py:exc", "LookupError"), + ("py:exc", "MemoryError"), + ("py:exc", "NameError"), + ("py:exc", "NotImplementedError"), + ("py:exc", "OSError"), + ("py:exc", "OverflowError"), + ("py:exc", "PendingDeprecationWarning"), + ("py:exc", "ReferenceError"), + ("py:exc", "RuntimeError"), + ("py:exc", "RuntimeWarning"), + ("py:exc", "StandardError"), + ("py:exc", "StopIteration"), + ("py:exc", "SyntaxError"), + ("py:exc", "SyntaxWarning"), + ("py:exc", "SystemError"), + ("py:exc", "SystemExit"), + ("py:exc", "TabError"), + ("py:exc", "TypeError"), + ("py:exc", "UnboundLocalError"), + ("py:exc", "UnicodeDecodeError"), + ("py:exc", "UnicodeEncodeError"), + ("py:exc", "UnicodeError"), + ("py:exc", "UnicodeTranslateError"), + ("py:exc", "UnicodeWarning"), + ("py:exc", "UserWarning"), + ("py:exc", "VMSError"), + ("py:exc", "ValueError"), + ("py:exc", "Warning"), + ("py:exc", "WindowsError"), + ("py:exc", "ZeroDivisionError"), + ("py:obj", "str"), + ("py:obj", "list"), + ("py:obj", "tuple"), + ("py:obj", "int"), + ("py:obj", "float"), + ("py:obj", "bool"), + ("py:obj", "Mapping"), + ("py:class", "list"), + ("py:class", "tuple"), + ("py:class", "dict"), ] diff --git a/examples/simple_calculations/example_base.py b/examples/simple_calculations/example_base.py index 11567ec..dd4dab8 100755 --- a/examples/simple_calculations/example_base.py +++ b/examples/simple_calculations/example_base.py @@ -1,18 +1,19 @@ -# -*- coding: utf-8 -*- """Run simple RASPA calculation.""" -import os import sys + import click import pytest - from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict from aiida.plugins import DataFactory +from importlib_resources import files + +import aiida_raspa # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("cif") # pylint: disable=invalid-name def example_base(raspa_code, submit=True): @@ -49,10 +50,11 @@ def example_base(raspa_code, submit=True): "CreateNumberOfMolecules": 0, } }, - }) + } + ) # framework - framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'files', 'TCC1RS.cif')) + framework = CifData(file=(files(aiida_raspa).parent / "examples" / "files" / "TCC1RS.cif").as_posix()) # Contructing builder builder = raspa_code.get_builder() @@ -75,8 +77,10 @@ def example_base(raspa_code, submit=True): print("Testing RASPA with simple input ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc:", - res['output_parameters'].dict.tcc1rs['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc:", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") pytest.base_calc_pk = pk else: @@ -89,20 +93,20 @@ def example_base(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_base_restart.py b/examples/simple_calculations/example_base_restart.py index 2eddae3..0cd5129 100755 --- a/examples/simple_calculations/example_base_restart.py +++ b/examples/simple_calculations/example_base_restart.py @@ -1,29 +1,21 @@ -# -*- coding: utf-8 -*- """Restart from simple RASPA calculation.""" -import os import sys -import click -import pytest +import click +from aiida import orm from aiida.common import NotExistent -from aiida.engine import run_get_pk, run -from aiida.orm import Code, Dict, load_node -from aiida.plugins import DataFactory +from aiida.engine import run, run_get_pk +from importlib_resources import files -# data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +import aiida_raspa -def example_base_restart(raspa_code, base_calc_pk=None, submit=True): +def example_base_restart(raspa_code, base_calc_pk, submit=True): """Prepare and submit restart from simple RASPA calculation.""" - # This line is needed for tests only - if base_calc_pk is None: - base_calc_pk = pytest.base_calc_pk # pylint: disable=no-member - # parameters - parameters = Dict( + parameters = orm.Dict( dict={ "GeneralSettings": { "SimulationType": "MonteCarlo", @@ -52,13 +44,13 @@ def example_base_restart(raspa_code, base_calc_pk=None, submit=True): "CreateNumberOfMolecules": 0, } }, - }) + } + ) # framework - framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'files', 'TCC1RS.cif')) - + framework = orm.CifData(file=(files(aiida_raspa).parent / "examples" / "files" / "TCC1RS.cif").as_posix()) # restart file - retrieved_parent_folder = load_node(base_calc_pk).outputs.retrieved + retrieved_parent_folder = orm.load_node(base_calc_pk).outputs.retrieved # Contructing builder builder = raspa_code.get_builder() @@ -82,8 +74,10 @@ def example_base_restart(raspa_code, base_calc_pk=None, submit=True): print("Testing RASPA with simple input, restart ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc:", - res['output_parameters'].dict.tcc1rs['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc:", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -95,21 +89,21 @@ def example_base_restart(raspa_code, base_calc_pk=None, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--previous_calc', '-p', required=True, type=int, help='PK of example_base.py calculation') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--previous_calc", "-p", required=True, type=int, help="PK of example_base.py calculation") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, previous_calc, submit): """Click interface""" try: - code = Code.get_from_string(codelabel) + code = orm.Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base_restart(code, previous_calc, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_binary_mixture.py b/examples/simple_calculations/example_binary_mixture.py index 60bde7d..0e7ff56 100755 --- a/examples/simple_calculations/example_binary_mixture.py +++ b/examples/simple_calculations/example_binary_mixture.py @@ -1,11 +1,10 @@ -# -*- coding: utf-8 -*- """Run RASPA calculation with components mixture.""" import sys -import click +import click from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict @@ -50,7 +49,8 @@ def example_binary_misture(raspa_code, submit=True): "CreateNumberOfMolecules": 30, }, }, - }) + } + ) # Contructing builder builder = raspa_code.get_builder() @@ -70,8 +70,10 @@ def example_binary_misture(raspa_code, submit=True): print("Testing RASPA with binary mixture (propane/butane) ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of propane molecules/uc:", - res['output_parameters'].dict.box_25_angstrom['components']['propane']['loading_absolute_average']) + print( + "Average number of propane molecules/uc:", + res["output_parameters"].dict.box_25_angstrom["components"]["propane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -83,20 +85,20 @@ def example_binary_misture(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_binary_misture(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_block_pockets_2frameworks_2molecules.py b/examples/simple_calculations/example_block_pockets_2frameworks_2molecules.py index 319c948..63be7d4 100755 --- a/examples/simple_calculations/example_block_pockets_2frameworks_2molecules.py +++ b/examples/simple_calculations/example_block_pockets_2frameworks_2molecules.py @@ -1,23 +1,20 @@ -# -*- coding: utf-8 -*- """Run RASPA calculation with blocked pockets.""" -import os import sys -import click +import click +from aiida import orm from aiida.common import NotExistent -from aiida.engine import run_get_pk, run -from aiida.orm import Code, Dict, SinglefileData -from aiida.plugins import DataFactory +from aiida.engine import run, run_get_pk +from importlib_resources import files -# data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +import aiida_raspa def example_block_pockets(raspa_code, submit=True): """Prepare and submit RASPA calculation with blocked pockets.""" # parameters - parameters = Dict( + parameters = orm.Dict( dict={ "GeneralSettings": { "SimulationType": "MonteCarlo", @@ -43,7 +40,7 @@ def example_block_pockets(raspa_code, submit=True): "HeliumVoidFraction": 0.149, "ExternalTemperature": 300.0, "ExternalPressure": 1e5, - } + }, }, "Component": { "methane": { @@ -75,16 +72,20 @@ def example_block_pockets(raspa_code, submit=True): }, }, }, - }) + } + ) # frameworks - pwd = os.path.dirname(os.path.realpath(__file__)) - framework_1 = CifData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1.cif')) - framework_10 = CifData(file=os.path.join(pwd, '..', 'files', 'IRMOF-10.cif')) + framework_1 = orm.CifData(file=(files(aiida_raspa).parent / "examples" / "files" / "IRMOF-1.cif").as_posix()) + framework_10 = orm.CifData(file=(files(aiida_raspa).parent / "examples" / "files" / "IRMOF-10.cif").as_posix()) # block pocket - block_pocket_1 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1_test.block')).store() - block_pocket_10 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'IRMOF-10_test.block')).store() + block_pocket_1 = orm.SinglefileData( + file=(files(aiida_raspa).parent / "examples" / "files" / "IRMOF-1_test.block").as_posix() + ) + block_pocket_10 = orm.SinglefileData( + file=(files(aiida_raspa).parent / "examples" / "files" / "IRMOF-10_test.block").as_posix() + ) # Contructing builder builder = raspa_code.get_builder() @@ -109,14 +110,20 @@ def example_block_pockets(raspa_code, submit=True): builder.metadata.store_provenance = True if submit: - print("Testing RASPA calculation with two frameworks each one " - "containing 2 molecules (metahne/xenon) and block pockets ...") + print( + "Testing RASPA calculation with two frameworks each one " + "containing 2 molecules (metahne/xenon) and block pockets ..." + ) res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc (irmof-1):", - res['output_parameters'].dict.irmof_1['components']['methane']['loading_absolute_average']) - print("Average number of methane molecules/uc (irmof-10):", - res['output_parameters'].dict.irmof_1['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc (irmof-1):", + res["output_parameters"].dict.irmof_1["components"]["methane"]["loading_absolute_average"], + ) + print( + "Average number of methane molecules/uc (irmof-10):", + res["output_parameters"].dict.irmof_1["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -127,20 +134,20 @@ def example_block_pockets(raspa_code, submit=True): print("In order to actually submit, add '--submit'") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: - code = Code.get_from_string(codelabel) + code = orm.load_code(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_block_pockets(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_block_pockets_simple.py b/examples/simple_calculations/example_block_pockets_simple.py index ca53c94..1422541 100755 --- a/examples/simple_calculations/example_block_pockets_simple.py +++ b/examples/simple_calculations/example_block_pockets_simple.py @@ -1,23 +1,20 @@ -# -*- coding: utf-8 -*- """Run RASPA calculation with blocked pockets.""" -import os import sys -import click +import click +from aiida import orm from aiida.common import NotExistent -from aiida.engine import run_get_pk, run -from aiida.orm import Code, Dict, SinglefileData -from aiida.plugins import DataFactory +from aiida.engine import run, run_get_pk +from importlib_resources import files -# data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +import aiida_raspa def example_block_pockets(raspa_code, submit=True): """Prepare and submit RASPA calculation with blocked pockets.""" # parameters - parameters = Dict( + parameters = orm.Dict( dict={ "GeneralSettings": { "SimulationType": "MonteCarlo", @@ -47,14 +44,16 @@ def example_block_pockets(raspa_code, submit=True): "BlockPocketsFileName": "block_tcc1rs_methane", } }, - }) + } + ) # framework - pwd = os.path.dirname(os.path.realpath(__file__)) - framework = CifData(file=os.path.join(pwd, '..', 'files', 'TCC1RS.cif')) + framework = orm.CifData(file=(files(aiida_raspa).parent / "examples" / "files" / "TCC1RS.cif").as_posix()) # block pocket - block_pocket_node = SinglefileData(file=os.path.join(pwd, '..', 'files', 'block_pocket.block')).store() + block_pocket_node = orm.SinglefileData( + file=(files(aiida_raspa).parent / "examples" / "files" / "block_pocket.block").as_posix() + ).store() # Contructing builder builder = raspa_code.get_builder() @@ -80,8 +79,10 @@ def example_block_pockets(raspa_code, submit=True): print("Testing RASPA with block pockets ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc:", - res['output_parameters'].dict.tcc1rs['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc:", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -92,20 +93,20 @@ def example_block_pockets(raspa_code, submit=True): print("In order to actually submit, add '--submit'") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: - code = Code.get_from_string(codelabel) + code = orm.load_code(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_block_pockets(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_ff_files.py b/examples/simple_calculations/example_ff_files.py index c19e14b..d8b33f7 100755 --- a/examples/simple_calculations/example_ff_files.py +++ b/examples/simple_calculations/example_ff_files.py @@ -1,13 +1,11 @@ -# -*- coding: utf-8 -*- """Run RASPA calculation using Local force field""" - -import sys import os -import click +import sys +import click from aiida.common import NotExistent -from aiida.engine import run_get_pk, run -from aiida.orm import Code, Dict, CifData, SinglefileData +from aiida.engine import run, run_get_pk +from aiida.orm import CifData, Code, Dict, SinglefileData def example_ff_files(raspa_code, submit=True): @@ -55,21 +53,22 @@ def example_ff_files(raspa_code, submit=True): "CreateNumberOfMolecules": 0, }, }, - }) + } + ) # Contructing builder pwd = os.path.dirname(os.path.realpath(__file__)) builder = raspa_code.get_builder() builder.framework = { - "irmof_1": CifData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1_eqeq.cif')), + "irmof_1": CifData(file=os.path.join(pwd, "..", "files", "IRMOF-1_eqeq.cif")), } # Note: Here the SinglefileData in the dict are stored otherwise the dry_run crashes. # However, this is not needed for real calculations (e.g., using --submit), since the work chains stores them. builder.file = { - "file_1": SinglefileData(file=os.path.join(pwd, '..', 'files', 'force_field_mixing_rules.def')).store(), - "file_2": SinglefileData(file=os.path.join(pwd, '..', 'files', 'pseudo_atoms.def')).store(), - "file_3": SinglefileData(file=os.path.join(pwd, '..', 'files', 'CO2.def')).store(), - "file_4": SinglefileData(file=os.path.join(pwd, '..', 'files', 'N2.def')).store(), + "file_1": SinglefileData(file=os.path.join(pwd, "..", "files", "force_field_mixing_rules.def")).store(), + "file_2": SinglefileData(file=os.path.join(pwd, "..", "files", "pseudo_atoms.def")).store(), + "file_3": SinglefileData(file=os.path.join(pwd, "..", "files", "CO2.def")).store(), + "file_4": SinglefileData(file=os.path.join(pwd, "..", "files", "N2.def")).store(), } builder.parameters = parameters builder.metadata.options = { @@ -87,11 +86,14 @@ def example_ff_files(raspa_code, submit=True): print("Testing RASPA CO2/N2 adsorption in IRMOF-1, using Local force field ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("CO2/N2 uptake ({:s}): {:.2f}/{:.2f} ".format( - res['output_parameters']["irmof_1"]["components"]['N2']["loading_absolute_unit"], - res['output_parameters']["irmof_1"]["components"]['CO2']["loading_absolute_average"], - res['output_parameters']["irmof_1"]["components"]['N2']["loading_absolute_average"], - )) + # pylint: disable=consider-using-f-string + print( + "CO2/N2 uptake ({:s}): {:.2f}/{:.2f} ".format( + res["output_parameters"]["irmof_1"]["components"]["N2"]["loading_absolute_unit"], + res["output_parameters"]["irmof_1"]["components"]["CO2"]["loading_absolute_average"], + res["output_parameters"]["irmof_1"]["components"]["N2"]["loading_absolute_average"], + ) + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -103,20 +105,20 @@ def example_ff_files(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_ff_files(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_framework_box.py b/examples/simple_calculations/example_framework_box.py index ab10a69..8867f0d 100755 --- a/examples/simple_calculations/example_framework_box.py +++ b/examples/simple_calculations/example_framework_box.py @@ -1,23 +1,22 @@ #!/usr/bin/env python2 -# -*- coding: utf-8 -*- """Run simple RASPA calculation.""" import os import sys + import click import pytest - from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict from aiida.plugins import DataFactory # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("cif") # pylint: disable=invalid-name def example_framework_box(raspa_code, submit=True): - """"Test RASPA with framework and box.""" + """ "Test RASPA with framework and box.""" # parameters parameters = Dict( @@ -55,14 +54,15 @@ def example_framework_box(raspa_code, submit=True): "CreateNumberOfMolecules": { "tcc1rs": 1, "box_25_angstroms": 2, - } + }, } }, - }) + } + ) pwd = os.path.dirname(os.path.realpath(__file__)) # framework - framework = CifData(file=os.path.join(pwd, '..', 'files', 'TCC1RS.cif')) + framework = CifData(file=os.path.join(pwd, "..", "files", "TCC1RS.cif")) # Contructing builder builder = raspa_code.get_builder() @@ -85,10 +85,14 @@ def example_framework_box(raspa_code, submit=True): print("Testing RASPA with framework and box ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc (tcc1rs):", - res['output_parameters'].dict.tcc1rs['components']['methane']['loading_absolute_average']) - print("Average number of methane molecules/uc (box):", - res['output_parameters'].dict.box_25_angstroms['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc (tcc1rs):", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["loading_absolute_average"], + ) + print( + "Average number of methane molecules/uc (box):", + res["output_parameters"].dict.box_25_angstroms["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") pytest.framework_box_calc_pk = pk else: @@ -101,20 +105,20 @@ def example_framework_box(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_framework_box(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_framework_box_restart.py b/examples/simple_calculations/example_framework_box_restart.py index adc510d..bf59e90 100755 --- a/examples/simple_calculations/example_framework_box_restart.py +++ b/examples/simple_calculations/example_framework_box_restart.py @@ -1,18 +1,17 @@ -# -*- coding: utf-8 -*- """Run simple RASPA calculation.""" import os import sys + import click import pytest - from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict, load_node from aiida.plugins import DataFactory # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("cif") # pylint: disable=invalid-name def example_framework_box_restart(raspa_code, framework_box_calc_pk=None, submit=True): @@ -57,10 +56,11 @@ def example_framework_box_restart(raspa_code, framework_box_calc_pk=None, submit "SwapProbability": 1.0, } }, - }) + } + ) # framework - framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'files', 'TCC1RS.cif')) + framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "files", "TCC1RS.cif")) # restart file retrieved_parent_folder = load_node(framework_box_calc_pk).outputs.retrieved @@ -87,10 +87,14 @@ def example_framework_box_restart(raspa_code, framework_box_calc_pk=None, submit print("Testing RASPA with framework and box, restart ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc (tcc1rs):", - res['output_parameters'].dict.tcc1rs['components']['methane']['loading_absolute_average']) - print("Average number of methane molecules/uc (box):", - res['output_parameters'].dict.box_25_angstroms['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc (tcc1rs):", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["loading_absolute_average"], + ) + print( + "Average number of methane molecules/uc (box):", + res["output_parameters"].dict.box_25_angstroms["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -102,21 +106,21 @@ def example_framework_box_restart(raspa_code, framework_box_calc_pk=None, submit print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--previous_calc', '-p', required=True, type=int, help='PK of example_framework_box.py calculation') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--previous_calc", "-p", required=True, type=int, help="PK of example_framework_box.py calculation") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, previous_calc, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_framework_box_restart(code, previous_calc, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_gemc_single_comp.py b/examples/simple_calculations/example_gemc_single_comp.py index d7ba3fa..0987258 100755 --- a/examples/simple_calculations/example_gemc_single_comp.py +++ b/examples/simple_calculations/example_gemc_single_comp.py @@ -1,12 +1,11 @@ -# -*- coding: utf-8 -*- """Run RASPA single-component GEMC calculation""" import sys + import click import pytest - from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict @@ -38,7 +37,7 @@ def example_gemc_single_comp(raspa_code, submit=True): "BoxLengths": "25 25 25", "BoxAngles": "90 90 90", "ExternalTemperature": 300.0, - } + }, }, "Component": { "methane": { @@ -52,7 +51,8 @@ def example_gemc_single_comp(raspa_code, submit=True): }, }, }, - }) + } + ) # Contructing builder builder = raspa_code.get_builder() @@ -72,10 +72,14 @@ def example_gemc_single_comp(raspa_code, submit=True): print("Testing RASPA GEMC with methane ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc (box_one):", - res['output_parameters'].dict.box_one['components']['methane']['loading_absolute_average']) - print("Average number of methane molecules/uc (box_two):", - res['output_parameters'].dict.box_two['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc (box_one):", + res["output_parameters"].dict.box_one["components"]["methane"]["loading_absolute_average"], + ) + print( + "Average number of methane molecules/uc (box_two):", + res["output_parameters"].dict.box_two["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") pytest.gemc_single_comp_calc_pk = pk else: @@ -88,20 +92,20 @@ def example_gemc_single_comp(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_gemc_single_comp(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_gemc_single_comp_restart.py b/examples/simple_calculations/example_gemc_single_comp_restart.py index c4b8ea3..170e72c 100755 --- a/examples/simple_calculations/example_gemc_single_comp_restart.py +++ b/examples/simple_calculations/example_gemc_single_comp_restart.py @@ -1,12 +1,11 @@ -# -*- coding: utf-8 -*- """Run RASPA single-component GEMC calculation -- Restart""" import sys + import click import pytest - from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict, load_node @@ -42,7 +41,7 @@ def example_gemc_single_comp(raspa_code, gemc_single_comp_calc_pk=None, submit=T "BoxLengths": "25 25 25", "BoxAngles": "90 90 90", "ExternalTemperature": 200.0, - } + }, }, "Component": { "methane": { @@ -56,7 +55,8 @@ def example_gemc_single_comp(raspa_code, gemc_single_comp_calc_pk=None, submit=T }, }, }, - }) + } + ) # restart file retrieved_parent_folder = load_node(gemc_single_comp_calc_pk).outputs.retrieved @@ -80,10 +80,14 @@ def example_gemc_single_comp(raspa_code, gemc_single_comp_calc_pk=None, submit=T print("Testing RASPA GEMC with methane (Restart)...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc (box_one):", - res['output_parameters'].dict.box_one['components']['methane']['loading_absolute_average']) - print("Average number of methane molecules/uc (box_two):", - res['output_parameters'].dict.box_two['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc (box_one):", + res["output_parameters"].dict.box_one["components"]["methane"]["loading_absolute_average"], + ) + print( + "Average number of methane molecules/uc (box_two):", + res["output_parameters"].dict.box_two["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -95,21 +99,21 @@ def example_gemc_single_comp(raspa_code, gemc_single_comp_calc_pk=None, submit=T print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--previous_calc', '-p', required=True, type=int, help='PK of example_framework_box.py calculation') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--previous_calc", "-p", required=True, type=int, help="PK of example_framework_box.py calculation") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, previous_calc, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_gemc_single_comp(code, previous_calc, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_henry.py b/examples/simple_calculations/example_henry.py index 9614a83..531d40b 100755 --- a/examples/simple_calculations/example_henry.py +++ b/examples/simple_calculations/example_henry.py @@ -1,16 +1,15 @@ -# -*- coding: utf-8 -*- """Run RASPA calculation to compute Henry coefficient.""" import os import sys -import click +import click from aiida.common import NotExistent -from aiida.engine import run_get_pk, run -from aiida.plugins import DataFactory +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict +from aiida.plugins import DataFactory # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("cif") # pylint: disable=invalid-name def example_henry(raspa_code, submit=True): @@ -42,11 +41,12 @@ def example_henry(raspa_code, submit=True): "CreateNumberOfMolecules": 0, } }, - }) + } + ) # framework pwd = os.path.dirname(os.path.realpath(__file__)) - framework = CifData(file=os.path.join(pwd, '..', 'files', 'TCC1RS.cif')) + framework = CifData(file=os.path.join(pwd, "..", "files", "TCC1RS.cif")) # Contructing builder builder = raspa_code.get_builder() @@ -69,8 +69,10 @@ def example_henry(raspa_code, submit=True): print("Testing RASPA on computing Henry coefficient ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average Henry coefficient (methane in tcc1rs):", - res['output_parameters'].dict.tcc1rs['components']['methane']['henry_coefficient_average']) + print( + "Average Henry coefficient (methane in tcc1rs):", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["henry_coefficient_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -82,20 +84,20 @@ def example_henry(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_henry(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/example_identity.py b/examples/simple_calculations/example_identity.py index 92840b6..7da3812 100755 --- a/examples/simple_calculations/example_identity.py +++ b/examples/simple_calculations/example_identity.py @@ -1,17 +1,16 @@ -# -*- coding: utf-8 -*- """Run simple RASPA calculation.""" import os import sys -import click +import click from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict from aiida.plugins import DataFactory # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("cif") # pylint: disable=invalid-name def example_identity(raspa_code, submit=True): @@ -82,10 +81,11 @@ def example_identity(raspa_code, submit=True): "CreateNumberOfMolecules": 0, }, }, - }) + } + ) # framework - framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'files', 'TCC1RS.cif')) + framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "files", "TCC1RS.cif")) # Contructing builder builder = raspa_code.get_builder() @@ -108,8 +108,10 @@ def example_identity(raspa_code, submit=True): print("Testing RASPA with changing identity ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Average number of methane molecules/uc:", - res['output_parameters'].dict.tcc1rs['components']['methane']['loading_absolute_average']) + print( + "Average number of methane molecules/uc:", + res["output_parameters"].dict.tcc1rs["components"]["methane"]["loading_absolute_average"], + ) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -121,20 +123,20 @@ def example_identity(raspa_code, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_identity(code, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/simple_calculations/fixme_base_binary_restart.py b/examples/simple_calculations/fixme_base_binary_restart.py index f8a5591..b999534 100755 --- a/examples/simple_calculations/fixme_base_binary_restart.py +++ b/examples/simple_calculations/fixme_base_binary_restart.py @@ -1,18 +1,17 @@ -# -*- coding: utf-8 -*- """Restart from simple RASPA calculation.""" import os import sys + import click import pytest - from aiida.common import NotExistent -from aiida.engine import run_get_pk, run +from aiida.engine import run, run_get_pk from aiida.orm import Code, Dict, load_node from aiida.plugins import DataFactory # data objects -CifData = DataFactory('cif') # pylint: disable=invalid-name +CifData = DataFactory("cif") # pylint: disable=invalid-name def example_binary_restart(raspa_code, base_calc_pk=None, submit=True): @@ -52,10 +51,11 @@ def example_binary_restart(raspa_code, base_calc_pk=None, submit=True): "CreateNumberOfMolecules": 0, } }, - }) + } + ) # framework - framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'files', 'TCC1RS.cif')) + framework = CifData(file=os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "files", "TCC1RS.cif")) # restart file parent_folder = load_node(base_calc_pk).outputs.remote_folder @@ -82,7 +82,7 @@ def example_binary_restart(raspa_code, base_calc_pk=None, submit=True): print("Testing RASPA with simple input, binary restart ...") res, pk = run_get_pk(builder) print("calculation pk: ", pk) - print("Total Energy average (tcc1rs):", res['output_parameters'].dict.tcc1rs['general']['total_energy_average']) + print("Total Energy average (tcc1rs):", res["output_parameters"].dict.tcc1rs["general"]["total_energy_average"]) print("OK, calculation has completed successfully") else: print("Generating test input ...") @@ -94,21 +94,21 @@ def example_binary_restart(raspa_code, base_calc_pk=None, submit=True): print("-----") -@click.command('cli') -@click.argument('codelabel') -@click.option('--previous_calc', '-p', required=True, type=int, help='PK of example_base.py calculation') -@click.option('--submit', is_flag=True, help='Actually submit calculation') +@click.command("cli") +@click.argument("codelabel") +@click.option("--previous_calc", "-p", required=True, type=int, help="PK of example_base.py calculation") +@click.option("--submit", is_flag=True, help="Actually submit calculation") def cli(codelabel, previous_calc, submit): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_binary_restart(code, previous_calc, submit) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/workchains/example_base_restart_timeout.py b/examples/workchains/example_base_restart_timeout.py index 7fd25a7..e158e60 100644 --- a/examples/workchains/example_base_restart_timeout.py +++ b/examples/workchains/example_base_restart_timeout.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- """Example for RaspaBaseWorkChain.""" import os import sys -import click +import click from aiida.common import NotExistent from aiida.engine import run_get_node -from aiida.orm import CifData, Code, Dict, SinglefileData, Int +from aiida.orm import CifData, Code, Dict, Int, SinglefileData + from aiida_raspa.workchains import RaspaBaseWorkChain @@ -51,14 +51,15 @@ def example_base_restart_timeout(raspa_code): }, }, }, - }) + } + ) # framework pwd = os.path.dirname(os.path.realpath(__file__)) - structure = CifData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1.cif')) + structure = CifData(file=os.path.join(pwd, "..", "files", "IRMOF-1.cif")) structure_label = "irmof_1" - block_pocket_node1 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1_test.block')).store() + block_pocket_node1 = SinglefileData(file=os.path.join(pwd, "..", "files", "IRMOF-1_test.block")).store() # Constructing builder builder = RaspaBaseWorkChain.get_builder() @@ -97,19 +98,19 @@ def example_base_restart_timeout(raspa_code): assert node.exit_status == 0 -@click.command('cli') -@click.argument('codelabel') +@click.command("cli") +@click.argument("codelabel") def cli(codelabel): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base_restart_timeout(code) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/workchains/example_base_workchain_gcmc_2comp.py b/examples/workchains/example_base_workchain_gcmc_2comp.py index 2d6c8f9..8fbc832 100644 --- a/examples/workchains/example_base_workchain_gcmc_2comp.py +++ b/examples/workchains/example_base_workchain_gcmc_2comp.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- """Two-component GCMC through RaspaBaseWorkChain""" import os import sys -import click +import click from aiida.common import NotExistent from aiida.engine import run_get_node from aiida.orm import CifData, Code, Dict, SinglefileData + from aiida_raspa.workchains import RaspaBaseWorkChain @@ -59,15 +59,16 @@ def example_base_workchain_gcmc(raspa_code): }, }, }, - }) + } + ) # framework pwd = os.path.dirname(os.path.realpath(__file__)) - structure = CifData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1.cif')) + structure = CifData(file=os.path.join(pwd, "..", "files", "IRMOF-1.cif")) structure_label = "irmof_1" - block_pocket_node1 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1_test.block')).store() - block_pocket_node2 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'IRMOF-1_test.block')).store() + block_pocket_node1 = SinglefileData(file=os.path.join(pwd, "..", "files", "IRMOF-1_test.block")).store() + block_pocket_node2 = SinglefileData(file=os.path.join(pwd, "..", "files", "IRMOF-1_test.block")).store() # Constructing builder builder = RaspaBaseWorkChain.get_builder() @@ -89,8 +90,9 @@ def example_base_workchain_gcmc(raspa_code): "irmof_1_xenon": block_pocket_node2, } - builder.handler_overrides = Dict(dict={'check_gcmc_convergence': True - }) # Enable gcmc convergence handler disabled by default. + builder.handler_overrides = Dict( + dict={"check_gcmc_convergence": True} + ) # Enable gcmc convergence handler disabled by default. # Specifying the scheduler options builder.raspa.metadata.options = { @@ -106,19 +108,19 @@ def example_base_workchain_gcmc(raspa_code): assert node.exit_status == 0 -@click.command('cli') -@click.argument('codelabel') +@click.command("cli") +@click.argument("codelabel") def cli(codelabel): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base_workchain_gcmc(code) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/workchains/example_base_workchain_widom_1comp.py b/examples/workchains/example_base_workchain_widom_1comp.py index 6caae7d..3e9aef0 100644 --- a/examples/workchains/example_base_workchain_widom_1comp.py +++ b/examples/workchains/example_base_workchain_widom_1comp.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- """One-component Widom particle insertion through RaspaBaseWorkChain""" import os import sys -import click +import click from aiida.common import NotExistent from aiida.engine import run_get_node from aiida.orm import CifData, Code, Dict, SinglefileData + from aiida_raspa.workchains import RaspaBaseWorkChain @@ -41,14 +41,15 @@ def example_base_workchain_widom(raspa_code): "BlockPocketsFileName": "block_tcc1rs_xenon", }, }, - }) + } + ) # framework pwd = os.path.dirname(os.path.realpath(__file__)) - structure = CifData(file=os.path.join(pwd, '..', 'files', 'TCC1RS.cif')) + structure = CifData(file=os.path.join(pwd, "..", "files", "TCC1RS.cif")) structure_label = structure.filename[:-4].lower() - block_pocket_node1 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'block_pocket.block')).store() + block_pocket_node1 = SinglefileData(file=os.path.join(pwd, "..", "files", "block_pocket.block")).store() # Constructing builder builder = RaspaBaseWorkChain.get_builder() @@ -70,8 +71,9 @@ def example_base_workchain_widom(raspa_code): } # Add handlers that could handle physics-related problems. - builder.handler_overrides = Dict(dict={'check_widom_convergence': True - }) # Enable widom convergence handler disabled by default. + builder.handler_overrides = Dict( + dict={"check_widom_convergence": True} + ) # Enable widom convergence handler disabled by default. # Specifying the scheduler options builder.raspa.metadata.options = { @@ -87,19 +89,19 @@ def example_base_workchain_widom(raspa_code): assert node.exit_status == 0 -@click.command('cli') -@click.argument('codelabel') +@click.command("cli") +@click.argument("codelabel") def cli(codelabel): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base_workchain_widom(code) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/workchains/example_base_workchain_widom_2comp.py b/examples/workchains/example_base_workchain_widom_2comp.py index 6e150ac..6046b75 100644 --- a/examples/workchains/example_base_workchain_widom_2comp.py +++ b/examples/workchains/example_base_workchain_widom_2comp.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- """Two-component Widom insertion through RaspaBaseWorkChain""" import os import sys -import click +import click from aiida.common import NotExistent from aiida.engine import run_get_node from aiida.orm import CifData, Code, Dict, SinglefileData + from aiida_raspa.workchains import RaspaBaseWorkChain @@ -48,15 +48,16 @@ def example_base_workchain_widom_2(raspa_code): "BlockPocketsFileName": "block_tcc1rs_xenon", }, }, - }) + } + ) # framework pwd = os.path.dirname(os.path.realpath(__file__)) - structure = CifData(file=os.path.join(pwd, '..', 'files', 'TCC1RS.cif')) + structure = CifData(file=os.path.join(pwd, "..", "files", "TCC1RS.cif")) structure_label = structure.filename[:-4].lower() - block_pocket_node1 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'block_pocket.block')).store() - block_pocket_node2 = SinglefileData(file=os.path.join(pwd, '..', 'files', 'block_pocket.block')).store() + block_pocket_node1 = SinglefileData(file=os.path.join(pwd, "..", "files", "block_pocket.block")).store() + block_pocket_node2 = SinglefileData(file=os.path.join(pwd, "..", "files", "block_pocket.block")).store() # Constructing builder builder = RaspaBaseWorkChain.get_builder() @@ -78,8 +79,9 @@ def example_base_workchain_widom_2(raspa_code): "block_tcc1rs_xenon": block_pocket_node2, } - builder.handler_overrides = Dict(dict={'check_widom_convergence': True - }) # Enable widom convergence handler disabled by default. + builder.handler_overrides = Dict( + dict={"check_widom_convergence": True} + ) # Enable widom convergence handler disabled by default. # Specifying the scheduler options builder.raspa.metadata.options = { @@ -95,19 +97,19 @@ def example_base_workchain_widom_2(raspa_code): assert node.exit_status == 0 -@click.command('cli') -@click.argument('codelabel') +@click.command("cli") +@click.argument("codelabel") def cli(codelabel): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base_workchain_widom_2(code) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/examples/workchains/too_long_base_workchain_gemc_1comp.py b/examples/workchains/too_long_base_workchain_gemc_1comp.py index 5f65923..76fce5a 100644 --- a/examples/workchains/too_long_base_workchain_gemc_1comp.py +++ b/examples/workchains/too_long_base_workchain_gemc_1comp.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- """One-component GEMC through RaspaBaseWorkChain""" import sys -import click +import click from aiida.common import NotExistent from aiida.engine import run_get_node from aiida.orm import Code, Dict + from aiida_raspa.workchains import RaspaBaseWorkChain @@ -41,7 +41,7 @@ def example_base_workchain_gemc(raspa_code): "BoxLengths": "30 30 30", "BoxAngles": "90 90 90", "ExternalTemperature": 300.0, - } + }, }, "Component": { "methane": { @@ -55,7 +55,8 @@ def example_base_workchain_gemc(raspa_code): }, }, }, - }) + } + ) # Constructing builder builder = RaspaBaseWorkChain.get_builder() @@ -67,10 +68,12 @@ def example_base_workchain_gemc(raspa_code): builder.raspa.parameters = parameters # Add handlers that could handle physics-related problems. - builder.handler_overrides = Dict(dict={ - 'check_gemc_box': True, - 'check_gemc_convergence': True, - }) # Enable gemc handlers disabled by default. + builder.handler_overrides = Dict( + dict={ + "check_gemc_box": True, + "check_gemc_convergence": True, + } + ) # Enable gemc handlers disabled by default. # Specifying the scheduler options builder.raspa.metadata.options = { @@ -86,19 +89,19 @@ def example_base_workchain_gemc(raspa_code): assert node.exit_status == 0 -@click.command('cli') -@click.argument('codelabel') +@click.command("cli") +@click.argument("codelabel") def cli(codelabel): """Click interface""" try: code = Code.get_from_string(codelabel) except NotExistent: - print("The code '{}' does not exist".format(codelabel)) + print(f"The code '{codelabel}' does not exist") sys.exit(1) example_base_workchain_gemc(code) -if __name__ == '__main__': +if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter # EOF diff --git a/pyproject.toml b/pyproject.toml index ded61ae..99d2212 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,37 +1,109 @@ +[build-system] +requires = ['flit_core >=3.4,<4'] +build-backend = 'flit_core.buildapi' + +[project] +name = 'aiida-raspa' +dynamic = ['version'] +description = 'AiiDA plugin for RASPA code' +authors = [ + { name = 'Aliaksandr Yakutovich', email = 'aliaksandr.yakutovich@epfl.ch' }, + { name = 'Miriam Pougin', email = 'miriam.pougin@epfl.ch' }, +] +readme = 'README.md' +license = {file = 'LICENSE'} +classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Framework :: AiiDA', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', +] +keywords = ['aiida', 'workflows'] +requires-python = '>=3.8' +dependencies = [ + 'aiida_core[atomic_tools]~=2.3', + 'importlib_resources' +] + +[project.urls] +Home = 'https://github.com/yakutovicha/aiida-raspa' +Source = 'https://github.com/yakutovicha/aiida-raspa' + +[project.optional-dependencies] +tests = [ + 'pgtest~=1.3', + 'pytest~=6.0' +] +pre-commit = [ + 'pre-commit~=3.3', + 'black~=23.7', + 'isort~=5.12.0', + 'pylint~=2.17.0', +] +docs = [ + 'sphinx', + 'sphinx-rtd-theme', + 'sphinxcontrib-contentui', + 'sphinxcontrib-details-directive', +] + +[project.entry-points.'aiida.calculations'] +'raspa' = 'aiida_raspa.calculations:RaspaCalculation' + +[project.entry-points.'aiida.parsers'] +'raspa' = 'aiida_raspa.parsers:RaspaParser' + +[project.entry-points.'aiida.workflows'] +'raspa.base' = 'aiida_raspa.workchains:RaspaBaseWorkChain' + +[tool.black] +line-length = 120 +target-version = ['py310'] +include = '\.pyi?$' + [tool.pylint.format] max-line-length = 120 [tool.pylint.messages_control] disable = [ - "too-many-ancestors", - "duplicate-code", - "import-outside-toplevel", + 'too-many-ancestors', + 'too-many-function-args', + 'duplicate-code', + 'import-outside-toplevel', + 'inconsistent-return-statements', ] -module-naming-style="any" +module-naming-style='any' [tool.pytest.ini_options] -python_files = "test_*.py example_*.py" -python_functions = "example_* test_*" +python_files = 'test_*.py' +python_functions = 'test_*' filterwarnings = [ - "ignore::DeprecationWarning:aiida:", - "ignore::DeprecationWarning:plumpy:", - "ignore::DeprecationWarning:django:", - "ignore::DeprecationWarning:frozendict:", - "ignore::DeprecationWarning:sqlalchemy:", - "ignore::DeprecationWarning:yaml:", - "ignore::DeprecationWarning:pymatgen:", + 'ignore::DeprecationWarning:aiida:', + 'ignore::DeprecationWarning:plumpy:', + 'ignore::DeprecationWarning:django:', + 'ignore::DeprecationWarning:frozendict:', + 'ignore::DeprecationWarning:sqlalchemy:', + 'ignore::DeprecationWarning:yaml:', + 'ignore::DeprecationWarning:pymatgen:', ] [tool.pylint.basic] good-names = [ - "_", - "x", - "y", - "z", - "i", - "j", - "k", - "pk", -] -no-docstring-rgx = "^_,setUp,tearDown" + '_', + 'x', + 'y', + 'z', + 'i', + 'j', + 'k', + 'pk', +] +no-docstring-rgx = '^_,setUp,tearDown' docstring-min-length = 5 + +[tool.isort] +profile = "black" diff --git a/setup.json b/setup.json deleted file mode 100644 index 5a6f862..0000000 --- a/setup.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "aiida-raspa", - "version": "1.2.0", - "author": "Aliaksandr Yakutovich", - "author_email": "aliaksandr.yakutovich@epfl.ch", - "description": "AiiDA plugin for RASPA code", - "url": "https://github.com/yakutovicha/aiida-raspa", - "license": "MIT License", - "classifiers": [ - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Framework :: AiiDA", - "Development Status :: 5 - Production/Stable" - ], - "setup_requires": ["reentry"], - "reentry_register": true, - "install_requires": [ - "aiida-core>=1.0.0,<2", - "pycifrw" - ], - "entry_points": { - "aiida.calculations": [ - "raspa = aiida_raspa.calculations:RaspaCalculation" - ], - "aiida.parsers": [ - "raspa = aiida_raspa.parsers:RaspaParser" - ], - "aiida.workflows": [ - "raspa.base = aiida_raspa.workchains:RaspaBaseWorkChain" - ] - }, - "data_files": [ - [".", ["setup.json"]] - ], - "extras_require": { - "test": [ - "pgtest==1.2.0", - "pytest>=4.4,<5.0.0", - "pytest-cov>=2.6.1,<3.0.0", - "coverage" - ], - "pre-commit": [ - "pre-commit~=2.2", - "yapf==0.28.0", - "pylint==1.9.4; python_version<'3.0'", - "pylint~=2.5.0; python_version>='3.0'" - ], - "docs": [ - "sphinx", - "sphinx-rtd-theme", - "sphinxcontrib-contentui", - "sphinxcontrib-details-directive; python_version>='3.0'" - ] - } -} diff --git a/setup.py b/setup.py deleted file mode 100644 index e7f87d8..0000000 --- a/setup.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -"""Setting up RASPA plugin for AiiDA""" - -import json -from setuptools import setup, find_packages - - -def run_setup(): - """Provide static information in setup.json such that - it can be discovered automatically""" - with open('setup.json', 'r') as info: - kwargs = json.load(info) - setup(packages=find_packages(), - long_description=open('README.md').read(), - long_description_content_type='text/markdown', - **kwargs) - - -if __name__ == '__main__': - run_setup() diff --git a/tests/test_input_generator.py b/tests/test_input_generator.py index c778cd4..723222c 100644 --- a/tests/test_input_generator.py +++ b/tests/test_input_generator.py @@ -64,7 +64,9 @@ def test_render_base_input(): }, } inp = RaspaInput(inp_dict) - assert inp.render() == """!!! Generated by AiiDA !!! + assert ( + inp.render() + == """!!! Generated by AiiDA !!! CutOff 12.0 EwaldPrecision 1e-06 Forcefield GenericMOFs @@ -86,3 +88,4 @@ def test_render_base_input(): SwapProbability 1.0 TranslationProbability 0.5 """ + ) diff --git a/tests/test_output_parser.py b/tests/test_output_parser.py index 08717be..78bb968 100644 --- a/tests/test_output_parser.py +++ b/tests/test_output_parser.py @@ -1,6 +1,7 @@ """Test Raspa output parser""" import os +from pathlib import Path from aiida_raspa.utils import parse_base_output @@ -9,361 +10,364 @@ def test_parse_output_one_cmpnt(): """Testing output parser on an output file with one component""" - parsed_parameters = parse_base_output(os.path.join(CWD, "outputs/one_component.out"), - system_name="system1", - ncomponents=1)[0] + + with Path(CWD, "outputs/one_component.out").open("r", encoding="utf-8") as handle: + parsed_parameters = parse_base_output(handle.read(), system_name="system1", ncomponents=1)[0] + general = { - 'exceeded_walltime': False, - 'framework_density': '739.995779685958', - 'framework_density_unit': 'kg/m^3', - 'energy_unit': 'kJ/mol', - 'energy_host/ads_tot_initial': 0.0, - 'energy_host/ads_vdw_initial': 0.0, - 'energy_host/ads_coulomb_initial': 0.0, - 'energy_host/ads_tot_final': -171.717724280208, - 'energy_host/ads_vdw_final': -171.717724280208, - 'energy_host/ads_coulomb_final': 0.0, - 'cell_volume_average': 12025.61229, - 'cell_volume_unit': 'A^3', - 'cell_volume_dev': 0.0, - 'box_ax_average': 34.1995, - 'box_ax_unit': 'A^3', - 'box_ax_dev': 0.0, - 'box_by_average': 22.6557, - 'box_by_unit': 'A^3', - 'box_by_dev': 0.0, - 'box_cz_average': 15.52065, - 'box_cz_unit': 'A^3', - 'box_cz_dev': 0.0, - 'box_alpha_average': 90.0, - 'box_alpha_unit': 'degrees', - 'box_alpha_dev': 0.0, - 'box_beta_average': 52.8626, - 'box_beta_unit': 'degrees', - 'box_beta_dev': 0.0, - 'box_gamma_average': 90.0, - 'box_gamma_unit': 'degrees', - 'box_gamma_dev': 0.0, - 'adsorbate_density_average': 26.62672, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 5.35266, - 'enthalpy_of_adsorption_average': -1928.58214, - 'enthalpy_of_adsorption_unit': 'K', - 'enthalpy_of_adsorption_dev': 204.730157, - 'energy_ads/ads_tot_average': -4.5501817208796655, - 'energy_ads/ads_vdw_average': -4.550181687621805, - 'energy_ads/ads_coulomb_average': 0.0, - 'energy_ads/ads_tot_dev': 2.0057559085076093, - 'energy_ads/ads_vdw_dev': 2.0057559334510042, - 'energy_ads/ads_coulomb_dev': 0.0, - 'energy_host/ads_tot_average': -174.60996722014394, - 'energy_host/ads_vdw_average': -174.60996720351505, - 'energy_host/ads_coulomb_average': 0.0, - 'energy_host/ads_tot_dev': 34.12887304355653, - 'energy_host/ads_vdw_dev': 34.12887304355653, - 'energy_host/ads_coulomb_dev': 0.0, - 'tail_correction_energy_average': 0.0, - 'tail_correction_energy_unit': 'K', - 'tail_correction_energy_dev': 0.0 + "exceeded_walltime": False, + "framework_density": "739.995779685958", + "framework_density_unit": "kg/m^3", + "energy_unit": "kJ/mol", + "energy_host/ads_tot_initial": 0.0, + "energy_host/ads_vdw_initial": 0.0, + "energy_host/ads_coulomb_initial": 0.0, + "energy_host/ads_tot_final": -171.717724280208, + "energy_host/ads_vdw_final": -171.717724280208, + "energy_host/ads_coulomb_final": 0.0, + "cell_volume_average": 12025.61229, + "cell_volume_unit": "A^3", + "cell_volume_dev": 0.0, + "box_ax_average": 34.1995, + "box_ax_unit": "A^3", + "box_ax_dev": 0.0, + "box_by_average": 22.6557, + "box_by_unit": "A^3", + "box_by_dev": 0.0, + "box_cz_average": 15.52065, + "box_cz_unit": "A^3", + "box_cz_dev": 0.0, + "box_alpha_average": 90.0, + "box_alpha_unit": "degrees", + "box_alpha_dev": 0.0, + "box_beta_average": 52.8626, + "box_beta_unit": "degrees", + "box_beta_dev": 0.0, + "box_gamma_average": 90.0, + "box_gamma_unit": "degrees", + "box_gamma_dev": 0.0, + "adsorbate_density_average": 26.62672, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 5.35266, + "enthalpy_of_adsorption_average": -1928.58214, + "enthalpy_of_adsorption_unit": "K", + "enthalpy_of_adsorption_dev": 204.730157, + "energy_ads/ads_tot_average": -4.5501817208796655, + "energy_ads/ads_vdw_average": -4.550181687621805, + "energy_ads/ads_coulomb_average": 0.0, + "energy_ads/ads_tot_dev": 2.0057559085076093, + "energy_ads/ads_vdw_dev": 2.0057559334510042, + "energy_ads/ads_coulomb_dev": 0.0, + "energy_host/ads_tot_average": -174.60996722014394, + "energy_host/ads_vdw_average": -174.60996720351505, + "energy_host/ads_coulomb_average": 0.0, + "energy_host/ads_tot_dev": 34.12887304355653, + "energy_host/ads_vdw_dev": 34.12887304355653, + "energy_host/ads_coulomb_dev": 0.0, + "tail_correction_energy_average": 0.0, + "tail_correction_energy_unit": "K", + "tail_correction_energy_dev": 0.0, } methane = { - 'mol_fraction': 1.0, - 'mol_fraction_unit': '-', - 'conversion_factor_molec_uc_to_mol_kg': 0.1866003989, - 'conversion_factor_molec_uc_to_mol_kg_unit': '(mol/kg)/(molec/uc)', - 'conversion_factor_molec_uc_to_mg_g': 2.9935294361, - 'conversion_factor_molec_uc_to_mg_g_unit': '(mg/g)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_gr': 4.1824568165, - 'conversion_factor_molec_uc_to_cm3stp_gr_unit': '(cm^3_STP/gr)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_cm3': 3.095000393, - 'conversion_factor_molec_uc_to_cm3stp_cm3_unit': '(cm^3_STP/cm^3)/(molec/uc)', - 'partial_pressure': 500000.0, - 'partial_pressure_unit': 'Pa', - 'partial_fugacity': 494612.1383597442, - 'partial_fugacity_unit': 'Pa', - 'adsorbate_density_average': 26.62672, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 5.35266, - 'loading_absolute_average': 12.02, - 'loading_absolute_dev': 2.4163298616, - 'loading_absolute_unit': 'molecules/unit cell', - 'loading_excess_average': 11.02, - 'loading_excess_dev': 2.4163298616, - 'loading_excess_unit': 'molecules/unit cell', - 'widom_rosenbluth_factor_unit': '-', - 'widom_rosenbluth_factor_dev': None, - 'widom_rosenbluth_factor_average': None, - 'chemical_potential_unit': 'K', - 'chemical_potential_dev': None, - 'chemical_potential_average': None, - 'henry_coefficient_unit': 'mol/kg/Pa', - 'henry_coefficient_dev': None, - 'henry_coefficient_average': None, - 'adsorption_energy_widom_unit': 'kJ/mol', - 'adsorption_energy_widom_dev': None, - 'adsorption_energy_widom_average': None + "mol_fraction": 1.0, + "mol_fraction_unit": "-", + "conversion_factor_molec_uc_to_mol_kg": 0.1866003989, + "conversion_factor_molec_uc_to_mol_kg_unit": "(mol/kg)/(molec/uc)", + "conversion_factor_molec_uc_to_mg_g": 2.9935294361, + "conversion_factor_molec_uc_to_mg_g_unit": "(mg/g)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_gr": 4.1824568165, + "conversion_factor_molec_uc_to_cm3stp_gr_unit": "(cm^3_STP/gr)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_cm3": 3.095000393, + "conversion_factor_molec_uc_to_cm3stp_cm3_unit": "(cm^3_STP/cm^3)/(molec/uc)", + "partial_pressure": 500000.0, + "partial_pressure_unit": "Pa", + "partial_fugacity": 494612.1383597442, + "partial_fugacity_unit": "Pa", + "adsorbate_density_average": 26.62672, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 5.35266, + "loading_absolute_average": 12.02, + "loading_absolute_dev": 2.4163298616, + "loading_absolute_unit": "molecules/unit cell", + "loading_excess_average": 11.02, + "loading_excess_dev": 2.4163298616, + "loading_excess_unit": "molecules/unit cell", + "widom_rosenbluth_factor_unit": "-", + "widom_rosenbluth_factor_dev": None, + "widom_rosenbluth_factor_average": None, + "chemical_potential_unit": "K", + "chemical_potential_dev": None, + "chemical_potential_average": None, + "henry_coefficient_unit": "mol/kg/Pa", + "henry_coefficient_dev": None, + "henry_coefficient_average": None, + "adsorption_energy_widom_unit": "kJ/mol", + "adsorption_energy_widom_dev": None, + "adsorption_energy_widom_average": None, } for key, value in general.items(): - assert value == parsed_parameters['general'][key] + assert value == parsed_parameters["general"][key] for key, value in methane.items(): - assert value == parsed_parameters['components']['methane'][key] + assert value == parsed_parameters["components"]["methane"][key] def test_parse_output_two_cmpnt(): """Testing output parser on an output file with two components""" - parsed_parameters = parse_base_output(os.path.join(CWD, "outputs/two_components.out"), - system_name="system1", - ncomponents=2)[0] + + with Path(CWD, "outputs/two_components.out").open("r", encoding="utf-8") as handle: + parsed_parameters = parse_base_output(handle.read(), system_name="system1", ncomponents=2)[0] + general = { - 'exceeded_walltime': False, - 'framework_density': '0.000000000000', - 'framework_density_unit': 'kg/m^3', - 'energy_unit': 'kJ/mol', - 'energy_host/ads_tot_initial': 0.0, - 'energy_host/ads_vdw_initial': 0.0, - 'energy_host/ads_coulomb_initial': 0.0, - 'energy_host/ads_tot_final': 0.0, - 'energy_host/ads_vdw_final': 0.0, - 'energy_host/ads_coulomb_final': 0.0, - 'cell_volume_average': 15625.0, - 'cell_volume_unit': 'A^3', - 'cell_volume_dev': 0.0, - 'box_ax_average': 25.0, - 'box_ax_unit': 'A^3', - 'box_ax_dev': 0.0, - 'box_by_average': 25.0, - 'box_by_unit': 'A^3', - 'box_by_dev': 0.0, - 'box_cz_average': 25.0, - 'box_cz_unit': 'A^3', - 'box_cz_dev': 0.0, - 'box_alpha_average': 90.0, - 'box_alpha_unit': 'degrees', - 'box_alpha_dev': 0.0, - 'box_beta_average': 90.0, - 'box_beta_unit': 'degrees', - 'box_beta_dev': 0.0, - 'box_gamma_average': 90.0, - 'box_gamma_unit': 'degrees', - 'box_gamma_dev': 0.0, - 'adsorbate_density_average': 4.40397, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 0.74921, - 'enthalpy_of_adsorption_average': 137.68727, - 'enthalpy_of_adsorption_unit': 'K', - 'enthalpy_of_adsorption_dev': 86.158033, - 'energy_ads/ads_tot_average': -0.15252104334203112, - 'energy_ads/ads_vdw_average': -0.15252104334203112, - 'energy_ads/ads_coulomb_average': 0.0, - 'energy_ads/ads_tot_dev': 0.16141328042825245, - 'energy_ads/ads_vdw_dev': 0.16141332200057704, - 'energy_ads/ads_coulomb_dev': 0.0, - 'energy_host/ads_tot_average': 0.0, - 'energy_host/ads_vdw_average': 0.0, - 'energy_host/ads_coulomb_average': 0.0, - 'energy_host/ads_tot_dev': 0.0, - 'energy_host/ads_vdw_dev': 0.0, - 'energy_host/ads_coulomb_dev': 0.0, - 'tail_correction_energy_average': 0.0, - 'tail_correction_energy_unit': 'K', - 'tail_correction_energy_dev': 0.0 + "exceeded_walltime": False, + "framework_density": "0.000000000000", + "framework_density_unit": "kg/m^3", + "energy_unit": "kJ/mol", + "energy_host/ads_tot_initial": 0.0, + "energy_host/ads_vdw_initial": 0.0, + "energy_host/ads_coulomb_initial": 0.0, + "energy_host/ads_tot_final": 0.0, + "energy_host/ads_vdw_final": 0.0, + "energy_host/ads_coulomb_final": 0.0, + "cell_volume_average": 15625.0, + "cell_volume_unit": "A^3", + "cell_volume_dev": 0.0, + "box_ax_average": 25.0, + "box_ax_unit": "A^3", + "box_ax_dev": 0.0, + "box_by_average": 25.0, + "box_by_unit": "A^3", + "box_by_dev": 0.0, + "box_cz_average": 25.0, + "box_cz_unit": "A^3", + "box_cz_dev": 0.0, + "box_alpha_average": 90.0, + "box_alpha_unit": "degrees", + "box_alpha_dev": 0.0, + "box_beta_average": 90.0, + "box_beta_unit": "degrees", + "box_beta_dev": 0.0, + "box_gamma_average": 90.0, + "box_gamma_unit": "degrees", + "box_gamma_dev": 0.0, + "adsorbate_density_average": 4.40397, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 0.74921, + "enthalpy_of_adsorption_average": 137.68727, + "enthalpy_of_adsorption_unit": "K", + "enthalpy_of_adsorption_dev": 86.158033, + "energy_ads/ads_tot_average": -0.15252104334203112, + "energy_ads/ads_vdw_average": -0.15252104334203112, + "energy_ads/ads_coulomb_average": 0.0, + "energy_ads/ads_tot_dev": 0.16141328042825245, + "energy_ads/ads_vdw_dev": 0.16141332200057704, + "energy_ads/ads_coulomb_dev": 0.0, + "energy_host/ads_tot_average": 0.0, + "energy_host/ads_vdw_average": 0.0, + "energy_host/ads_coulomb_average": 0.0, + "energy_host/ads_tot_dev": 0.0, + "energy_host/ads_vdw_dev": 0.0, + "energy_host/ads_coulomb_dev": 0.0, + "tail_correction_energy_average": 0.0, + "tail_correction_energy_unit": "K", + "tail_correction_energy_dev": 0.0, } butane = { - 'mol_fraction': 0.5, - 'mol_fraction_unit': '-', - 'conversion_factor_molec_uc_to_mol_kg': None, - 'conversion_factor_molec_uc_to_mol_kg_unit': '(mol/kg)/(molec/uc)', - 'conversion_factor_molec_uc_to_mg_g': None, - 'conversion_factor_molec_uc_to_mg_g_unit': '(mg/g)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_gr': None, - 'conversion_factor_molec_uc_to_cm3stp_gr_unit': '(cm^3_STP/gr)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_cm3': 2.3820335839, - 'conversion_factor_molec_uc_to_cm3stp_cm3_unit': '(cm^3_STP/cm^3)/(molec/uc)', - 'partial_pressure': 250000.0, - 'partial_pressure_unit': 'Pa', - 'partial_fugacity': 121261.37081517381, - 'partial_fugacity_unit': 'Pa', - 'adsorbate_density_average': 0.43238, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 0.23112, - 'enthalpy_of_adsorption_average': 740.33952, - 'enthalpy_of_adsorption_unit': 'K', - 'enthalpy_of_adsorption_dev': 398.536954, - 'loading_absolute_average': 0.07, - 'loading_absolute_dev': 0.0374165739, - 'loading_absolute_unit': 'molecules/unit cell', - 'loading_excess_average': 0.07, - 'loading_excess_dev': 0.0374165739, - 'loading_excess_unit': 'molecules/unit cell', - 'widom_rosenbluth_factor_unit': '-', - 'widom_rosenbluth_factor_dev': None, - 'widom_rosenbluth_factor_average': None, - 'chemical_potential_unit': 'K', - 'chemical_potential_dev': None, - 'chemical_potential_average': None, - 'henry_coefficient_unit': 'mol/kg/Pa', - 'henry_coefficient_dev': None, - 'henry_coefficient_average': None, - 'adsorption_energy_widom_unit': 'kJ/mol', - 'adsorption_energy_widom_dev': None, - 'adsorption_energy_widom_average': None + "mol_fraction": 0.5, + "mol_fraction_unit": "-", + "conversion_factor_molec_uc_to_mol_kg": None, + "conversion_factor_molec_uc_to_mol_kg_unit": "(mol/kg)/(molec/uc)", + "conversion_factor_molec_uc_to_mg_g": None, + "conversion_factor_molec_uc_to_mg_g_unit": "(mg/g)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_gr": None, + "conversion_factor_molec_uc_to_cm3stp_gr_unit": "(cm^3_STP/gr)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_cm3": 2.3820335839, + "conversion_factor_molec_uc_to_cm3stp_cm3_unit": "(cm^3_STP/cm^3)/(molec/uc)", + "partial_pressure": 250000.0, + "partial_pressure_unit": "Pa", + "partial_fugacity": 121261.37081517381, + "partial_fugacity_unit": "Pa", + "adsorbate_density_average": 0.43238, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 0.23112, + "enthalpy_of_adsorption_average": 740.33952, + "enthalpy_of_adsorption_unit": "K", + "enthalpy_of_adsorption_dev": 398.536954, + "loading_absolute_average": 0.07, + "loading_absolute_dev": 0.0374165739, + "loading_absolute_unit": "molecules/unit cell", + "loading_excess_average": 0.07, + "loading_excess_dev": 0.0374165739, + "loading_excess_unit": "molecules/unit cell", + "widom_rosenbluth_factor_unit": "-", + "widom_rosenbluth_factor_dev": None, + "widom_rosenbluth_factor_average": None, + "chemical_potential_unit": "K", + "chemical_potential_dev": None, + "chemical_potential_average": None, + "henry_coefficient_unit": "mol/kg/Pa", + "henry_coefficient_dev": None, + "henry_coefficient_average": None, + "adsorption_energy_widom_unit": "kJ/mol", + "adsorption_energy_widom_dev": None, + "adsorption_energy_widom_average": None, } propane = { - 'mol_fraction': 0.5, - 'mol_fraction_unit': '-', - 'conversion_factor_molec_uc_to_mol_kg': None, - 'conversion_factor_molec_uc_to_mol_kg_unit': '(mol/kg)/(molec/uc)', - 'conversion_factor_molec_uc_to_mg_g': None, - 'conversion_factor_molec_uc_to_mg_g_unit': '(mg/g)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_gr': None, - 'conversion_factor_molec_uc_to_cm3stp_gr_unit': '(cm^3_STP/gr)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_cm3': 2.3820335839, - 'conversion_factor_molec_uc_to_cm3stp_cm3_unit': '(cm^3_STP/cm^3)/(molec/uc)', - 'partial_pressure': 250000.0, - 'partial_pressure_unit': 'Pa', - 'partial_fugacity': 230618.81828829306, - 'partial_fugacity_unit': 'Pa', - 'adsorbate_density_average': 3.97159, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 0.7045, - 'enthalpy_of_adsorption_average': 103.567, - 'enthalpy_of_adsorption_unit': 'K', - 'enthalpy_of_adsorption_dev': 98.162438, - 'loading_absolute_average': 0.8475, - 'loading_absolute_dev': 0.1503329638, - 'loading_absolute_unit': 'molecules/unit cell', - 'loading_excess_average': 0.8475, - 'loading_excess_dev': 0.1503329638, - 'loading_excess_unit': 'molecules/unit cell', - 'widom_rosenbluth_factor_unit': '-', - 'widom_rosenbluth_factor_dev': None, - 'widom_rosenbluth_factor_average': None, - 'chemical_potential_unit': 'K', - 'chemical_potential_dev': None, - 'chemical_potential_average': None, - 'henry_coefficient_unit': 'mol/kg/Pa', - 'henry_coefficient_dev': None, - 'henry_coefficient_average': None, - 'adsorption_energy_widom_unit': 'kJ/mol', - 'adsorption_energy_widom_dev': None, - 'adsorption_energy_widom_average': None + "mol_fraction": 0.5, + "mol_fraction_unit": "-", + "conversion_factor_molec_uc_to_mol_kg": None, + "conversion_factor_molec_uc_to_mol_kg_unit": "(mol/kg)/(molec/uc)", + "conversion_factor_molec_uc_to_mg_g": None, + "conversion_factor_molec_uc_to_mg_g_unit": "(mg/g)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_gr": None, + "conversion_factor_molec_uc_to_cm3stp_gr_unit": "(cm^3_STP/gr)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_cm3": 2.3820335839, + "conversion_factor_molec_uc_to_cm3stp_cm3_unit": "(cm^3_STP/cm^3)/(molec/uc)", + "partial_pressure": 250000.0, + "partial_pressure_unit": "Pa", + "partial_fugacity": 230618.81828829306, + "partial_fugacity_unit": "Pa", + "adsorbate_density_average": 3.97159, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 0.7045, + "enthalpy_of_adsorption_average": 103.567, + "enthalpy_of_adsorption_unit": "K", + "enthalpy_of_adsorption_dev": 98.162438, + "loading_absolute_average": 0.8475, + "loading_absolute_dev": 0.1503329638, + "loading_absolute_unit": "molecules/unit cell", + "loading_excess_average": 0.8475, + "loading_excess_dev": 0.1503329638, + "loading_excess_unit": "molecules/unit cell", + "widom_rosenbluth_factor_unit": "-", + "widom_rosenbluth_factor_dev": None, + "widom_rosenbluth_factor_average": None, + "chemical_potential_unit": "K", + "chemical_potential_dev": None, + "chemical_potential_average": None, + "henry_coefficient_unit": "mol/kg/Pa", + "henry_coefficient_dev": None, + "henry_coefficient_average": None, + "adsorption_energy_widom_unit": "kJ/mol", + "adsorption_energy_widom_dev": None, + "adsorption_energy_widom_average": None, } for key, value in general.items(): - assert value == parsed_parameters['general'][key] + assert value == parsed_parameters["general"][key] for key, value in butane.items(): - assert value == parsed_parameters['components']['butane'][key] + assert value == parsed_parameters["components"]["butane"][key] for key, value in propane.items(): - assert value == parsed_parameters['components']['propane'][key] + assert value == parsed_parameters["components"]["propane"][key] def test_parse_output_widom(): """Testing output parser on an output file of a widom calculation of H2 in an empty COF""" - parsed_parameters = parse_base_output(os.path.join(CWD, "outputs/widom_insertion.out"), - system_name="system1", - ncomponents=1)[0] + + with Path(CWD, "outputs/widom_insertion.out").open("r", encoding="utf-8") as handle: + parsed_parameters = parse_base_output(handle.read(), system_name="system1", ncomponents=1)[0] + general = { - 'exceeded_walltime': False, - 'framework_density': '935.523150616336', - 'framework_density_unit': 'kg/m^3', - 'energy_unit': 'kJ/mol', - 'energy_host/ads_tot_initial': 0.0, - 'energy_host/ads_vdw_initial': 0.0, - 'energy_host/ads_coulomb_initial': 0.0, - 'energy_host/ads_tot_final': 0.0, - 'energy_host/ads_vdw_final': 0.0, - 'energy_host/ads_coulomb_final': 0.0, - 'cell_volume_average': 56953.44, - 'cell_volume_unit': 'A^3', - 'cell_volume_dev': 0.0, - 'box_ax_average': 46.009, - 'box_ax_unit': 'A^3', - 'box_ax_dev': 0.0, - 'box_by_average': 46.01567, - 'box_by_unit': 'A^3', - 'box_by_dev': 0.0, - 'box_cz_average': 26.90119, - 'box_cz_unit': 'A^3', - 'box_cz_dev': 0.0, - 'box_alpha_average': 121.11, - 'box_alpha_unit': 'degrees', - 'box_alpha_dev': 0.0, - 'box_beta_average': 89.6387, - 'box_beta_unit': 'degrees', - 'box_beta_dev': 0.0, - 'box_gamma_average': 90.2479, - 'box_gamma_unit': 'degrees', - 'box_gamma_dev': 0.0, - 'adsorbate_density_average': 0.0, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 0.0, - 'enthalpy_of_adsorption_average': None, - 'enthalpy_of_adsorption_unit': 'K', - 'enthalpy_of_adsorption_dev': None, - 'energy_ads/ads_tot_average': 0.0, - 'energy_ads/ads_vdw_average': 0.0, - 'energy_ads/ads_coulomb_average': 0.0, - 'energy_ads/ads_tot_dev': 0.0, - 'energy_ads/ads_vdw_dev': 0.0, - 'energy_ads/ads_coulomb_dev': 0.0, - 'energy_host/ads_tot_average': 0.0, - 'energy_host/ads_vdw_average': 0.0, - 'energy_host/ads_coulomb_average': 0.0, - 'energy_host/ads_tot_dev': 0.0, - 'energy_host/ads_vdw_dev': 0.0, - 'energy_host/ads_coulomb_dev': 0.0, - 'tail_correction_energy_average': -37375.15068, - 'tail_correction_energy_unit': 'K', - 'tail_correction_energy_dev': 0.0 + "exceeded_walltime": False, + "framework_density": "935.523150616336", + "framework_density_unit": "kg/m^3", + "energy_unit": "kJ/mol", + "energy_host/ads_tot_initial": 0.0, + "energy_host/ads_vdw_initial": 0.0, + "energy_host/ads_coulomb_initial": 0.0, + "energy_host/ads_tot_final": 0.0, + "energy_host/ads_vdw_final": 0.0, + "energy_host/ads_coulomb_final": 0.0, + "cell_volume_average": 56953.44, + "cell_volume_unit": "A^3", + "cell_volume_dev": 0.0, + "box_ax_average": 46.009, + "box_ax_unit": "A^3", + "box_ax_dev": 0.0, + "box_by_average": 46.01567, + "box_by_unit": "A^3", + "box_by_dev": 0.0, + "box_cz_average": 26.90119, + "box_cz_unit": "A^3", + "box_cz_dev": 0.0, + "box_alpha_average": 121.11, + "box_alpha_unit": "degrees", + "box_alpha_dev": 0.0, + "box_beta_average": 89.6387, + "box_beta_unit": "degrees", + "box_beta_dev": 0.0, + "box_gamma_average": 90.2479, + "box_gamma_unit": "degrees", + "box_gamma_dev": 0.0, + "adsorbate_density_average": 0.0, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 0.0, + "enthalpy_of_adsorption_average": None, + "enthalpy_of_adsorption_unit": "K", + "enthalpy_of_adsorption_dev": None, + "energy_ads/ads_tot_average": 0.0, + "energy_ads/ads_vdw_average": 0.0, + "energy_ads/ads_coulomb_average": 0.0, + "energy_ads/ads_tot_dev": 0.0, + "energy_ads/ads_vdw_dev": 0.0, + "energy_ads/ads_coulomb_dev": 0.0, + "energy_host/ads_tot_average": 0.0, + "energy_host/ads_vdw_average": 0.0, + "energy_host/ads_coulomb_average": 0.0, + "energy_host/ads_tot_dev": 0.0, + "energy_host/ads_vdw_dev": 0.0, + "energy_host/ads_coulomb_dev": 0.0, + "tail_correction_energy_average": -37375.15068, + "tail_correction_energy_unit": "K", + "tail_correction_energy_dev": 0.0, } hydrogen = { - 'mol_fraction': 1.0, - 'mol_fraction_unit': '-', - 'conversion_factor_molec_uc_to_mol_kg': 0.1246621177, - 'conversion_factor_molec_uc_to_mol_kg_unit': '(mol/kg)/(molec/uc)', - 'conversion_factor_molec_uc_to_mg_g': 0.2493242354, - 'conversion_factor_molec_uc_to_mg_g_unit': '(mg/g)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_gr': 2.7941736824, - 'conversion_factor_molec_uc_to_cm3stp_gr_unit': '(cm^3_STP/gr)/(molec/uc)', - 'conversion_factor_molec_uc_to_cm3stp_cm3': 2.6140141668, - 'conversion_factor_molec_uc_to_cm3stp_cm3_unit': '(cm^3_STP/cm^3)/(molec/uc)', - 'partial_pressure': -16605402.0, - 'partial_pressure_unit': 'Pa', - 'partial_fugacity': 16605402.0, - 'partial_fugacity_unit': 'Pa', - 'adsorbate_density_average': 0.0, - 'adsorbate_density_unit': 'kg/m^3', - 'adsorbate_density_dev': 0.0, - 'loading_absolute_average': 0.0, - 'loading_absolute_dev': 0.0, - 'loading_absolute_unit': 'molecules/unit cell', - 'loading_excess_average': 0.0, - 'loading_excess_dev': 0.0, - 'loading_excess_unit': 'molecules/unit cell', - 'widom_rosenbluth_factor_unit': '-', - 'widom_rosenbluth_factor_dev': 78741.06669, - 'widom_rosenbluth_factor_average': 6973260.0, - 'chemical_potential_unit': 'K', - 'chemical_potential_dev': 0.86752, - 'chemical_potential_average': -2056.48, - 'henry_coefficient_unit': 'mol/kg/Pa', - 'henry_coefficient_dev': 0.131469, - 'henry_coefficient_average': 11.6428, - 'adsorption_energy_widom_unit': 'kJ/mol', - 'adsorption_energy_widom_dev': 0.0111060559, - 'adsorption_energy_widom_average': -13.5545306415 + "mol_fraction": 1.0, + "mol_fraction_unit": "-", + "conversion_factor_molec_uc_to_mol_kg": 0.1246621177, + "conversion_factor_molec_uc_to_mol_kg_unit": "(mol/kg)/(molec/uc)", + "conversion_factor_molec_uc_to_mg_g": 0.2493242354, + "conversion_factor_molec_uc_to_mg_g_unit": "(mg/g)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_gr": 2.7941736824, + "conversion_factor_molec_uc_to_cm3stp_gr_unit": "(cm^3_STP/gr)/(molec/uc)", + "conversion_factor_molec_uc_to_cm3stp_cm3": 2.6140141668, + "conversion_factor_molec_uc_to_cm3stp_cm3_unit": "(cm^3_STP/cm^3)/(molec/uc)", + "partial_pressure": -16605402.0, + "partial_pressure_unit": "Pa", + "partial_fugacity": 16605402.0, + "partial_fugacity_unit": "Pa", + "adsorbate_density_average": 0.0, + "adsorbate_density_unit": "kg/m^3", + "adsorbate_density_dev": 0.0, + "loading_absolute_average": 0.0, + "loading_absolute_dev": 0.0, + "loading_absolute_unit": "molecules/unit cell", + "loading_excess_average": 0.0, + "loading_excess_dev": 0.0, + "loading_excess_unit": "molecules/unit cell", + "widom_rosenbluth_factor_unit": "-", + "widom_rosenbluth_factor_dev": 78741.06669, + "widom_rosenbluth_factor_average": 6973260.0, + "chemical_potential_unit": "K", + "chemical_potential_dev": 0.86752, + "chemical_potential_average": -2056.48, + "henry_coefficient_unit": "mol/kg/Pa", + "henry_coefficient_dev": 0.131469, + "henry_coefficient_average": 11.6428, + "adsorption_energy_widom_unit": "kJ/mol", + "adsorption_energy_widom_dev": 0.0111060559, + "adsorption_energy_widom_average": -13.5545306415, } for key, value in general.items(): - assert value == parsed_parameters['general'][key] + assert value == parsed_parameters["general"][key] for key, value in hydrogen.items(): - assert value == parsed_parameters['components']['H2'][key] + assert value == parsed_parameters["components"]["H2"][key] diff --git a/tests/test_version_agreement.py b/tests/test_version_agreement.py deleted file mode 100644 index 287b855..0000000 --- a/tests/test_version_agreement.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -"""Check versions""" - -import sys -import json -import aiida_raspa - - -def test_version_agreement(): - """Check if versions in setup.json and in plugin are consistent""" - version1 = aiida_raspa.__version__ - with open("setup.json") as fhandle: - version2 = json.load(fhandle)['version'] - - if version1 != version2: - print("ERROR: Versions in aiida_raspa/__init__.py and setup.json are inconsistent: {} vs {}".format( - version1, version2)) - sys.exit(3)