Skip to content

Commit

Permalink
Add support for aiida-core==2.X
Browse files Browse the repository at this point in the history
  • Loading branch information
mpougin committed Aug 25, 2023
1 parent 5d77891 commit 751fa53
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 335 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,6 @@ tags
[._]*.un~

# End of https://www.gitignore.io/api/vim,linux,macos,python,pycharm
submit_test
submit_test

.vscode
58 changes: 36 additions & 22 deletions aiida_raspa/calculations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""Raspa input plugin."""
import os
from shutil import copyfile, copytree
from pathlib import Path

from aiida.orm import Dict, FolderData, List, RemoteData, SinglefileData
from aiida.common import CalcInfo, CodeInfo, InputValidationError
Expand All @@ -12,7 +13,7 @@
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):
Expand Down Expand Up @@ -51,7 +52,8 @@ def define(cls, spec):
spec.input('retrieved_parent_folder',
valid_type=FolderData,
required=False,
help='To use an old calculation as a starting poing for a new one.')
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,
Expand All @@ -77,6 +79,17 @@ def define(cls, spec):
# Default output node
spec.default_output_node = 'output_parameters'

@staticmethod
def validate_retrieved_parent_folder(value, _):

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
def prepare_for_submission(self, folder):
Expand Down Expand Up @@ -168,27 +181,21 @@ def _handle_system_section(self, system_dict, folder):
"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.")

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)
Expand All @@ -203,6 +210,13 @@ def _handle_retrieved_parent_folder(self, inp, folder):

external_pressure = system['ExternalPressure'] if 'ExternalPressure' in system else 0

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))
new_fname = (
f"restart_{system_or_box:d}_{n_x:d}.{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(),
)
27 changes: 10 additions & 17 deletions aiida_raspa/parsers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
"""Raspa output parser."""
import os
from pathlib import Path

from aiida.common import NotExistent, OutputParsingError
from aiida.engine import ExitCode
Expand All @@ -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')):
# 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

Expand Down
Loading

0 comments on commit 751fa53

Please sign in to comment.