Skip to content

Commit

Permalink
Merge pull request #11 from JuDFTteam/develop
Browse files Browse the repository at this point in the history
Version v0.2.0
  • Loading branch information
PhilippRue committed Dec 1, 2021
2 parents 70d0749 + c992fb4 commit 8d02b78
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 34 deletions.
2 changes: 1 addition & 1 deletion aiida_spirit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
AiiDA plugin for the spirit code
"""

__version__ = '0.1.0'
__version__ = '0.2.0'
13 changes: 9 additions & 4 deletions aiida_spirit/calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ def prepare_for_submission(self, folder):

# this should be a list of the filenames we expect when spirit ran
# i.e. the files we specify here will be copied back to the file repository
# note that the retlist_tmp contains only files which are only needed in parsing
# but are then not kept in the file repository (e.g. magnetization arrays which are
# stored as numy arrays instead of also keeping the raw text files)
retlist = _RETLIST.copy()
retlist_tmp = []
if 'pinning' in self.inputs:
# also retreive the pinning file
retlist += ['pinning.txt']
Expand All @@ -194,17 +198,18 @@ def prepare_for_submission(self, folder):

run_opts = self.inputs.run_options.get_dict()
if run_opts['simulation_method'].upper() == 'LLG':
retlist += ['spirit_Image-00_Energy-archive.txt',
'spirit_Image-00_Spins-final.ovf',
'spirit_Image-00_Spins-initial.ovf']
retlist_tmp += ['spirit_Image-00_Energy-archive.txt',
'spirit_Image-00_Spins-final.ovf',
'spirit_Image-00_Spins-initial.ovf']
elif run_opts['simulation_method'].upper() == 'MC':
retlist += ['output_mc.txt']
retlist_tmp += ['output_mc.txt']

# from the input we can specify additional files that should be retrieved
if 'add_to_retrieved' in self.inputs:
retlist += self.inputs.add_to_retrieved.get_list()

calcinfo.retrieve_list = retlist
calcinfo.retrieve_temporary_list = retlist_tmp

return calcinfo

Expand Down
86 changes: 58 additions & 28 deletions aiida_spirit/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
Register parsers via the "aiida.parsers" entry point in setup.json.
"""
import pathlib
import numpy as np
from aiida.engine import ExitCode
from aiida.parsers.parser import Parser
Expand Down Expand Up @@ -54,6 +55,14 @@ def parse(self, **kwargs):
# parse information from output file (number of iterations, convergence info, ...)
retrieved_dict = self.parse_retrieved()

# parse files in temporary folder
# these files are not kept in the file repository but become numy arrays and are stored as ArrayData output nodes
retrieved_temporary_folder = kwargs.get('retrieved_temporary_folder',
None)
if retrieved_temporary_folder is not None:
retrieved_dict = self.parse_temporary_retrieved(
retrieved_dict, retrieved_temporary_folder)

for key, value in retrieved_dict.items():
self.out(key, value)

Expand All @@ -70,17 +79,27 @@ def parse(self, **kwargs):

return ExitCode(0)

def _retrieve_if_found(self, filename, *args, **kwargs):
"""Retrieves a file and loads it with `np.loadtxt`.
def _parse_if_found(self, filename, *args, folder=None, **kwargs):
"""Parses a file and loads it with `np.loadtxt`.
The `*args` and `**kwargs` are passed to `np.loadtxt`.
If the file is not found it returns None."""
retrieved = self.retrieved
if filename in retrieved.list_object_names():
with retrieved.open(filename, 'r') as _f:
return np.loadtxt(_f, *args, **kwargs)
if folder is None:
folder = self.retrieved
if filename in folder.list_object_names():
with folder.open(filename, 'r') as _f:
return np.loadtxt(_f, *args, **kwargs)
else:
return self._file_not_found(filename)
else:
self.logger.info('{} not found!'.format(filename))
return None
filenames = [f.name for f in folder.glob('*')]
if filename in filenames:
with (folder / filename).open('r') as _f:
return np.loadtxt(_f, *args, **kwargs)
else:
return self._file_not_found(filename)

def _file_not_found(self, filename):
self.logger.info('{} not found!'.format(filename))

def parse_retrieved(self): # pylint: disable=too-many-locals
"""Parse the output from the retrieved and create aiida nodes"""
Expand All @@ -96,26 +115,45 @@ def parse_retrieved(self): # pylint: disable=too-many-locals
output_node = Dict(dict=out_dict)

# parse output files
self.logger.info('Parsing atom types')
atyp = self._parse_if_found(_ATOM_TYPES)

# Write dictionary of retrieved quantities
_retrieved_dict = {'output_parameters': output_node}

# collect arrays in ArrayData
if atyp is not None:
atypes = ArrayData()
atypes.set_array('atom_types', atyp)
atypes.extras['description'] = {
'atom_types': 'list of atom types for all positions',
}
_retrieved_dict.update({'atom_types': atypes})

return _retrieved_dict

def parse_temporary_retrieved(self, _retrieved_dict,
retrieved_temporary_folder):
"""Parse files that are defined in the retrieve_temporary_list"""
retrieved_temporary_folder = pathlib.Path(retrieved_temporary_folder)

self.logger.info('Parsing energy archive')
energ = self._retrieve_if_found('spirit_Image-00_Energy-archive.txt',
skiprows=1)
energ = self._parse_if_found('spirit_Image-00_Energy-archive.txt',
folder=retrieved_temporary_folder,
skiprows=1)

self.logger.info('Parsing initial magnetization')
m_init = self._retrieve_if_found('spirit_Image-00_Spins-initial.ovf')
m_init = self._parse_if_found('spirit_Image-00_Spins-initial.ovf',
folder=retrieved_temporary_folder)

self.logger.info('Parsing final magnetization')
m_final = self._retrieve_if_found('spirit_Image-00_Spins-final.ovf')

self.logger.info('Parsing atom types')
atyp = self._retrieve_if_found(_ATOM_TYPES)
m_final = self._parse_if_found('spirit_Image-00_Spins-final.ovf',
folder=retrieved_temporary_folder)

self.logger.info('Parsing MC output')
out_mc = self._retrieve_if_found('output_mc.txt')
out_mc = self._parse_if_found('output_mc.txt',
folder=retrieved_temporary_folder)

# Write dictionary of retrieved quantities
_retrieved_dict = {'output_parameters': output_node}

# collect arrays in ArrayData
if m_init is not None and m_final is not None:
mag = ArrayData()
mag.set_array(
Expand All @@ -136,14 +174,6 @@ def parse_retrieved(self): # pylint: disable=too-many-locals
}
_retrieved_dict.update({'energies': energies})

if atyp is not None:
atypes = ArrayData()
atypes.set_array('atom_types', atyp)
atypes.extras['description'] = {
'atom_types': 'list of atom types for all positions',
}
_retrieved_dict.update({'atom_types': atypes})

# Only add mc if it is found
if out_mc is not None:
output_mc = ArrayData()
Expand Down
2 changes: 1 addition & 1 deletion setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"Natural Language :: English",
"Framework :: AiiDA"
],
"version": "0.1.0",
"version": "0.2.0",
"entry_points": {
"aiida.calculations": [
"spirit = aiida_spirit.calculations:SpiritCalculation"
Expand Down

0 comments on commit 8d02b78

Please sign in to comment.