diff --git a/aiida_kkr/calculations/kkrimp.py b/aiida_kkr/calculations/kkrimp.py index 17fe0b82..c41dd17d 100644 --- a/aiida_kkr/calculations/kkrimp.py +++ b/aiida_kkr/calculations/kkrimp.py @@ -22,7 +22,7 @@ __copyright__ = (u'Copyright (c), 2018, Forschungszentrum Jülich GmbH, ' 'IAS-1/PGI-1, Germany. All rights reserved.') __license__ = 'MIT license, see LICENSE.txt file' -__version__ = '0.8.2' +__version__ = '0.9.0' __contributors__ = (u'Philipp Rüßmann', u'Fabian Bertoldo') #TODO: implement 'ilayer_center' consistency check @@ -171,13 +171,6 @@ def define(cls, spec): Note: The length of the theta, phi and fix_dir lists have to be equal to the number of atoms in the impurity cluster. """ ) - spec.input( - 'cleanup_outfiles', - valid_type=Bool, - required=False, - default=lambda: Bool(False), - help='Cleanup and compress output (works only in aiida-core<2.0 and breaks caching ability).' - ) # define outputs spec.output('output_parameters', valid_type=Dict, required=True, help='results of the KKRimp calculation') diff --git a/aiida_kkr/parsers/kkr.py b/aiida_kkr/parsers/kkr.py index 663b68b7..e1203dec 100644 --- a/aiida_kkr/parsers/kkr.py +++ b/aiida_kkr/parsers/kkr.py @@ -18,7 +18,7 @@ __copyright__ = (u'Copyright (c), 2017, Forschungszentrum Jülich GmbH, ' 'IAS-1/PGI-1, Germany. All rights reserved.') __license__ = 'MIT license, see LICENSE.txt file' -__version__ = '0.7.0' +__version__ = '0.8.0' __contributors__ = ('Jens Broeder', u'Philipp Rüßmann') @@ -229,21 +229,3 @@ def parse(self, debug=False, **kwargs): if not success: return self.exit_codes.ERROR_KKR_PARSING_FAILED - else: # cleanup after parsing (only if parsing was successful) - # cleanup only works below aiida-core v2.0 - if int(aiida_core_version.split('.')[0]) < 2: - # delete completely parsed output files - self.remove_unnecessary_files() - # then (maybe) tar the output to save space - # TODO needs implementing (see kkrimp parser) - - def remove_unnecessary_files(self): - """ - Remove files that are not needed anymore after parsing - The information is completely parsed (i.e. in outdict of calculation) - and keeping the file would just be a duplication. - """ - files_to_delete = [KkrCalculation._POTENTIAL, KkrCalculation._SHAPEFUN] - for fileid in files_to_delete: - if fileid in self.retrieved.list_object_names(): - self.retrieved.delete_object(fileid, force=True) diff --git a/aiida_kkr/parsers/kkrimp.py b/aiida_kkr/parsers/kkrimp.py index d3d40a4c..146d8fb5 100644 --- a/aiida_kkr/parsers/kkrimp.py +++ b/aiida_kkr/parsers/kkrimp.py @@ -21,7 +21,7 @@ __copyright__ = (u'Copyright (c), 2018, Forschungszentrum Jülich GmbH, ' 'IAS-1/PGI-1, Germany. All rights reserved.') __license__ = 'MIT license, see LICENSE.txt file' -__version__ = '0.5.0' +__version__ = '0.6.0' __contributors__ = ('Philipp Rüßmann') @@ -42,7 +42,7 @@ def __init__(self, calc): # pylint: disable=protected-access - def parse(self, debug=False, **kwargs): + def parse(self, debug=False, ignore_nan=True, **kwargs): # pylint: disable=unexpected-keyword-arg """ Parse output data folder, store results in database. @@ -113,7 +113,7 @@ def parse(self, debug=False, **kwargs): # now we can parse the output files success, msg_list, out_dict = KkrimpParserFunctions().parse_kkrimp_outputfile( - out_dict, named_file_handles, debug=debug + out_dict, named_file_handles, debug=debug, ignore_nan=ignore_nan ) out_dict['parser_errors'] = msg_list @@ -132,22 +132,7 @@ def parse(self, debug=False, **kwargs): # create output node and link self.out('output_parameters', Dict(dict=out_dict)) - # cleanup after parsing (only if parsing was successful), only works below aiida-core v2.0 - if success: - if int(aiida_core_version.split('.')[0]) < 2: - # check if we should do the cleanup or not - cleanup_outfiles = False - if 'cleanup_outfiles' in self.node.inputs: - cleanup_outfiles = self.node.inputs.cleanup_outfiles.value - if cleanup_outfiles: - # reduce size of timing file - self.cleanup_outfiles(files['out_timing'], ['Iteration number', 'time until scf starts']) - # reduce size of out_log file - self.cleanup_outfiles(files['out_log'], ['Iteration Number']) - # delete completely parsed output files and create a tar ball to reduce size - self.remove_unnecessary_files() - self.final_cleanup() - else: + if not success: return self.exit_codes.ERROR_PARSING_KKRIMPCALC def _check_file_existance(self, files, keyname, fname, icrit, file_errors): @@ -168,71 +153,3 @@ def _check_file_existance(self, files, keyname, fname, icrit, file_errors): raise ValueError('icrit should be either 1 or 2') file_errors.append((icrit, crit_level + f" File '{fname}' not found.")) files[keyname] = None - - def cleanup_outfiles(self, fileidentifier, keyslist): - """open file and remove unneeded output""" - if fileidentifier is not None: - lineids = [] - with self.retrieved.open(fileidentifier) as tfile: - txt = tfile.readlines() - for iline in range(len(txt)): - for key in keyslist: # go through all keys - if key in txt[iline]: # add line id to list if key has been found - lineids.append(iline) - # rewrite file deleting the middle part - if len(lineids) > 1: # cut only if more than one iteration was found - txt = txt[:lineids[0]] + \ - ['# ... [removed output except for last iteration] ...\n'] + \ - txt[lineids[-1]:] - with self.retrieved.open(fileidentifier, 'w') as tfilenew: - tfilenew.writelines(txt) - - def remove_unnecessary_files(self): - """ - Remove files that are not needed anymore after parsing - The information is completely parsed (i.e. in outdict of calculation) - and keeping the file would just be a duplication. - """ - # first delete unused files (completely in parsed output) - files_to_delete = [ - KkrimpCalculation._OUT_ENERGYSP_PER_ATOM, KkrimpCalculation._OUT_ENERGYTOT_PER_ATOM, - KkrimpCalculation._SHAPEFUN - ] - for fileid in files_to_delete: - if fileid in self.retrieved.list_object_names(): - self.retrieved.delete_object(fileid, force=True) - - def final_cleanup(self): - """Create a tarball of the rest.""" - - # short name for retrieved folder - ret = self.retrieved - - # Now create tarball of output - # - # check if output has been packed to tarfile already - # only if tarfile is not there we create the output tar file - if KkrimpCalculation._FILENAME_TAR not in ret.list_object_names(): - # first create dummy file which is used to extract the full path that is given to tarfile.open - with ret.open(KkrimpCalculation._FILENAME_TAR, 'w') as f: - filepath_tar = f.name - - # now create tarfile and loop over content of retrieved directory - to_delete = [] - with tarfile.open(filepath_tar, 'w:gz') as tf: - for f in ret.list_object_names(): - with ret.open(f) as ftest: - filesize = os.stat(ftest.name).st_size - ffull = ftest.name - if ( - f != KkrimpCalculation._FILENAME_TAR # ignore tar file - and filesize > 0 # ignore empty files - # ignore files starting with '.' like '.nfs...' - and f[0] != '.' - ): - tf.add(ffull, arcname=os.path.basename(ffull)) - to_delete.append(f) - - # finally delete files that have been added to tarfile - for f in to_delete: - ret.delete_object(f, force=True) diff --git a/aiida_kkr/workflows/imp_BdG.py b/aiida_kkr/workflows/imp_BdG.py index 872a0be6..6f695b94 100644 --- a/aiida_kkr/workflows/imp_BdG.py +++ b/aiida_kkr/workflows/imp_BdG.py @@ -144,7 +144,7 @@ def define(cls, spec): spec.expose_inputs( kkr_imp_wc, namespace='imp_scf', - include=('startpot', 'wf_parameters', 'gf_writeout', 'scf.params_overwrite') + include=('startpot', 'wf_parameters', 'gf_writeout', 'scf.params_overwrite', 'scf.initial_noco_angles') ) spec.inputs['imp_scf']['gf_writeout']['kkr'].required = False spec.input('imp_scf.options', required=False, help='computer options for impurity scf step') @@ -157,7 +157,11 @@ def define(cls, spec): ) # inputs for impurity BdG scf - spec.expose_inputs(kkr_imp_wc, namespace='BdG_scf', include=('startpot', 'remote_data_gf', 'gf_writeout')) + spec.expose_inputs( + kkr_imp_wc, + namespace='BdG_scf', + include=('startpot', 'remote_data_gf', 'gf_writeout', 'scf.initial_noco_angles') + ) spec.inputs['BdG_scf']['gf_writeout']['kkr'].required = False spec.input('BdG_scf.options', required=False, help='computer options for BdG impurity scf step') @@ -166,7 +170,11 @@ def define(cls, spec): ) # inputs for impurity dos - spec.expose_inputs(kkr_imp_dos_wc, namespace='dos', include=('wf_parameters', 'gf_dos_remote', 'gf_writeout')) + spec.expose_inputs( + kkr_imp_dos_wc, + namespace='dos', + include=('wf_parameters', 'gf_dos_remote', 'gf_writeout', 'initial_noco_angles') + ) spec.input( 'dos.gf_writeout.host_remote', @@ -275,6 +283,8 @@ def imp_pot_calc(self): builder.options = self.inputs.imp_scf.options else: builder.options = self.inputs.options + if 'initial_noco_angles' in self.inputs.imp_scf: + builder.scf.initial_noco_angles = self.inputs.imp_scf.initial_noco_angles # pylint: disable=no-member if 'gf_writeout' in self.inputs.imp_scf: if 'options' in self.inputs.imp_scf.gf_writeout: @@ -319,6 +329,8 @@ def imp_BdG_calc(self): builder.params_kkr_overwrite = self.inputs.BdG_scf.gf_writeout.params_kkr_overwrite if 'kkr' in self.inputs: builder.gf_writeout.kkr = builder.kkr # pylint: disable=no-member + if 'initial_noco_angles' in self.inputs.BdG_scf: + builder.scf.initial_noco_angles = self.inputs.BdG_scf.initial_noco_angles # pylint: disable=no-member builder.remote_data_host = self.inputs.BdG_scf.remote_data_host @@ -384,6 +396,10 @@ def DOS_calc(self): else: builder.options = self.inputs.options + # set nonco angles + if 'initial_noco_angles' in self.inputs.dos: + builder.initial_noco_angles = self.inputs.dos.initial_noco_angles + # skip BdG step and just use the starting potential instead? # faster and same accuracy?! if 'startpot' in self.inputs.BdG_scf: diff --git a/aiida_kkr/workflows/kkr_imp.py b/aiida_kkr/workflows/kkr_imp.py index 6ae94ed0..f5583a56 100644 --- a/aiida_kkr/workflows/kkr_imp.py +++ b/aiida_kkr/workflows/kkr_imp.py @@ -13,7 +13,7 @@ from aiida_kkr.tools import test_and_get_codenode, neworder_potential_wf, update_params_wf from aiida_kkr.workflows.gf_writeout import kkr_flex_wc from aiida_kkr.workflows.voro_start import kkr_startpot_wc -from aiida_kkr.workflows.kkr_imp_sub import kkr_imp_sub_wc, clean_sfd +from aiida_kkr.workflows.kkr_imp_sub import kkr_imp_sub_wc import numpy as np from aiida_kkr.tools.save_output_nodes import create_out_dict_node @@ -101,7 +101,8 @@ def define(cls, spec): # 'kkrimp', 'options', # 'wf_parameters', - 'params_overwrite' + 'params_overwrite', + 'initial_noco_angles' ) ) @@ -338,7 +339,6 @@ def start(self): self.ctx.hfield = wf_dict.get('hfield', self._wf_default['hfield']) self.ctx.init_pos = wf_dict.get('init_pos', self._wf_default['init_pos']) self.ctx.accuracy_params = wf_dict.get('accuracy_params', self._wf_default['accuracy_params']) - self.ctx.do_final_cleanup = wf_dict.get('do_final_cleanup', self._wf_default['do_final_cleanup']) # set up new parameter dict to pass to kkrimp subworkflow later self.ctx.kkrimp_params_dict = Dict({ 'nsteps': self.ctx.nsteps, @@ -354,15 +354,11 @@ def start(self): 'hfield': self.ctx.hfield, 'init_pos': self.ctx.init_pos, 'accuracy_params': self.ctx.accuracy_params, - 'do_final_cleanup': self.ctx.do_final_cleanup }) # retrieve option for kkrlfex files self.ctx.retrieve_kkrflex = wf_dict.get('retrieve_kkrflex', self._wf_default['retrieve_kkrflex']) - # list of things that are cleaned if everything ran through - self.ctx.sfd_final_cleanup = [] - # report the chosen parameters to the user self.report( 'INFO: use the following parameter:\n' @@ -738,8 +734,6 @@ def construct_startpot(self): # add starting potential for kkrimp calculation to context self.ctx.startpot_kkrimp = startpot_kkrimp - # add to list for final cleanup - self.ctx.sfd_final_cleanup.append(startpot_kkrimp) self.report( 'INFO: created startpotential (pid: {}) for the impurity calculation ' @@ -793,6 +787,8 @@ def run_kkrimp_scf(self): builder.params_overwrite = self.inputs.scf.params_overwrite if 'options' in self.inputs.scf: builder.options = self.inputs.scf.options + if 'initial_noco_angles' in self.inputs.scf: + builder.initial_noco_angles = self.inputs.scf.initial_noco_angles builder.wf_parameters = kkrimp_params future = self.submit(builder) @@ -853,10 +849,6 @@ def return_results(self): self.out('converged_potential', self.ctx.kkrimp_scf_sub.outputs.host_imp_pot) self.out('remote_data_gf', self.ctx.gf_remote) - # cleanup things that are not needed anymore - if self.ctx.do_final_cleanup: - self.final_cleanup() - # print final message before exiting self.report('INFO: created 3 output nodes for the KKR impurity workflow.') self.report( @@ -869,23 +861,6 @@ def return_results(self): self.report(self.exit_codes.ERROR_KKRIMP_SUB_WORKFLOW_FAILURE) # pylint: disable=no-member return self.exit_codes.ERROR_KKRIMP_SUB_WORKFLOW_FAILURE # pylint: disable=no-member - def final_cleanup(self): - """ - Remove unneeded files to save space - """ - for sfd in self.ctx.sfd_final_cleanup: - clean_sfd(sfd) - if self.ctx.create_startpot: - kkr_startpot = self.ctx.last_voro_calc - vorocalc = kkr_startpot.outputs.last_voronoi_remote.get_incoming(link_label_filter=u'remote_folder' - ).first().node - ret = vorocalc.outputs.retrieved - for fname in ret.list_object_names(): - if fname not in [VoronoiCalculation._OUTPUT_FILE_NAME, VoronoiCalculation._OUT_POTENTIAL_voronoi]: - # delete all except vor default output file - with ret.open(fname) as f: - ret.delete_object(fname, force=True) - def error_handler(self): """Capture errors raised in validate_input""" if self.ctx.exit_code is not None: diff --git a/aiida_kkr/workflows/kkr_imp_dos.py b/aiida_kkr/workflows/kkr_imp_dos.py index 2600ae0e..0e72914d 100644 --- a/aiida_kkr/workflows/kkr_imp_dos.py +++ b/aiida_kkr/workflows/kkr_imp_dos.py @@ -21,9 +21,12 @@ __copyright__ = (u'Copyright (c), 2019, Forschungszentrum Jülich GmbH, ' 'IAS-1/PGI-1, Germany. All rights reserved.') __license__ = 'MIT license, see LICENSE.txt file' -__version__ = '0.6.13' +__version__ = '0.7.0' __contributors__ = (u'Fabian Bertoldo', u'Philipp Rüßmann') +# activate verbose output, for debugging only +_VERBOSE_ = True + #TODO: improve workflow output node structure #TODO: generalise search for imp_info and conv_host from startpot @@ -60,7 +63,6 @@ class kkr_imp_dos_wc(WorkChain): } # execute KKR with mpi or without _wf_default = { - 'clean_impcalc_retrieved': True, # remove output of KKRimp calculation after successful parsing of DOS files 'jij_run': False, # calculate Jij's energy resolved 'lmdos': False, # calculate also (l,m) or only l-resolved DOS 'retrieve_kkrflex': True, # retrieve kkrflex files to repository or leave on remote computer only @@ -148,6 +150,7 @@ def define(cls, spec): ) spec.expose_inputs(kkr_imp_sub_wc, namespace='BdG', include=('params_overwrite')) + spec.expose_inputs(kkr_imp_sub_wc, include=('initial_noco_angles')) spec.expose_inputs(kkr_flex_wc, namespace='gf_writeout', include=('params_kkr_overwrite', 'options')) # specify the outputs @@ -206,6 +209,8 @@ def start(self): """ self.report(f'INFO: started KKR impurity DOS workflow version {self._workflowversion}') + if _VERBOSE_: + self.report(f'inputs: {self.inputs}') # input both wf and options parameters if 'wf_parameters' in self.inputs: @@ -248,10 +253,6 @@ def start(self): if k not in self.ctx.dos_params_dict.keys(): self.ctx.dos_params_dict[k] = v - self.ctx.cleanup_impcalc_output = wf_dict.get( - 'clean_impcalc_retrieved', self._wf_default['clean_impcalc_retrieved'] - ) - # set workflow parameters for the KKR impurity calculation self.ctx.jij_run = wf_dict.get('jij_run', self._wf_default['jij_run']) @@ -487,7 +488,6 @@ def run_imp_dos(self): 'dos_run': True, 'lmdos': self.ctx.lmdos, 'jij_run': self.ctx.jij_run, - 'do_final_cleanup': self.ctx.cleanup_impcalc_output }) kkrimp_params = self.ctx.kkrimp_params_dict label_imp = 'KKRimp DOS (GF: {}, imp_pot: {}, Zimp: {}, ilayer_cent: {})'.format( @@ -523,6 +523,8 @@ def run_imp_dos(self): if 'params_overwrite' in self.inputs.BdG: builder.params_overwrite = self.inputs.BdG.params_overwrite + if 'initial_noco_angles' in self.inputs: + builder.initial_noco_angles = self.inputs.initial_noco_angles future = self.submit(builder) @@ -594,13 +596,6 @@ def return_results(self): if self.ctx.lmdos: self.out('dos_data_lm', dosXyDatas['dos_data_lm']) self.out('dos_data_interpol_lm', dosXyDatas['dos_data_interpol_lm']) - # maybe cleanup retrieved folder of DOS calculation - if self.ctx.cleanup_impcalc_output: - message = 'INFO: cleanup after storing of DOS data' - print(message) - self.report(message) - pk_impcalc = self.ctx.kkrimp_dos.outputs.workflow_info['pks_all_calcs'][0] - cleanup_kkrimp_retrieved(pk_impcalc) message = f'INFO: workflow_info node: {outputnode_t.uuid}' print(message) @@ -791,22 +786,3 @@ def parse_impdosfiles(folder, natom, nspin, ef, use_lmdos): output = {'dos_data': dosnode, 'dos_data_interpol': dosnode2} return output - - -def cleanup_kkrimp_retrieved(pk_impcalc): - """ - remove output_all.tar.gz from retrieved of impurity calculation identified by pk_impcalc - """ - from aiida.orm import load_node - from aiida_kkr.calculations import KkrimpCalculation - - # extract retrieved folder - doscalc = load_node(pk_impcalc) - ret = doscalc.outputs.retrieved - - # name of tarfile - tfname = KkrimpCalculation._FILENAME_TAR - - # remove tarfile from retreived dir - if tfname in ret.list_object_names(): - ret.delete_object(tfname, force=True) diff --git a/aiida_kkr/workflows/kkr_imp_sub.py b/aiida_kkr/workflows/kkr_imp_sub.py index ba80eb8a..4f7f8a3b 100644 --- a/aiida_kkr/workflows/kkr_imp_sub.py +++ b/aiida_kkr/workflows/kkr_imp_sub.py @@ -17,7 +17,7 @@ __copyright__ = (u'Copyright (c), 2017, Forschungszentrum Jülich GmbH, ' 'IAS-1/PGI-1, Germany. All rights reserved.') __license__ = 'MIT license, see LICENSE.txt file' -__version__ = '0.9.4' +__version__ = '0.10.0' __contributors__ = (u'Fabian Bertoldo', u'Philipp Ruessmann') #TODO: work on return results function @@ -82,8 +82,6 @@ class kkr_imp_sub_wc(WorkChain): False, # specify if DOS should be calculated (!KKRFLEXFILES with energy contour necessary as GF_remote_data!) 'lmdos': True, # specify if DOS calculation should calculate l-resolved or l and m resolved output 'jij_run': False, # specify if Jijs should be calculated (!changes behavior of the code!!!) - 'do_final_cleanup': - True, # decide whether or not to clean up intermediate files (THIS BREAKS CACHABILITY!) # TODO: remove for aiida-core>2 # # Some parameter for direct solver (if None, use the same as in host code, otherwise overwrite) 'accuracy_params': { 'RADIUS_LOGPANELS': None, # where to set change of logarithmic to linear radial mesh @@ -132,6 +130,8 @@ def define(cls, spec): help='Dict of parameters that are given to the KKRimpCalculation. Overwrites automatically set values!' ) + spec.expose_inputs(KkrimpCalculation, include=('initial_noco_angles')) + # Here the structure of the workflow is defined spec.outline( cls.start, @@ -229,8 +229,6 @@ def start(self): self.ctx.last_remote = None # link to previous host impurity potential self.ctx.last_pot = None - # intermediate single file data objects that contain potential files which can be clean up at the end - self.ctx.sfd_pot_to_clean = [] # convergence info about rms etc. (used to determine convergence behavior) self.ctx.last_rms_all = [] self.ctx.rms_all_steps = [] @@ -253,9 +251,6 @@ def start(self): message = 'INFO: using default wf parameter' self.report(message) - # cleanup intermediate calculations (WARNING: THIS PREVENTS USING CACHING!!!) - self.ctx.do_final_cleanup = wf_dict.get('do_final_cleanup', self._wf_default['do_final_cleanup']) - # set option parameters from input, or defaults self.ctx.withmpi = options_dict.get('withmpi', self._options_default['withmpi']) self.ctx.resources = options_dict.get('resources', self._options_default['resources']) @@ -765,7 +760,6 @@ def run_kkrimp(self): emin = GF_out_params.get_dict().get('energy_contour_group').get('emin') # then use this value to get rid of all core states that are lower than emin (return the same input potential if no states have been removed imp_pot = kick_out_corestates_wf(imp_pot, Float(emin)) - self.ctx.sfd_pot_to_clean.append(imp_pot) if 'impurity_info' in self.inputs: message = 'INFO: using impurity_info node as input for kkrimp calculation' self.report(message) @@ -858,9 +852,10 @@ def run_kkrimp(self): # add LDA+U input node if it was set in parent calculation of last kkrimp_remote or from input port if self.ctx.settings_LDAU is not None: inputs['settings_LDAU'] = self.ctx.settings_LDAU - # set cleanup option - if int(aiida_core_version.split('.')[0]) < 2 and self.ctx.do_final_cleanup: - inputs['cleanup_outfiles'] = Bool(self.ctx.do_final_cleanup) + + # set nonco angles if given + if 'initial_noco_angles' in self.inputs: + inputs['initial_noco_angles'] = self.inputs.initial_noco_angles # run the KKR calculation message = 'INFO: doing calculation' @@ -895,7 +890,6 @@ def inspect_kkrimp(self): retrieved_folder = self.ctx.kkr.outputs.retrieved imp_pot_sfd = extract_imp_pot_sfd(retrieved_folder) self.ctx.last_pot = imp_pot_sfd - self.ctx.sfd_pot_to_clean.append(self.ctx.last_pot) print('use potfile sfd:', self.ctx.last_pot) except: message = 'ERROR: no output potential found' @@ -1199,19 +1193,6 @@ def return_results(self): """ self.report(message) - # cleanup of unnecessary files after convergence - # WARNING: THIS DESTROYS CACHABILITY OF THE WORKFLOW!!! - if self.ctx.do_final_cleanup: - if self.ctx.successful: - self.report('INFO: clean output of calcs') - remove_out_pot_impcalcs(self.ctx.successful, all_pks) - self.report('INFO: clean up raw_input folders') - clean_raw_input(self.ctx.successful, all_pks) - - # clean intermediate single file data which are not needed after successful run or after DOS run - if self.ctx.successful or self.ctx.dos_run: - self.final_cleanup() - self.report('INFO: done with kkr_scf workflow!\n') def error_handler(self): @@ -1219,17 +1200,6 @@ def error_handler(self): if self.ctx.exit_code is not None: return self.ctx.exit_code - def final_cleanup(self): - uuid_last_calc = self.ctx.last_pot.uuid - if not self.ctx.dos_run: - sfds_to_clean = [i for i in self.ctx.sfd_pot_to_clean if i.uuid != uuid_last_calc] - else: - # in case of DOS run we can also clean the last output sfd file since this is never used - sfds_to_clean = self.ctx.sfd_pot_to_clean - # now clean all sfd files that are not needed anymore - for sfd_to_clean in sfds_to_clean: - clean_sfd(sfd_to_clean) - def _overwrite_parameters_from_input(self, new_params): """Overwrite input parameters for KKRimpCalculation if found in input""" params_overwrite = self.inputs.params_overwrite.get_dict() @@ -1242,120 +1212,6 @@ def _overwrite_parameters_from_input(self, new_params): new_params[key] = val -def remove_out_pot_impcalcs(successful, pks_all_calcs, dry_run=False): - """ - Remove out_potential file from all but the last KKRimp calculation if workflow was successful - - Usage:: - - imp_wf = load_node(266885) # maybe start with outer workflow - pk_imp_scf = imp_wf.outputs.workflow_info['used_subworkflows'].get('kkr_imp_sub') - imp_scf_wf = load_node(pk_imp_scf) # this is now the imp scf sub workflow - successful = imp_scf_wf.outputs.workflow_info['successful'] - pks_all_calcs = imp_scf_wf.outputs.workflow_info['pks_all_calcs'] - """ - import tarfile, os - from aiida.orm import load_node - from aiida.common.folders import SandboxFolder - from aiida_kkr.calculations import KkrimpCalculation - - if dry_run: - print('test', successful, len(pks_all_calcs)) - - # name of tarfile - tfname = KkrimpCalculation._FILENAME_TAR - - # cleanup only if calculation was successful - if successful and len(pks_all_calcs) > 1: - # remove out_potential for calculations - # note that also last calc can be cleaned since output potential is stored in single file data - pks_for_cleanup = pks_all_calcs[:] - - # loop over all calculations - for pk in pks_for_cleanup: - if dry_run: - print('pk_for_cleanup:', pk) - # get getreived folder of calc - calc = load_node(pk) - ret = calc.outputs.retrieved - - # open tarfile if present - if tfname in ret.list_object_names(): - delete_and_retar = False - with ret.open(tfname) as tf: - tf_abspath = tf.name - - # create Sandbox folder which is used to temporarily extract output_all.tar.gz - tmpfolder = SandboxFolder() - tmpfolder_path = tmpfolder.abspath - with tarfile.open(tf_abspath) as tf: - tar_filenames = [ifile.name for ifile in tf.getmembers()] - # check if out_potential is in tarfile - if KkrimpCalculation._OUT_POTENTIAL in tar_filenames: - tf.extractall(tmpfolder_path) - delete_and_retar = True - - if delete_and_retar and not dry_run: - # delete out_potential - os.remove(os.path.join(tmpfolder_path, KkrimpCalculation._OUT_POTENTIAL)) - with tarfile.open(tf_abspath, 'w:gz') as tf: - # remove out_potential from list of files - tar_filenames = [i for i in tar_filenames if i != KkrimpCalculation._OUT_POTENTIAL] - for f in tar_filenames: - # create new tarfile without out_potential file - fabs = os.path.join(tmpfolder_path, f) - tf.add(fabs, arcname=os.path.basename(fabs)) - elif dry_run: - print('dry run:') - print('delete and retar?', delete_and_retar) - print('tmpfolder_path', tmpfolder_path) - - # clean up temporary Sandbox folder - if not dry_run: - tmpfolder.erase() - - -def clean_raw_input(successful, pks_calcs, dry_run=False): - """ - Clean raw_input directories that contain copies of shapefun and potential files - This however breaks provenance (strictly speaking) and therefore should only be done - for the calculations of a successfully finished workflow (see email on mailing list from 25.11.2019). - """ - from aiida.orm import load_node - from aiida_kkr.calculations import KkrimpCalculation - if successful: - for pk in pks_calcs: - node = load_node(pk) - # clean only nodes that are KkrimpCalculations - if node.process_class == KkrimpCalculation: - raw_input_folder = node._raw_input_folder - # clean potential and shapefun files - for filename in [KkrimpCalculation._POTENTIAL, KkrimpCalculation._SHAPEFUN]: - if filename in raw_input_folder.get_content_list(): - if dry_run: - print(f'clean {filename}') - else: - raw_input_folder.remove_path(filename) - elif dry_run: - print('no raw_inputs to clean') - - -def clean_sfd(sfd_to_clean, nkeep=30): - """ - Clean up potential file (keep only header) to save space in the repository - WARNING: this breaks cachability! - """ - with sfd_to_clean.open(sfd_to_clean.filename) as f: - txt = f.readlines() - # remove all lines after nkeep lines - txt2 = txt[:nkeep] - # add note to end of file - txt2 += [u'WARNING: REST OF FILE WAS CLEANED SO SAVE SPACE!!!\n'] - # overwrite file - with sfd_to_clean.open(sfd_to_clean.filename, 'w') as fnew: - fnew.writelines(txt2) - - @calcfunction def extract_imp_pot_sfd(retrieved_folder): """