diff --git a/aiida_kkr/tools/__init__.py b/aiida_kkr/tools/__init__.py index 4732a28d..4c0793d8 100644 --- a/aiida_kkr/tools/__init__.py +++ b/aiida_kkr/tools/__init__.py @@ -6,7 +6,7 @@ from .common_workfunctions import ( update_params_wf, prepare_VCA_structure_wf, prepare_2Dcalc_wf, test_and_get_codenode, get_inputs_kkr, get_inputs_kkrimporter, get_inputs_voronoi, get_inputs_kkrimp, get_parent_paranode, - generate_inputcard_from_structure, check_2Dinput_consistency, structure_from_params, vca_check + generate_inputcard_from_structure, check_2Dinput_consistency, structure_from_params, vca_check, truncate_string ) from .find_cluster_radius import find_cluster_radius from .plot_kkr import plot_kkr diff --git a/aiida_kkr/tools/common_workfunctions.py b/aiida_kkr/tools/common_workfunctions.py index 746c2d99..bc544e30 100644 --- a/aiida_kkr/tools/common_workfunctions.py +++ b/aiida_kkr/tools/common_workfunctions.py @@ -336,6 +336,16 @@ def get_inputs_kkrimp( return builder +def truncate_string(string, max_length): + """ + Truncate the length of a string to max_length-3 entries. + The last three characters '...' to indicate the truncation. + """ + if len(string) > max_length: + string = string[:max_length - 3] + '...' + return string + + def get_inputs_common( calculation, code, @@ -381,7 +391,8 @@ def get_inputs_common( inputs.metadata.description = '' if label: - inputs.metadata.label = label + # Attention: max label length is 255 characters + inputs.metadata.label = truncate_string(label, 255) else: inputs.metadata.label = '' diff --git a/aiida_kkr/workflows/kkr_STM.py b/aiida_kkr/workflows/kkr_STM.py index 591b3cee..5da3ff6e 100644 --- a/aiida_kkr/workflows/kkr_STM.py +++ b/aiida_kkr/workflows/kkr_STM.py @@ -153,7 +153,7 @@ def define(cls, spec): # Here we expose the inputs for the GF calculations step. # One parameter which is crucial is the NSHELD, which determines the impurity cluster radius. - spec.expose_inputs(kkr_flex_wc, namespace='gf_writeout', include=('params_kkr_overwrite')) + spec.expose_inputs(kkr_flex_wc, namespace='gf_writeout', include=('params_kkr_overwrite', 'options')) # Here we expose the BdG calculations from the kkr_imp_dos_wc spec.expose_inputs(kkr_imp_sub_wc, namespace='BdG', include=('params_overwrite')) @@ -334,16 +334,14 @@ def validate_input(self): return self.exit_codes.ERROR_NO_DATA_FOR_THE_GF_STEP # pylint: disable=no-member def impurity_cluster_evaluation(self): - from aiida_kkr.tools import tools_STM_scan + """ + Create the combined impurity cluster and potential for the impurity region + used in self-consistency + the additional scanning sites. + """ from aiida_kkr.tools import find_parent_structure # Here we create an impurity cluster that has inside all the positions on which the STM will scan - # We now want to iterate over several in-plane positions. - # These are the number of vectors in which we want to move the STM tip. - x = self.inputs.tip_position['nx'] - y = self.inputs.tip_position['ny'] - impurity_info = self.inputs.imp_info # for the first step we combine the impurity info from the input imp_potential_node = self.inputs.imp_potential_node # for the first step we combine the impurity node from the input @@ -351,16 +349,10 @@ def impurity_cluster_evaluation(self): host_calc = host_remote.get_incoming(node_class=CalcJobNode).first().node host_structure = find_parent_structure(host_remote) - # Information of the host structure - struc_info, symm_matrices = tools_STM_scan.STM_pathfinder(host_remote) - - # Path creation step. (The the identity operator is present, but will be excluded) - unused_pos, used_pos = tools_STM_scan.lattice_generation(x, y, symm_matrices, struc_info['plane_vectors']) - - # Since the combine tools use the element already in the units of da and db, we use a helper function - # to have the indices of the linear combination of the used position vectors in the base of the Bravais lattice. - coeff = tools_STM_scan.find_linear_combination_coefficients(struc_info['plane_vectors'], used_pos) + # now find all the positions we need to scan + coeff = self.get_scanning_positions(host_remote) + # construct impurity potential and imp_info for the impurity cluster + scanning area for element in coeff: tmp_imp_info = self.combine_potentials(host_structure, impurity_info, element[0], element[1]) impurity_info = tmp_imp_info @@ -371,6 +363,45 @@ def impurity_cluster_evaluation(self): return impurity_info, imp_potential_node + def get_scanning_positions(self, host_remote): + """ + Extract scanning positions either from input 'scan_positions' or from 'nx', 'ny' + symmetry analysis + + If 'scan_positions' is found in 'tip_position' input dict we use these positions which should + be 2D array of integers with the positions in units of the structure's in-plane Bravais matrix. + + Otherwise we use the 'nx', 'ny' input to define a scanning region where an automated symmetry + analysis is done to reduce the scanning area to the irreducible part. + """ + from aiida_kkr.tools import tools_STM_scan + + generate_scan_positions = True + if 'scan_positions' in self.inputs.tip_position: + coeff = self.inputs.tip_position['scan_positions'] + if coeff is not None: + # check if coefficients exists and are valid + # TODO: improve the validity check + generate_scan_positions = False + + if generate_scan_positions: + + # Information of the host structure + struc_info, symm_matrices = tools_STM_scan.STM_pathfinder(host_remote) + + # We now want to iterate over several in-plane positions. + # These are the number of vectors in which we want to move the STM tip. + x = self.inputs.tip_position['nx'] + y = self.inputs.tip_position['ny'] + + # Path creation step. (The the identity operator is present, but will be excluded) + unused_pos, used_pos = tools_STM_scan.lattice_generation(x, y, symm_matrices, struc_info['plane_vectors']) + + # Since the combine tools use the element already in the units of da and db, we use a helper function + # to have the indices of the linear combination of the used position vectors in the base of the Bravais lattice. + coeff = tools_STM_scan.find_linear_combination_coefficients(struc_info['plane_vectors'], used_pos) + + return coeff + def STM_lmdos_run(self): """In this part of the worflow we want to simulate the lmdos which a STM is able to measure """ @@ -387,7 +418,6 @@ def STM_lmdos_run(self): if 'kkrflex_files' in self.inputs: builder.gf_dos_remote = self.inputs.kkrflex_files message = f'Remote host function is given in the outputs from the node: {self.inputs.kkrflex_files}' - print(message) self.report(message) else: builder.kkr = self.inputs.kkr # needed to evaluate the kkr_flex files in the DOS step @@ -408,9 +438,9 @@ def STM_lmdos_run(self): self.ctx.kkrimp_params_dict = Dict( dict={ - 'nsteps': 1, - 'kkr_runmax': 1, - 'dos_run': True, + 'nsteps': 1, # redundant because this is already set inside the kkr_imp_dos workchain?! + 'kkr_runmax': 1, # redundant because this is already set inside the kkr_imp_dos workchain?! + 'dos_run': True, # redundant because this is already set inside the kkr_imp_dos workchain?! 'retrieve_kkrflex': self.ctx.retrieve_kkrflex, 'lmdos': self.ctx.lmdos, 'jij_run': self.ctx.jij_run, diff --git a/aiida_kkr/workflows/kkr_imp_dos.py b/aiida_kkr/workflows/kkr_imp_dos.py index a8f33425..b516b1bc 100644 --- a/aiida_kkr/workflows/kkr_imp_dos.py +++ b/aiida_kkr/workflows/kkr_imp_dos.py @@ -10,6 +10,7 @@ from aiida.engine import if_, ToContext, WorkChain, calcfunction from aiida.common import LinkType from aiida.common.folders import SandboxFolder +from aiida_kkr.tools import truncate_string from aiida_kkr.workflows.gf_writeout import kkr_flex_wc from aiida_kkr.workflows.kkr_imp_sub import kkr_imp_sub_wc from aiida_kkr.workflows.dos import kkr_dos_wc @@ -507,7 +508,8 @@ def run_imp_dos(self): ) builder = kkr_imp_sub_wc.get_builder() - builder.metadata.label = label_imp # pylint: disable=no-member + # Attention: label and description must not be loo long (255 characters max)! + builder.metadata.label = truncate_string(label_imp, 255) # pylint: disable=no-member builder.metadata.description = description_imp # pylint: disable=no-member builder.kkrimp = kkrimpcode builder.options = options