Exemple #1
0
    def prepare_for_submission(self, folder):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param folder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        """

        if 'structure' in self.inputs:
            pmg_structure = self.inputs.structure.get_pymatgen_molecule()
        else:
            # If structure is not specified, it is read from the chk file
            pmg_structure = None

        # Generate the input file
        input_string = GaussianCalculation._render_input_string_from_params(
            self.inputs.parameters.get_dict(), pmg_structure)

        with open(folder.get_abs_path(self.INPUT_FILE), "w") as out_file:
            out_file.write(input_string)

        settings = self.inputs.settings.get_dict(
        ) if "settings" in self.inputs else {}

        # create code info
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings.pop("cmdline", [])
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.stdin_name = self.INPUT_FILE
        codeinfo.stdout_name = self.OUTPUT_FILE
        codeinfo.withmpi = self.inputs.metadata.options.withmpi

        # create calculation info
        calcinfo = CalcInfo()
        calcinfo.remote_copy_list = []
        calcinfo.local_copy_list = []
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self.INPUT_FILE
        calcinfo.stdout_name = self.OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]
        calcinfo.retrieve_list = [self.OUTPUT_FILE]

        # symlink or copy to parent calculation
        calcinfo.remote_symlink_list = []
        calcinfo.remote_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.PARENT_FOLDER_NAME)
            if (self.inputs.code.computer.uuid == comp_uuid):
                # if running on the same computer - make a symlink
                # if not - copy the folder
                calcinfo.remote_symlink_list.append(copy_info)
            else:
                calcinfo.remote_copy_list.append(copy_info)

        return calcinfo
Exemple #2
0
    def prepare_for_submission(self, folder):
        """Create the input files from the input nodes passed to this instance of the `CalcJob`.

        :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """
        from aiida_orca.utils import OrcaInput

        # create input structure(s)
        if 'structure' in self.inputs:
            self._write_structure(self.inputs.structure, folder,
                                  self._INPUT_COORDS_FILE)

        settings = self.inputs.settings.get_dict(
        ) if 'settings' in self.inputs else {}

        # create code info
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings.pop('cmdline',
                                               []) + [self._INPUT_FILE]
        codeinfo.stdout_name = self._OUTPUT_FILE
        codeinfo.join_files = True
        codeinfo.code_uuid = self.inputs.code.uuid

        # create calc info
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._INPUT_FILE
        calcinfo.stdout_name = self._OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]

        # files or additional structures
        if 'file' in self.inputs:
            calcinfo.local_copy_list = []
            for name, obj in self.inputs.file.items():
                if name == 'gbw':
                    calcinfo.local_copy_list.append(
                        (obj.uuid, obj.filename, 'aiida_old.gbw'))
                else:
                    calcinfo.local_copy_list.append(
                        (obj.uuid, obj.filename, obj.filename))

        # Retrive list
        calcinfo.retrieve_list = [
            self._OUTPUT_FILE, self._GBW_FILE, self._HESSIAN_FILE,
            self._RELAX_COORDS_FILE
        ]
        calcinfo.retrieve_list += settings.pop('additional_retrieve_list', [])

        # create ORCA input file
        # inp = OrcaInput(self.inputs.parameters.get_dict(), remote_path=remote_path)
        inp = OrcaInput(self.inputs.parameters.get_dict())
        with io.open(folder.get_abs_path(self._INPUT_FILE), mode='w') as fobj:
            fobj.write(inp.render())

        return calcinfo
Exemple #3
0
    def prepare_for_submission(self, folder):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param folder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        """
        # create calc info
        calcinfo = CalcInfo()
        calcinfo.remote_copy_list = []
        calcinfo.local_copy_list = []

        # The main input
        try:
            input_string = GaussianCalculation._render_input_string_from_params(
                self.inputs.parameters.get_dict(), self.inputs.structure
            )
        # If structure is not specified the user might want to restart from a chk
        except AttributeError:
            input_string = GaussianCalculation._render_input_string_from_params(
                self.inputs.parameters.get_dict(), None
            )

        # Parse additional link1 sections
        if "extra_link1_sections" in self.inputs:
            for l1_name, l1_params in self.inputs.extra_link1_sections.items():
                input_string += "--Link1--\n"
                # The link1 secions don't support their own geometries.
                input_string += GaussianCalculation._render_input_string_from_params(
                    l1_params.get_dict(), None
                )

        with open(folder.get_abs_path(self.INPUT_FILE), "w") as out_file:
            out_file.write(input_string)

        settings = self.inputs.settings.get_dict() if "settings" in self.inputs else {}

        # create code info
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings.pop("cmdline", [])
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.stdin_name = self.INPUT_FILE
        codeinfo.stdout_name = self.OUTPUT_FILE
        codeinfo.withmpi = self.inputs.metadata.options.withmpi

        # create calculation info
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self.INPUT_FILE
        calcinfo.stdout_name = self.OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]
        calcinfo.retrieve_list = [self.OUTPUT_FILE]

        # symlink or copy to parent calculation
        calcinfo.remote_symlink_list = []
        calcinfo.remote_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, "parent_calc")
            if (
                self.inputs.code.computer.uuid == comp_uuid
            ):  # if running on the same computer - make a symlink
                # if not - copy the folder
                calcinfo.remote_symlink_list.append(copy_info)
            else:
                calcinfo.remote_copy_list.append(copy_info)

        return calcinfo
