Skip to content

Commit

Permalink
Add GULP calculations (#4)
Browse files Browse the repository at this point in the history
- update aiida-core to v1.0.0b3
- added GULP calculations, tests and documentation
- add dependencies for reading CIF files
- implement calculation submission tests (using process.prepare_for_submission)
- implement new calculation immigration method
- re-number calculation exit codes
- update readthedocs build
  • Loading branch information
chrisjsewell committed Jun 13, 2019
1 parent f9136f1 commit b0a4de5
Show file tree
Hide file tree
Showing 85 changed files with 20,718 additions and 1,029 deletions.
10 changes: 10 additions & 0 deletions .condarc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
channels:
- conda-forge
- defaults

# Show channel URLs when displaying what is going to be downloaded
# and in 'conda list'. The default is False.
show_channel_urls: True

# For more information about this file see:
# https://conda.io/docs/user-guide/configuration/use-condarc.html
4 changes: 2 additions & 2 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ python:
install:
- method: pip
path: .
extra_requirements:
- docs
# extra_requirements:
# - docs

# default
# sphinx:
Expand Down
8 changes: 4 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.enabled": true,
"python.unitTest.pyTestArgs": [
"python.testing.pyTestArgs": [
"aiida_crystal17"
],
"python.unitTest.unittestEnabled": false,
"python.unitTest.nosetestsEnabled": false,
"python.unitTest.pyTestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.nosetestsEnabled": false,
"python.testing.pyTestEnabled": true,
"restructuredtext.preview.sphinx.disabled": true,
"restructuredtext.confPath": "${workspaceFolder}/docs/source"
}
2 changes: 1 addition & 1 deletion aiida_crystal17/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
AiiDA plugin for running the CRYSTAL17 code
"""

__version__ = "0.5.0b2"
__version__ = "0.5.0b3"
23 changes: 15 additions & 8 deletions aiida_crystal17/calculations/cry_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,31 @@ def define(cls, spec):
spec.input('metadata.options.parser_name',
valid_type=six.string_types, default='crystal17.main')

# TODO review aiidateam/aiida_core#2997, when closed, for exit code formalization

# Unrecoverable errors: resources like the retrieved folder or its expected contents are missing
spec.exit_code(
130, 'ERROR_NO_RETRIEVED_FOLDER',
200, 'ERROR_NO_RETRIEVED_FOLDER',
message='The retrieved folder data node could not be accessed.')
spec.exit_code(
140, 'ERROR_OUTPUT_FILE_MISSING',
210, 'ERROR_OUTPUT_FILE_MISSING',
message='the main output file was not found')

# Unrecoverable errors: required retrieved files could not be read, parsed or are otherwise incomplete
spec.exit_code(
200, 'ERROR_CRYSTAL_RUN',
message='The main crystal output file flagged an error')
spec.exit_code(
210, 'ERROR_OUTPUT_PARSING',
300, 'ERROR_OUTPUT_PARSING',
message=('An error was flagged trying to parse the '
'main crystal output file'))

# Significant errors but calculation can be used to restart
spec.exit_code(
400, 'ERROR_CRYSTAL_RUN',
message='The main crystal output file flagged an error')
spec.exit_code(
220, 'ERROR_SYMMETRY_INCONSISTENCY',
410, 'ERROR_SYMMETRY_INCONSISTENCY',
message=('inconsistency in the input and output symmetry'))
spec.exit_code(
230, 'ERROR_SYMMETRY_NOT_FOUND',
420, 'ERROR_SYMMETRY_NOT_FOUND',
message=('primitive symmops were not found in the output file'))

spec.output(cls.link_output_results,
Expand Down
16 changes: 10 additions & 6 deletions aiida_crystal17/calculations/cry_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import six
from aiida.common.datastructures import (CalcInfo, CodeInfo)
from aiida.common.exceptions import InputValidationError
from aiida.orm import Code
from aiida.plugins import DataFactory

from aiida_crystal17.calculations.cry_abstract import CryAbstractCalculation
from aiida_crystal17.parsers.gui_parse import gui_file_write
from aiida_crystal17.parsers.inputd12_write import (
Expand Down Expand Up @@ -57,7 +59,7 @@ def define(cls, spec):
@classmethod
def create_builder(cls, parameters, structure, bases,
symmetry=None, kinds=None,
code=None, options=None, unflatten=False):
code=None, metadata=None, unflatten=False):
""" prepare and validate the inputs to the calculation,
and return a builder pre-populated with the calculation inputs
Expand All @@ -72,9 +74,9 @@ def create_builder(cls, parameters, structure, bases,
or dict mapping {<symbol>: <BasisSetData>}
symmetry: SymmetryData or None
giving symmetry operations, etc
options: dict
the computation option, e.g.
{"resources": {"num_machines": 1, "num_mpiprocs_per_machine": 1}}
metadata: dict
the computation metadata, e.g.
{"options": {"resources": {"num_machines": 1, "num_mpiprocs_per_machine": 1}}}
unflatten: bool
whether to unflatten the input parameters dictionary
Expand All @@ -94,9 +96,11 @@ def create_builder(cls, parameters, structure, bases,
if kinds is not None:
builder.kinds = kinds
if code is not None:
if isinstance(code, six.string_types):
code = Code.get_from_string(code)
builder.code = code
if options is not None:
builder.metadata.options = options
if metadata is not None:
builder.metadata = metadata

# validate parameters
atom_props = create_atom_properties(structure, kinds)
Expand Down
40 changes: 24 additions & 16 deletions aiida_crystal17/calculations/tests/test_cry_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,24 @@
"""
import os

import aiida_crystal17
from aiida_crystal17.tests import TEST_DIR
import ejplugins
from jsonextended import edict
import pytest

import aiida_crystal17
from aiida_crystal17.tests import TEST_DIR
from aiida_crystal17.tests.utils import AiidaTestApp # noqa: F401

@pytest.mark.skip(reason="dry run implemented after v1.0.0b2")
def test_dry_run(db_test_app):

def test_calcjob_submission(db_test_app):
# type: (AiidaTestApp) -> None
"""Test submitting a calculation"""
from aiida.engine import run_get_node
from aiida.plugins import DataFactory
SinglefileData = DataFactory('singlefile')
singlefile_data_cls = DataFactory('singlefile')

# Prepare input parameters
code = db_test_app.get_or_create_code('crystal17.basic')
infile = SinglefileData(
infile = singlefile_data_cls(
file=os.path.join(TEST_DIR, "input_files",
'mgo_sto3g_scf.crystal.d12'))
infile.store()
Expand All @@ -29,15 +30,21 @@ def test_dry_run(db_test_app):
builder.metadata.options.withmpi = False
builder.metadata.options.resources = {
"num_machines": 1, "num_mpiprocs_per_machine": 1}
builder.metadata.store_provenance = True
builder.input_file = infile

builder.metadata.dry_run = True
with db_test_app.sandbox_folder() as folder:
calc_info = db_test_app.generate_calcinfo(
'crystal17.basic', folder, builder)

outcome = run_get_node(builder)
cmdline_params = ['main']
local_copy_list = [[infile.uuid, infile.filename, u'main.d12']]
retrieve_list = ['main.out', 'main.gui']

incoming = outcome.node.get_incoming()
assert set(incoming.all_link_labels()) == set(['code', 'input_file'])
# Check the attributes of the returned `CalcInfo`
assert calc_info.codes_info[0].cmdline_params == cmdline_params
assert sorted(calc_info.local_copy_list) == sorted(local_copy_list)
assert sorted(calc_info.retrieve_list) == sorted(retrieve_list)
assert sorted(calc_info.retrieve_temporary_list) == sorted([])


@pytest.mark.parametrize("inpath_main,inpath_gui", (
Expand All @@ -47,11 +54,12 @@ def test_dry_run(db_test_app):
))
@pytest.mark.timeout(60)
@pytest.mark.process_execution
def test_full_runs(db_test_app, inpath_main, inpath_gui):
def test_calcjob_run(db_test_app, inpath_main, inpath_gui):
# type: (AiidaTestApp, str, str) -> None
"""Test running an optimisation calculation"""
from aiida.engine import run_get_node
from aiida.plugins import DataFactory
SinglefileData = DataFactory('singlefile')
singlefile_data_cls = DataFactory('singlefile')

code = db_test_app.get_or_create_code('crystal17.basic')

Expand All @@ -69,11 +77,11 @@ def test_full_runs(db_test_app, inpath_main, inpath_gui):
}

# Prepare input parameters
infile = SinglefileData(
infile = singlefile_data_cls(
file=os.path.join(TEST_DIR, "input_files", inpath_main))
builder.input_file = infile
if inpath_gui is not None:
ingui = SinglefileData(
ingui = singlefile_data_cls(
file=os.path.join(TEST_DIR, "input_files", inpath_gui))
builder.input_external = ingui

Expand Down
Loading

0 comments on commit b0a4de5

Please sign in to comment.