예제 #1
0
    def run_stage(self):
        """Check for restart, prepare input, submit and direct output to context."""

        # Update structure
        self.ctx.base_inp['cp2k']['structure'] = self.ctx.structure

        # Check if it is needed to restart the calculation and provide the parent folder and new structure
        if self.ctx.parent_calc_folder:
            self.ctx.base_inp['cp2k']['parent_calc_folder'] = self.ctx.parent_calc_folder
            self.ctx.cp2k_param['FORCE_EVAL']['DFT']['SCF']['SCF_GUESS'] = 'RESTART'
            self.ctx.cp2k_param['FORCE_EVAL']['DFT']['WFN_RESTART_FILE_NAME'] = './parent_calc/aiida-RESTART.wfn'
        else:
            self.ctx.cp2k_param['FORCE_EVAL']['DFT']['SCF']['SCF_GUESS'] = 'ATOMIC'

        # Overwrite the generated input with the custom cp2k/parameters
        if 'parameters' in self.exposed_inputs(Cp2kBaseWorkChain, 'cp2k_base')['cp2k']:
            merge_dict(
                self.ctx.cp2k_param,
                AttributeDict(self.exposed_inputs(Cp2kBaseWorkChain, 'cp2k_base')['cp2k']['parameters'].get_dict()))
        self.ctx.base_inp['cp2k']['parameters'] = Dict(dict=self.ctx.cp2k_param).store()

        # Update labels
        self.ctx.base_inp['metadata'].update({
            'label': '{}_{}'.format(self.ctx.stage_tag, self.ctx.settings_tag),
            'call_link_label': 'run_{}_{}'.format(self.ctx.stage_tag, self.ctx.settings_tag),
        })
        self.ctx.base_inp['cp2k']['metadata'].update(
            {'label': self.ctx.base_inp['cp2k']['parameters'].get_dict()['GLOBAL']['RUN_TYPE']})

        running_base = self.submit(Cp2kBaseWorkChain, **self.ctx.base_inp)
        self.report("submitted Cp2kBaseWorkChain for {}/{}".format(self.ctx.stage_tag, self.ctx.settings_tag))
        return ToContext(stages=append_(running_base))
예제 #2
0
    def inspect_and_update_stage(self):
        """Update geometry, parent folder and the new &MOTION settings."""
        last_stage = self.ctx.stages[-1]

        if 'output_structure' in last_stage.outputs:
            self.ctx.structure = last_stage.outputs.output_structure
            self.report('Structure updated for next stage')
        else:
            self.report(
                'New structure NOT found and NOT updated for next stage')

        self.ctx.parent_calc_folder = last_stage.outputs.remote_folder
        last_stage.outputs.output_parameters.label = '{}_{}_valid'.format(
            self.ctx.stage_tag, self.ctx.settings_tag)

        self.ctx.stage_idx += 1
        next_stage_tag = 'stage_{}'.format(self.ctx.stage_idx)

        if next_stage_tag in self.ctx.protocol:
            self.ctx.stage_tag = next_stage_tag
            self.ctx.next_stage_exists = True
            merge_dict(self.ctx.cp2k_param,
                       self.ctx.protocol[self.ctx.stage_tag])
        else:
            self.ctx.next_stage_exists = False
            self.report("All stages computed, finishing...")