Exemple #4
0
    def prepare_for_submission(self, tempfolder):
        # Setup template
        with open(self.inputs.template, 'r') as tempfile:
            temp_contents = tempfile.read()
        lmp_template = Template(temp_contents)

        # # check variables
        # for variable in self.inputs.variables.values():
        #     if not isinstance(variable, list):
        #         raise TypeError('Values in variables must be list')
        # check kinds
        if 'kinds' in self.inputs:
            kind_var = {
                kind: kind_index + 1
                for kind_index, kind in enumerate(self.inputs.kinds)
            }
            lmp_template = Template(lmp_template.safe_substitute(**kind_var))

        for i, case in enumerate(self.inputs.cases):
            structure = case.pop('structure')
            if isinstance(structure, StructureData):
                structure_txt, struct_transform = generate_lammps_structure(
                    structure, kinds=self.inputs.kinds)
            elif isinstance(structure, SinglefileData):
                structure_txt = structure.get_content()
            else:
                raise TypeError(
                    'Input structure must be StructureData or SinglefileData')
            input_txt = lmp_template.safe_substitute(**case)

            # ========================= dump to file ===========================
            tempfolder.get_subfolder(i, create=True)
            input_filename = tempfolder.get_abs_path(
                f'{i}/{self._INPUT_FILE_NAME}')
            with open(input_filename, 'w') as infile:
                infile.write(input_txt)

            structure_filename = tempfolder.get_abs_path(
                f'{i}/{self._INPUT_STRUCTURE}')
            with open(structure_filename, 'w') as infile:
                infile.write(structure_txt)

            case_filename = tempfolder.get_abs_path(f'{i}/case.json')
            case.update({'structure pk': structure.pk})
            with open(case_filename, 'w') as infile:
                json.dump(case, infile, sort_keys=True, indent=2)

        # ============================ calcinfo ================================
        settings = self.inputs.settings.get_dict() \
            if 'settings' in self.inputs else {}

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = self._cmdline_params
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.stdout_name = self._stdout_name
        codeinfo.join_files = True

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.prepend_text = (f'for i in $(seq 0 {i})\n'
                                 'do\n'
                                 'cd "${i}" || exit')
        calcinfo.append_text = ('cd ..\n' 'done')
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._INPUT_FILE_NAME
        calcinfo.stdout_name = self._stdout_name
        calcinfo.retrieve_list = self._retrieve_list + [
            self.options.output_filename
        ]
        calcinfo.retrieve_list += settings.pop('additional_retrieve_list', [])
        calcinfo.retrieve_temporary_list = self._retrieve_temporary_list
        calcinfo.codes_info = [codeinfo]

        # =========================== local_copy_list ==========================

        if 'file' in self.inputs:
            calcinfo.local_copy_list = []
            for name, obj in self.inputs.file.items():
                calcinfo.local_copy_list.append(
                    (obj.uuid, obj.filename, f'{name}.pb'))

        return calcinfo
