示例#1
0
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
示例#2
0
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'))
示例#4
0
def get_total_magnetization(parameters):
    """Return the total magnetization from the given parameters node."""
    return orm.Float(parameters['total_magnetization'])
示例#5
0
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'))
示例#6
0
    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
示例#7
0
def get_energy(pardict):
    """Extract the energy from the `output_parameters` dictionary"""
    return orm.Float(pardict['E_KS'])
示例#8
0
    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
示例#10
0
    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
示例#11
0
    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.'
        )
示例#12
0
def get_total_energy(parameters):
    """Return the total energy [eV] from the output parameters node."""
    return orm.Float(parameters['scfenergies'][-1])  # already eV
示例#13
0
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)
示例#14
0
    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)
示例#16
0
    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.')
示例#17
0
    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
示例#18
0
def get_total_energy(parameters):
    """Return the total energy from the given parameters node."""
    return orm.Float(parameters.get_attribute('energy'))
示例#19
0
 def add(a, b):
     """Add 2 numbers"""
     return {'res': orm.Float(a + b)}
示例#20
0
def get_magn(pardict):
    """Extract the energy from the `output_parameters` dictionary"""
    return orm.Float(pardict['stot'])