From 11dfe385515fb742da182bd222ee0cbd9228c824 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philipp=20R=C3=BC=C3=9Fmann?=
Date: Fri, 31 May 2024 08:32:10 +0000
Subject: [PATCH] Bugfix label length and add 'scan_positions' input
possibility
- Fix error where process gets stuck due to label being too long (255 max numbe rof chars)
- Add possibility to use custom scanning positions via 'scan_positions' entry in 'tip_position' input dict
---
aiida_kkr/tools/__init__.py | 2 +-
aiida_kkr/tools/common_workfunctions.py | 13 ++++-
aiida_kkr/workflows/kkr_STM.py | 70 ++++++++++++++++++-------
aiida_kkr/workflows/kkr_imp_dos.py | 4 +-
4 files changed, 66 insertions(+), 23 deletions(-)
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