Exemple #5
0
    def prepare_for_submission(self, tempfolder):

        # Setup structure
        if isinstance(self.inputs.structure, StructureData):
            structure_txt, struct_transform = generate_lammps_structure(
                self.inputs.structure, kinds=self.inputs.kinds)
        elif isinstance(self.inputs.structure, SinglefileData):
            structure_txt = self.inputs.structure.get_content()
        else:
            raise TypeError(
                'Input structure must be StructureData or SinglefileData')

        with open(self.inputs.template, 'r') as tempfile:
            temp_contents = tempfile.read()
        init_temp = Template(temp_contents)
        input_txt = init_temp.safe_substitute(**self.inputs.variables)
        if 'kinds' in self.inputs:
            kind_temp = Template(input_txt)
            kind_var = {
                kind: kind_index + 1
                for kind_index, kind in enumerate(self.inputs.kinds)
            }
            input_txt = kind_temp.safe_substitute(**kind_var)

        # =========================== dump to file =============================
        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        with open(input_filename, 'w') as infile:
            infile.write(input_txt)

        structure_filename = tempfolder.get_abs_path(self._INPUT_STRUCTURE)
        with open(structure_filename, 'w') as infile:
            infile.write(structure_txt)

        # ============================ calcinfo ================================
        settings = self.inputs.settings.get_dict() \
            if 'settings' in self.inputs else {}

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = self._cmdline_params
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.stdout_name = self._stdout_name
        codeinfo.join_files = True

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._INPUT_FILE_NAME
        calcinfo.stdout_name = self._stdout_name
        calcinfo.retrieve_list = self._retrieve_list + [
            self.options.output_filename
        ]
        calcinfo.retrieve_list += settings.pop('additional_retrieve_list', [])
        calcinfo.retrieve_temporary_list = self._retrieve_temporary_list
        calcinfo.codes_info = [codeinfo]

        # =========================== local_copy_list ==========================

        if 'file' in self.inputs:
            calcinfo.local_copy_list = []
            for name, obj in self.inputs.file.items():
                calcinfo.local_copy_list.append(
                    (obj.uuid, obj.filename, f'{name}.pb'))

        return calcinfo
Exemple #6
0
    def prepare_for_submission(self, folder):
        """Create the input files from the input nodes passed to this instance of the `CalcJob`.

        :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """
        from aiida_cp2k.utils import Cp2kInput

        # create cp2k input file
        inp = Cp2kInput(self.inputs.parameters.get_dict())
        inp.add_keyword("GLOBAL/PROJECT", self._DEFAULT_PROJECT_NAME)

        # create input structure(s)
        if 'structure' in self.inputs:
            # As far as I understand self.inputs.structure can't deal with tags
            # self.inputs.structure.export(folder.get_abs_path(self._DEFAULT_COORDS_FILE_NAME), fileformat="xyz")
            self._write_structure(self.inputs.structure, folder,
                                  self._DEFAULT_COORDS_FILE_NAME)

            # modify the input dictionary accordingly
            for i, letter in enumerate('ABC'):
                inp.add_keyword('FORCE_EVAL/SUBSYS/CELL/' + letter,
                                '{:<15} {:<15} {:<15}'.format(
                                    *self.inputs.structure.cell[i]),
                                override=False,
                                conflicting_keys=[
                                    'ABC', 'ALPHA_BETA_GAMMA', 'CELL_FILE_NAME'
                                ])

            topo = "FORCE_EVAL/SUBSYS/TOPOLOGY"
            inp.add_keyword(topo + "/COORD_FILE_NAME",
                            self._DEFAULT_COORDS_FILE_NAME,
                            override=False)
            inp.add_keyword(topo + "/COORD_FILE_FORMAT",
                            "XYZ",
                            override=False,
                            conflicting_keys=['COORDINATE'])

        with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE),
                     mode="w",
                     encoding="utf-8") as fobj:
            try:
                fobj.write(inp.render())
            except ValueError as exc:
                six.raise_from(
                    InputValidationError(
                        "invalid keys or values in input parameters found"),
                    exc)

        settings = self.inputs.settings.get_dict(
        ) if 'settings' in self.inputs else {}

        # create code info
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings.pop(
            'cmdline', []) + ["-i", self._DEFAULT_INPUT_FILE]
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.join_files = True
        codeinfo.code_uuid = self.inputs.code.uuid

        # create calc info
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._DEFAULT_INPUT_FILE
        calcinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]

        # files or additional structures
        if 'file' in self.inputs:
            calcinfo.local_copy_list = []
            for name, obj in self.inputs.file.items():
                if isinstance(obj, SinglefileData):
                    calcinfo.local_copy_list.append(
                        (obj.uuid, obj.filename, obj.filename))
                elif isinstance(obj, StructureData):
                    self._write_structure(obj, folder, name + '.xyz')

        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE, self._DEFAULT_RESTART_FILE_NAME,
            self._DEFAULT_TRAJECT_FILE_NAME
        ]
        calcinfo.retrieve_list += settings.pop('additional_retrieve_list', [])

        # symlinks
        calcinfo.remote_symlink_list = []
        calcinfo.remote_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 self.inputs.code.computer.uuid == comp_uuid:  # if running on the same computer - make a symlink
                # if not - copy the folder
                calcinfo.remote_symlink_list.append(copy_info)
            else:
                calcinfo.remote_copy_list.append(copy_info)

        # check for left over settings
        if settings:
            raise InputValidationError(
                "The following keys have been found " +
                "in the settings input node {}, ".format(self.pk) +
                "but were not understood: " + ",".join(settings.keys()))

        return calcinfo
