def get_total_energy(misc): """Return the total energy from misc.""" misc_dict = misc.get_dict() total_energy = orm.Float(misc_dict['total_energies']['energy_no_entropy']) return total_energy
def get_total_magnetization(parameters): """ Return the free energy from the given parameters node. The free energy reported by CASTEP is the one that is consistent with the forces. """ return orm.Float(parameters.get_attribute('spin_density'))
def get_total_energy(parameters): return orm.Float(parameters.get_attribute('energy'))
def get_total_magnetization(parameters): """Return the total magnetization from the given parameters node.""" return orm.Float(parameters['total_magnetization'])
def get_free_energy(parameters): """ Return the free energy from the given parameters node. The free energy reported by CASTEP is the one that is consistent with the forces. """ return orm.Float(parameters.get_attribute('free_energy'))
def get_builder_from_protocol(cls, code, structure, protocol=None, overrides=None, electronic_type=ElectronicType.METAL, spin_type=SpinType.NONE, initial_magnetic_moments=None, **_): """Return a builder prepopulated with inputs selected according to the chosen protocol. :param code: the ``Code`` instance configured for the ``quantumespresso.pw`` plugin. :param structure: the ``StructureData`` instance to use. :param protocol: protocol to use, if not specified, the default will be used. :param overrides: optional dictionary of inputs to override the defaults of the protocol. :param electronic_type: indicate the electronic character of the system through ``ElectronicType`` instance. :param spin_type: indicate the spin polarization type to use through a ``SpinType`` instance. :param initial_magnetic_moments: optional dictionary that maps the initial magnetic moment of each kind to a desired value for a spin polarized calculation. Note that for ``spin_type == SpinType.COLLINEAR`` an initial guess for the magnetic moment is automatically set in case this argument is not provided. :return: a process builder instance with all inputs defined ready for launch. """ from qe_tools import CONSTANTS from aiida_quantumespresso.workflows.protocols.utils import get_starting_magnetization if isinstance(code, str): code = orm.load_code(code) type_check(code, orm.Code) type_check(electronic_type, ElectronicType) type_check(spin_type, SpinType) if electronic_type not in [ ElectronicType.METAL, ElectronicType.INSULATOR ]: raise NotImplementedError( f'electronic type `{electronic_type}` is not supported.') if spin_type not in [SpinType.NONE, SpinType.COLLINEAR]: raise NotImplementedError( f'spin type `{spin_type}` is not supported.') if initial_magnetic_moments is not None and spin_type is not SpinType.COLLINEAR: raise ValueError( f'`initial_magnetic_moments` is specified but spin type `{spin_type}` is incompatible.' ) builder = cls.get_builder() inputs = cls.get_protocol_inputs(protocol, overrides) meta_parameters = inputs.pop('meta_parameters') pseudo_family = inputs.pop('pseudo_family') natoms = len(structure.sites) try: pseudo_set = (PseudoDojoFamily, SsspFamily) pseudo_family = orm.QueryBuilder().append(pseudo_set, filters={ 'label': pseudo_family }).one()[0] except exceptions.NotExistent as exception: raise ValueError( f'required pseudo family `{pseudo_family}` is not installed. Please use `aiida-pseudo install` to' 'install it.') from exception cutoff_wfc, cutoff_rho = pseudo_family.get_recommended_cutoffs( structure=structure) parameters = inputs['pw']['parameters'] parameters['CONTROL']['etot_conv_thr'] = natoms * meta_parameters[ 'etot_conv_thr_per_atom'] parameters['ELECTRONS'][ 'conv_thr'] = natoms * meta_parameters['conv_thr_per_atom'] parameters['SYSTEM']['ecutwfc'] = cutoff_wfc / CONSTANTS.ry_to_ev parameters['SYSTEM']['ecutrho'] = cutoff_rho / CONSTANTS.ry_to_ev if electronic_type is ElectronicType.INSULATOR: parameters['SYSTEM']['occupations'] = 'fixed' parameters['SYSTEM'].pop('degauss') parameters['SYSTEM'].pop('smearing') if spin_type is SpinType.COLLINEAR: starting_magnetization = get_starting_magnetization( structure, pseudo_family, initial_magnetic_moments) parameters['SYSTEM']['nspin'] = 2 parameters['SYSTEM'][ 'starting_magnetization'] = starting_magnetization builder.pw['code'] = code # pylint: disable=no-member builder.pw['pseudos'] = pseudo_family.get_pseudos(structure=structure) # pylint: disable=no-member builder.pw['structure'] = structure # pylint: disable=no-member builder.pw['parameters'] = orm.Dict(dict=parameters) # pylint: disable=no-member builder.pw['metadata'] = inputs['metadata'] # pylint: disable=no-member builder.clean_workdir = orm.Bool(inputs['clean_workdir']) builder.kpoints_distance = orm.Float(inputs['kpoints_distance']) builder.kpoints_force_parity = orm.Bool(inputs['kpoints_force_parity']) return builder
def get_energy(pardict): """Extract the energy from the `output_parameters` dictionary""" return orm.Float(pardict['E_KS'])
def get_builder(self, structure: StructureData, calc_engines: Dict[str, Any], *, protocol: str = None, relax_type: RelaxType = RelaxType.ATOMS, electronic_type: ElectronicType = ElectronicType.METAL, spin_type: SpinType = SpinType.NONE, magnetization_per_site: List[float] = None, threshold_forces: float = None, threshold_stress: float = None, previous_workchain=None, **kwargs) -> engine.ProcessBuilder: """Return a process builder for the corresponding workchain class with inputs set according to the protocol. :param structure: the structure to be relaxed. :param calc_engines: a dictionary containing the computational resources for the relaxation. :param protocol: the protocol to use when determining the workchain inputs. :param relax_type: the type of relaxation to perform. :param electronic_type: the electronic character that is to be used for the structure. :param spin_type: the spin polarization type to use for the calculation. :param magnetization_per_site: a list with the initial spin polarization for each site. Float or integer in units of electrons. If not defined, the builder will automatically define the initial magnetization if and only if `spin_type != SpinType.NONE`. :param threshold_forces: target threshold for the forces in eV/Å. :param threshold_stress: target threshold for the stress in eV/Å^3. :param previous_workchain: a <Code>RelaxWorkChain node. :param kwargs: any inputs that are specific to the plugin. :return: a `aiida.engine.processes.ProcessBuilder` instance ready to be submitted. """ # pylint: disable=too-many-locals protocol = protocol or self.get_default_protocol_name() super().get_builder(structure, calc_engines, protocol=protocol, relax_type=relax_type, electronic_type=electronic_type, spin_type=spin_type, magnetization_per_site=magnetization_per_site, threshold_forces=threshold_forces, threshold_stress=threshold_stress, previous_workchain=previous_workchain, **kwargs) if relax_type == RelaxType.ATOMS: relaxation_schema = 'relax' else: raise ValueError('relaxation type `{}` is not supported'.format( relax_type.value)) builder = self.process_class.get_builder() builder.structure = structure # Will be implemented in the bigdft plugin # inputdict = BigDFTParameters.get_input_dict(protocol, structure, 'relax') # for now apply simple stupid heuristic : atoms < 200 -> cubic, else -> linear. if len(structure.sites) <= 200: inputdict = self.get_protocol(protocol)['inputdict_cubic'] else: inputdict = self.get_protocol(protocol)['inputdict_linear'] builder.parameters = BigDFTParameters(dict=inputdict) builder.code = orm.load_code(calc_engines[relaxation_schema]['code']) run_opts = {'options': calc_engines[relaxation_schema]['options']} builder.run_opts = orm.Dict(dict=run_opts) if threshold_forces is not None: builder.relax.threshold_forces = orm.Float(threshold_forces) return builder
def get_builder(self, structure: StructureData, engines: Dict[str, Any], *, protocol: str = None, relax_type: RelaxType = RelaxType.POSITIONS, electronic_type: ElectronicType = ElectronicType.METAL, spin_type: SpinType = SpinType.NONE, magnetization_per_site: List[float] = None, threshold_forces: float = None, threshold_stress: float = None, reference_workchain=None, **kwargs) -> engine.ProcessBuilder: """Return a process builder for the corresponding workchain class with inputs set according to the protocol. :param structure: the structure to be relaxed. :param engines: a dictionary containing the computational resources for the relaxation. :param protocol: the protocol to use when determining the workchain inputs. :param relax_type: the type of relaxation to perform. :param electronic_type: the electronic character that is to be used for the structure. :param spin_type: the spin polarization type to use for the calculation. :param magnetization_per_site: a list with the initial spin polarization for each site. Float or integer in units of electrons. If not defined, the builder will automatically define the initial magnetization if and only if `spin_type != SpinType.NONE`. :param threshold_forces: target threshold for the forces in eV/Å. :param threshold_stress: target threshold for the stress in eV/Å^3. :param reference_workchain: a <Code>RelaxWorkChain node. :param kwargs: any inputs that are specific to the plugin. :return: a `aiida.engine.processes.ProcessBuilder` instance ready to be submitted. """ # pylint: disable=too-many-locals, too-many-branches, too-many-statements protocol = protocol or self.get_default_protocol_name() super().get_builder(structure, engines, protocol=protocol, relax_type=relax_type, electronic_type=electronic_type, spin_type=spin_type, magnetization_per_site=magnetization_per_site, threshold_forces=threshold_forces, threshold_stress=threshold_stress, reference_workchain=reference_workchain, **kwargs) builder = self.process_class.get_builder() if relax_type == RelaxType.POSITIONS: relaxation_schema = 'relax' elif relax_type == RelaxType.NONE: relaxation_schema = 'relax' builder.relax.perform = orm.Bool(False) else: raise ValueError('relaxation type `{}` is not supported'.format( relax_type.value)) pymatgen_struct = structure.get_pymatgen() ortho_dict = None if pymatgen_struct.ntypesp <= 1: # pass the structure through a transform to generate orthorhombic structure if possible/needed. new = ortho_struct(structure) newstruct = new.get('outstruct') ortho_dict = new.get('outdict') newstruct.store() builder.structure = newstruct else: builder.structure = structure # for now apply simple stupid heuristic : atoms < 200 -> cubic, else -> linear. import copy if len(builder.structure.sites) <= 200: inputdict = copy.deepcopy( self.get_protocol(protocol)['inputdict_cubic']) else: inputdict = copy.deepcopy( self.get_protocol(protocol)['inputdict_linear']) # adapt hgrid to the strain if reference_workchain is not None and reference_workchain.is_finished_ok: logfile = reference_workchain.outputs.bigdft_logfile.logfile if isinstance(logfile, list): hgrids = logfile[0].get('dft').get('hgrids') else: hgrids = logfile.get('dft').get('hgrids') inputdict['dft']['hgrids'] = hgrids[0] * builder.structure.cell_lengths[0] / \ reference_workchain.inputs.structure.cell_lengths[0] # Soon : Use inputActions if electronic_type is ElectronicType.METAL: if 'mix' not in inputdict: inputdict['mix'] = {} inputdict['mix'].update({ 'iscf': 17, 'itrpmax': 200, 'rpnrm_cv': 1.E-12, 'norbsempty': 120, 'tel': 0.01, 'alphamix': 0.8, 'alphadiis': 1.0 }) if spin_type is SpinType.NONE: inputdict['dft'].update({'nspin': 1}) elif spin_type is SpinType.COLLINEAR: inputdict['dft'].update({'nspin': 2}) psp = [] if ortho_dict is not None: inputdict = BigDFTParameters.set_inputfile( inputdict['dft']['hgrids'], ortho_dict, inputdict, psp=psp, units='angstroem') else: # use HGH pseudopotentials instead of default ones from BigDFT, if the user does not specify new ones. # This may be moved to the plugin if we decide to make it the default behavior. for elem in pymatgen_struct.types_of_specie: BigDFTParameters.set_psp(elem.name, psp) inputdict['kpt'] = BigDFTParameters.set_kpoints( len(builder.structure.sites)) if pymatgen_struct.ntypesp <= 1: inputdict['dft'].update( BigDFTParameters.set_spin( builder.structure.sites[0].kind_name, len(builder.structure.sites))) if magnetization_per_site: for (i, atom) in enumerate(inputdict['posinp']['positions']): atom['IGSpin'] = int(magnetization_per_site[i]) if psp: import os builder.pseudos = orm.List() psprel = [os.path.relpath(i) for i in psp] builder.pseudos.extend(psprel) builder.parameters = BigDFTParameters(dict=inputdict) builder.code = orm.load_code(engines[relaxation_schema]['code']) run_opts = {'options': engines[relaxation_schema]['options']} builder.run_opts = orm.Dict(dict=run_opts) if threshold_forces is not None: builder.relax.threshold_forces = orm.Float(threshold_forces) return builder
def get_builder_from_protocol(cls, code, structure, protocol=None, overrides=None, relax_type=RelaxType.POSITIONS_CELL, **kwargs): """Return a builder prepopulated with inputs selected according to the chosen protocol. :param code: the ``Code`` instance configured for the ``quantumespresso.pw`` plugin. :param structure: the ``StructureData`` instance to use. :param protocol: protocol to use, if not specified, the default will be used. :param overrides: optional dictionary of inputs to override the defaults of the protocol. :param relax_type: the relax type to use: should be a value of the enum ``common.types.RelaxType``. :param kwargs: additional keyword arguments that will be passed to the ``get_builder_from_protocol`` of all the sub processes that are called by this workchain. :return: a process builder instance with all inputs defined ready for launch. """ type_check(relax_type, RelaxType) args = (code, structure, protocol) inputs = cls.get_protocol_inputs(protocol, overrides) builder = cls.get_builder() base = PwBaseWorkChain.get_builder_from_protocol(*args, overrides=inputs.get( 'base', None), **kwargs) base_final_scf = PwBaseWorkChain.get_builder_from_protocol( *args, overrides=inputs.get('base_final_scf', None), **kwargs) base['pw'].pop('structure', None) base.pop('clean_workdir', None) base_final_scf['pw'].pop('structure', None) base_final_scf.pop('clean_workdir', None) # Quantum ESPRESSO currently only supports optimization of the volume for simple cubic systems. It requires # to set `ibrav=1` or the code will except. if relax_type in (RelaxType.VOLUME, RelaxType.POSITIONS_VOLUME): raise ValueError(f'relax type `{relax_type} is not yet supported.') if relax_type in (RelaxType.VOLUME, RelaxType.SHAPE, RelaxType.CELL): base.pw.settings = orm.Dict( dict=PwRelaxWorkChain._fix_atomic_positions( structure, base.pw.settings)) if relax_type is RelaxType.NONE: base.pw.parameters['CONTROL']['calculation'] = 'scf' base.pw.parameters.delete_attribute('CELL') elif relax_type is RelaxType.POSITIONS: base.pw.parameters['CONTROL']['calculation'] = 'relax' base.pw.parameters.delete_attribute('CELL') else: base.pw.parameters['CONTROL']['calculation'] = 'vc-relax' if relax_type in (RelaxType.VOLUME, RelaxType.POSITIONS_VOLUME): base.pw.parameters['CELL']['cell_dofree'] = 'volume' if relax_type in (RelaxType.SHAPE, RelaxType.POSITIONS_SHAPE): base.pw.parameters['CELL']['cell_dofree'] = 'shape' if relax_type in (RelaxType.CELL, RelaxType.POSITIONS_CELL): base.pw.parameters['CELL']['cell_dofree'] = 'all' builder.base = base builder.base_final_scf = base_final_scf builder.structure = structure builder.clean_workdir = orm.Bool(inputs['clean_workdir']) builder.max_meta_convergence_iterations = orm.Int( inputs['max_meta_convergence_iterations']) builder.meta_convergence = orm.Bool(inputs['meta_convergence']) builder.volume_convergence = orm.Float(inputs['volume_convergence']) return builder
def define(cls, spec): """Define the process specification.""" super().define(spec) # spec.input('vdw_table', valid_type=orm.SinglefileData, required=False) spec.input( 'code.pw', valid_type=orm.Code, help='The `pw.x` code to use for the `PwCalculations`.' ) spec.input( 'code.pw2wannier90', valid_type=orm.Code, help= 'The `pw2wannier90.x` code to use for the `Pw2WannierCalculations`.' ) spec.input( 'code.wannier90', valid_type=orm.Code, help='The `wannier90.x` code to use for the `PwCalculations`.' ) spec.input( 'code.projwfc', valid_type=orm.Code, required=False, help='The `projwfc.x` code to use for the `PwCalculations`.' ) spec.input( 'structure', valid_type=orm.StructureData, help='The input structure.' ) spec.input( 'protocol', valid_type=orm.Dict, default=lambda: orm.Dict(dict={'name': 'theos-ht-1.0'}), help='The protocol to use for the workchain.', validator=validate_protocol ) spec.input( 'controls.auto_projections', valid_type=orm.Bool, default=lambda: orm.Bool(True), help= 'Whether using SCDM to automatically construct Wannier functions or not.' ) spec.input( 'controls.only_valence', valid_type=orm.Bool, default=lambda: orm.Bool(False), help='Group name that the calculations will be added to.' ) spec.input( 'controls.retrieve_hamiltonian', valid_type=orm.Bool, default=lambda: orm.Bool(False), help='Group name that the calculations will be added to.' ) spec.input( 'controls.plot_wannier_functions', valid_type=orm.Bool, default=lambda: orm.Bool(False), help='Group name that the calculations will be added to.' ) spec.input( 'controls.do_disentanglement', valid_type=orm.Bool, default=lambda: orm.Bool(False), help= 'Used only if only_valence == False. Usually disentanglement worsens SCDM bands, keep it default to False.' ) spec.input( 'controls.do_mlwf', valid_type=orm.Bool, default=lambda: orm.Bool(True), help='Group name that the calculations will be added to.' ) spec.input( 'controls.kpoints_distance_for_bands', valid_type=orm.Float, default=lambda: orm.Float(0.01), help='Kpoint mesh density of the resulting band structure.' ) # spec.input('controls.nbands_factor', valid_type=orm.Float, default=orm.Float(1.5), # help='The number of bands for the NSCF calculation is that used for the SCF multiplied by this factor.') spec.output( 'primitive_structure', valid_type=orm.StructureData, help= 'The normalized and primitivized structure for which the calculations are computed.' ) spec.output( 'seekpath_parameters', valid_type=orm.Dict, help= 'The parameters used in the SeeKpath call to normalize the input or relaxed structure.' ) spec.output( 'scf_parameters', valid_type=orm.Dict, help='The output parameters of the SCF `PwBaseWorkChain`.' ) spec.output( 'nscf_parameters', valid_type=orm.Dict, help='The output parameters of the NSCF `PwBaseWorkChain`.' ) spec.output( 'projwfc_bands', valid_type=orm.BandsData, required=False, help='The output bands of projwfc run.' ) spec.output( 'projwfc_projections', valid_type=orm.ProjectionData, required=False, help='The output projections of projwfc run.' ) spec.output( 'pw2wannier90_remote_folder', valid_type=orm.RemoteData, required=False ) spec.output('wannier90_parameters', valid_type=orm.Dict) spec.output('wannier90_retrieved', valid_type=orm.FolderData) spec.output( 'wannier90_remote_folder', valid_type=orm.RemoteData, required=False ) spec.output( 'wannier90_interpolated_bands', valid_type=orm.BandsData, required=False, help='The computed band structure.' ) spec.outline( cls.setup, cls.run_seekpath, cls.setup_parameters, cls.run_wannier_workchain, cls.results ) spec.exit_code( 201, 'ERROR_INVALID_INPUT_UNRECOGNIZED_KIND', message='Input `StructureData` contains an unsupported kind.' ) spec.exit_code( 401, 'ERROR_SUB_PROCESS_FAILED_BANDS', message='The `PwBandsWorkChain` sub process failed.' )
def get_total_energy(parameters): """Return the total energy [eV] from the output parameters node.""" return orm.Float(parameters['scfenergies'][-1]) # already eV
def get_final_energy(parameters): """Return the total energy [eV] from the output parameters node for an optimisation calculation.""" return orm.Float(parameters['final_energy']['total_energy'] * HA_TO_EV)
def define(cls, spec): """Define the process specification.""" # yapf: disable super().define(spec) spec.expose_inputs(PwBaseWorkChain, namespace='scf', exclude=('clean_workdir', 'pw.structure'), namespace_options={'help': 'Inputs for the `PwBaseWorkChain` for the SCF calculation.'}) spec.expose_inputs(PwBaseWorkChain, namespace='nscf_full', exclude=('clean_workdir', 'pw.structure'), namespace_options={'help': 'Inputs for the `PwBaseWorkChain` for the NSCF calculation.'}) spec.expose_inputs(PwBaseWorkChain, namespace='nscf_crop', exclude=('clean_workdir', 'pw.structure'), namespace_options={'help': 'Inputs for the `PwBaseWorkChain` for the NSCF calculation.'}) spec.expose_inputs(DosCalc, namespace='dos_full', exclude=('parent_folder', ), namespace_options={'help': 'Inputs for the `DosCalculation` for the DOS calculation.'}) spec.expose_inputs(DosCalc, namespace='dos_crop', exclude=('parent_folder', ), namespace_options={'help': 'Inputs for the `DosCalculation` for the DOS calculation.'}) spec.input('parent_folder', valid_type=orm.RemoteData, required=False) spec.input('structure', valid_type=orm.StructureData, help='The inputs structure.') spec.input('nbands_factor_full', valid_type=orm.Float, default=lambda: orm.Float(1.5), help='The number of bands for the BANDS calculation is that used for the SCF multiplied by this factor.') spec.input('nbands_factor_crop', valid_type=orm.Float, default=lambda: orm.Float(1.5), help='The number of bands for the BANDS calculation is that used for the SCF multiplied by this factor.') spec.input('clean_workdir', valid_type=orm.Bool, default=lambda: orm.Bool(False), help='If `True`, work directories of all called calculation will be cleaned at the end of execution.') spec.input('crop_radii', valid_type=orm.ArrayData) spec.input('crop_centers', valid_type=orm.ArrayData) spec.input('override_dos', valid_type=orm.XyData) spec.input('override_dos_weight', valid_type=orm.Float, required=False) spec.outline( cls.setup, cls.validate_crop_inputs, if_(cls.should_do_scf)( cls.run_scf, cls.inspect_scf, ), cls.prepare_kgrids, if_(cls.should_do_full)( cls.run_nscf_full, cls.inspect_nscf_full, cls.run_dos_full, cls.inspect_dos_full ), cls.run_nscf_crop, cls.inspect_nscf_crop, cls.run_dos_crop, cls.inspect_dos_crop, cls.merge_results, cls.results, ) spec.exit_code(201, 'ERROR_INVALID_INPUT_NUMBER_OF_BANDS', message='Cannot specify both `nbands_factor` and `bands.pw.parameters.SYSTEM.nbnd`.') spec.exit_code(202, 'ERROR_INVALID_INPUT_KPOINTS', message='Cannot specify both `bands_kpoints` and `bands_kpoints_distance`.') spec.exit_code(203, 'ERROR_INVALID_INPUT_CROP', message='Cannot specify both `bands_kpoints` and `bands_kpoints_distance`.') spec.exit_code(401, 'ERROR_SUB_PROCESS_FAILED_RELAX', message='The PwRelaxWorkChain sub process failed') spec.exit_code(402, 'ERROR_SUB_PROCESS_FAILED_SCF', message='The scf PwBasexWorkChain sub process failed') spec.exit_code(403, 'ERROR_SUB_PROCESS_FAILED_NSCF', message='The bands PwBasexWorkChain sub process failed') spec.exit_code(404, 'ERROR_SUB_PROCESS_FAILED_DOS', message='The dos DosCalculation sub process failed') spec.output('scf_remote_folder', valid_type=orm.RemoteData) spec.output('nscf_full_remote_folder', valid_type=orm.RemoteData, required=False) spec.output('nscf_crop_remote_folder', valid_type=orm.RemoteData) spec.output('scf_parameters', valid_type=orm.Dict, help='The output parameters of the SCF `PwBaseWorkChain`.') spec.output('nscf_full_parameters', valid_type=orm.Dict, help='The output parameters of the NSCF full `PwBaseWorkChain`.', required=False) spec.output('nscf_crop_parameters', valid_type=orm.Dict, help='The output parameters of the NSCF crop `PwBaseWorkChain`.') spec.output('dos_full_parameters', valid_type=orm.Dict, required=False, help='The output parameters of the DOS full calculation.') spec.output('output_dos_full', valid_type=orm.XyData, required=False) spec.output('dos_crop_parameters', valid_type=orm.Dict, help='The output parameters of the DOS crop calculation.') spec.output('output_dos_crop', valid_type=orm.XyData) spec.output('kpoints_full', valid_type=orm.KpointsData) spec.output('kpoints_crop', valid_type=orm.KpointsData) spec.output('output_dos_merged', valid_type=orm.XyData)
def run_bands(self): """Run the `PwBandsWorkChain` to compute the band structure.""" def get_common_inputs(): """Return the dictionary of inputs to be used as the basis for each `PwBaseWorkChain`.""" protocol, protocol_modifiers = self._get_protocol() checked_pseudos = protocol.check_pseudos( modifier_name=protocol_modifiers.get('pseudo', None), pseudo_data=protocol_modifiers.get('pseudo_data', None)) known_pseudos = checked_pseudos['found'] inputs = AttributeDict({ 'pw': { 'code': self.inputs.code, 'pseudos': get_pseudos_from_dict(self.inputs.structure, known_pseudos), 'parameters': self.ctx.parameters, 'metadata': {}, } }) if 'options' in self.inputs: inputs.pw.metadata.options = self.inputs.options.get_dict() else: inputs.pw.metadata.options = get_default_options(with_mpi=True) return inputs inputs = AttributeDict({ 'structure': self.inputs.structure, 'relax': { 'base': get_common_inputs(), 'relaxation_scheme': orm.Str('vc-relax'), 'meta_convergence': orm.Bool(self.ctx.protocol['meta_convergence']), 'volume_convergence': orm.Float(self.ctx.protocol['volume_convergence']), }, 'scf': get_common_inputs(), 'bands': get_common_inputs(), }) inputs.relax.base.kpoints_distance = orm.Float( self.ctx.protocol['kpoints_mesh_density']) inputs.scf.kpoints_distance = orm.Float( self.ctx.protocol['kpoints_mesh_density']) inputs.bands.kpoints_distance = orm.Float( self.ctx.protocol['kpoints_distance_for_bands']) num_bands_factor = self.ctx.protocol.get('num_bands_factor', None) if num_bands_factor is not None: inputs.nbands_factor = orm.Float(num_bands_factor) running = self.submit(PwBandsWorkChain, **inputs) self.report(f'launching PwBandsWorkChain<{running.pk}>') return ToContext(workchain_bands=running)
def define(cls, spec): # yapf: disable super().define(spec) # SCF INPUTS ########################################################### spec.expose_inputs( PwBaseWorkChain, namespace='scf', exclude=('clean_workdir', 'pw.structure', 'pw.code'), namespace_options={ 'required':False, 'populate_defaults':False, 'help': 'Inputs for the `PwBaseWorkChain` for the SCF calculation.' } ) spec.input( 'structure', valid_type=orm.StructureData, help='The inputs structure.' ) spec.input( 'pw_code', valid_type=orm.Code, help='The code for pw calculations.' ) spec.input( 'clean_workdir', valid_type=orm.Bool, default=lambda: orm.Bool(False), help='If `True`, work directories of all called calculation will be cleaned at the end of execution.' ) spec.input( 'parent_folder', valid_type=orm.RemoteData, required=False, help=( 'Output of a previous scf calculation to start a new z2pack calclulation from. ' 'If specified, will not run the scf calculation and start straight from z2pack.' ) ) #Z2pack inputs ########################################################### spec.input( 'min_neighbour_distance_scale_factor', valid_type=orm.Float, default=lambda: orm.Float(10.0), help='Scale factor for min_neighbour_distance to be used between restarts when convergence is not achieved.' ) spec.input( 'min_neighbour_distance_threshold_minimum', valid_type=orm.Float, default=lambda: orm.Float(1E-4), help='Stop the restart iterations when `min_neighbour_distance` becomes smaller than this threshold.' ) spec.expose_inputs( Z2packCalculation, namespace='z2pack', exclude=('parent_folder', 'pw_code'), namespace_options={ 'help': 'Inputs for the `Z2packCalculation` for the SCF calculation.' } ) spec.outline( cls.setup, if_(cls.should_do_scf)( cls.run_scf, cls.inspect_scf, ), cls.setup_z2pack, while_(cls.should_run_process)( cls.prepare_process, cls.run_process, cls.inspect_process ), cls.results ) spec.expose_outputs(Z2packCalculation) spec.output( 'wannier90_parameters', valid_type=orm.Dict, required=False, help='Auto-setted w90parameters.' ) spec.exit_code(101, 'ERROR_UNRECOVERABLE_FAILURE', message='Can\'t recover. Aborting!') spec.exit_code(111, 'ERROR_SUB_PROCESS_FAILED_STARTING_SCF', message='the starting scf PwBaseWorkChain sub process failed') spec.exit_code(201, 'ERROR_NOT_CONVERGED', message='Calculation finished, but convergence not achieved.') spec.exit_code(211, 'ERROR_POS_TOL_CONVERGENCE_FAILED', message='WCCs position is not stable when increasing k-points on a line.') spec.exit_code(221, 'ERROR_GAP_TOL_CONVERGENCE_FAILED', message='Position of largest gap between WCCs varies too much between neighboring lines.') spec.exit_code(231, 'ERROR_FAILED_SAVEFILE_TWICE', message='The calculation failed to produce the savefile for a restart twice.')
def inner(): inputs = get_fp_tb_inputs() inputs['initial_window'] = orm.List(list=[-4.5, -4, 6.5, 16]) inputs['window_tol'] = orm.Float(1.5) return inputs
def get_total_energy(parameters): """Return the total energy from the given parameters node.""" return orm.Float(parameters.get_attribute('energy'))
def add(a, b): """Add 2 numbers""" return {'res': orm.Float(a + b)}
def get_magn(pardict): """Extract the energy from the `output_parameters` dictionary""" return orm.Float(pardict['stot'])