예제 #3
0
    def setup_multistage(self):
        """Setup initial parameters."""

        # Store the workchain inputs in context (to be modified later)
        self.ctx.base_inp = AttributeDict(self.exposed_inputs(Cp2kBaseWorkChain, 'cp2k_base'))

        # Check if an input parent_calc_folder is provided
        if 'parent_calc_folder' in self.inputs:
            self.ctx.parent_calc_folder = self.inputs.parent_calc_folder
        else:
            self.ctx.parent_calc_folder = None

        # Read yaml file selected as SinglefileData or chosen with the tag, and overwrite with custom modifications
        if 'protocol_yaml' in self.inputs:
            self.ctx.protocol = yaml.safe_load(self.inputs.protocol_yaml.open())
        else:
            thisdir = os.path.dirname(os.path.abspath(__file__))
            yamlfullpath = os.path.join(thisdir, 'multistage_protocols', self.inputs.protocol_tag.value + '.yaml')
            with open(yamlfullpath, 'r') as stream:
                self.ctx.protocol = yaml.safe_load(stream)
        merge_dict(self.ctx.protocol, self.inputs.protocol_modify.get_dict())

        # Initialize
        self.ctx.settings_ok = False
        self.ctx.stage_idx = 0
        self.ctx.stage_tag = 'stage_{}'.format(self.ctx.stage_idx)
        self.ctx.settings_idx = 0
        self.ctx.settings_tag = 'settings_{}'.format(self.ctx.settings_idx)
        self.ctx.structure = self.inputs.structure

        # Resize the unit cell if min(perp_with) < inputs.min_cell_size
        self.ctx.resize = check_resize_unit_cell(self.ctx.structure, self.inputs.min_cell_size)  # Dict
        if self.ctx.resize['nx'] > 1 or self.ctx.resize['ny'] > 1 or self.ctx.resize['nz'] > 1:
            resized_struct = resize_unit_cell(self.ctx.structure, self.ctx.resize)
            self.ctx.structure = resized_struct
            self.report("Unit cell resized by {}x{}x{} (StructureData<{}>)".format(self.ctx.resize['nx'],
                                                                                   self.ctx.resize['ny'],
                                                                                   self.ctx.resize['nz'],
                                                                                   resized_struct.pk))
        else:
            self.report("Unit cell was NOT resized")

        # Generate input parameters and store them
        self.ctx.cp2k_param = deepcopy(self.ctx.protocol['settings_0'])
        while self.inputs.starting_settings_idx < self.ctx.settings_idx:
            # overwrite untill the desired starting setting are obtained
            self.ctx.settings_idx += 1
            self.ctx.settings_tag = 'settings_{}'.format(self.ctx.settings_idx)
            if self.ctx.settings_tag in self.ctx.protocol:
                merge_dict(self.ctx.cp2k_param, self.ctx.protocol[self.ctx.settings_tag])
            else:
                return self.exit_codes.ERROR_MISSING_INITIAL_SETTINGS  # pylint: disable=no-member
        kinds = get_kinds_section(self.ctx.structure, self.ctx.protocol)
        merge_dict(self.ctx.cp2k_param, kinds)
        multiplicity = get_input_multiplicity(self.ctx.structure, self.ctx.protocol)
        merge_dict(self.ctx.cp2k_param, multiplicity)
        merge_dict(self.ctx.cp2k_param, self.ctx.protocol['stage_0'])
예제 #4
0
    def inspect_and_update_settings_stage0(self):  # pylint: disable=inconsistent-return-statements
        """Inspect the stage0/settings_{idx} calculation and check if it is
        needed to update the settings and resubmint the calculation."""
        self.ctx.settings_ok = True

        # Settings/structure are bad: there are problems in parsing the output file
        # and, most probably, the calculation didn't even start the scf cycles
        if 'output_parameters' in self.ctx.stages[-1].outputs:
            cp2k_out = self.ctx.stages[-1].outputs.output_parameters
        else:
            self.report('ERROR_PARSING_OUTPUT')
            return self.exit_codes.ERROR_PARSING_OUTPUT  # pylint: disable=no-member

        # Settings are bad: the SCF did not converge in the final step
        if not cp2k_out["motion_step_info"]["scf_converged"][-1]:
            self.report("BAD SETTINGS: the SCF did not converge")
            self.ctx.settings_ok = False
            self.ctx.settings_idx += 1
        else:
            # SCF converged, but the computed bandgap needs to be checked
            self.report("Bandgaps spin1/spin2: {:.3f} and {:.3f} ev".format(
                cp2k_out["bandgap_spin1_au"] * HARTREE2EV,
                cp2k_out["bandgap_spin2_au"] * HARTREE2EV))
            bandgap_thr_ev = self.ctx.protocol['bandgap_thr_ev']
            if ot_has_small_bandgap(self.ctx.cp2k_param, cp2k_out,
                                    bandgap_thr_ev):
                self.report("BAD SETTINGS: band gap is < {:.3f} eV".format(
                    bandgap_thr_ev))
                self.ctx.settings_ok = False
                self.ctx.settings_idx += 1

        # Update the settings tag, check if it is available and overwrite
        if not self.ctx.settings_ok:
            cp2k_out.label = '{}_{}_discard'.format(self.ctx.stage_tag,
                                                    self.ctx.settings_tag)
            next_settings_tag = 'settings_{}'.format(self.ctx.settings_idx)
            if next_settings_tag in self.ctx.protocol:
                self.ctx.settings_tag = next_settings_tag
                merge_dict(self.ctx.cp2k_param,
                           self.ctx.protocol[self.ctx.settings_tag])
            else:
                return self.exit_codes.ERROR_NO_MORE_SETTINGS  # pylint: disable=no-member