Exemple #7
0
    def prepare_for_submission(self, folder):
        """Create the input files from the input nodes passed to this instance of the `CalcJob`.

        :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """
        from .utils import Cp2kInput

        # create input structure
        if "structure" in self.inputs:
            self.inputs.structure.export(folder.get_abs_path(
                self._DEFAULT_COORDS_FILE_NAME),
                                         fileformat="xyz")

        # create cp2k input file
        inp = Cp2kInput(self.inputs.parameters.get_dict())
        inp.add_keyword("GLOBAL/PROJECT", self._DEFAULT_PROJECT_NAME)
        if "structure" in self.inputs:
            for i, letter in enumerate("ABC"):
                inp.add_keyword(
                    "FORCE_EVAL/SUBSYS/CELL/" + letter,
                    "{:<15} {:<15} {:<15}".format(
                        *self.inputs.structure.cell[i]),
                )
            topo = "FORCE_EVAL/SUBSYS/TOPOLOGY"
            inp.add_keyword(topo + "/COORD_FILE_NAME",
                            self._DEFAULT_COORDS_FILE_NAME)
            inp.add_keyword(topo + "/COORD_FILE_FORMAT", "XYZ")

        with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE),
                     mode="w",
                     encoding="utf-8") as fobj:
            try:
                inp.to_file(fobj)
            except ValueError as exc:
                six.raise_from(
                    InputValidationError(
                        "invalid keys or values in input parameters found"),
                    exc,
                )

        if "settings" in self.inputs:
            settings = self.inputs.settings.get_dict()
        else:
            settings = {}

        # create code info
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings.pop("cmdline", []) + [
            "-i",
            self._DEFAULT_INPUT_FILE,
        ]
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.join_files = True
        codeinfo.code_uuid = self.inputs.code.uuid

        # create calc info
        calcinfo = CalcInfo()
        calcinfo.stdin_name = self._DEFAULT_INPUT_FILE
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._DEFAULT_INPUT_FILE
        calcinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]

        # file lists
        calcinfo.remote_symlink_list = []
        if "file" in self.inputs:
            calcinfo.local_copy_list = []
            for fobj in self.inputs.file.values():
                calcinfo.local_copy_list.append(
                    (fobj.uuid, fobj.filename, fobj.filename))

        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE,
            self._DEFAULT_RESTART_FILE_NAME,
        ]
        calcinfo.retrieve_list += settings.pop("additional_retrieve_list", [])

        # symlinks
        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()
            symlink = (comp_uuid, remote_path,
                       self._DEFAULT_PARENT_CALC_FLDR_NAME)
            calcinfo.remote_symlink_list.append(symlink)

        # check for left over settings
        if settings:
            raise InputValidationError(
                "The following keys have been found " +
                "in the settings input node {}, ".format(self.pk) +
                "but were not understood: " + ",".join(settings.keys()))

        return calcinfo
