def run_bands(self): """ Run the PwBaseWorkChain to run a bands PwCalculation along the path of high-symmetry determined by Seekpath """ try: remote_folder = self.ctx.workchain_scf.out.remote_folder except AttributeError as exception: self.abort_nowait( 'the scf workchain did not output a remote_folder node') return inputs = self.ctx.inputs restart_mode = 'restart' calculation_mode = 'bands' # Set the correct pw.x input parameters inputs.parameters['CONTROL']['restart_mode'] = restart_mode inputs.parameters['CONTROL']['calculation'] = calculation_mode if 'kpoints' in self.inputs: inputs.kpoints = self.inputs.kpoints else: inputs.kpoints = self.ctx.kpoints_path inputs.structure = self.ctx.structure inputs.parent_folder = remote_folder inputs = prepare_process_inputs(inputs) running = submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> in {} mode'.format( running.pid, calculation_mode)) return ToContext(workchain_bands=running)
def run_wannier90(self): try: remote_folder = self.ctx.calc_pw2wannier90.outputs.remote_folder except AttributeError: self.report( 'the Pw2wannier90Calculation did not output a remote_folder node' ) return self.exit_codes.ERROR_SUB_PROCESS_FAILED_WANNIER90 # we need metadata in exposed_inputs inputs = AttributeDict( self.exposed_inputs(Wannier90Calculation, namespace='wannier90')) pp_inputs = self.ctx.calc_wannier90_pp.inputs pp_keys = [ 'code', 'parameters', 'kpoint_path', 'structure', 'kpoints', 'settings' ] for key in pp_keys: inputs[key] = pp_inputs[key] inputs['remote_input_folder'] = remote_folder settings = inputs.settings.get_dict() settings['postproc_setup'] = False inputs.settings = settings inputs = prepare_process_inputs(Wannier90Calculation, inputs) running = self.submit(Wannier90Calculation, **inputs) self.report( 'wannier90 step - launching Wannier90Calculation<{}>'.format( running.pk)) return ToContext(calc_wannier90=running)
def run_relax(self): """Run the `PwRelaxWorkChain`.""" inputs = AttributeDict( self.exposed_inputs(PwRelaxWorkChain, namespace="relax")) inputs.metadata.call_link_label = "relax" inputs.structure = self.ctx.current_structure if "kpoints_distance_override" in self.inputs: inputs.base.kpoints_distance = self.inputs.kpoints_distance_override if "base_scf" in inputs: inputs.base_scf.kpoints_distance = self.inputs.kpoints_distance_override if "degauss_override" in self.inputs: inputs.base.pw.parameters = inputs.base.pw.parameters.get_dict() inputs.base.pw.parameters.setdefault( "SYSTEM", {})["degauss"] = self.inputs.degauss_override.value if "base_scf" in inputs: inputs.base_scf_params.pw.parameters = ( inputs.base_scf_params.pw.parameters.get_dict()) inputs.base_scf_params.pw.parameters.setdefault( "SYSTEM", {})["degauss"] = self.inputs.degauss_override.value inputs = prepare_process_inputs(PwRelaxWorkChain, inputs) running = self.submit(PwRelaxWorkChain, **inputs) self.report(f"launching PwRelaxWorkChain<{running.pk}>") return ToContext(workchain_relax=running)
def run_pdos(self): """Run the `PdosWorkChain`.""" inputs = AttributeDict( self.exposed_inputs(PdosWorkChain, namespace="pdos")) inputs.metadata.call_link_label = "pdos" inputs.structure = self.ctx.current_structure inputs.nscf.pw.parameters = inputs.nscf.pw.parameters.get_dict() if self.ctx.current_number_of_bands: inputs.nscf.pw.parameters.setdefault("SYSTEM", {}).setdefault( "nbnd", self.ctx.current_number_of_bands) if self.ctx.scf_parent_folder: inputs.pop("scf") inputs.nscf.pw.parent_folder = self.ctx.scf_parent_folder else: if "kpoints_distance_override" in self.inputs: inputs.scf.kpoints_distance = self.inputs.kpoints_distance_override if "degauss_override" in self.inputs: inputs.scf.pw.parameters = inputs.scf.pw.parameters.get_dict() inputs.scf.pw.parameters.setdefault( "SYSTEM", {})["degauss"] = self.inputs.degauss_override.value inputs = prepare_process_inputs(PdosWorkChain, inputs) running = self.submit(PdosWorkChain, **inputs) self.report(f"launching PdosWorkChain<{running.pk}>") return ToContext(workchain_pdos=running)
def run_relax(self): """Run the `PwBaseWorkChain` to run a relax `PwCalculation`.""" self.ctx.iteration += 1 inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, namespace='base')) inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters['CONTROL']['calculation'] = self.inputs.relaxation_scheme.value inputs.pw.parameters['CONTROL']['restart_mode'] = 'from_scratch' # If one of the nested `PwBaseWorkChains` changed the number of bands, apply it here if self.ctx.current_number_of_bands is not None: inputs.pw.parameters.setdefault('SYSTEM', {})['nbnd'] = self.ctx.current_number_of_bands # Set the `CALL` link label inputs.metadata.call_link_label = 'iteration_{:02d}'.format(self.ctx.iteration) inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}>'.format(running.pk)) return ToContext(workchains=append_(running))
def run_calculation(self): """Run the next calculation, taking the input dictionary from the context at `self.ctx.inputs`.""" from aiida_quantumespresso.utils.mapping import prepare_process_inputs self.ctx.iteration += 1 try: unwrapped_inputs = self.ctx.inputs except AttributeError: raise AttributeError('no calculation input dictionary was defined in `self.ctx.inputs`') # Set the `CALL` link label unwrapped_inputs['metadata']['call_link_label'] = 'iteration_{:02d}'.format(self.ctx.iteration) inputs = prepare_process_inputs(self._calculation_class, unwrapped_inputs) calculation = self.submit(self._calculation_class, **inputs) # Add a new empty list to the `errors_handled` extra. If any errors handled registered through the # `register_error_handler` decorator return an `ErrorHandlerReport`, their name will be appended to that list. errors_handled = self.node.get_extra('errors_handled', []) errors_handled.append([]) self.node.set_extra('errors_handled', errors_handled) self.report('launching {}<{}> iteration #{}'.format(self.ctx.calc_name, calculation.pk, self.ctx.iteration)) return ToContext(calculations=append_(calculation))
def run_nscf(self): """Run an NSCF calculation, to generate eigenvalues with a denser k-point mesh. This calculation modifies the base scf calculation inputs by: - Using the parent folder from the scf calculation. - Replacing the kpoints, if an alternative is specified for nscf. - Changing ``SYSTEM.occupations`` to 'tetrahedra'. - Changing ``SYSTEM.nosym`` to True, to avoid generation of additional k-points in low symmetry cases. - Replace the ``pw.metadata.options``, if an alternative is specified for nscf. """ inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, 'nscf')) if 'scf' in self.inputs: inputs.pw.parent_folder = self.ctx.scf_parent_folder inputs.pw.structure = self.inputs.structure inputs.metadata.call_link_label = 'nscf' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) if self.ctx.dry_run: return inputs future = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching NSCF PwBaseWorkChain<{future.pk}>') return ToContext(workchain_nscf=future)
def run_relax(self): """Run the `PwBaseWorkChain` to run a relax `PwCalculation`.""" self.ctx.iteration += 1 inputs = AttributeDict( self.exposed_inputs(PwBaseWorkChain, namespace='base')) inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CELL', {}) inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters['CONTROL']['restart_mode'] = 'from_scratch' if 'relaxation_scheme' in self.inputs: if self.inputs.relaxation_scheme.value == 'relax': relax_type = RelaxType.ATOMS elif self.inputs.relaxation_scheme.value == 'vc-relax': relax_type = RelaxType.ATOMS_CELL else: raise ValueError( 'unsupported value for the `relaxation_scheme` input.') else: relax_type = RelaxType(self.inputs.relax_type) if relax_type in [ RelaxType.NONE, RelaxType.VOLUME, RelaxType.SHAPE, RelaxType.CELL ]: inputs.pw.settings = self._fix_atomic_positions( inputs.pw.structure, inputs.pw.get('settings', None)) if relax_type in [RelaxType.NONE, RelaxType.ATOMS]: inputs.pw.parameters['CONTROL']['calculation'] = 'relax' inputs.pw.parameters.pop('CELL', None) else: inputs.pw.parameters['CONTROL']['calculation'] = 'vc-relax' if relax_type in [RelaxType.VOLUME, RelaxType.ATOMS_VOLUME]: inputs.pw.parameters['CELL']['cell_dofree'] = 'volume' if relax_type in [RelaxType.SHAPE, RelaxType.ATOMS_SHAPE]: inputs.pw.parameters['CELL']['cell_dofree'] = 'shape' if relax_type in [RelaxType.CELL, RelaxType.ATOMS_CELL]: inputs.pw.parameters['CELL']['cell_dofree'] = 'all' # If one of the nested `PwBaseWorkChains` changed the number of bands, apply it here if self.ctx.current_number_of_bands is not None: inputs.pw.parameters.setdefault( 'SYSTEM', {})['nbnd'] = self.ctx.current_number_of_bands # Set the `CALL` link label inputs.metadata.call_link_label = f'iteration_{self.ctx.iteration:02d}' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching PwBaseWorkChain<{running.pk}>') return ToContext(workchains=append_(running))
def calculate_trim_wf(self): """Launch a pw_bands calculation on the TRIM points for the structure.""" self.report( 'Using parities at TRIM points to calculatte Z2 invariant.') kpoints = generate_trim(self.ctx.current_structure, self.inputs.dimensionality) inputs = AttributeDict( self.exposed_inputs(PwBaseWorkChain, namespace='band')) inputs.clean_workdir = self.inputs.clean_workdir inputs.pw.code = self.inputs.pw_code inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters['CONTROL']['calculation'] = 'bands' inputs.pw.parent_folder = self.ctx.scf_folder inputs.kpoints = kpoints inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> in {} mode'.format( running.pk, 'bands')) return ToContext(workchain_trim=running)
def _prepare_process_inputs(self, inputs): """ Prepare the inputs dictionary for a calculation process. Any remaining bare dictionaries in the inputs dictionary will be wrapped in a ParameterData data node except for the '_options' key which should remain a standard dictionary. Another exception are dictionaries whose keys are not strings but for example tuples. This is the format used by input groups as in for example the explicit pseudo dictionary where the key is a tuple of kind to which the UpfData corresponds. """ from aiida_quantumespresso.utils.mapping import prepare_process_inputs return prepare_process_inputs(inputs)
def run_dos_full(self): """Run the PwBaseWorkChain in bands mode along the path of high-symmetry determined by seekpath.""" inputs = AttributeDict(self.exposed_inputs(DosCalc, namespace='dos_full')) inputs.metadata.call_link_label = 'dos_full' inputs.parent_folder = self.ctx.current_folder inputs = prepare_process_inputs(DosCalc, inputs) running = self.submit(DosCalc, **inputs) self.report('launching DosCalculation<{}> in {} mode for the FULL - CROP grid'.format(running.pk, 'dos')) return ToContext(workchain_dos_full=running)
def run_pw2gw(self): """Run the PwBaseWorkChain in bands mode along the path of high-symmetry determined by seekpath.""" inputs = AttributeDict(self.exposed_inputs(Pw2gwCalc, namespace='pw2gw')) inputs.metadata.call_link_label = 'pw2gw' inputs.parent_folder = self.ctx.current_folder inputs = prepare_process_inputs(Pw2gwCalc, inputs) running = self.submit(Pw2gwCalc, **inputs) self.report('launching Pw2gwCalculation<{}>'.format(running.pk)) return ToContext(workchain_pw2gw=running)
def run_bands(self): """Run the band calculation.""" self.ctx.iteration += 1 inputs = self.ctx.inputs inputs.kpoints = self.ctx.current_kpoints inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report( 'launching PwBaseWorkChain<{}> in {} mode, iteration {}'.format( running.pk, 'bands', self.ctx.iteration)) return ToContext(workchain_bands=append_(running))
def run_scf(self): """Run the PwBaseWorkChain in scf mode on the primitive cell of (optionally relaxed) input structure.""" inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, namespace='scf')) inputs.metadata.call_link_label = 'scf' inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {})['calculation'] = 'scf' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching PwBaseWorkChain<{running.pk}> in scf mode') return ToContext(workchain_scf=running)
def run_nscf_crop(self): """Run the PwBaseWorkChain in nscf mode along the path of high-symmetry determined by seekpath.""" inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, namespace='nscf_crop')) inputs.metadata.call_link_label = 'nscf_crop' # inputs.pw.metadata.options.max_wallclock_seconds *= 4 # inputs.kpoints_distance = self.inputs.kpoints_distance inputs.pw.structure = self.ctx.current_structure inputs.pw.parent_folder = self.ctx.current_folder inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters.setdefault('SYSTEM', {}) inputs.pw.parameters.setdefault('ELECTRONS', {}) # The following flags always have to be set in the parameters, regardless of what caller specified in the inputs inputs.pw.parameters['CONTROL']['calculation'] = 'nscf' inputs.pop('kpoints_distance', None) inputs.kpoints = self.ctx.kpoint_crop # Only set the following parameters if not directly explicitly defined in the inputs # inputs.pw.parameters['ELECTRONS'].setdefault('diagonalization', 'cg') # inputs.pw.parameters['ELECTRONS'].setdefault('diago_full_acc', True) # If `nbands_factor` is defined in the inputs we set the `nbnd` parameter if 'nbands_factor_crop' in self.inputs: factor = self.inputs.nbands_factor_crop.value parameters = self.ctx.workchain_scf.outputs.output_parameters.get_dict() if int(parameters['number_of_spin_components']) > 1: nspin_factor = 2 else: nspin_factor = 1 nbands = int(parameters['number_of_bands']) nelectron = int(parameters['number_of_electrons']) nbnd = max( int(0.5 * nelectron * nspin_factor * factor), int(0.5 * nelectron * nspin_factor) + 4 * nspin_factor, nbands) inputs.pw.parameters['SYSTEM']['nbnd'] = nbnd # Otherwise set the current number of bands, unless explicitly set in the inputs else: inputs.pw.parameters['SYSTEM'].setdefault('nbnd', self.ctx.current_number_of_bands) inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> in {} mode for CROP grid'.format(running.pk, 'nscf')) return ToContext(workchain_nscf_crop=running)
def run_final_scf(self): """Run the `PwBaseWorkChain` to run a final scf `PwCalculation` for the relaxed structure.""" inputs = self.ctx.final_scf_inputs inputs.pw.structure = self.ctx.current_structure if self.ctx.current_number_of_bands is not None: inputs.pw.parameters.setdefault( 'SYSTEM', {})['nbnd'] = self.ctx.current_number_of_bands inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching PwBaseWorkChain<{running.pk}> for final scf') return ToContext(workchain_scf=running)
def run_pw2wannier90(self): inputs = AttributeDict( self.exposed_inputs(Pw2wannier90Calculation, namespace='pw2wannier90')) try: remote_folder = self.ctx.workchain_nscf.outputs.remote_folder except AttributeError: return self.exit_codes.ERROR_SUB_PROCESS_FAILED_PW2WANNIER90( 'the nscf WorkChain did not output a remote_folder node') inputs['parent_folder'] = remote_folder inputs['nnkp_file'] = self.ctx.calc_wannier90_pp.outputs.nnkp_file inputs.parameters = inputs.parameters.get_dict() inputs.parameters['inputpp'].update({ 'write_mmn': True, 'write_amn': True, }) if self.ctx.auto_projections: inputs.parameters['inputpp']['scdm_proj'] = True # TODO: if exclude_band: gaussian # TODO: auto check if is insulator? if self.inputs.only_valence: inputs.parameters['inputpp']['scdm_entanglement'] = 'isolated' else: inputs.parameters['inputpp']['scdm_entanglement'] = 'erfc' try: inputs.parameters = update_pw2wan_params_mu_sigma( parameters=orm.Dict(dict=inputs.parameters), wannier_parameters=self.ctx.calc_wannier90_pp.inputs. parameters, bands=self.ctx.calc_projwfc.outputs.bands, projections=self.ctx.calc_projwfc.outputs.projections, thresholds=self.inputs.get('scdm_thresholds')) except ValueError: self.report( 'WARNING: update_pw2wan_params_mu_sigma failed!') return self.exit_codes.ERROR_SUB_PROCESS_FAILED_PW2WANNIER90 inputs = prepare_process_inputs(Pw2wannier90Calculation, inputs) running = self.submit(Pw2wannier90Calculation, **inputs) self.report( 'pw2wannier90 step - launching Pw2Wannier90Calculation<{}>'.format( running.pk)) return ToContext(calc_pw2wannier90=running)
def run_projwfc(self): """ Projwfc step :return: """ inputs = AttributeDict( self.exposed_inputs(ProjwfcCalculation, namespace='projwfc')) inputs.parent_folder = self.ctx.current_folder inputs = prepare_process_inputs(ProjwfcCalculation, inputs) running = self.submit(ProjwfcCalculation, **inputs) self.report('projwfc step - launching ProjwfcCalculation<{}>'.format( running.pk)) return ToContext(calc_projwfc=running)
def run_scf(self): """Run an SCF calculation, to generate the wavefunction.""" inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, 'scf')) inputs.pw.structure = self.inputs.structure inputs.metadata.call_link_label = 'scf' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) if self.ctx.dry_run: return inputs future = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching SCF PwBaseWorkChain<{future.pk}>') return ToContext(workchain_scf=future)
def run_pp(self): """Run the PwBaseWorkChain in scf mode on the primitive cell of (optionally relaxed) input structure.""" inputs = AttributeDict(self.exposed_inputs(PpCalculation, namespace='pp')) inputs.metadata.call_link_label = 'pp' inputs.parent_folder = self.ctx.current_folder nscf_params = self.ctx.workchain_nscf.outputs.output_parameters inputs.parameters = inputs.parameters.get_dict() inputs.parameters.setdefault('INPUTPP', {}) inputs.parameters.setdefault('PLOT', {}) inputs.parameters['INPUTPP']['plot_num'] = 7 nel = int(nscf_params['number_of_electrons']) if 'wavefunction_min' in self.inputs: kband_min = self.inputs.wavefunction_min.value else: if 'wavefunction_ef_min' in self.inputs: i = self.inputs.wavefunction_ef_min.value - 1 kband_min = nel - i else: kband_min = 1 if 'wavefunction_max' in self.inputs: kband_max = self.inputs.wavefunction_max.value else: if 'wavefunction_ef_max' in self.inputs: i = self.inputs.wavefunction_ef_max.value kband_max = nel + i else: kband_max = nscf_params['number_of_atomic_wfc'] inputs.parameters['INPUTPP']['kband(1)'] = kband_min inputs.parameters['INPUTPP']['kband(2)'] = kband_max inputs.parameters['INPUTPP']['kpoint(1)'] = 1 inputs.parameters['INPUTPP']['kpoint(2)'] = nscf_params['number_of_k_points'] inputs.parameters['PLOT']['iflag'] = 3 # inputs.parameters['PLOT']['output_format'] = 5 inputs = prepare_process_inputs(PpCalculation, inputs) running = self.submit(PpCalculation, **inputs) self.report(f'launching PpCalculation<{running.pk}>') return ToContext(workchain_pp=running)
def run_scf(self): """Run the PwBaseWorkChain in scf mode on the primitive cell of (optionally relaxed) input structure.""" inputs = self._get_common_inputs() if not self.should_do_relax(): self.ctx.current_structure = self.inputs.structure inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters['CONTROL']['calculation'] = 'scf' inputs.kpoints_distance = orm.Float(self.ctx.protocol['kpoints_mesh_density']) inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> in {} mode'.format(running.pk, 'scf')) return ToContext(workchain_scf=running)
def run_scf(self): """Run the PwBaseWorkChain in scf mode on the input structure.""" inputs = AttributeDict( self.exposed_inputs(PwBaseWorkChain, namespace='scf')) inputs.clean_workdir = self.inputs.clean_workdir inputs.pw.code = self.inputs.pw_code inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters['CONTROL']['calculation'] = 'scf' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> in {} mode'.format( running.pk, 'scf')) return ToContext(workchain_scf=running)
def first_bands_step(self): """Do a bandcalculation using the kpoints provided in `starting_kpoints`.""" self.ctx.iteration += 1 inputs = AttributeDict(deep_copy(self.ctx.inputs)) inputs.kpoints = self.inputs.starting_kpoints try: kpt = inputs.kpoints.get_kpoints() except: kpt = inputs.kpoints.get_kpoints_mesh(print_list=True) nkpt = len(kpt) if 'settings' in inputs.pw: settings = inputs.pw.settings.get_dict() if 'cmdline' in settings: ptr = settings['cmdline'] npools = None if '-npools' in ptr: i = ptr.index('-npools') npools = int(ptr[i + 1]) elif '-nk' in ptr: i = ptr.index('-nk') npools = int(ptr[i + 1]) if not npools is None and npools > nkpt: self.report('WARNING: npools={} > nkpt={}'.format( npools, nkpt)) for n in range(nkpt, 0, -1): if npools % n == 0: ptr[i + 1] = str(n) self.report('... reducing npools to {}.'.format(n)) break inputs.pw.settings = settings inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report( 'launching PwBaseWorkChain<{}> in {} mode, iteration {}'.format( running.pk, 'bands', self.ctx.iteration)) return ToContext(workchain_bands=append_(running))
def run_scf(self): """ Run the PwBaseWorkChain in scf mode on the primitive cell of (optionally relaxed) input structure """ inputs = self.ctx.inputs calculation_mode = 'scf' # Set the correct pw.x input parameters inputs.parameters['CONTROL']['calculation'] = calculation_mode inputs.kpoints = self.ctx.kpoints_mesh inputs.structure = self.ctx.structure inputs = prepare_process_inputs(inputs) running = submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> in {} mode'.format( running.pid, calculation_mode)) return ToContext(workchain_scf=running)
def run_init(self): """Run an initialization `PwCalculation` that will exit after the preamble. In the preamble, all the relevant dimensions of the problem are computed which allows us to make an estimate of the required resources and what parallelization flags need to be set. """ inputs = self.ctx.inputs # Set the initialization flag and the initial default options inputs.settings['ONLY_INITIALIZATION'] = True inputs.metadata['options'] = update_mapping(inputs.metadata['options'], get_default_options()) # Prepare the final input dictionary inputs = prepare_process_inputs(PwCalculation, inputs) running = self.submit(PwCalculation, **inputs) self.report('launching initialization {}<{}>'.format(running.pk, self._process_class.__name__)) return ToContext(calculation_init=running)
def run_final_scf(self): """Run the PwBaseWorkChain to run a final scf PwCalculation for the relaxed structure.""" inputs = AttributeDict( self.exposed_inputs(PwBaseWorkChain, namespace='base')) inputs.structure = self.ctx.current_structure inputs.parent_folder = self.ctx.current_parent_folder inputs.parameters = inputs.parameters.get_dict() inputs.parameters.setdefault('CONTROL', {}) inputs.parameters['CONTROL']['calculation'] = 'scf' inputs.parameters['CONTROL']['restart_mode'] = 'restart' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report('launching PwBaseWorkChain<{}> for final scf'.format( running.pk)) return ToContext(workchain_scf=running)
def run_nscf(self): """Run the PwBaseWorkChain in bands mode along the path of high-symmetry determined by seekpath.""" inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, namespace='nscf')) inputs.metadata.call_link_label = 'nscf' inputs.kpoints = self.ctx.bands_kpoints inputs.pw.structure = self.ctx.current_structure inputs.pw.parent_folder = self.ctx.current_folder inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters.setdefault('SYSTEM', {}) inputs.pw.parameters.setdefault('ELECTRONS', {}) # The following flags always have to be set in the parameters, regardless of what caller specified in the inputs inputs.pw.parameters['CONTROL']['calculation'] = 'nscf' # Only set the following parameters if not directly explicitly defined in the inputs inputs.pw.parameters['ELECTRONS'].setdefault('diagonalization', 'cg') inputs.pw.parameters['ELECTRONS'].setdefault('diago_full_acc', True) # If `nbands_factor` is defined in the inputs we set the `nbnd` parameter factor = 1.2 parameters = self.ctx.workchain_scf.outputs.output_parameters.get_dict() if int(parameters['number_of_spin_components']) > 1: nspin_factor = 2 else: nspin_factor = 1 nbands = int(parameters['number_of_bands']) nelectron = int(parameters['number_of_electrons']) nbnd = max( int(0.5 * nelectron * nspin_factor * factor), int(0.5 * nelectron * nspin_factor) + 4 * nspin_factor, nbands ) inputs.pw.parameters['SYSTEM']['nbnd'] = nbnd inputs.pw.parameters['SYSTEM']['nosym'] = True inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching PwBaseWorkChain<{running.pk}> in nscf mode') return ToContext(workchain_nscf=running)
def run_scf(self): """Run the PwBaseWorkChain in scf mode on the primitive cell of (optionally relaxed) input structure.""" inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, namespace='scf')) inputs.metadata.call_link_label = 'scf' inputs.pw.structure = self.ctx.current_structure inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {})['calculation'] = 'scf' # Make sure to carry the number of bands from the relax workchain if it was run and it wasn't explicitly defined # in the inputs. One of the base workchains in the relax workchain may have changed the number automatically in # the sanity checks on band occupations. if self.ctx.current_number_of_bands: inputs.pw.parameters.setdefault('SYSTEM', {}).setdefault('nbnd', self.ctx.current_number_of_bands) inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching PwBaseWorkChain<{running.pk}> in scf mode') return ToContext(workchain_scf=running)
def run_relax(self): """Run the `PwBaseWorkChain` to run a relax `PwCalculation`.""" self.ctx.iteration += 1 inputs = self.ctx.relax_inputs inputs.pw.structure = self.ctx.current_structure # If one of the nested `PwBaseWorkChains` changed the number of bands, apply it here if self.ctx.current_number_of_bands is not None: inputs.pw.parameters.setdefault( 'SYSTEM', {})['nbnd'] = self.ctx.current_number_of_bands # Set the `CALL` link label inputs.metadata.call_link_label = f'iteration_{self.ctx.iteration:02d}' inputs = prepare_process_inputs(PwBaseWorkChain, inputs) running = self.submit(PwBaseWorkChain, **inputs) self.report(f'launching PwBaseWorkChain<{running.pk}>') return ToContext(workchains=append_(running))
def setup_bands(self): """Set the inputs for the `bands` calculation.""" inputs = AttributeDict( self.exposed_inputs(PwBaseWorkChain, namespace='bands')) inputs.pw.code = self.inputs.code inputs.kpoints = self.ctx.kpt_data inputs.pw.pseudos = self.inputs.pseudos inputs.pw.structure = self.inputs.structure inputs.pw.parent_folder = self.ctx.remote inputs.clean_workdir = self.inputs.clean_workdir inputs.pw.parameters = inputs.pw.parameters.get_dict() inputs.pw.parameters.setdefault('CONTROL', {}) inputs.pw.parameters['CONTROL']['calculation'] = 'bands' inputs.pw.parameters['SYSTEM']['nosym'] = True inputs = prepare_process_inputs(PwBaseWorkChain, inputs) self.ctx.inputs = inputs