def change_fleurinp(self): """ This routine sets somethings in the fleurinp file before running a fleur calculation. """ self.report('INFO: run change_fleurinp') inputs = self.inputs # Has to never crash because corresponding check was done in validate function if self.ctx.fleurinp: # something was already changed return elif 'fleurinp' in inputs: fleurin = self.inputs.fleurinp elif 'structure' in inputs: if not self.ctx['inpgen'].is_finished_ok: error = 'Inpgen calculation failed' self.control_end_wc(error) return self.exit_codes.ERROR_INPGEN_CALCULATION_FAILED fleurin = self.ctx['inpgen'].outputs.fleurinpData elif 'remote_data' in inputs: # In this case only remote_data for input structure is given # fleurinp data has to be generated from the remote inp.xml file to use change_fleurinp fleurin = get_fleurinp_from_remote_data(self.inputs.remote_data, store=True) self.report(f'INFO: generated FleurinpData from files {fleurin}') wf_dict = self.ctx.wf_dict force_dict = wf_dict.get('force_dict') converge_mode = wf_dict.get('mode') fchanges = wf_dict.get('inpxml_changes', []) fleurmode = FleurinpModifier(fleurin) # set proper convergence parameters in inp.xml if converge_mode == 'density': dist = wf_dict.get('density_converged') fleurmode.set_inpchanges({ 'itmax': self.ctx.default_itmax, 'minDistance': dist }) elif converge_mode == 'force': force_converged = wf_dict.get('force_converged') dist = wf_dict.get('density_converged') fleurmode.set_inpchanges({ 'itmax': self.ctx.default_itmax, 'minDistance': dist, 'force_converged': force_converged, 'l_f': True, 'qfix': force_dict.get('qfix'), 'forcealpha': force_dict.get('forcealpha'), 'forcemix': force_dict.get('forcemix') }) elif converge_mode == 'energy': dist = 0.0 fleurmode.set_inpchanges({ 'itmax': self.ctx.default_itmax, 'minDistance': dist }) elif converge_mode == 'gw': dist = 0.0 fleurmode.set_inpchanges({ 'itmax': self.ctx.default_itmax, 'minDistance': dist, 'gw': 1 }) if 'settings' in self.inputs: self.inputs.settings.append({ 'additional_retrieve_list': ['basis.hdf', 'pot.hdf', 'ecore'] }) self.inputs.settings.append({ 'additional_remotecopy_list': ['basis.hdf', 'pot.hdf', 'ecore'] }) else: self.inputs.settings = { 'additional_retrieve_list': ['basis.hdf', 'pot.hdf', 'ecore'], 'additional_remotecopy_list': ['basis.hdf', 'pot.hdf', 'ecore'] } # apply further user dependend changes if fchanges: try: fleurmode.add_task_list(fchanges) except (ValueError, TypeError) as exc: error = ( 'ERROR: Changing the inp.xml file failed. Tried to apply inpxml_changes' f', which failed with {exc}. I abort, good luck next time!' ) self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED # validate? try: fleurmode.show(display=False, validate=True) except etree.DocumentInvalid: error = ( 'ERROR: input, user wanted inp.xml changes did not validate') self.report(error) return self.exit_codes.ERROR_INVALID_INPUT_FILE except ValueError as exc: error = ( 'ERROR: input, user wanted inp.xml changes could not be applied.' f'The following error was raised {exc}') self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED # apply out = fleurmode.freeze() self.ctx.fleurinp = out return
def change_fleurinp(self): """ create a new fleurinp from the old with certain parameters """ # TODO allow change of kpoint mesh?, tria? wf_dict = self.ctx.wf_dict if self.ctx.scf_needed: try: fleurin = self.ctx.scf.outputs.fleurinp except NotExistent: error = 'Fleurinp generated in the SCF calculation is not found.' self.control_end_wc(error) return self.exit_codes.ERROR_SCF_CALCULATION_FAILED else: if 'fleurinp' not in self.inputs: fleurin = get_fleurinp_from_remote_data(self.inputs.remote) else: fleurin = self.inputs.fleurinp # how can the user say he want to use the given kpoint mesh, ZZ nkpts : False/0 fleurmode = FleurinpModifier(fleurin) fchanges = wf_dict.get('inpxml_changes', []) # apply further user dependend changes if fchanges: try: fleurmode.add_task_list(fchanges) except (ValueError, TypeError) as exc: error = ( 'ERROR: Changing the inp.xml file failed. Tried to apply inpxml_changes' f', which failed with {exc}. I abort, good luck next time!' ) self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED kpath = wf_dict['kpath'] explicit = wf_dict['kpoints_explicit'] distance = wf_dict['kpoints_distance'] nkpts = wf_dict['kpoints_number'] listname = wf_dict['klistname'] if explicit is not None: try: fleurmode.set_kpointlist(**explicit) except (ValueError, TypeError) as exc: error = ( 'ERROR: Changing the inp.xml file failed. Tried to apply kpoints_explicit' f', which failed with {exc}. I abort, good luck next time!' ) self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED if listname is None: if wf_dict.get('mode') == 'band': listname = 'path-2' if nkpts is None and distance is None: nkpts = 500 if 'kpoints' in self.inputs: fleurmode.set_kpointsdata(self.inputs.kpoints, switch=True) if kpath == 'auto': if fleurin.inp_version >= '0.32' and listname is not None: fleurmode.switch_kpointset(listname) elif isinstance(kpath, dict): if fleurin.inp_version < '0.32': if distance is not None: raise ValueError( 'set_kpath only supports specifying the number of points for the kpoints' ) fleurmode.set_kpath(kpath, nkpts) else: raise ValueError( 'set_kpath is only supported for inputs up to Max4') elif kpath == 'seek': #Use aiida functionality struc = fleurin.get_structuredata() if distance is not None: output = get_explicit_kpoints_path(struc, reference_distance=distance) else: output = get_explicit_kpoints_path(struc) primitive_struc = output['primitive_structure'] #check if primitive_structure and input structure are identical: maxdiff_cell = sum( abs(np.array(primitive_struc.cell) - np.array(struc.cell))).max() if maxdiff_cell > 3e-9: self.report(f'Error in cell : {maxdiff_cell}') self.report( 'WARNING: The structure data from the fleurinp is not the primitive structure type, which is mandatory in some cases' ) output['explicit_kpoints'].store() fleurmode.set_kpointsdata(output['explicit_kpoints'], switch=True) elif kpath == 'skip': return else: #Use ase struc = fleurin.get_structuredata() path = bandpath(kpath, cell=struc.cell, npoints=nkpts, density=distance) special_points = path.special_points labels = [] for label, special_kpoint in special_points.items(): for index, kpoint in enumerate(path.kpts): if sum(abs(np.array(special_kpoint) - np.array(kpoint))).max() < 1e-12: labels.append((index, label)) labels = sorted(labels, key=lambda x: x[0]) kpts = KpointsData() kpts.set_cell(struc.cell) kpts.pbc = struc.pbc weights = np.ones(len(path.kpts)) / len(path.kpts) kpts.set_kpoints(kpoints=path.kpts, cartesian=False, weights=weights, labels=labels) kpts.store() fleurmode.set_kpointsdata(kpts, switch=True) sigma = wf_dict['sigma'] emin = wf_dict['emin'] emax = wf_dict['emax'] if fleurin.inp_version < '0.32': if wf_dict.get('mode') == 'dos': fleurmode.set_inpchanges({'ndir': -1}) if wf_dict.get('mode') == 'dos': change_dict = { 'dos': True, 'minEnergy': emin, 'maxEnergy': emax, 'sigma': sigma } else: change_dict = { 'band': True, 'minEnergy': emin, 'maxEnergy': emax, 'sigma': sigma } fleurmode.set_inpchanges(change_dict) try: fleurmode.show(display=False, validate=True) except etree.DocumentInvalid: error = ( 'ERROR: input, user wanted inp.xml changes did not validate') self.control_end_wc(error) return self.exit_codes.ERROR_INVALID_INPUT_FILE except ValueError as exc: error = ( 'ERROR: input, user wanted inp.xml changes could not be applied.' f'The following error was raised {exc}') self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED fleurinp_new = fleurmode.freeze() self.ctx.fleurinp_banddos = fleurinp_new