Exemple #8
0
    def prepare_for_submission(self, folder):
        """Create the input files from the input nodes passed to this instance of the `CalcJob`.

        :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """

        # pylint: disable=too-many-statements,too-many-branches

        # Create cp2k input file.
        inp = Cp2kInput(self.inputs.parameters.get_dict())
        inp.add_keyword("GLOBAL/PROJECT", self._DEFAULT_PROJECT_NAME)

        # Create input structure(s).
        if 'structure' in self.inputs:
            # As far as I understand self.inputs.structure can't deal with tags
            # self.inputs.structure.export(folder.get_abs_path(self._DEFAULT_COORDS_FILE_NAME), fileformat="xyz")
            self._write_structure(self.inputs.structure, folder, self._DEFAULT_COORDS_FILE_NAME)

            # modify the input dictionary accordingly
            for i, letter in enumerate('ABC'):
                inp.add_keyword('FORCE_EVAL/SUBSYS/CELL/' + letter,
                                '{:<15} {:<15} {:<15}'.format(*self.inputs.structure.cell[i]),
                                override=False,
                                conflicting_keys=['ABC', 'ALPHA_BETA_GAMMA', 'CELL_FILE_NAME'])

            topo = "FORCE_EVAL/SUBSYS/TOPOLOGY"
            inp.add_keyword(topo + "/COORD_FILE_NAME", self._DEFAULT_COORDS_FILE_NAME, override=False)
            inp.add_keyword(topo + "/COORD_FILE_FORMAT", "XYZ", override=False, conflicting_keys=['COORDINATE'])

        if 'basissets' in self.inputs:
            validate_basissets(inp, self.inputs.basissets,
                               self.inputs.structure if 'structure' in self.inputs else None)
            write_basissets(inp, self.inputs.basissets, folder)

        if 'pseudos' in self.inputs:
            validate_pseudos(inp, self.inputs.pseudos, self.inputs.structure if 'structure' in self.inputs else None)
            write_pseudos(inp, self.inputs.pseudos, folder)

        # Kpoints.
        if 'kpoints' in self.inputs:
            try:
                mesh, _ = self.inputs.kpoints.get_kpoints_mesh()
            except AttributeError:
                raise InputValidationError("K-point sampling for SCF must be given in mesh form.")

            inp.add_keyword('FORCE_EVAL/DFT/KPOINTS', {'WAVEFUNCTIONS': ' COMPLEX', 'FULL_GRID': '.TRUE.'})
            inp.add_keyword('FORCE_EVAL/DFT/KPOINTS/SCHEME MONKHORST-PACK', f'{mesh[0]} {mesh[1]} {mesh[2]}')

        with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE), mode="w", encoding="utf-8") as fobj:
            try:
                fobj.write(inp.render())
            except ValueError as exc:
                raise InputValidationError("Invalid keys or values in input parameters found") from exc

        settings = self.inputs.settings.get_dict() if 'settings' in self.inputs else {}

        # Create code info.
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings.pop('cmdline', []) + ["-i", self._DEFAULT_INPUT_FILE]
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.join_files = True
        codeinfo.code_uuid = self.inputs.code.uuid

        # Create calc info.
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._DEFAULT_INPUT_FILE
        calcinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        calcinfo.codes_info = [codeinfo]

        # Files or additional structures.
        if 'file' in self.inputs:
            calcinfo.local_copy_list = []
            for name, obj in self.inputs.file.items():
                if isinstance(obj, SinglefileData):
                    calcinfo.local_copy_list.append((obj.uuid, obj.filename, obj.filename))
                elif isinstance(obj, StructureData):
                    self._write_structure(obj, folder, name + '.xyz')

        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE, self._DEFAULT_RESTART_FILE_NAME, self._DEFAULT_TRAJECT_FILE_NAME
        ]
        calcinfo.retrieve_list += settings.pop('additional_retrieve_list', [])

        # Symlinks.
        calcinfo.remote_symlink_list = []
        calcinfo.remote_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)

        # Check for left over settings.
        if settings:
            raise InputValidationError(
                f"The following keys have been found in the settings input node {self.pk}, but were not understood: " +
                ",".join(settings.keys()))

        return calcinfo
