def test_update_params_wf(self): from aiida_kkr.tools.common_workfunctions import update_params_wf from aiida_kkr.tools.kkr_params import kkrparams from aiida.orm import DataFactory ParameterData = DataFactory('parameter') k = kkrparams(LMAX=2) node1 = ParameterData(dict=k.values) node2 = ParameterData( dict={ 'nodename': 'my_changed_name', 'nodedesc': 'My description text', 'EMIN': -1, 'RMAX': 10. }) unode = update_params_wf(node1, node1) assert unode == node1 unode = update_params_wf(node1, node2) d0 = node1.get_dict() for i in d0.keys(): if d0[i] is None: d0.pop(i) d1 = unode.get_dict() for i in d1.keys(): if d1[i] is None: d1.pop(i) l_identical, l_diff = [], [] for i in d0.keys(): if i in d1.keys(): l_identical.append([i, d0[i], d1[i]]) else: l_diff.append([0, i, d0[i]]) for i in d1.keys(): if i not in d0.keys(): l_diff.append([1, i, d1[i]]) assert l_identical == [[u'LMAX', 2, 2]] assert l_diff == [[1, u'RMAX', 10.0], [1, u'EMIN', -1.0]] return node1, node2, unode
def check_voro_out(self): """ check outout of vorostart workflow and create input for rest of calculations (rmtcore setting etc.) """ self.report('INFO: checking voronoi output') # get output of kkr_startpot out_wc = self.ctx.kkr_startpot try: res = out_wc.outputs.results_vorostart_wc voro_params = out_wc.outputs.last_params_voronoi smallest_voro_remote = out_wc.outputs.last_voronoi_remote smallest_voro_results = out_wc.outputs.last_voronoi_results vorostart_success = res.get_dict()['successful'] except: vorostart_success = False if vorostart_success: rmt = [] radii = smallest_voro_results.get_dict()['radii_atoms_group'] for rad_iatom in radii: if 'rmt0' in list(rad_iatom.keys()): rmt.append(rad_iatom['rmt0']) rmtcore_min = array(rmt) * smallest_voro_results.get_dict().get( 'alat') # needs to be mutiplied by alat in atomic units! self.report('INFO: extracted rmtcore_min ({})'.format(rmtcore_min)) else: return self.exit_codes.ERROR_VOROSTART_NOT_SUCCESSFUL # update parameter node with rmtcore setting voro_params_with_rmtcore = kkrparams(**voro_params.get_dict()) voro_params_with_rmtcore.set_value('<RMTCORE>', rmtcore_min) voro_params_with_rmtcore_dict = voro_params_with_rmtcore.get_dict() voro_params_with_rmtcore = update_params_wf( voro_params, Dict(dict=voro_params_with_rmtcore_dict)) self.report( 'INFO: updated kkr_parameters inlcuding RMTCORE setting (uuid={})'. format(voro_params_with_rmtcore.uuid)) # store links to context self.ctx.params_kkr_run = voro_params_with_rmtcore self.ctx.smallest_voro_remote = smallest_voro_remote
def run_voronoi(self): """ run voronoi calculation with parameters from input """ # incerement iteration counter self.ctx.iter += 1 # increase some parameters if self.ctx.iter > 1: # check if cluster size is actually the reason for failure if self.ctx.dos_check_fail_reason not in [ 'EMIN too high', 'core state in contour', 'core state too close' ]: self.ctx.r_cls = self.ctx.r_cls * self.ctx.fac_clsincrease structure = self.inputs.structure self.ctx.formula = structure.get_formula() label = 'voronoi calculation step {}'.format(self.ctx.iter) description = '{} vornoi on {}'.format(self.ctx.description_wf, self.ctx.formula) voronoicode = self.inputs.voronoi # get valid KKR parameters if self.ctx.iter > 1: # take value from last run to continue params = self.ctx.last_params first_iter = False else: # used input or defaults in first iteration first_iter = True if 'calc_parameters' in self.inputs: params = self.inputs.calc_parameters else: kkrparams_default = kkrparams() para_version = self._kkr_default_params[1] for key, val in self._kkr_default_params[0].items(): kkrparams_default.set_value(key, val, silent=True) # create Dict node params = Dict(dict=kkrparams_default.get_dict()) params.label = 'Defaults for KKR parameter node' params.description = 'defaults as defined in kkrparams of version {}'.format( para_version) # set last_params accordingly (used below for provenance tracking) self.ctx.last_params = params self.report("INFO: input params: {}".format(params.get_dict())) # check if RCLUSTZ is set and use setting from wf_parameters instead (calls update_params_wf to keep track of provenance) updated_params = False update_list = [] kkr_para = kkrparams() for key, val in params.get_dict().items(): kkr_para.set_value(key, val, silent=True) set_vals = kkr_para.get_set_values() set_vals = [keyvalpair[0] for keyvalpair in set_vals] default_values = kkrparams.get_KKRcalc_parameter_defaults()[0] if 'RCLUSTZ' in set_vals: rcls_input = params.get_dict()['RCLUSTZ'] # set r_cls by default or from input in first iteration if self.ctx.r_cls < rcls_input and first_iter: self.ctx.r_cls = rcls_input updated_params = True update_list.append('RCLUSTZ') elif self.ctx.r_cls > rcls_input: # change rcls with iterations updated_params = True update_list.append('RCLUSTZ') else: updated_params = True update_list.append('RCLUSTZ') # in case of dos check verify that RMAX, GMAX are set and use setting from wf_parameters otherwise if 'RMAX' in set_vals: update_list.append('RMAX') rmax_input = params.get_dict()['RMAX'] elif self.ctx.check_dos: # add only if doscheck is done updated_params = True update_list.append('RMAX') rmax_input = kkrparams.default_values.get('RMAX') if 'GMAX' in set_vals: update_list.append('GMAX') gmax_input = params.get_dict()['GMAX'] elif self.ctx.check_dos: # add only if doscheck is done updated_params = True update_list.append('GMAX') gmax_input = kkrparams.default_values.get('GMAX') # check if any mandatory keys are not set and set them with the default values if missing in input parameters for key, value in default_values.items(): if key not in update_list and key not in set_vals: self.report("INFO: setting {} to default value {}".format( key, value)) kkr_para.set_value(key, value) # check if Fermi lavel should be set with input value if self.ctx.ef_set is not None: update_list.append('ef_set') # check if emin should be changed: skip_voro = False if self.ctx.iter > 1: if (self.ctx.dos_check_fail_reason == 'EMIN too high' or self.ctx.dos_check_fail_reason == 'core state too close'): # decrease emin by self.ctx.delta_e emin_old = self.ctx.dos_params_dict['emin'] eV2Ry = 1. / get_Ry2eV() emin_new = emin_old - self.ctx.delta_e * eV2Ry self.ctx.dos_params_dict['emin'] = emin_new updated_params = True update_list.append('EMIN') skip_voro = True # store updated nodes (also used via last_params in kkr_scf_wc) if updated_params: # set values that are updated if 'RCLUSTZ' in update_list: kkr_para.set_value('RCLUSTZ', self.ctx.r_cls) self.report("INFO: setting RCLUSTZ to {}".format( self.ctx.r_cls)) if 'EMIN' in update_list: kkr_para.set_value('EMIN', emin_new) self.report("INFO: setting EMIN to {}".format(emin_new)) if 'RMAX' in update_list: kkr_para.set_value('RMAX', rmax_input) self.report( "INFO: setting RMAX to {} (needed for DOS check with KKRcode)" .format(rmax_input)) if 'GMAX' in update_list: kkr_para.set_value('GMAX', gmax_input) self.report( "INFO: setting GMAX to {} (needed for DOS check with KKRcode)" .format(gmax_input)) if 'ef_set' in update_list: kkr_para.set_value('EFSET', self.ctx.ef_set) self.report( "INFO: setting Fermi level of stating potential to {}". format(self.ctx.ef_set)) updatenode = Dict(dict=kkr_para.get_dict()) updatenode.description = 'changed values: {}'.format(update_list) if first_iter: updatenode.label = 'initial params from wf input' # used workfunction for provenance tracking if parameters have been changed params = update_params_wf(self.ctx.last_params, updatenode) self.ctx.last_params = params else: updatenode.label = 'updated params: {}'.format(update_list) # also keep track of last voronoi output if that has been used voro_out = self.ctx.voro_calc.outputs.output_parameters params = update_voro_input(self.ctx.last_params, updatenode, voro_out) self.ctx.last_params = params # run voronoi step if not skip_voro: options = { 'queue_name': self.ctx.queue, 'resources': self.ctx.resources, 'max_wallclock_seconds': self.ctx.max_wallclock_seconds, 'custom_scheduler_commands': self.ctx.custom_scheduler_commands } builder = get_inputs_voronoi(voronoicode, structure, options, label, description, params=params) if 'startpot_overwrite' in self.inputs: builder.potential_overwrite = self.inputs.startpot_overwrite self.report('INFO: run voronoi step {}'.format(self.ctx.iter)) future = self.submit(builder) # return remote_voro (passed to dos calculation as input) return ToContext(voro_calc=future) else: self.report( "INFO: skipping voronoi calculation (do DOS run with different emin only)" )
def _prepare_for_submission(self, tempfolder, inputdict): """ Create input files. :param tempfolder: aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: dictionary of the input nodes as they would be returned by get_inputs_dict """ has_parent = False local_copy_list = [] # Check inputdict try: parameters = inputdict.pop(self.get_linkname('parameters')) except KeyError: raise InputValidationError( "No parameters specified for this calculation") if not isinstance(parameters, ParameterData): raise InputValidationError("parameters not of type ParameterData") try: imp_info = inputdict.pop(self.get_linkname('impurity_info')) found_imp_info = True except KeyError: imp_info = None found_imp_info = False if found_imp_info and not isinstance(imp_info, ParameterData): raise InputValidationError( "impurity_info not of type ParameterData") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "No code specified for this calculation") # get qdos inputs try: kpath = inputdict.pop(self.get_linkname('kpoints')) found_kpath = True except KeyError: found_kpath = False try: parent_calc_folder = inputdict.pop( self.get_linkname('parent_folder')) except KeyError: raise InputValidationError( "Voronoi or previous KKR files needed for KKR calculation, " "you need to provide a Parent Folder/RemoteData node.") #TODO deal with data from folder data if calculation is continued on a different machine if not isinstance(parent_calc_folder, RemoteData): raise InputValidationError( "parent_calc_folder must be of type RemoteData") # extract parent calculation parent_calcs = parent_calc_folder.get_inputs(node_type=JobCalculation) n_parents = len(parent_calcs) if n_parents != 1: raise UniquenessError( "Input RemoteData is child of {} " "calculation{}, while it should have a single parent" "".format(n_parents, "" if n_parents == 0 else "s")) parent_calc = parent_calcs[0] has_parent = True if n_parents == 1: parent_calc = parent_calcs[0] has_parent = True # check if parent is either Voronoi or previous KKR calculation self._check_valid_parent(parent_calc) # extract parent input parameter dict for following check try: parent_inp_dict = parent_calc.inp.parameters.get_dict() except: self.logger.error( "Failed trying to find input parameter of parent {}".format( parent_calc)) raise InputValidationError( "No parameter node found of parent calculation.") # check if no keys are illegally overwritten (i.e. compare with keys in self._do_never_modify) for key in parameters.get_dict().keys(): value = parameters.get_dict()[key] #self.logger.info("Checking {} {}".format(key, value)) if not value is None: if key in self._do_never_modify: oldvalue = parent_inp_dict[key] if oldvalue is None and key in __kkr_default_params__: oldvalue = __kkr_default_params__.get(key) if value != oldvalue: self.logger.error( "You are trying to set keyword {} = {} but this is not allowed since the structure would be modified. Please use a suitable workfunction instead." .format(key, value)) raise InputValidationError( "You are trying to modify a keyword that is not allowed to be changed! (key={}, oldvalue={}, newvalue={})" .format(key, oldvalue, value)) #TODO check for remote folder (starting from folder data not implemented yet) # if voronoi calc check if folder from db given, or get folder from rep. # Parent calc does not has to be on the same computer. # so far we copy every thing from local computer ggf if kkr we want to copy remotely # get StructureData node from Parent if Voronoi structure = None self.logger.info( "KkrCalculation: Get structure node from voronoi parent") if isinstance(parent_calc, VoronoiCalculation): self.logger.info("KkrCalculation: Parent is Voronoi calculation") try: structure, voro_parent = VoronoiCalculation.find_parent_structure( parent_calc) except: self.logger.error( 'KkrCalculation: Could not get structure from Voronoi parent.' ) raise ValidationError("Cound not find structure node") elif isinstance(parent_calc, KkrCalculation): self.logger.info("KkrCalculation: Parent is KKR calculation") try: self.logger.info( 'KkrCalculation: extract structure from KKR parent') structure, voro_parent = VoronoiCalculation.find_parent_structure( parent_calc) except: self.logger.error('Could not get structure from parent.') raise ValidationError( 'Cound not find structure node starting from parent {}'. format(parent_calc)) else: self.logger.error( "KkrCalculation: Parent is neither Voronoi nor KKR calculation!" ) raise ValidationError('Cound not find structure node') if inputdict: self.logger.error( 'KkrCalculation: Unknown inputs for structure lookup') raise ValidationError("Unknown inputs") # for VCA: check if input structure and parameter node define VCA structure vca_structure = vca_check(structure, parameters) ################################### # prepare scoef file if impurity_info was given write_scoef = False runopt = parameters.get_dict().get('RUNOPT', None) kkrflex_opt = False if runopt is not None: if 'KKRFLEX' in runopt: kkrflex_opt = True if kkrflex_opt: write_scoef = True elif found_imp_info: self.logger.info( 'Found impurity_info in inputs of the calculation, automatically add runopt KKRFLEX' ) write_scoef = True runopt = parameters.get_dict().get('RUNOPT', []) runopt.append('KKRFLEX') parameters = update_params_wf( parameters, ParameterData( dict={ 'RUNOPT': runopt, 'nodename': 'update_KKRFLEX', 'nodedesc': 'Update Parameter node with KKRFLEX runopt' })) if found_imp_info and write_scoef: scoef_filename = os.path.join(tempfolder.get_abs_path(''), self._SCOEF) imp_info_dict = imp_info.get_dict() Rcut = imp_info_dict.get('Rcut', None) hcut = imp_info_dict.get('hcut', -1.) cylinder_orient = imp_info_dict.get('cylinder_orient', [0., 0., 1.]) ilayer_center = imp_info_dict.get('ilayer_center', 0) for i in range(len(cylinder_orient)): try: len(cylinder_orient[i]) vec_shape = False except TypeError: vec_shape = True if ilayer_center > len(structure.sites) - 1: raise IndexError( 'Index of the reference site is out of range! Possible values: 0 to {}.' .format(len(structure.sites) - 1)) elif Rcut < 0: raise ValueError('Cutoff radius has to be positive!') elif vec_shape == False or len(cylinder_orient) != 3: raise TypeError( 'Input orientation vector ({}) has the wrong shape! It needs to be a 3D-vector!' .format(cylinder_orient)) else: print('Input parameters for make_scoef read in correctly!') make_scoef(structure, Rcut, scoef_filename, hcut, cylinder_orient, ilayer_center) elif write_scoef: self.logger.info( 'Need to write scoef file but no impurity_info given!') raise ValidationError( 'Found RUNOPT KKRFLEX but no impurity_info in inputs') # Check for 2D case twoDimcheck, msg = check_2Dinput_consistency(structure, parameters) if not twoDimcheck: raise InputValidationError(msg) # set shapes array either from parent voronoi run or read from inputcard in kkrimporter calculation if parent_calc.get_parser_name() != 'kkr.kkrimporterparser': # get shapes array from voronoi parent shapes = voro_parent.res.shapes else: # extract shapes from input parameters node constructed by kkrimporter calculation shapes = voro_parent.inp.parameters.get_dict().get('<SHAPE>') # use_alat_input = parameters.get_dict().get('use_input_alat', False) # qdos option, ensure low T, E-contour, qdos run option and write qvec.dat file if found_kpath: # check qdos settings change_values = [] runopt = parameters.get_dict().get('RUNOPT') if runopt is None: runopt = [] runopt = [i.strip() for i in runopt] if 'qdos' not in runopt: runopt.append('qdos') change_values.append(['RUNOPT', runopt]) tempr = parameters.get_dict().get('TEMPR') if tempr is None or tempr > 100.: change_values.append(['TEMPR', 50.]) N1 = parameters.get_dict().get('TEMPR') if N1 is None or N1 > 0: change_values.append(['NPT1', 0]) N2 = parameters.get_dict().get('NPT2') if N2 is None: change_values.append(['NPT2', 100]) N3 = parameters.get_dict().get('NPT3') if N3 is None or N3 > 0.: change_values.append(['NPT3', 0]) NPOL = parameters.get_dict().get('NPOL') if NPOL is None or NPOL > 0.: change_values.append(['NPOL', 0]) if change_values != []: new_params = { 'nodename': 'changed_params_qdos', 'nodedesc': 'Changed parameters to mathc qdos mode. Changed values: {}' .format(change_values) } for key, val in change_values: new_params[key] = val new_params_node = ParameterData(dict=new_params) parameters = update_params_wf(parameters, new_params_node) # write qvec.dat file kpath_array = kpath.get_kpoints() # convert automatically to internal units if use_alat_input: alat = parameters.get_dict().get('ALATBASIS') else: alat = get_alat_from_bravais( array(structure.cell), is3D=structure.pbc[2]) * get_Ang2aBohr() kpath_array = kpath_array * (alat / 2. / pi) qvec = ['%i\n' % len(kpath_array)] qvec += [ '%e %e %e\n' % (kpt[0], kpt[1], kpt[2]) for kpt in kpath_array ] qvecpath = tempfolder.get_abs_path(self._QVEC) with open(qvecpath, 'w') as file: file.writelines(qvec) # Prepare inputcard from Structure and input parameter data input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) natom, nspin, newsosol = generate_inputcard_from_structure( parameters, structure, input_filename, parent_calc, shapes=shapes, vca_structure=vca_structure, use_input_alat=use_alat_input) ################# # Decide what files to copy based on settings to the code (e.g. KKRFLEX option needs scoef) if has_parent: # copy the right files #TODO check first if file, exists and throw # warning, now this will throw an error outfolderpath = parent_calc.out.retrieved.folder.abspath outfolderpath = os.path.join(outfolderpath, 'path') self.logger.info("out folder path {}".format(outfolderpath)) copylist = [] if isinstance(parent_calc, KkrCalculation): copylist = self._copy_filelist_kkr # TODO ggf copy remotely... if isinstance(parent_calc, VoronoiCalculation): copylist = [parent_calc._SHAPEFUN] # copy either overwrite potential or voronoi output potential # (voronoi caclualtion retreives only one of the two) if parent_calc._POTENTIAL_IN_OVERWRITE in os.listdir( outfolderpath): copylist.append(parent_calc._POTENTIAL_IN_OVERWRITE) else: copylist.append(parent_calc._OUT_POTENTIAL_voronoi) #change copylist in case the calculation starts from an imported calculation if parent_calc.get_parser_name() == 'kkr.kkrimporterparser': copylist = [] if not os.path.exists( os.path.join(outfolderpath, self._OUT_POTENTIAL)): copylist.append(self._POTENTIAL) else: copylist.append(self._OUT_POTENTIAL) if os.path.exists(os.path.join(outfolderpath, self._SHAPEFUN)): copylist.append(self._SHAPEFUN) # create local_copy_list from copylist and change some names automatically for file1 in copylist: filename = file1 if (file1 == 'output.pot' or file1 == self._OUT_POTENTIAL or (isinstance(parent_calc, VoronoiCalculation) and file1 == parent_calc._POTENTIAL_IN_OVERWRITE)): filename = self._POTENTIAL local_copy_list.append( (os.path.join(outfolderpath, file1), os.path.join(filename))) # for set-ef option: ef_set = parameters.get_dict().get('ef_set', None) if ef_set is not None: print('local copy list before change: {}'.format( local_copy_list)) print( "found 'ef_set' in parameters: change EF of potential to this value" ) potcopy_info = [ i for i in local_copy_list if i[1] == self._POTENTIAL ][0] with open(potcopy_info[0]) as file: # change potential and copy list local_copy_list.remove(potcopy_info) pot_new_name = tempfolder.get_abs_path(self._POTENTIAL + '_new_ef') local_copy_list.append((pot_new_name, self._POTENTIAL)) # change potential txt = file.readlines() potstart = [] for iline in range(len(txt)): line = txt[iline] if 'exc:' in line: potstart.append(iline) for ipotstart in potstart: tmpline = txt[ipotstart + 3] tmpline = tmpline.split() newline = '%10.5f%20.14f%20.14f\n' % (float( tmpline[0]), ef_set, float(tmpline[-1])) txt[ipotstart + 3] = newline # write new file pot_new_ef = open(pot_new_name, 'w') pot_new_ef.writelines(txt) pot_new_ef.close() # TODO different copy lists, depending on the keywors input print('local copy list: {}'.format(local_copy_list)) self.logger.info('local copy list: {}'.format(local_copy_list)) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = [] # TODO retrieve list needs some logic, retrieve certain files, # only if certain input keys are specified.... calcinfo.retrieve_list = [ self._DEFAULT_OUTPUT_FILE, self._INPUT_FILE_NAME, self._POTENTIAL, self._SHAPEFUN, self._SCOEF, self._NONCO_ANGLES_OUT, self._OUT_POTENTIAL, self._OUTPUT_0_INIT, self._OUTPUT_000, self._OUTPUT_2, self._OUT_TIMING_000 ] # for special cases add files to retireve list: # 1. dos calculation, add *dos* files if NPOL==0 retrieve_dos_files = False print('NPOL in parameter input:', parameters.get_dict()['NPOL']) if 'NPOL' in parameters.get_dict().keys(): if parameters.get_dict()['NPOL'] == 0: retrieve_dos_files = True if 'TESTOPT' in parameters.get_dict().keys(): testopts = parameters.get_dict()['TESTOPT'] if testopts is not None: stripped_test_opts = [i.strip() for i in testopts] if 'DOS' in stripped_test_opts: retrieve_dos_files = True if retrieve_dos_files: print('adding files for dos output', self._COMPLEXDOS, self._DOS_ATOM, self._LMDOS) add_files = [self._COMPLEXDOS] for iatom in range(natom): add_files.append(self._DOS_ATOM % (iatom + 1)) for ispin in range(nspin): add_files.append( (self._LMDOS % (iatom + 1, ispin + 1)).replace( ' ', '0')) calcinfo.retrieve_list += add_files # 2. KKRFLEX calculation retrieve_kkrflex_files = False if 'RUNOPT' in parameters.get_dict().keys(): runopts = parameters.get_dict()['RUNOPT'] if runopts is not None: stripped_run_opts = [i.strip() for i in runopts] if 'KKRFLEX' in stripped_run_opts: retrieve_kkrflex_files = True if retrieve_kkrflex_files: add_files = self._ALL_KKRFLEX_FILES print('adding files for KKRFLEX output', add_files) calcinfo.retrieve_list += add_files # 3. qdos claculation retrieve_qdos_files = False if 'RUNOPT' in parameters.get_dict().keys(): runopts = parameters.get_dict()['RUNOPT'] if runopts is not None: stripped_run_opts = [i.strip() for i in runopts] if 'qdos' in stripped_run_opts: retrieve_qdos_files = True if retrieve_qdos_files: print('adding files for qdos output', self._QDOS_ATOM, self._QVEC) add_files = [self._QVEC] for iatom in range(natom): for ispin in range(nspin): add_files.append( (self._QDOS_ATOM % (iatom + 1, ispin + 1)).replace( ' ', '0')) calcinfo.retrieve_list += add_files codeinfo = CodeInfo() codeinfo.cmdline_params = [] codeinfo.code_uuid = code.uuid codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE calcinfo.codes_info = [codeinfo] return calcinfo
def set_params_dos(self): """ take input parameter node and change to DOS contour according to input from wf_parameter input internally calls the update_params work function to keep track of provenance """ params = self.ctx.input_params_KKR input_dict = params.get_dict() para_check = kkrparams() # step 1 try to fill keywords try: for key, val in input_dict.iteritems(): para_check.set_value(key, val, silent=True) except: error = 'ERROR: calc_parameters given are not consistent! Hint: did you give an unknown keyword?' self.ctx.errors.append(error) self.control_end_wc(error) # step 2: check if all mandatory keys are there label = '' descr = '' missing_list = para_check.get_missing_keys(use_aiida=True) if missing_list != []: kkrdefaults = kkrparams.get_KKRcalc_parameter_defaults()[0] kkrdefaults_updated = [] for key_default, val_default in kkrdefaults.items(): if key_default in missing_list: para_check.set_value(key_default, kkrdefaults.get(key_default), silent=True) kkrdefaults_updated.append(key_default) missing_list.remove(key_default) if len(missing_list) > 0: error = 'ERROR: calc_parameters misses keys: {}'.format( missing_list) self.ctx.errors.append(error) self.control_end_wc(error) else: self.report( 'updated KKR parameter node with default values: {}'. format(kkrdefaults_updated)) label = 'add_defaults_' descr = 'added missing default keys, ' # overwrite energy contour to DOS contour no matter what is in input parameter node. # Contour parameter given as input to workflow. econt_new = self.ctx.dos_params_dict # always overwrite NPOL, N1, N3, thus add these to econt_new econt_new['NPOL'] = 0 econt_new['NPT1'] = 0 econt_new['NPT3'] = 0 try: for key, val in econt_new.iteritems(): if key == 'kmesh': key = 'BZDIVIDE' elif key == 'nepts': key = 'NPT2' elif key == 'emin': key = 'EMIN' elif key == 'emax': key = 'EMAX' elif key == 'tempr': key = 'TEMPR' # set params para_check.set_value(key, val, silent=True) except: error = 'ERROR: dos_params given in wf_params are not valid!' self.ctx.errors.append(error) self.control_end_wc(error) updatenode = ParameterData(dict=para_check.get_dict()) updatenode.label = label + 'KKRparam_DOS' updatenode.description = descr + 'KKR parameter node extracted from parent parameters and wf_parameter input node.' paranode_dos = update_params_wf(self.ctx.input_params_KKR, updatenode) self.ctx.dos_kkrparams = paranode_dos
def run_voroaux(self): """ Perform a voronoi calculation for every impurity charge using the structure from the converged KKR host calculation """ # TODO: generalize to multiple impurities # collect inputs vorocode = self.inputs.voronoi kkrcode = self.inputs.kkr imp_info = self.inputs.impurity_info voro_params = self.ctx.voro_params_dict if self.ctx.do_gf_calc: self.report('INFO: get converged host remote from inputs to extract structure for Voronoi calculation') converged_host_remote = self.inputs.remote_data_host else: self.report('INFO: get converged host remote from GF_host_calc and graph to extract structure for Voronoi calculation') remote_data_gf_node = load_node(self.inputs.remote_data_gf.pk) GF_host_calc = remote_data_gf_node.get_incoming(link_label_filter=u'remote_folder').first().node converged_host_remote = GF_host_calc.inputs.parent_folder # get previous kkr parameters following remote_folder->calc->parameters links prev_kkrparams = converged_host_remote.get_incoming(link_label_filter='remote_folder').first().node.get_incoming(link_label_filter='parameters').first().node calc_params = prev_kkrparams # set Fermi level for auxiliary impurity potential correctly (extract from EF that is used in impurity calc) set_efermi = self.get_ef_from_parent() self.report('INFO: set Fermi level in jellium starting potential to {}'.format(set_efermi)) # change voronoi parameters updatenode = Dict(dict={'ef_set': set_efermi, 'add_direct': True}) updatenode.label = 'Added Fermi energy' voro_params = update_params_wf(voro_params, updatenode) # add or overwrite some parameters (e.g. things that are only used by voronoi) calc_params_dict = calc_params.get_dict() # add some voronoi specific parameters automatically if found (RMTREF should also set RMTCORE to the same value) if '<RMTREF>' in calc_params_dict.keys(): self.report('INFO: add rmtcore to voro params') self.ctx.change_voro_params['<RMTCORE>'] = calc_params_dict['<RMTREF>'] self.report(self.ctx.change_voro_params) changed_params = False for key, val in self.ctx.change_voro_params.items(): if key in ['RUNOPT', 'TESTOPT']: opt_old = calc_params_dict.get(key, []) if type(val)!=list: val = [val] val = opt_old + val calc_params_dict[key] = val changed_params = True if changed_params: updatenode = Dict(dict=calc_params_dict) updatenode.label = 'Changed params for voroaux: {}'.format(self.ctx.change_voro_params.keys()) updatenode.description = 'Overwritten voronoi input parameter from kkr_imp_wc input.' calc_params = update_params_wf(calc_params, updatenode) # find host structure structure_host, voro_calc = VoronoiCalculation.find_parent_structure(converged_host_remote) # for every impurity, generate a structure and launch the voronoi workflow # to get the auxiliary impurity startpotentials self.ctx.voro_calcs = {} inter_struc = change_struc_imp_aux_wf(structure_host, imp_info) sub_label = 'voroaux calc for Zimp: {} in host-struc'.format(imp_info.get_dict().get('Zimp')) sub_description = 'Auxiliary voronoi calculation for an impurity with charge ' sub_description += '{} in the host structure from pid: {}'.format(imp_info.get_dict().get('Zimp'), converged_host_remote.pk) builder = kkr_startpot_wc.get_builder() builder.metadata.label = sub_label builder.metadata.description = sub_description builder.structure = inter_struc builder.voronoi = vorocode builder.kkr = kkrcode builder.wf_parameters = voro_params builder.calc_parameters = calc_params builder.options = Dict(dict=self.ctx.options_params_dict_voronoi) future = self.submit(builder) tmp_calcname = 'voro_aux_{}'.format(1) self.ctx.voro_calcs[tmp_calcname] = future self.report('INFO: running voro aux (Zimp= {}, pid: {})'.format(imp_info.get_dict().get('Zimp'), future.pk)) return ToContext(last_voro_calc=future)
def prepare_for_submission(self, tempfolder): """ Create input files. :param tempfolder: aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: dictionary of the input nodes as they would be returned by get_inputs_dict """ has_parent = False local_copy_list = [] # get mandatory input nodes parameters = self.inputs.parameters code = self.inputs.code parent_calc_folder = self.inputs.parent_folder # now check for optional nodes # for GF writeout if 'impurity_info' in self.inputs: imp_info = self.inputs.impurity_info found_imp_info = True else: imp_info = None found_imp_info = False # for qdos funcitonality if 'kpoints' in self.inputs: kpath = self.inputs.kpoints found_kpath = True else: found_kpath = False # extract parent calculation parent_calcs = parent_calc_folder.get_incoming(node_class=CalcJobNode) n_parents = len(parent_calcs.all_link_labels()) if n_parents != 1: raise UniquenessError( "Input RemoteData is child of {} " "calculation{}, while it should have a single parent" "".format(n_parents, "" if n_parents == 0 else "s")) # TODO change to exit code if n_parents == 1: parent_calc = parent_calcs.first().node has_parent = True # check if parent is either Voronoi or previous KKR calculation #self._check_valid_parent(parent_calc) # extract parent input parameter dict for following check try: parent_inp_dict = parent_calc.inputs.parameters.get_dict() except: self.logger.error( "Failed trying to find input parameter of parent {}".format( parent_calc)) raise InputValidationError( "No parameter node found of parent calculation.") # check if no keys are illegally overwritten (i.e. compare with keys in self._do_never_modify) for key in list(parameters.get_dict().keys()): value = parameters.get_dict()[key] #self.logger.info("Checking {} {}".format(key, value)) if not value is None: if key in self._do_never_modify: oldvalue = parent_inp_dict[key] if oldvalue is None and key in __kkr_default_params__: oldvalue = __kkr_default_params__.get(key) if value == oldvalue: values_eqivalent = True else: values_eqivalent = False # check if values match up to certain numerical accuracy if type(value) == float: if abs(value - oldvalue) < self._eps: values_eqivalent = True elif type(value) == list or type(value) == ndarray: tmp_value, tmp_oldvalue = array(value).reshape( -1), array(oldvalue).reshape(-1) values_eqivalent_tmp = [] for ival in range(len(tmp_value)): if abs(tmp_value[ival] - tmp_oldvalue[ival]) < self._eps: values_eqivalent_tmp.append(True) else: values_eqivalent_tmp.append(False) if all(values_eqivalent_tmp) and len(value) == len( oldvalue): values_eqivalent = True if not values_eqivalent: self.logger.error( "You are trying to set keyword {} = {} but this is not allowed since the structure would be modified. Please use a suitable workfunction instead." .format(key, value)) raise InputValidationError( "You are trying to modify a keyword that is not allowed to be changed! (key={}, oldvalue={}, newvalue={})" .format(key, oldvalue, value)) #TODO check for remote folder (starting from folder data not implemented yet) # if voronoi calc check if folder from db given, or get folder from rep. # Parent calc does not has to be on the same computer. # so far we copy every thing from local computer ggf if kkr we want to copy remotely # get StructureData node from Parent if Voronoi structure = None self.logger.info( "KkrCalculation: Get structure node from voronoi parent") try: structure, voro_parent = VoronoiCalculation.find_parent_structure( parent_calc) except: self.logger.error( 'KkrCalculation: Could not get structure from Voronoi parent ({}).' .format(parent_calc)) raise ValidationError( "Cound not find structure node from parent {}".format( parent_calc)) # for VCA: check if input structure and parameter node define VCA structure vca_structure = vca_check(structure, parameters) ################################### # check whether or not the alat from the input parameters are used (this enters as a scaling factor for some parameters) use_alat_input = parameters.get_dict().get('use_input_alat', False) # prepare scoef file if impurity_info was given write_scoef = False runopt = parameters.get_dict().get('RUNOPT', None) kkrflex_opt = False if runopt is not None: if 'KKRFLEX' in runopt: kkrflex_opt = True if kkrflex_opt: write_scoef = True elif found_imp_info: self.logger.info( 'Found impurity_info in inputs of the calculation, automatically add runopt KKRFLEX' ) write_scoef = True runopt = parameters.get_dict().get('RUNOPT', []) runopt.append('KKRFLEX') parameters = update_params_wf( parameters, Dict( dict={ 'RUNOPT': runopt, 'nodename': 'update_KKRFLEX', 'nodedesc': 'Update Parameter node with KKRFLEX runopt' })) if found_imp_info and write_scoef: imp_info_dict = imp_info.get_dict() Rcut = imp_info_dict.get('Rcut', None) hcut = imp_info_dict.get('hcut', -1.) cylinder_orient = imp_info_dict.get('cylinder_orient', [0., 0., 1.]) ilayer_center = imp_info_dict.get('ilayer_center', 0) for i in range(len(cylinder_orient)): try: len(cylinder_orient[i]) vec_shape = False except TypeError: vec_shape = True if ilayer_center > len(structure.sites) - 1: raise IndexError( 'Index of the reference site is out of range! Possible values: 0 to {}.' .format(len(structure.sites) - 1)) elif Rcut < 0: raise ValueError('Cutoff radius has to be positive!') elif vec_shape == False or len(cylinder_orient) != 3: raise TypeError( 'Input orientation vector ({}) has the wrong shape! It needs to be a 3D-vector!' .format(cylinder_orient)) else: print('Input parameters for make_scoef read in correctly!') with tempfolder.open(self._SCOEF, 'w') as scoef_file: if use_alat_input: alat_input = parameters.get_dict().get( 'ALATBASIS', None) / get_Ang2aBohr() self.logger.info('alat_input is ' + str(alat_input)) else: self.logger.info('alat_input is None') alat_input = None make_scoef(structure, Rcut, scoef_file, hcut, cylinder_orient, ilayer_center, alat_input) elif write_scoef: self.logger.info( 'Need to write scoef file but no impurity_info given!') raise ValidationError( 'Found RUNOPT KKRFLEX but no impurity_info in inputs') # Check for 2D case twoDimcheck, msg = check_2Dinput_consistency(structure, parameters) if not twoDimcheck: raise InputValidationError(msg) # set shapes array either from parent voronoi run or read from inputcard in kkrimporter calculation if parent_calc.process_label == 'VoronoiCalculation' or parent_calc.process_label == 'KkrCalculation': # get shapes array from voronoi parent shapes = voro_parent.outputs.output_parameters.get_dict().get( 'shapes') else: # extract shapes from input parameters node constructed by kkrimporter calculation shapes = voro_parent.inputs.parameters.get_dict().get('<SHAPE>') self.logger.info('Extracted shapes: {}'.format(shapes)) # qdos option, ensure low T, E-contour, qdos run option and write qvec.dat file if found_kpath: # check qdos settings change_values = [] runopt = parameters.get_dict().get('RUNOPT') if runopt is None: runopt = [] runopt = [i.strip() for i in runopt] if 'qdos' not in runopt: runopt.append('qdos') change_values.append(['RUNOPT', runopt]) tempr = parameters.get_dict().get('TEMPR') if tempr is None or tempr > 100.: change_values.append(['TEMPR', 50.]) N1 = parameters.get_dict().get('NPT1') if N1 is None or N1 > 0: change_values.append(['NPT1', 0]) N2 = parameters.get_dict().get('NPT2') if N2 is None: change_values.append(['NPT2', 100]) N3 = parameters.get_dict().get('NPT3') if N3 is None or N3 > 0.: change_values.append(['NPT3', 0]) NPOL = parameters.get_dict().get('NPOL') if NPOL is None or NPOL > 0.: change_values.append(['NPOL', 0]) if change_values != []: new_params = {} #{'nodename': 'changed_params_qdos', 'nodedesc': 'Changed parameters to mathc qdos mode. Changed values: {}'.format(change_values)} for key, val in parameters.get_dict().items(): new_params[key] = val for key, val in change_values: new_params[key] = val new_params_node = Dict(dict=new_params) #parameters = update_params_wf(parameters, new_params_node) parameters = new_params_node # write qvec.dat file kpath_array = kpath.get_kpoints(cartesian=True) # convert automatically to internal units alat = get_alat_from_bravais( array( structure.cell), is3D=structure.pbc[2]) * get_Ang2aBohr() if use_alat_input: alat_input = parameters.get_dict().get('ALATBASIS') else: alat_input = alat kpath_array = kpath_array * ( alat_input / alat) / get_Ang2aBohr() / (2 * pi / alat) # now write file qvec = ['%i\n' % len(kpath_array)] qvec += [ '%e %e %e\n' % (kpt[0], kpt[1], kpt[2]) for kpt in kpath_array ] with tempfolder.open(self._QVEC, 'w') as qvecfile: qvecfile.writelines(qvec) # Prepare inputcard from Structure and input parameter data with tempfolder.open(self._INPUT_FILE_NAME, u'w') as input_file: natom, nspin, newsosol, warnings_write_inputcard = generate_inputcard_from_structure( parameters, structure, input_file, parent_calc, shapes=shapes, vca_structure=vca_structure, use_input_alat=use_alat_input) ################# # Decide what files to copy based on settings to the code (e.g. KKRFLEX option needs scoef) if has_parent: # copy the right files #TODO check first if file, exists and throw # warning, now this will throw an error outfolder = parent_calc.outputs.retrieved copylist = [] if parent_calc.process_class == KkrCalculation: copylist = [self._OUT_POTENTIAL] # TODO ggf copy remotely from remote node if present ... elif parent_calc.process_class == VoronoiCalculation: copylist = [parent_calc.process_class._SHAPEFUN] # copy either overwrite potential or voronoi output potential # (voronoi caclualtion retreives only one of the two) if parent_calc.process_class._POTENTIAL_IN_OVERWRITE in outfolder.list_object_names( ): copylist.append( parent_calc.process_class._POTENTIAL_IN_OVERWRITE) else: copylist.append( parent_calc.process_class._OUT_POTENTIAL_voronoi) #change copylist in case the calculation starts from an imported calculation else: #if parent_calc.process_class == KkrImporterCalculation: if self._OUT_POTENTIAL in outfolder.list_object_names(): copylist.append(self._OUT_POTENTIAL) else: copylist.append(self._POTENTIAL) if self._SHAPEFUN in outfolder.list_object_names(): copylist.append(self._SHAPEFUN) # create local_copy_list from copylist and change some names automatically for file1 in copylist: # deal with special case that file is written to another name if (file1 == 'output.pot' or file1 == self._OUT_POTENTIAL or (parent_calc.process_class == VoronoiCalculation and file1 == parent_calc.process_class._POTENTIAL_IN_OVERWRITE)): filename = self._POTENTIAL else: filename = file1 # now add to copy list local_copy_list.append((outfolder.uuid, file1, filename)) # add shapefun file from voronoi parent if needed if self._SHAPEFUN not in copylist: try: struc, voro_parent = VoronoiCalculation.find_parent_structure( parent_calc) except ValueError: return self.exit_codes.ERROR_NO_SHAPEFUN_FOUND # copy shapefun from retrieved of voro calc voro_retrieved = voro_parent.outputs.retrieved local_copy_list.append( (voro_retrieved.uuid, VoronoiCalculation._SHAPEFUN, self._SHAPEFUN)) # for set-ef option: ef_set = parameters.get_dict().get('ef_set', None) if ef_set is not None: print('local copy list before change: {}'.format( local_copy_list)) print( "found 'ef_set' in parameters: change EF of potential to this value" ) potcopy_info = [ i for i in local_copy_list if i[2] == self._POTENTIAL ][0] with load_node(potcopy_info[0]).open( potcopy_info[1]) as potfile: # remove previous output potential from copy list local_copy_list.remove(potcopy_info) # create potential here by readin in old potential and overwriting with changed Fermi energy with tempfolder.open(self._POTENTIAL, 'w') as pot_new_ef: # change potential txt = potfile.readlines() potstart = [] for iline in range(len(txt)): line = txt[iline] if 'exc:' in line: potstart.append(iline) for ipotstart in potstart: tmpline = txt[ipotstart + 3] tmpline = tmpline.split() newline = '%10.5f%20.14f%20.14f\n' % (float( tmpline[0]), ef_set, float(tmpline[-1])) txt[ipotstart + 3] = newline # write new file pot_new_ef.writelines(txt) # now this directory contains the updated potential file, thus it is not needed to put it in the local copy list anymore # TODO different copy lists, depending on the keywors input print('local copy list: {}'.format(local_copy_list)) self.logger.info('local copy list: {}'.format(local_copy_list)) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = [] # TODO retrieve list needs some logic, retrieve certain files, # only if certain input keys are specified.... calcinfo.retrieve_list = [ self._DEFAULT_OUTPUT_FILE, self._INPUT_FILE_NAME, self._SCOEF, self._NONCO_ANGLES_OUT, self._OUT_POTENTIAL, self._OUTPUT_0_INIT, self._OUTPUT_000, self._OUTPUT_2, self._OUT_TIMING_000 ] # for special cases add files to retireve list: # 1. dos calculation, add *dos* files if NPOL==0 retrieve_dos_files = False print('NPOL in parameter input:', parameters.get_dict()['NPOL']) if 'NPOL' in list(parameters.get_dict().keys()): if parameters.get_dict()['NPOL'] == 0: retrieve_dos_files = True if 'TESTOPT' in list(parameters.get_dict().keys()): testopts = parameters.get_dict()['TESTOPT'] if testopts is not None: stripped_test_opts = [i.strip() for i in testopts] if 'DOS' in stripped_test_opts: retrieve_dos_files = True if retrieve_dos_files: print('adding files for dos output', self._COMPLEXDOS, self._DOS_ATOM, self._LMDOS) add_files = [self._COMPLEXDOS] for iatom in range(natom): add_files.append(self._DOS_ATOM % (iatom + 1)) for ispin in range(nspin): add_files.append( (self._LMDOS % (iatom + 1, ispin + 1)).replace( ' ', '0')) calcinfo.retrieve_list += add_files # 2. KKRFLEX calculation retrieve_kkrflex_files = False if 'RUNOPT' in list(parameters.get_dict().keys()): runopts = parameters.get_dict()['RUNOPT'] if runopts is not None: stripped_run_opts = [i.strip() for i in runopts] if 'KKRFLEX' in stripped_run_opts: retrieve_kkrflex_files = True if retrieve_kkrflex_files: add_files = self._ALL_KKRFLEX_FILES print('adding files for KKRFLEX output', add_files) calcinfo.retrieve_list += add_files # 3. qdos claculation retrieve_qdos_files = False if 'RUNOPT' in list(parameters.get_dict().keys()): runopts = parameters.get_dict()['RUNOPT'] if runopts is not None: stripped_run_opts = [i.strip() for i in runopts] if 'qdos' in stripped_run_opts: retrieve_qdos_files = True if retrieve_qdos_files: print('adding files for qdos output', self._QDOS_ATOM, self._QVEC) add_files = [self._QVEC] for iatom in range(natom): for ispin in range(nspin): add_files.append( (self._QDOS_ATOM % (iatom + 1, ispin + 1)).replace( ' ', '0')) # retrieve also qdos_sx,y,z files if written out add_files.append( (self._QDOS_SX % (iatom + 1)).replace(' ', '0')) add_files.append( (self._QDOS_SY % (iatom + 1)).replace(' ', '0')) add_files.append( (self._QDOS_SZ % (iatom + 1)).replace(' ', '0')) calcinfo.retrieve_list += add_files # 4. Jij calculation retrieve_Jij_files = False if 'RUNOPT' in list(parameters.get_dict().keys()): runopts = parameters.get_dict()['RUNOPT'] if runopts is not None: stripped_run_opts = [i.strip() for i in runopts] if 'XCPL' in stripped_run_opts: retrieve_Jij_files = True if retrieve_Jij_files: add_files = [self._SHELLS_DAT] + [ self._Jij_ATOM % iatom for iatom in range(1, natom + 1) ] print('adding files for Jij output', add_files) calcinfo.retrieve_list += add_files codeinfo = CodeInfo() codeinfo.cmdline_params = [] codeinfo.code_uuid = code.uuid codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE calcinfo.codes_info = [codeinfo] return calcinfo
def set_params_dos(self): """ take input parameter node and change to DOS contour according to input from wf_parameter input internally calls the update_params work function to keep track of provenance """ params = self.ctx.input_params_KKR input_dict = params.get_dict() para_check = kkrparams() # step 1 try to fill keywords try: for key, val in input_dict.items(): para_check.set_value(key, val, silent=True) except: return self.exit_codes.ERROR_CALC_PARAMETERS_INVALID # step 2: check if all mandatory keys are there label = '' descr = '' missing_list = para_check.get_missing_keys(use_aiida=True) if missing_list != []: kkrdefaults = kkrparams.get_KKRcalc_parameter_defaults()[0] kkrdefaults_updated = [] for key_default, val_default in list(kkrdefaults.items()): if key_default in missing_list: para_check.set_value(key_default, kkrdefaults.get(key_default), silent=True) kkrdefaults_updated.append(key_default) missing_list.remove(key_default) if len(missing_list) > 0: self.report('ERROR: calc_parameters misses keys: {}'.format( missing_list)) return self.exit_codes.ERROR_CALC_PARAMETERS_INCOMPLETE else: self.report( 'updated KKR parameter node with default values: {}'. format(kkrdefaults_updated)) label = 'add_defaults_' descr = 'added missing default keys, ' # overwrite energy contour to DOS contour no matter what is in input parameter node. # Contour parameter given as input to workflow. econt_new = self.ctx.dos_params_dict # always overwrite NPOL, N1, N3, thus add these to econt_new econt_new['NPOL'] = 0 econt_new['NPT1'] = 0 econt_new['NPT3'] = 0 try: for key, val in econt_new.items(): if key == 'kmesh': key = 'BZDIVIDE' elif key == 'nepts': key = 'NPT2' # add IEMXD which has to be big enough print('setting IEMXD', val) para_check.set_value('IEMXD', val, silent=True) elif key == 'emin': key = 'EMIN' elif key == 'emax': key = 'EMAX' elif key == 'tempr': key = 'TEMPR' # set params para_check.set_value(key, val, silent=True) except: return self.exit_codes.ERROR_DOS_PARAMS_INVALID updatenode = Dict(dict=para_check.get_dict()) updatenode.label = label + 'KKRparam_DOS' updatenode.description = descr + 'KKR parameter node extracted from parent parameters and wf_parameter input node.' paranode_dos = update_params_wf(self.ctx.input_params_KKR, updatenode) self.ctx.dos_kkrparams = paranode_dos
def set_params_flex(self): """ Take input parameter node and change to input from wf_parameter and options """ self.report('INFO: setting parameters ...') params = self.ctx.input_params_KKR input_dict = params.get_dict() para_check = kkrparams() # step 1: try to fill keywords try: for key, val in input_dict.items(): para_check.set_value(key, val, silent=True) except: return self.exit_codes.ERROR_INVALID_CALC_PARAMETERS # step 2: check if all mandatory keys are there label = '' descr = '' missing_list = para_check.get_missing_keys(use_aiida=True) if missing_list != []: kkrdefaults = kkrparams.get_KKRcalc_parameter_defaults()[0] kkrdefaults_updated = [] for key_default, val_default in list(kkrdefaults.items()): if key_default in missing_list: para_check.set_value(key_default, kkrdefaults.get(key_default), silent=True) kkrdefaults_updated.append(key_default) missing_list.remove(key_default) if len(missing_list) > 0: self.report('ERROR: calc_parameters misses keys: {}'.format( missing_list)) return self.exit_codes.ERROR_CALC_PARAMETERS_INCOMPLETE else: self.report( 'updated KKR parameter node with default values: {}'. format(kkrdefaults_updated)) label = 'add_defaults_' descr = 'added missing default keys, ' # updatedict contains all things that will be updated with update_params_wf later on updatedict = {} runopt = para_check.get_dict().get('RUNOPT', None) if runopt == None: runopt = [] # overwrite some parameters of the KKR calculation by hand before setting mandatory keys if "params_kkr_overwrite" in self.inputs: for key, val in self.inputs.params_kkr_overwrite.get_dict().items( ): if key != runopt: updatedict[key] = val else: runopt = val self.report( 'INFO: overwriting KKR parameter: {} with {} from params_kkr_overwrite input node' .format(key, val)) runopt = [i.strip() for i in runopt] if 'KKRFLEX' not in runopt: runopt.append('KKRFLEX') updatedict['RUNOPT'] = runopt self.report('INFO: RUNOPT set to: {}'.format(runopt)) if 'wf_parameters' in self.inputs: if self.ctx.dos_run: for key, val in { 'EMIN': self.ctx.dos_params_dict['emin'], 'EMAX': self.ctx.dos_params_dict['emax'], 'NPT2': self.ctx.dos_params_dict['nepts'], 'NPOL': 0, 'NPT1': 0, 'NPT3': 0, 'BZDIVIDE': self.ctx.dos_params_dict['kmesh'], 'IEMXD': self.ctx.dos_params_dict['nepts'], 'TEMPR': self.ctx.dos_params_dict['tempr'] }.items(): updatedict[key] = val elif self.ctx.ef_shift != 0: # extract old Fermi energy in Ry remote_data_parent = self.inputs.remote_data parent_calc = remote_data_parent.get_incoming( link_label_filter='remote_folder').first().node ef_old = parent_calc.outputs.output_parameters.get_dict().get( 'fermi_energy') # get Fermi energy shift in eV ef_shift = self.ctx.ef_shift #set new E_F in eV # calculate new Fermi energy in Ry ef_new = (ef_old + ef_shift / get_Ry2eV()) self.report( 'INFO: ef_old + ef_shift = ef_new: {} eV + {} eV = {} eV'. format(ef_old * get_Ry2eV(), ef_shift, ef_new * get_Ry2eV())) updatedict['ef_set'] = ef_new #construct the final param node containing all of the params updatenode = Dict(dict=updatedict) updatenode.label = label + 'KKRparam_flex' updatenode.description = descr + 'KKR parameter node extracted from parent parameters and wf_parameter and options input node.' paranode_flex = update_params_wf(self.ctx.input_params_KKR, updatenode) self.ctx.flex_kkrparams = paranode_flex self.ctx.flex_runopt = runopt self.report('INFO: Updated params= {}'.format( paranode_flex.get_dict()))