Пример #1
0
    def _generate_inputdata(self,
                            parameters: orm.Dict,
                            pseudos,
                            structure: orm.StructureData,
                            kpoints: orm.KpointsData) -> ty.Tuple[str, list]:
        """Generate the input file content and list of pseudopotential files to copy.

        :param parameters: input parameters Dict
        :param pseudos: pseudopotential input namespace
        :param structure: input structure
        :param kpoints: input kpoints
        :returns: input file content, pseudopotential copy list
        """
        local_copy_pseudo_list = []

        # abipy has its own subclass of Pymatgen's `Structure`, so we use that
        pmg_structure = structure.get_pymatgen()
        abi_structure = AbiStructure.as_structure(pmg_structure)
        abi_structure = abi_structure.abi_sanitize(primitive=True)

        for kind in structure.get_kind_names():
            pseudo = pseudos[kind]
            local_copy_pseudo_list.append((pseudo.uuid, pseudo.filename, f'{self._PSEUDO_SUBFOLDER}{pseudo.filename}'))
        # Pseudopotentials _must_ be listed in the same order as 'znucl' in the input file.
        # So, we need to get 'znucl' as abipy will write it then construct the appropriate 'pseudos' string.
        znucl = structure_to_abivars(abi_structure)['znucl']
        ordered_pseudo_filenames = [pseudos[constants.elements[Z]['symbol']].filename for Z in znucl]
        pseudo_parameters = {
            'pseudos': '"' + ', '.join(ordered_pseudo_filenames) + '"',
            'pp_dirpath': f'"{self._PSEUDO_SUBFOLDER}"'
        }

        input_parameters = parameters.get_dict()
        # k-points are provided to abipy separately from the main input parameters, so we pop out
        # parameters related to the k-points
        shiftk = input_parameters.pop('shiftk', [0.0, 0.0, 0.0])
        # NOTE: currently, only k-point mesh are supported, not k-point paths
        kpoints_mesh = kpoints.get_kpoints_mesh()[0]

        # use abipy to write the input file
        input_parameters = {**input_parameters, **pseudo_parameters}
        # give abipy the HGH_TABLE only so it won't error, but don't actually print these to file
        abi_input = AbinitInput(
            structure=abi_structure,
            pseudos=HGH_TABLE,
            abi_kwargs=input_parameters
        )
        abi_input.set_kmesh(
            ngkpt=kpoints_mesh,
            shiftk=shiftk
        )

        return abi_input.to_string(with_pseudos=False), local_copy_pseudo_list
Пример #2
0
    def prepare_for_submission(self, folder):
        """
        Create input files.

        :param folder: an `aiida.common.folders.Folder` where the plugin should temporarily place all files needed by
            the calculation.
        :return: `aiida.common.datastructures.CalcInfo` instance
        """
        ### SETUP ###
        local_copy_list = []

        ### INPUT CHECK ###
        # PSEUDOS
        for kind in self.inputs.structure.get_kind_names():
            if kind not in self.inputs.pseudos:
                raise ValueError(f'no pseudo available for element {kind}')
            elif not isinstance(self.inputs.pseudos[kind], (Psp8Data, JthXmlData)):
                raise ValueError(f'pseudo for element {kind} is not of type Psp8Data or JthXmlData')

        # KPOINTS
        if 'ngkpt' in self.inputs.parameters.keys():
            raise ValueError('`ngkpt` should not be specified in input parameters')
        if 'kptopt' in self.inputs.parameters.keys():
            raise ValueError('`kptopt` should not be specified in input parameters')

        ### PREPARATION ###
        # PSEUDOS
        folder.get_subfolder(self._DEFAULT_PSEUDO_SUBFOLDER, create=True)
        for kind in self.inputs.structure.get_kind_names():
            psp = self.inputs.pseudos[kind]
            local_copy_list.append((psp.uuid, psp.filename, self._DEFAULT_PSEUDO_SUBFOLDER + kind + '.psp8'))

        # KPOINTS
        kpoints_mesh = self.inputs.kpoints.get_kpoints_mesh()[0]

        ### INPUTS ###
        input_parameters = self.inputs.parameters.get_dict()
        shiftk = input_parameters.pop('shiftk', [0.0, 0.0, 0.0])

        # TODO: There must be a better way to do this
        # maybe we can convert the PseudoPotential objects into pymatgen Pseudo objects?
        znucl = structure_to_abivars(self.inputs.structure.get_pymatgen())['znucl']
        pseudo_parameters = {
            'pseudos': '"' + ', '.join([Element.from_Z(Z).symbol + '.psp8' for Z in znucl]) + '"',
            'pp_dirpath': '"' + self._DEFAULT_PSEUDO_SUBFOLDER + '"'
        }

        input_parameters = {**input_parameters, **pseudo_parameters}

        abin = AbinitInput(
            structure=self.inputs.structure.get_pymatgen(),
            pseudos=HGH_TABLE,
            abi_kwargs=input_parameters
        )
        abin.set_kmesh(
            ngkpt=kpoints_mesh,
            shiftk=shiftk
        )

        with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE), mode='w', encoding='utf-8') as f:
            f.write(abin.to_string(with_pseudos=False))

        ### CODE ###
        codeinfo = datastructures.CodeInfo()
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.cmdline_params = [self.options.input_filename]
        codeinfo.stdout_name = self.metadata.options.output_filename
        codeinfo.withmpi = self.inputs.metadata.options.withmpi

        ### CALC INFO ###
        calcinfo = datastructures.CalcInfo()
        calcinfo.codes_info = [codeinfo]
        calcinfo.stdin_name = self.options.input_filename
        calcinfo.stdout_name = self.options.output_filename
        calcinfo.retrieve_list = [self.metadata.options.output_filename]
        calcinfo.retrieve_list = [self._DEFAULT_OUTPUT_FILE, self._DEFAULT_GSR_FILE_NAME, self._DEFAULT_TRAJECT_FILE_NAME]
        calcinfo.remote_symlink_list = []
        calcinfo.remote_copy_list = []
        calcinfo.local_copy_list = local_copy_list
        if 'parent_calc_folder' in self.inputs:
            comp_uuid = self.inputs.parent_calc_folder.computer.uuid
            remote_path = self.inputs.parent_calc_folder.get_remote_path()
            copy_info = (comp_uuid, remote_path, self._DEFAULT_PARENT_CALC_FLDR_NAME)
            # If running on the same computer - make a symlink.
            if self.inputs.code.computer.uuid == comp_uuid:
                calcinfo.remote_symlink_list.append(copy_info)
            # If not - copy the folder.
            else:
                calcinfo.remote_copy_list.append(copy_info)

        return calcinfo