Exemple #9
0
    def prepare_for_submission(self, folder):
        """Create the input files from the input nodes passed to this instance of the `CalcJob`.

        :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """
        # from aiida_deepmd.utils import DpInput

        # create json input file
        # input = DpInput(self.inputs.model.get_dict(), self.inputs.learning_rate.get_dict(), self.inputs.loss.get_dict(), self.inputs.training.get_dict())
        input = dict()
        input['model'] = self.inputs.model.get_dict()
        input['learning_rate'] = self.inputs.learning_rate.get_dict()
        input['loss'] = self.inputs.loss.get_dict()
        input['training'] = self.inputs.training.get_dict()
        json_str = json.dumps(input, indent=4, sort_keys=False)

        with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE), mode="w", encoding="utf-8") as fobj:
            try:
                fobj.write(json_str)
            except ValueError as exc:
                raise InputValidationError("invalid keys or values in input parameters found")

        local_copy_list = []
        # Create the subfolder that will contain the train data
        folder.get_subfolder(self._TRAIN_DATA_SUBFOLDER, create=True)
        for fn in self.inputs.file:
            fobj = self.inputs.file[fn]
            src_path = fobj.filename
            dst_path = os.path.join(self._TRAIN_DATA_SUBFOLDER, fobj.filename)
            local_copy_list.append((fobj.uuid, src_path, dst_path))

        def create_array_from_files(files):
            for f in files:
                content = f.get_content()
                # function from aiida_ce
                pass
            return data_array

        # create train set and store the data in
        data_array = create_array_from_files(self.inputs.file)

        # for simplicity do not split the folder
        n = 0
        set_folder = folder.get_subfolder(os.path.join(self._TRAIN_DATA_SUBFOLDER, self._TRAIN_SET_PRFIX + str(n)), create=True)
        with io.open(set_folder.get_abs_path(coord.npy), mode="w") as fobj:
            try:
                np.dump(fobj, array=data_array)
            except ValueError as exc:
                raise InputValidationError("invalid keys or values in input parameters found")

        # settings = self.inputs.settings.get_dict() if 'settings' in self.inputs else {}

        # create code info
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = ["train", self._DEFAULT_INPUT_FILE]
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.join_files = True
        codeinfo.code_uuid = self.inputs.code.uuid

        # create calc info
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.cmdline_params = codeinfo.cmdline_params
        calcinfo.stdin_name = self._DEFAULT_INPUT_FILE
        calcinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        calcinfo.local_copy_list = local_copy_list
        calcinfo.codes_info = [codeinfo]

        calcinfo.retrieve_list = [
            # self._DEFAULT_OUTPUT_FILE,
            # self._DEFAULT_OUTPUT_INFO_FILE,
            # self._DEFAULT_CHECK_META_FILE,
            # self._DEFAULT_CHECK_INDEX_FILE,
        ]

        return calcinfo
    def prepare_for_submission(self, tempfolder):
        """
        Create the input files from the input nodes passed to this instance of the `CalcJob`.

        :param tempfolder: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """

        #####################################################
        # BEGINNING OF INITIAL INPUT CHECK                  #
        # All input ports that are defined via spec.input   #
        # are checked by default, only need to asses their  #
        # presence in case they are optional                #
        #####################################################

        code = self.inputs.code
        structure = self.inputs.structure
        parameters = self.inputs.parameters

        if 'kpoints' in self.inputs:
            kpoints = self.inputs.kpoints
        else:
            kpoints = None

        if 'basis' in self.inputs:
            basis = self.inputs.basis
        else:
            basis = None

        if 'settings' in self.inputs:
            settings = self.inputs.settings.get_dict()
            settings_dict = _uppercase_dict(settings, dict_name='settings')
        else:
            settings_dict = {}

        if 'bandskpoints' in self.inputs:
            bandskpoints = self.inputs.bandskpoints
        else:
            bandskpoints = None

        if 'parent_calc_folder' in self.inputs:
            parent_calc_folder = self.inputs.parent_calc_folder
        else:
            parent_calc_folder = None

        pseudos = self.inputs.pseudos
        kinds = [kind.name for kind in structure.kinds]
        if set(kinds) != set(pseudos.keys()):
            raise ValueError(
                'Mismatch between the defined pseudos and the list of kinds of the structure.\n',
                'Pseudos: {} \n'.format(', '.join(list(pseudos.keys()))),
                'Kinds: {}'.format(', '.join(list(kinds))),
            )

        # List of the file to copy in the folder where the calculation
        # runs, for instance pseudo files
        local_copy_list = []

        # List of files for restart
        remote_copy_list = []

        ##############################
        # END OF INITIAL INPUT CHECK #
        ##############################

        # ============== Preprocess of input parameters ===============
        # There should be a warning for duplicated (canonicalized) keys
        # in the original dictionary in the script

        input_params = FDFDict(parameters.get_dict())

        # Look for blocked keywords and
        # add the proper values to the dictionary
        for blocked_key in self._aiida_blocked_keywords:
            canonical_blocked = FDFDict.translate_key(blocked_key)
            for key in input_params:
                if key == canonical_blocked:
                    raise InputValidationError(
                        "You cannot specify explicitly the '{}' flag in the "
                        "input parameters".format(
                            input_params.get_last_key(key)))

        input_params.update({'system-name': self._PREFIX})
        input_params.update({'system-label': self._PREFIX})
        input_params.update({'use-tree-timer': 'T'})
        input_params.update({'xml-write': 'T'})
        input_params.update({'number-of-species': len(structure.kinds)})
        input_params.update({'number-of-atoms': len(structure.sites)})

        # Regarding the lattice-constant parameter:
        # -- The variable "alat" is not typically kept anywhere, and
        # has already been used to define the vectors.
        # We need to specify that the units of these vectors are Ang...
        input_params.update({'lattice-constant': '1.0 Ang'})
        # Note that this  will break havoc with the band-k-points "pi/a"
        # option. The use of this option should be banned.

        # Note that the implicit coordinate convention of the Structure
        # class corresponds to the "Ang" convention in Siesta.
        # That is why the "atomic-coordinates-format" keyword is blocked
        # and reset.
        input_params.update({'atomic-coordinates-format': 'Ang'})

        # ============== Preparation of input data ===============

        # ---------------- CELL_PARAMETERS ------------------------
        cell_parameters_card = "%block lattice-vectors\n"
        for vector in structure.cell:
            cell_parameters_card += ("{0:18.10f} {1:18.10f} {2:18.10f}"
                                     "\n".format(*vector))
        cell_parameters_card += "%endblock lattice-vectors\n"

        # --------------ATOMIC_SPECIES & PSEUDOS-------------------
        # I create the subfolder that will contain the pseudopotentials
        tempfolder.get_subfolder(self._PSEUDO_SUBFOLDER, create=True)
        # I create the subfolder with the output data
        tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True)

        atomic_species_card_list = []

        # Dictionary to get the atomic number of a given element
        datmn = dict([(v['symbol'], k) for k, v in six.iteritems(elements)])

        spind = {}
        spcount = 0
        for kind in structure.kinds:

            spcount += 1  # species count
            spind[kind.name] = spcount
            atomic_species_card_list.append("{0:5} {1:5} {2:5}\n".format(
                spind[kind.name], datmn[kind.symbol], kind.name.rjust(6)))

            ps = pseudos[kind.name]

            # Add this pseudo file to the list of files to copy, with
            # the appropiate name. In the case of sub-species
            # (different kind.name but same kind.symbol, e.g.,
            # 'C_surf', sharing the same pseudo with 'C'), we will
            # copy the file ('C.psf') twice, once as 'C.psf', and once
            # as 'C_surf.psf'.  This is required by Siesta.

            # ... list of tuples with format ('node_uuid', 'filename', relativedestpath')
            # We probably should be pre-pending 'self._PSEUDO_SUBFOLDER' in the
            # last slot, for generality...
            if isinstance(ps, PsfData):
                local_copy_list.append((ps.uuid, ps.filename,
                                        kind.name + ".psf"))
            elif isinstance(ps, PsmlData):
                local_copy_list.append((ps.uuid, ps.filename,
                                        kind.name + ".psml"))
            else:
                pass
                
        atomic_species_card_list = (["%block chemicalspecieslabel\n"] +
                                    list(atomic_species_card_list))
        atomic_species_card = "".join(atomic_species_card_list)
        atomic_species_card += "%endblock chemicalspecieslabel\n"
        # Free memory
        del atomic_species_card_list

        # --------------------- ATOMIC_POSITIONS -----------------------
        atomic_positions_card_list = [
            "%block atomiccoordinatesandatomicspecies\n"
        ]
        countatm = 0
        for site in structure.sites:
            countatm += 1
            atomic_positions_card_list.append(
                "{0:18.10f} {1:18.10f} {2:18.10f} {3:4} {4:6} {5:6}\n".format(
                    site.position[0], site.position[1], site.position[2],
                    spind[site.kind_name], site.kind_name.rjust(6), countatm))
        atomic_positions_card = "".join(atomic_positions_card_list)
        del atomic_positions_card_list  # Free memory
        atomic_positions_card += "%endblock atomiccoordinatesandatomicspecies\n"

        # -------------------- K-POINTS ----------------------------
        # It is optional, if not specified, gamma point only is performed,
        # this is default of siesta
        if kpoints is not None:
            #
            # Get a mesh for sampling
            # NOTE that there is not yet support for the 'kgrid-cutoff'
            # option in Siesta.
            #
            try:
                mesh, offset = kpoints.get_kpoints_mesh()
                has_mesh = True
            except AttributeError:
                raise InputValidationError("K-point sampling for scf "
                                           "must be given in mesh form")

            kpoints_card_list = ["%block kgrid_monkhorst_pack\n"]
            #
            # This will fail if has_mesh is False (for the case of a list),
            # since in that case 'offset' is undefined.
            #
            kpoints_card_list.append("{0:6} {1:6} {2:6} {3:18.10f}\n".format(
                mesh[0], 0, 0, offset[0]))
            kpoints_card_list.append("{0:6} {1:6} {2:6} {3:18.10f}\n".format(
                0, mesh[1], 0, offset[1]))
            kpoints_card_list.append("{0:6} {1:6} {2:6} {3:18.10f}\n".format(
                0, 0, mesh[2], offset[2]))

            kpoints_card = "".join(kpoints_card_list)
            kpoints_card += "%endblock kgrid_monkhorst_pack\n"
            del kpoints_card_list

        # ----------------- K-POINTS-FOR-BANDS ----------------------
        #Two possibility are supported in Siesta: BandLines ad BandPoints
        #At the moment the user can't choose directly one of the two options
        #BandsLine is set automatically if bandskpoints has labels,
        #BandsPoints if bandskpoints has no labels
        #BandLinesScale =pi/a is not supported at the moment because currently
        #a=1 always. BandLinesScale ReciprocalLatticeVectors is always set
        if bandskpoints is not None:
            bandskpoints_card_list = [
                "BandLinesScale ReciprocalLatticeVectors\n"
            ]
            if bandskpoints.labels == None:
                bandskpoints_card_list.append("%block BandPoints\n")
                for s in bandskpoints.get_kpoints():
                    bandskpoints_card_list.append(
                        "{0:8.3f} {1:8.3f} {2:8.3f} \n".format(
                            s[0], s[1], s[2]))
                fbkpoints_card = "".join(bandskpoints_card_list)
                fbkpoints_card += "%endblock BandPoints\n"
            else:
                bandskpoints_card_list.append("%block BandLines\n")
                savs = []
                listforbands = bandskpoints.get_kpoints()
                for s, m in bandskpoints.labels:
                    savs.append(s)
                rawindex = 0
                for s, m in bandskpoints.labels:
                    rawindex = rawindex + 1
                    x, y, z = listforbands[s]
                    if rawindex == 1:
                        bandskpoints_card_list.append(
                            "{0:3} {1:8.3f} {2:8.3f} {3:8.3f} {4:1} \n".format(
                                1, x, y, z, m))
                    else:
                        bandskpoints_card_list.append(
                            "{0:3} {1:8.3f} {2:8.3f} {3:8.3f} {4:1} \n".format(
                                s - savs[rawindex - 2], x, y, z, m))
                fbkpoints_card = "".join(bandskpoints_card_list)
                fbkpoints_card += "%endblock BandLines\n"
            del bandskpoints_card_list

        # ================ Operations for restart =======================

        # The presence of a 'parent_calc_folder' input node signals
        # that we want to get something from there, as indicated in the
        # self._restart_copy_from attribute.
        # In Siesta's case, for now, it is just the density-matrix file
        #
        # It will be copied to the current calculation's working folder.

        # NOTE: This mechanism is not flexible enough.
        # Maybe we should pass the information about which file(s) to
        # copy in the metadata 'options' dictionary
        if parent_calc_folder is not None:
            remote_copy_list.append(
                (parent_calc_folder.computer.uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              self._restart_copy_from), self._restart_copy_to))

            input_params.update({'dm-use-save-dm': "T"})

        # ====================== FDF file creation ========================

        # To have easy access to inputs metadata options
        metadataoption = self.inputs.metadata.options

        # input_filename = self.inputs.metadata.options.input_filename
        input_filename = tempfolder.get_abs_path(metadataoption.input_filename)

        with open(input_filename, 'w') as infile:
            # here print keys and values tp file

            # for k, v in sorted(six.iteritems(input_params)):
            for k, v in sorted(input_params.get_filtered_items()):
                infile.write("%s %s\n" % (k, v))

            # Basis set info is processed just like the general
            # parameters section. Some discipline is needed to
            # put any basis-related parameters (including blocks)
            # in the basis dictionary in the input script.
            #
            if basis is not None:
                infile.write("#\n# -- Basis Set Info follows\n#\n")
                for k, v in six.iteritems(basis.get_dict()):
                    infile.write("%s %s\n" % (k, v))

            # Write previously generated cards now
            infile.write("#\n# -- Structural Info follows\n#\n")
            infile.write(atomic_species_card)
            infile.write(cell_parameters_card)
            infile.write(atomic_positions_card)
            if kpoints is not None:
                infile.write("#\n# -- K-points Info follows\n#\n")
                infile.write(kpoints_card)
            if bandskpoints is not None:
                infile.write("#\n# -- Bandlines/Bandpoints Info follows\n#\n")
                infile.write(fbkpoints_card)

            # Write max wall-clock time
            infile.write("#\n# -- Max wall-clock time block\n#\n")
            infile.write("max.walltime {}".format(
                metadataoption.max_wallclock_seconds))

        # ====================== Code and Calc info ========================
        # Code information object and Calc information object are now
        # only used to set up the CMDLINE (the bash line that launches siesta)
        # and to set up the list of files to retrieve.

        cmdline_params = settings_dict.pop('CMDLINE', [])
        
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = list(cmdline_params)
        codeinfo.stdin_name = metadataoption.input_filename
        codeinfo.stdout_name = metadataoption.output_filename
        codeinfo.code_uuid = code.uuid
        
        calcinfo = CalcInfo()
        calcinfo.uuid = str(self.uuid)
        if cmdline_params:
            calcinfo.cmdline_params = list(cmdline_params)
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.stdin_name = metadataoption.input_filename
        calcinfo.stdout_name = metadataoption.output_filename
        calcinfo.codes_info = [codeinfo]
        # Retrieve by default: the output file, the xml file, the
        # messages file, and the json timing file.
        # If bandskpoints, also the bands file is added to the retrieve list.
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(metadataoption.output_filename)
        calcinfo.retrieve_list.append(self._DEFAULT_XML_FILE) 
        calcinfo.retrieve_list.append(self._DEFAULT_JSON_FILE) 
        calcinfo.retrieve_list.append(self._DEFAULT_MESSAGES_FILE) 
        if bandskpoints is not None:
            calcinfo.retrieve_list.append(self._DEFAULT_BANDS_FILE) 
        # Any other files specified in the settings dictionary
        settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST',
                                                   [])
        calcinfo.retrieve_list += settings_retrieve_list

        return calcinfo