Source code for aiida_kkr.tools.common_workfunctions

# -*- coding: utf-8 -*-
"""
Here workfunctions and normal functions using aiida-stuff (typically used
within workfunctions) are collected.
"""

from aiida.common.exceptions import InputValidationError
from aiida.engine import calcfunction
from aiida.orm import Dict
from masci_tools.io.kkr_params import kkrparams
from builtins import str

# keys that are used by aiida-kkr some something else than KKR parameters
_ignored_keys = ['ef_set', 'use_input_alat', '<NEWVERSION_BDG>', '<DECOUPLE_SPINS_CHEBY>']
_ignored_keys += [i.upper() for i in _ignored_keys]


[docs] @calcfunction def update_params_wf(parameternode, updatenode, **link_inputs): """ Work function to update a KKR input parameter node. Stores new node in database and creates a link from old parameter node to new node Returns updated parameter node using update_params function :note: Input nodes need to be valid aiida Dict objects. :param parameternode: Input aiida Dict node cotaining KKR specific parameters :param updatenode: Input aiida Dict node containing a dictionary with the parameters that are supposed to be changed. :note: If 'nodename' is contained in dict of updatenode the string corresponding to this key will be used as nodename for the new node. Otherwise a default name is used :note: Similar for 'nodedesc' which gives new node a description :example: updated_params = Dict(dict={'nodename': 'my_changed_name', 'nodedesc': 'My description text', 'EMIN': -1, 'RMAX': 10.}) new_params_node = update_params_wf(input_node, updated_params) """ updatenode_dict = updatenode.get_dict() if 'nodename' in list(updatenode_dict.keys()): # take nodename out of dict (should only contain valid KKR parameter) nodename = updatenode_dict.pop('nodename') else: nodename = None if 'nodedesc' in list(updatenode_dict.keys()): # take nodename out of dict (should only contain valid KKR parameter later on) nodedesc = updatenode_dict.pop('nodedesc') else: nodedesc = None # do nothing if updatenode is empty if len(list(updatenode_dict.keys())) == 0: print('Input node is empty, do nothing!') raise InputValidationError('Nothing to store in input') # new_parameternode = update_params(parameternode, nodename=nodename, nodedesc=nodedesc, **updatenode_dict) return new_parameternode
[docs] def update_params(node, nodename=None, nodedesc=None, strict=False, **kwargs): """ Update parameter node given with the values given as kwargs. Returns new node. :param node: Input parameter node (needs to be valid KKR input parameter node). :param **kwargs: Input keys with values as in kkrparams. :param linkname: Input linkname string. Give link from old to new node a name . If no linkname is given linkname defaults to 'updated parameters' :return: parameter node :example usage: OutputNode = KkrCalculation.update_params(InputNode, EMIN=-1, NSTEPS=30) :note: Keys are set as in kkrparams class. Check documentation of kkrparams for further information. :note: If kwargs contain the key `add_direct`, then no kkrparams instance is used and no checks are performed but the dictionary is filled directly! :note: By default nodename is 'updated KKR parameters' and description contains list of changed """ # check if node is a valid KKR parameters node if not isinstance(node, Dict): print('Input node is not a valid Dict node') raise InputValidationError('update_params needs valid parameter node as input') # check if add_direct is in kwargs (shortcuts checks of kkrparams by not using the kkrparams class to set the dict) add_direct = False if 'add_direct' in list(kwargs.keys()): add_direct = kwargs.pop('add_direct') # initialize temporary kkrparams instance containing all possible KKR parameters if not add_direct: params = kkrparams() else: params = {} # extract input dict from node inp_params = node.get_dict() # check if input dict contains only values for KKR parameters if not add_direct: remove_keys = [] for key in inp_params: if key not in list(params.values.keys()) and key not in _ignored_keys: print(f'WARNING: Input node contains invalid key "{key}"') if strict: raise InputValidationError(f'invalid key "{key}" in input parameter node') else: # print a warning and remove the key print(f'ignore this key/value pair: {key}: {inp_params.get(key)}') remove_keys.append(key) for key in remove_keys: inp_params.pop(key) # copy values from input node for key in inp_params: value = inp_params[key] if not add_direct: params.set_value(key, value, silent=True) else: params[key] = value # to keep track of changed values: changed_params = {} # check if values are given as **kwargs (otherwise return input node) if len(kwargs) == 0: print('No additional input keys given, return input node') return node.clone() for key in kwargs: # check if value of 'key' should be set (either because it differs from old para node or because it was not set at all) update_value = False if key in list(inp_params.keys()): if kwargs[key] != inp_params[key]: update_value = True else: update_value = True if update_value: if not add_direct: params.set_value(key, kwargs[key], silent=True) else: params[key] = kwargs[key] changed_params[key] = kwargs[key] if len(list(changed_params.keys())) == 0: print('No keys have been changed, return input node') return node.clone() # set linkname with input or default value if nodename is None or not isinstance(nodename, str): nodename = 'updated KKR parameters' if nodedesc is None or not isinstance(nodedesc, str): nodedesc = f'changed parameters: {changed_params}' # create new node if not add_direct: ParaNode = Dict(params.values) else: ParaNode = Dict(params) ParaNode.label = nodename ParaNode.description = nodedesc return ParaNode
# TODO implment VCA functionality # maybe one starts from a calculation closest to the VCA case and slowly # increase ZATOM which violates the _do_never_modify rule in KKR calculation # this should then create a new structure and modify the old potential accordingly # general rule: Nover destroy the data provenance!!! @calcfunction def prepare_VCA_structure_wf(): pass def prepare_VCA_structure(): pass # TODO implement 2D input helper # a helper workfunction would be nice to create the vacuum region etc. for 2D calculation @calcfunction def prepare_2Dcalc_wf(): pass def prepare_2Dcalc(): pass
[docs] def test_and_get_codenode(codenode, expected_code_type, use_exceptions=False): """ Pass a code node and an expected code (plugin) type. Check that the code exists, is unique, and return the Code object. :param codenode: the name of the code to load (in the form label@machine) :param expected_code_type: a string with the plugin that is expected to be loaded. In case no plugins exist with the given name, show all existing plugins of that type :param use_exceptions: if True, raise a ValueError exception instead of calling sys.exit(1) :return: a Code object :example usage: from kkr_scf workflow:: if 'voronoi' in inputs: try: test_and_get_codenode(inputs.voronoi, 'kkr.voro', use_exceptions=True) except ValueError: error = ("The code you provided for voronoi does not " "use the plugin kkr.voro") self.control_end_wc(error) """ import sys from aiida.common.exceptions import NotExistent from aiida.orm import Code try: if codenode is None: raise ValueError code = codenode if code.get_input_plugin_name() != expected_code_type: raise ValueError except (NotExistent, ValueError): from aiida.orm.querybuilder import QueryBuilder qb = QueryBuilder() qb.append(Code, filters={'attributes.input_plugin': {'==': expected_code_type}}, project='*') valid_code_labels = [f'{c.label}@{c.get_computer().name}' for [c] in qb.all()] if valid_code_labels: msg = ( 'Pass as further parameter a valid code label.\n' 'Valid labels with a {} executable are:\n'.format(expected_code_type) ) msg += '\n'.join(f'* {label}' for label in valid_code_labels) if use_exceptions: raise ValueError(msg) else: print(msg, file=sys.stderr) sys.exit(1) else: msg = ( 'Code not valid, and no valid codes for {}.\n' 'Configure at least one first using\n' ' verdi code setup'.format(expected_code_type) ) if use_exceptions: raise ValueError(msg) print(msg, file=sys.stderr) sys.exit(1) return code
[docs] def get_inputs_kkr(code, remote, options, label='', description='', parameters=None, serial=False, imp_info=None): """ Get the input for a voronoi calc. Wrapper for KkrProcess setting structure, code, options, label, description etc. :param code: a valid KKRcode installation (e.g. input from Code.get_from_string('codename@computername')) :param remote: remote directory of parent calculation (Voronoi or previous KKR calculation) """ from aiida_kkr.calculations.kkr import KkrCalculation # then reuse common inputs setter builder = get_inputs_common( KkrCalculation, code, remote, None, options, label, description, parameters, serial, imp_info ) return builder
[docs] def get_inputs_kkrimporter(code, remote, options, label='', description='', parameters=None, serial=False): """ Get the input for a voronoi calc. Wrapper for KkrProcess setting structure, code, options, label, description etc. """ from aiida_kkr.calculations.kkr import KkrCalculation KkrProcess = KkrCalculation.process() # then reuse common inputs setter inputs = get_inputs_common(KkrProcess, code, remote, None, options, label, description, parameters, serial) return inputs
[docs] def get_inputs_voronoi(code, structure, options, label='', description='', params=None, serial=True, parent_KKR=None): """ Get the input for a voronoi calc. Wrapper for VoronoiProcess setting structure, code, options, label, description etc. """ # get process for VoronoiCalculation from aiida_kkr.calculations.voro import VoronoiCalculation # then reuse common inputs setter all options if structure is not None: # for 'normal' case starting from structure builder = get_inputs_common( VoronoiCalculation, code, None, structure, options, label, description, params, serial ) else: # for parent_KKR feature used to increase lmax which cannot have 'structure' in inputs builder = get_inputs_common( VoronoiCalculation, code, None, None, options, label, description, params, serial, parent_KKR=parent_KKR ) return builder
[docs] def get_inputs_kkrimp( code, options, label='', description='', parameters=None, serial=False, imp_info=None, host_GF=None, imp_pot=None, kkrimp_remote=None, host_GF_Efshift=None ): """ Get the input for a kkrimp calc. Wrapper for KkrimpProcess setting structure, code, options, label, description etc. :param code: a valid KKRimpcode installation (e.g. input from Code.get_from_string('codename@computername')) TBD """ from aiida_kkr.calculations.kkrimp import KkrimpCalculation # then reuse common inputs setter builder = get_inputs_common( KkrimpCalculation, code, None, None, options, label, description, parameters, serial, imp_info, host_GF, imp_pot, kkrimp_remote, host_GF_Efshift ) return builder
[docs] def get_inputs_common( calculation, code, remote, structure, options, label, description, params, serial, imp_info=None, host_GF=None, imp_pot=None, kkrimp_remote=None, host_GF_Efshift=None, **kwargs ): """ Base function common in get_inputs_* functions for different codes """ inputs = calculation.get_builder() if structure: inputs.structure = structure if remote: inputs.parent_folder = remote if code: inputs.code = code _sched = code.computer.scheduler_type else: _sched = None if params: inputs.parameters = params if not options: options = {} if description: inputs.metadata.description = description else: inputs.metadata.description = '' if label: inputs.metadata.label = label else: inputs.metadata.label = '' if serial: # check for old aiida name (e.g. "slurm") and new aiida name ("core.slurm") of the scheduler if _sched in ['core.slurm', 'slurm', 'core.pbspro', 'pbspro']: # overwrite settings for serial run options['withmpi'] = False options['resources'] = {'num_machines': 1, 'tot_num_mpiprocs': 1} if _sched in ['core.sge', 'sge']: options['withmpi'] = False options['resources'] = {'parallel_env': 'smpslots', 'tot_num_mpiprocs': 1} else: # otherwise assume MPI parallelism if not given in input options if 'withmpi' not in list(options.keys()): options['withmpi'] = True if options: inputs.metadata.options = options ''' options = { "max_wallclock_seconds": int, "resources": dict, "custom_scheduler_commands": unicode, "queue_name": basestring, "computer": Computer, "withmpi": bool, "mpirun_extra_params": Any(list, tuple), "import_sys_environment": bool, "environment_variables": dict, "priority": unicode, "max_memory_kb": int, "prepend_text": unicode, "append_text": unicode} ''' # for kkrimp calculations if imp_info is not None: inputs.impurity_info = imp_info if host_GF is not None: inputs.host_Greenfunction_folder = host_GF if host_GF_Efshift is not None: inputs.host_Greenfunction_folder_Efshift = host_GF_Efshift if imp_pot is not None: inputs.impurity_potential = imp_pot if kkrimp_remote is not None: inputs.parent_calc_folder = kkrimp_remote # add additional inputs for link_label, node in kwargs.items(): inputs[link_label] = node return inputs
[docs] def get_parent_paranode(remote_data): """ Return the input parameter of the parent calculation giving the remote_data node """ inp_calc = remote_data.get_incoming(link_label_filter='remote_folder').first().node inp_para = inp_calc.get_incoming(link_label_filter='parameters').first().node return inp_para
[docs] def generate_inputcard_from_structure( parameters, structure, input_filename, parent_calc=None, shapes=None, isvoronoi=False, use_input_alat=False, vca_structure=False ): """ Takes information from parameter and structure data and writes input file 'input_filename' :param parameters: input parameters node containing KKR-related input parameter :param structure: input structure node containing lattice information :param input_filename: input filename, typically called 'inputcard' optional arguments :param parent_calc: input parent calculation node used to determine if EMIN parameter is automatically overwritten (from voronoi output) or not :param shapes: input shapes array (set automatically by aiida_kkr.calculations.Kkrcalculation and shall not be overwritten) :param isvoronoi: tell whether or not the parameter set is for a voronoi calculation or kkr calculation (have different lists of mandatory keys) :param use_input_alat: True/False, determines whether the input alat value is taken or the new alat is computed from the Bravais vectors :note: assumes valid structure and parameters, i.e. for 2D case all necessary information has to be given. This is checked with function 'check_2D_input' called in aiida_kkr.calculations.Kkrcalculation """ from aiida.common.constants import elements as PeriodicTableElements from numpy import array from masci_tools.io.kkr_params import kkrparams from masci_tools.io.common_functions import get_Ang2aBohr, get_alat_from_bravais from aiida_kkr.calculations.voro import VoronoiCalculation # initialize list of warnings warnings = [] # list of globally used constants a_to_bohr = get_Ang2aBohr() # Get the connection between coordination number and element symbol # maybe do in a different way _atomic_numbers = {data['symbol']: num for num, data in PeriodicTableElements.items()} # KKR wants units in bohr bravais = array(structure.cell) * a_to_bohr alat_input = parameters.get_dict().get('ALATBASIS') if use_input_alat and alat_input is not None: alat = alat_input wmess = 'found alat in input parameters, this will trigger scaling of RMAX, GMAX and RCLUSTZ!' print(f'WARNING: {wmess}') warnings.append(wmess) else: alat = get_alat_from_bravais(bravais, is3D=structure.pbc[2]) bravais = bravais / alat sites = structure.sites naez = len(sites) positions = [] charges = [] weights = [] # for CPA isitelist = [] # counter sites array for CPA isite = 0 for site in sites: pos = site.position # TODO maybe convert to rel pos and make sure that type is right for script (array or tuple) abspos = array(pos) * a_to_bohr / alat # also in units of alat positions.append(abspos) isite += 1 sitekind = structure.get_kind(site.kind_name) for ikind in range(len(sitekind.symbols)): site_symbol = sitekind.symbols[ikind] if sitekind.is_alloy: wght = sitekind.weights[ikind] else: wght = 1. if not sitekind.has_vacancies: zatom_tmp = _atomic_numbers[site_symbol] else: zatom_tmp = 0.0 if vca_structure and ikind > 0 and not isvoronoi: # for VCA case take weighted average (only for KKR code, voronoi code uses zatom of first site for dummy calculation) zatom = zatom * wght_last + zatom_tmp * wght # also reset weight to 1 wght = 1. else: zatom = zatom_tmp if vca_structure and isvoronoi: wght = 1. wght_last = wght # for VCA mode # make sure that for VCA only averaged position is written (or first for voronoi code) if (( vca_structure and ((len(sitekind.symbols) == 1) or (not isvoronoi and ikind == 1) or (isvoronoi and ikind == 0)) ) or (not vca_structure)): charges.append(zatom) weights.append(wght) isitelist.append(isite) weights = array(weights) isitelist = array(isitelist) charges = array(charges) positions = array(positions) ###################################### # Prepare keywords for kkr from input structure # get parameter dictionary input_dict = parameters.get_dict() # remove special keys that are used for special cases but are not part of the KKR parameter set for key in _ignored_keys: if input_dict.get(key) is not None: wmess = f'automatically removing value of key {key}' print('WARNING: ' + wmess) warnings.append(wmess) input_dict.pop(key) # get rid of structure related inputs that are overwritten from structure input for key in ['BRAVAIS', 'ALATBASIS', 'NAEZ', '<ZATOM>', '<RBASIS>', 'CARTESIAN']: if input_dict.get(key) is not None: wmess = f'automatically removing value of key {key}' print('WARNING: ' + wmess) warnings.append(wmess) input_dict.pop(key) # automatically rescale RMAX, GMAX, RCLUSTZ, RCLUSTXY which are scaled with the lattice constant if alat_input is not None: if input_dict.get('RMAX') is not None: wmess = f'rescale RMAX: {alat_input / alat}' print('WARNING: ' + wmess) warnings.append(wmess) input_dict['RMAX'] = input_dict['RMAX'] * alat_input / alat if input_dict.get('GMAX') is not None: wmess = f'rescale GMAX: {1 / (alat_input / alat)}' print('WARNING: ' + wmess) warnings.append(wmess) input_dict['GMAX'] = input_dict['GMAX'] * 1 / (alat_input / alat) if input_dict.get('RCLUSTZ') is not None: wmess = f'rescale RCLUSTZ: {alat_input / alat}' print('WARNING: ' + wmess) warnings.append(wmess) input_dict['RCLUSTZ'] = input_dict['RCLUSTZ'] * alat_input / alat if input_dict.get('RCLUSTXY') is not None: wmess = f'rescale RCLUSTXY: {alat_input / alat}' print('WARNING: ' + wmess) warnings.append(wmess) input_dict['RCLUSTXY'] = input_dict['RCLUSTXY'] * alat_input / alat # empty kkrparams instance (contains formatting info etc.) if not isvoronoi: params = kkrparams() else: params = kkrparams(params_type='voronoi') # for KKR calculation set EMIN automatically from parent_calc (always in res.emin of voronoi and kkr) if not provided in input node if (('EMIN' not in list(input_dict.keys()) or input_dict['EMIN'] is None) and parent_calc is not None): wmess = f'Overwriting EMIN with value from parent calculation {parent_calc}' print('WARNING: ' + wmess) warnings.append(wmess) if parent_calc.process_class == VoronoiCalculation: emin = parent_calc.outputs.output_parameters.get_dict().get('emin') else: emin = parent_calc.outputs.output_parameters.get_dict().get('energy_contour_group').get('emin') print('Setting emin:', emin, 'is emin None?', emin is None) params.set_value('EMIN', emin) # overwrite keywords with input parameter for key in list(input_dict.keys()): params.set_value(key, input_dict[key], silent=True) # Write input to file (the parameters that are set here are not allowed to be modfied externally) params.set_multiple_values( BRAVAIS=bravais, ALATBASIS=alat, NAEZ=naez, ZATOM=charges, RBASIS=positions, CARTESIAN=True ) # for CPA case: if len(weights) > naez: natyp = len(weights) params.set_value('NATYP', natyp) params.set_value('<CPA-CONC>', weights) params.set_value('<SITE>', isitelist) else: natyp = naez # write shapes (extracted from voronoi parent automatically in kkr calculation plugin) if shapes is not None: params.set_value('<SHAPE>', shapes) # change input values of 2D input to new alat: rbl = params.get_value('<RBLEFT>') rbr = params.get_value('<RBRIGHT>') zper_l = params.get_value('ZPERIODL') zper_r = params.get_value('ZPERIODR') if rbl is not None: params.set_value('<RBLEFT>', array(rbl) * a_to_bohr / alat) if rbr is not None: params.set_value('<RBRIGHT>', array(rbr) * a_to_bohr / alat) if zper_l is not None: params.set_value('ZPERIODL', array(zper_l) * a_to_bohr / alat) if zper_r is not None: params.set_value('ZPERIODR', array(zper_r) * a_to_bohr / alat) # write inputfile params.fill_keywords_to_inputfile(output=input_filename) nspin = params.get_value('NSPIN') newsosol = False if 'NEWSOSOL' in params.get_value('RUNOPT'): newsosol = True return natyp, nspin, newsosol, warnings
[docs] def check_2Dinput_consistency(structure, parameters): """ Check if structure and parameter data are complete and matching. :param input: structure, needs to be a valid aiida StructureData node :param input: parameters, needs to be valid aiida Dict node returns (False, errormessage) if an inconsistency has been found, otherwise return (True, '2D consistency check complete') """ # default is bulk, get 2D info from structure.pbc info (periodic boundary contitions) is2D = False if not all(structure.pbc): # check periodicity, assumes finite size in z-direction if structure.pbc != (True, True, False): return ( False, 'Structure.pbc is neither (True, True, True) for bulk nor (True, True, False) for surface calculation!' ) is2D = True # check for necessary info in 2D case inp_dict = parameters.get_dict() set_keys = [i for i in list(inp_dict.keys()) if inp_dict[i] is not None] has2Dinfo = True for icheck in ['INTERFACE', '<NRBASIS>', '<RBLEFT>', '<RBRIGHT>', 'ZPERIODL', 'ZPERIODR', '<NLBASIS>']: if icheck not in set_keys: has2Dinfo = False if has2Dinfo and not inp_dict['INTERFACE'] and is2D: return (False, "'INTERFACE' parameter set to False but structure is 2D") if has2Dinfo != is2D: if is2D: return ( False, '2D info given in parameters but structure is 3D\nstructure is 2D? {}\ninput has 2D info? {}\nset keys are: {}' .format(is2D, has2Dinfo, set_keys) ) return ( False, '3D info given in parameters but structure is 2D\nstructure is 2D? {}\ninput has 2D info? {}\nset keys are: {}' .format(is2D, has2Dinfo, set_keys) ) # if everything is ok: return (True, '2D consistency check complete')
[docs] def structure_from_params(parameters): """ Construct aiida structure out of kkr parameter set (if ALATBASIS, RBASIS, ZATOM etc. are given) :param input: parameters, kkrparams object with structure information set (e.g. extracted from read_inputcard function) :returns: success, boolean to determine if structure creatoin was successful :returns: structure, an aiida StructureData object """ from masci_tools.io.common_functions import get_aBohr2Ang from aiida.common.constants import elements as PeriodicTableElements from aiida.orm import StructureData from masci_tools.io.kkr_params import kkrparams from numpy import array # check input if not isinstance(parameters, kkrparams): raise InputValidationError('input parameters needs to be a "kkrparams" instance!') # initialize some stuff is_complete = True for icheck in ['<ZATOM>', '<RBASIS>', 'BRAVAIS', 'ALATBASIS']: if parameters.get_value(icheck) is None: is_complete = False # set natyp natyp = parameters.get_value('NATYP') naez = parameters.get_value('NAEZ') if natyp is None: if naez is None: is_complete = False else: natyp = naez # check if all necessary info for 2D calculation is there if parameters.get_value('INTERFACE'): for icheck in ['<NRBASIS>', '<RBLEFT>', '<RBRIGHT>', 'ZPERIODL', 'ZPERIODR', '<NLBASIS>']: if parameters.get_value(icheck) is None: is_complete = False # check CPA case if natyp != naez: for icheck in ['<SITE>', '<CPA-CONC>']: if parameters.get_value(icheck) is None: is_complete = False if not is_complete: return is_complete, StructureData() # extract cell using BRAVAIS and ALATBASIS and create empty structure alat = parameters.get_value('ALATBASIS') cell = array(parameters.get_value('BRAVAIS')) * alat * get_aBohr2Ang() struc = StructureData(cell=cell) # extract atom numbers zatom_all = parameters.get_value('<ZATOM>') # extract sites with positions, charges/Atom labels, weights # positions in units of alat pos_all = array(parameters.get_value('<RBASIS>')) if len(pos_all.shape) == 1: pos_all = array([pos_all]) zatom_all = [zatom_all] if not parameters.get_value('CARTESIAN'): # convert from internal to cartesian coordinates for isite, tmp_pos in enumerate(pos_all): # cell already contains alat factor to convert to Ang. units pos_all[isite] = tmp_pos[0]*cell[0] + \ tmp_pos[1]*cell[1] + tmp_pos[2]*cell[2] else: pos_all = pos_all * alat * get_aBohr2Ang() # now positions are in Ang. units # convert to list if input contains a single entry only if not isinstance(zatom_all, list): zatom_all = [zatom_all] pos_all = [pos_all] # extract weights and sites for CPA calculations if natyp == naez: weights = [1. for i in range(natyp)] sites = list(range(1, natyp + 1)) else: weights = parameters.get_value('<CPA-CONC>') sites = parameters.get_value('<SITE>') # fill structure from zatom, weights and sites information for isite in sites: pos = pos_all[sites.index(isite)] weight = weights[sites.index(isite)] if abs(zatom_all[isite - 1] - int(zatom_all[isite - 1])) > 10**-4: # TODO deal with VCA (non-integer zatom) print('VCA not implemented yet, stopping here!') raise NotImplementedError('VCA functionality not implemented') if zatom_all[isite - 1] < 1: symbol = 'X' struc.append_atom(position=pos, symbols='X', weights=weight) else: symbol = PeriodicTableElements.get(zatom_all[isite - 1]).get('symbol') struc.append_atom(position=pos, symbols=symbol, weights=weight) # set correct pbc for 2D case if parameters.get_value('INTERFACE'): struc.set_pbc((True, True, False)) # finally return structure return is_complete, struc
[docs] def vca_check(structure, parameters): """ """ nsites = 0 for site in structure.sites: sitekind = structure.get_kind(site.kind_name) nsites += len(sitekind.symbols) # VCA mode if CPAINFO = [-1,-1] first try: if parameters.get_dict().get('CPAINFO')[0] < 0: params_vca_mode = True else: params_vca_mode = False except: params_vca_mode = False # check if structure supports VCA mode vca_structure = False if params_vca_mode: if nsites > len(structure.sites): vca_structure = True return vca_structure
[docs] def get_username(computer): """ set upload dir (get the remote username and try 5 times if there was a connection error """ import time try_trans = 0 while try_trans < 5: try_trans += 1 try: with computer.get_transport() as transport: remote_user = transport.whoami() except: # this means we have some ssh connection error, thus we wait 5 seconds before we try again remote_user = None time.sleep(5) if remote_user is not None: break # check if username was extracted correctly and raise an error otherwise if remote_user is None: raise ValueError('Error getting the username from the computer!') return remote_user
[docs] def get_natyp(structure): """Count number of atom types (>NAEZ for CPA) for the structure""" counter = 0 # for CPA for site in structure.sites: sitekind = structure.get_kind(site.kind_name) for ikind in range(len(sitekind.symbols)): counter += 1 return counter