예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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))
예제 #4
0
    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)
예제 #5
0
    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
예제 #6
0
    def run_bands(self):
        """Run the PwBaseWorkChain in bands mode along the path of high-symmetry determined by seekpath."""

        # Get info from SCF on number of electrons and number of spin components
        scf_out_dict = self.ctx.workchain_scf.outputs.output_parameters.get_dict()
        nelectron = int(scf_out_dict['number_of_electrons'])
        nspin = int(scf_out_dict['number_of_spin_components'])
        nbands = max(
            int(0.5 * nelectron * nspin * self.inputs.nbands_factor.value),
            int(0.5 * nelectron * nspin) + 4 * nspin)

        inputs = AttributeDict(self.exposed_inputs(PwBaseWorkChain, namespace='bands'))
        inputs.pw.parameters = inputs.pw.parameters.get_dict()

        inputs.pw.parameters.setdefault('CONTROL', {})
        inputs.pw.parameters.setdefault('SYSTEM', {})
        inputs.pw.parameters.setdefault('ELECTRONS', {})

        inputs.pw.parameters['CONTROL']['restart_mode'] = 'restart'
        inputs.pw.parameters['CONTROL']['calculation'] = 'bands'
        inputs.pw.parameters['ELECTRONS']['diagonalization'] = 'cg'
        inputs.pw.parameters['ELECTRONS']['diago_full_acc'] = True
        inputs.pw.parameters['SYSTEM']['nbnd'] = nbands

        if 'kpoints' not in self.inputs.bands:
            inputs.kpoints = self.ctx.kpoints_path

        inputs.pw.structure = self.ctx.current_structure
        inputs.pw.parent_folder = self.ctx.current_folder

        inputs = prepare_process_inputs(PwBaseWorkChain, inputs)
        running = self.submit(PwBaseWorkChain, **inputs)

        self.report('launching PwBaseWorkChain<{}> in {} mode'.format(running.pk, 'bands'))

        return ToContext(workchain_bands=running)
예제 #7
0
    def run_wannier90_pp(self):
        """The input of wannier90 calculation is build here.

        :return: [description]
        :rtype: [type]
        """
        inputs = AttributeDict(
            self.exposed_inputs(Wannier90Calculation, namespace='wannier90'))
        inputs.structure = self.ctx.current_structure
        parameters = inputs.parameters.get_dict()

        # get nscf kmesh
        inputs.kpoints = self.ctx.workchain_nscf.inputs.kpoints
        # the input kpoints of nscf is an explicitly generated list of kpoints,
        # we mush retrieve the original kmesh, and explicitly set w90 mp_grid keyword
        parameters['mp_grid'] = self.ctx.nscf_kmesh.get_kpoints_mesh()[0]

        # check num_bands, exclude_bands, nscf nbnd
        nbnd = self.ctx.workchain_nscf.outputs.output_parameters.get_dict(
        )['number_of_bands']
        num_ex_bands = len(get_exclude_bands(inputs.parameters.get_dict()))
        parameters['num_bands'] = nbnd - num_ex_bands

        # set num_wann for auto_projections
        if self.ctx.auto_projections:
            if self.inputs.only_valence:
                parameters['num_wann'] = parameters['num_bands']
                inputs.parameters = orm.Dict(dict=parameters)
            else:
                inputs.parameters = orm.Dict(dict=parameters)
                inputs.parameters = update_w90_params_numwann(
                    inputs.parameters,
                    self.ctx.calc_projwfc.outputs.projections)
                self.report(
                    'number of Wannier functions extracted from projections: '
                    + str(inputs.parameters['num_wann']))

        # get scf Fermi energy
        try:
            energies_relative_to_fermi = self.inputs.get(
                'wannier_energies_relative_to_fermi')
            inputs.parameters = update_w90_params_fermi(
                inputs.parameters,
                self.ctx.workchain_scf.outputs.output_parameters,
                energies_relative_to_fermi)
        except TypeError:
            self.report("Error in retriving the SCF Fermi energy "
                        "from pk: {}".format(self.ctx.workchain_scf))
            return self.exit_codes.ERROR_SUB_PROCESS_FAILED_WANNIER90PP

        #Check if settings is given in input
        try:
            settings = inputs['settings'].get_dict()
        except KeyError:
            settings = {}
        settings['postproc_setup'] = True
        inputs['settings'] = settings

        inputs = prepare_process_inputs(Wannier90Calculation, inputs)
        running = self.submit(Wannier90Calculation, **inputs)

        self.report(
            'wannier90 postproc step - launching Wannier90Calculation<{}> in postproc mode'
            .format(running.pk))

        return ToContext(calc_wannier90_pp=running)
예제 #8
0
    def run_nscf(self):
        """
        Run the PwBaseWorkChain in nscf mode
        """
        inputs = AttributeDict(
            self.exposed_inputs(PwBaseWorkChain, namespace='nscf'))
        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', {})
        inputs.pw.parameters['CONTROL']['restart_mode'] = 'from_scratch'
        inputs.pw.parameters['CONTROL']['calculation'] = 'nscf'
        inputs.pw.parameters['SYSTEM']['nosym'] = True
        inputs.pw.parameters['SYSTEM']['noinv'] = True
        inputs.pw.parameters['ELECTRONS']['diagonalization'] = 'cg'
        inputs.pw.parameters['ELECTRONS']['diago_full_acc'] = True

        if self.inputs.only_valence:
            inputs.pw.parameters['SYSTEM']['occupations'] = 'fixed'
            inputs.pw.parameters['SYSTEM'].pop(
                'smearing', None)  # pop None to avoid KeyError
            inputs.pw.parameters['SYSTEM'].pop(
                'degauss', None)  # pop None to avoid KeyError

        # inputs.pw.pseudos is an AttributeDict, but calcfunction only accepts
        # orm.Data, so we unpack it to pass in orm.UpfData
        inputs.pw.parameters = update_nscf_num_bands(
            orm.Dict(dict=inputs.pw.parameters),
            self.ctx.workchain_scf.outputs.output_parameters,
            self.ctx.current_structure, self.inputs.only_valence,
            **inputs.pw.pseudos)
        self.report('nscf number of bands set as ' +
                    str(inputs.pw.parameters['SYSTEM']['nbnd']))

        # check kmesh
        try:
            inputs.kpoints
        except AttributeError:
            # then kpoints_distance must exists, since this is ensured by inputs check of this workchain
            from aiida_quantumespresso.workflows.functions.create_kpoints_from_distance import create_kpoints_from_distance
            force_parity = inputs.get('kpoints_force_parity', orm.Bool(False))
            kmesh = create_kpoints_from_distance(self.ctx.current_structure,
                                                 inputs.kpoints_distance,
                                                 force_parity)
            #kpoints_data = orm.KpointsData()
            # kpoints_data.set_cell_from_structure(self.ctx.current_structure)
            # kmesh = kpoints_data.set_kpoints_mesh_from_density(inputs.kpoints_distance.value)
        else:
            try:
                inputs.kpoints.get_kpoints_mesh()
            except AttributeError:
                self.report("nscf only support `mesh' type KpointsData")
                return self.exit_codes.ERROR_SUB_PROCESS_FAILED_NSCF
            else:
                kmesh = inputs.kpoints
        # convert kmesh to explicit list, since auto generated kpoints
        # maybe different between QE & Wannier90. Here we explicitly
        # generate a list of kpoint to avoid discrepencies between
        # QE's & Wannier90's automatically generated kpoints.
        self.ctx.nscf_kmesh = kmesh  # store it since it will be used by w90
        inputs.kpoints = convert_kpoints_mesh_to_list(kmesh)

        inputs = prepare_process_inputs(PwBaseWorkChain, inputs)
        running = self.submit(PwBaseWorkChain, **inputs)

        self.report(
            'nscf step - launching PwBaseWorkChain<{}> in {} mode'.format(
                running.pk, 'nscf'))

        return ToContext(workchain_nscf=running)