Exemplo n.º 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: an `aiida.common.folders.Folder` to temporarily write files on disk
        :return: `aiida.common.datastructures.CalcInfo` instance
        """
        code = self.inputs.code  # an aiida Code
        parameters = self.inputs.parameters  # an aiida Dict

        input_dict = parameters.get_dict()  # a python dict
        if 'x1' not in input_dict or 'x2' not in input_dict:
            raise InputValidationError(
                'The input parameters node should contain both keys "x1" and "x2", '
                'but it doesn\'t.')

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

        input_filename = self.inputs.metadata.options.input_filename
        output_filename = self.inputs.metadata.options.output_filename

        # write all the input to a file
        with folder.open(input_filename, 'w') as infile:
            json.dump(input_dict, infile)

        # ============================ calcinfo ================================

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [output_filename]
        calcinfo.retrieve_temporary_list = [[
            'path/hugefiles*[0-9].xml', '.', '1'
        ]]

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = [input_filename, output_filename]
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Exemplo n.º 2
0
 def prepare_for_submission(self, folder):
     """
     The baseclass will only setup the basic calcinfo arguments but will
     not write **any** files which has to be implemented in the subclassed
     prepare_for_submission() method
     """
     # if no custodian code is defined directly run the VASP calculation,
     # i.e. initialize the CodeInfo for the passed VASP code
     if not self.inputs.custodian.get('code', False):
         codeinfo = CodeInfo()
         codeinfo.code_uuid = self.inputs.code.uuid
         codeinfo.stdout_name = self._default_output_file
         codeinfo.stderr_name = self._default_error_file
     # otherwise wrap in Custodian calculation and initialize CodeInfo for
     # the passed Custodian code (This is sufficient as AiiDA will scan all
     # Code-inputs to generate the required prepend / append lines)
     else:
         codeinfo = CodeInfo()
         codeinfo.code_uuid = self.inputs.custodian.code.uuid
         # define custodian-exe command line arguments
         codeinfo.cmdline_params = ['run', PluginDefaults.CSTDN_SPEC_FNAME]
         # never add the MPI command to custodian since it will call
         # VASP using MPI itself
         codeinfo.withmpi = False
     calcinfo = CalcInfo()
     calcinfo.uuid = self.uuid
     calcinfo.codes_info = [codeinfo]
     # those list are set defined in the inherited classes
     calcinfo.local_copy_list = []
     calcinfo.remote_copy_list = []
     calcinfo.remote_symlink_list = []
     # retrieve lists are defined on the base class
     calcinfo.retrieve_temporary_list = self.retrieve_temporary_list()
     calcinfo.retrieve_list = self.retrieve_permanent_list()
     # need to set run mode since presubmit() takes all code inputs into
     # account and would complain if both vasp and custodian codes are set
     calcinfo.codes_run_mode = CodeRunMode.SERIAL
     # finally write the neccessary calculation inputs to the calculation's
     # input folder
     calcinfo = self.create_calculation_inputs(folder, calcinfo)
     return calcinfo
Exemplo n.º 3
0
    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.CalcInfo` instance
        """
        # assert that the potential and structure have the same kind elements
        if self.inputs.potential.allowed_element_names is not None and not set(
            k.symbol for k in self.inputs.structure.kinds
        ).issubset(self.inputs.potential.allowed_element_names):
            raise ValidationError(
                "the structure and potential are not compatible (different kind elements)"
            )

        # Setup structure
        structure_txt, struct_transform = generate_lammps_structure(
            self.inputs.structure, self.inputs.potential.atom_style
        )

        with open(
            tempfolder.get_abs_path(self.options.cell_transform_filename), "w+b"
        ) as handle:
            np.save(handle, struct_transform)

        if "parameters" in self.inputs:
            parameters = self.inputs.parameters
        else:
            parameters = Dict()

        # Setup input parameters
        input_txt = self.create_main_input_content(
            parameter_data=parameters,
            potential_data=self.inputs.potential,
            kind_symbols=[kind.symbol for kind in self.inputs.structure.kinds],
            structure_filename=self._INPUT_STRUCTURE,
            trajectory_filename=self.options.trajectory_suffix,
            system_filename=self.options.system_suffix,
            restart_filename=self.options.restart_filename,
        )

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        with open(input_filename, "w") as infile:
            infile.write(input_txt)

        self.validate_parameters(parameters, self.inputs.potential)
        retrieve_list, retrieve_temporary_list = self.get_retrieve_lists()
        retrieve_list.extend(
            [self.options.output_filename, self.options.cell_transform_filename]
        )

        # prepare extra files if needed
        self.prepare_extra_files(tempfolder, self.inputs.potential)

        # =========================== dump to file =============================

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

        for name, content in self.inputs.potential.get_external_files().items():
            fpath = tempfolder.get_abs_path(name)
            with open(fpath, "w") as infile:
                infile.write(content)

        # ============================ calcinfo ================================

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = list(self._cmdline_params)
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.withmpi = self.metadata.options.withmpi
        codeinfo.stdout_name = self._stdout_name

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.retrieve_list = retrieve_list
        calcinfo.retrieve_temporary_list = retrieve_temporary_list
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Exemplo n.º 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
Exemplo n.º 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
Exemplo n.º 6
0
    def prepare_for_submission(self, folder):

        # create calculation info
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.codes_info = []
        calcinfo.retrieve_list = []
        calcinfo.retrieve_temporary_list = []
        calcinfo.prepend_text = "export GAUSS_MEMDEF=%dMB\n" % self.inputs.gauss_memdef

        calcinfo.local_copy_list = []

        if "stencil" in self.inputs:
            calcinfo.local_copy_list.append(
                (self.inputs.stencil.uuid, self.inputs.stencil.filename,
                 'stencil.txt'))

        for key, params in self.inputs.parameters.get_dict().items():

            cube_name = key + ".cube"
            kind_str = params["kind"]
            npts = params["npts"]

            # create code info
            codeinfo = CodeInfo()

            codeinfo.cmdline_params = []
            codeinfo.cmdline_params.append(
                str(self.inputs.metadata.options.resources['tot_num_mpiprocs'])
            )
            codeinfo.cmdline_params.append(kind_str)
            codeinfo.cmdline_params.append(self.PARENT_FOLDER_NAME + "/" +
                                           self.DEFAULT_INPUT_FILE)
            codeinfo.cmdline_params.append(cube_name)

            if npts == -1:
                if 'stencil' not in self.inputs:
                    self.report(
                        "Warning: npts: -1 set but no stencil provided, using -2"
                    )
                    codeinfo.cmdline_params.append("-2")
                else:
                    codeinfo.cmdline_params.append(str(npts))
                    codeinfo.stdin_name = "stencil.txt"
            else:
                codeinfo.cmdline_params.append(str(npts))

            codeinfo.code_uuid = self.inputs.code.uuid
            codeinfo.withmpi = self.inputs.metadata.options.withmpi

            calcinfo.codes_info.append(codeinfo)

            if self.inputs.retrieve_cubes.value:
                calcinfo.retrieve_list.append(cube_name)
            else:
                calcinfo.retrieve_temporary_list.append(cube_name)

        # symlink or copy to parent calculation
        calcinfo.remote_symlink_list = []
        calcinfo.remote_copy_list = []
        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
Exemplo n.º 7
0
    def prepare_for_submission(self, folder):
        """
        Routine to be called when create the input files and other stuff

        :param folder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        :param inputdict: a dictionary with the input nodes, as they would
                be returned by get_inputs_dict (without the Code!)
        """
        self.prepare_inputs()

        local_copy_list = []
        remote_copy_list = []
        remote_symlink_list = []

        require_parent = False
        for k in self.param_dict:
            if str(k).lower() in ["reuse", "continuation"]:
                require_parent = True
                break

        parent_calc_folder = self.inputs.get('parent_calc_folder')
        if parent_calc_folder is None and require_parent:
            raise InputValidationError(
                "No parent calculation folder passed"
                " for restart calculation using reuse/continuation")

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

        # Generate input file
        self.prepare_inputs(reset=True)

        if self._write_headers is True:
            cell_nodes = []
            for name, inp in self.inputs.items():
                if name in self._cell_links and inp:
                    cell_nodes.append([name, inp])

            # process pseudos
            for name, pseudo in self.inputs.pseudos.items():
                cell_nodes.append(['pseudo__{}'.format(name), pseudo])

            self.cell_file.header = self._generate_header_lines(cell_nodes)

            param_nodes = []
            for name, inp in self.inputs.items():
                if name in self._param_links and inp:
                    param_nodes.append([name, inp])

            self.param_file.header = self._generate_header_lines(param_nodes)

        local_copy_list.extend(self.local_copy_list_to_append)
        seedname = self.inputs.metadata.options.seedname

        cell_fn = seedname + ".cell"
        param_fn = seedname + ".param"

        with folder.open(cell_fn, mode='w') as incell:
            incell.write(self.cell_file.get_string())

        with folder.open(param_fn, mode="w") as inparam:
            inparam.write(self.param_file.get_string())

        # IMPLEMENT OPERATIONS FOR RESTART

        symlink = self.inputs.metadata.options.symlink_usage
        parent_calc_folder = self.inputs.get('parent_calc_folder', None)
        if parent_calc_folder:
            comp_uuid = parent_calc_folder.computer.uuid
            remote_path = parent_calc_folder.get_remote_path()
            if symlink:
                remote_list = remote_symlink_list
            else:
                remote_list = remote_copy_list
            remote_list.append(
                (comp_uuid, remote_path,
                 self.inputs.metadata.options.parent_folder_name))

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid

        # COPY/SYMLINK LISTS
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # SET UP extra CMDLINE arguments
        cmdline_params = self.settings_dict.pop("CMDLINE", [])

        # Extra parameters are added after the seed for CASTEP
        calcinfo.cmdline_params = [seedname] + list(cmdline_params)

        # CASTEP don't have any STDOUT etc when running calculations
        # Error is shown in the *.err file

        # Construct codeinfo instance
        codeinfo = CodeInfo()
        codeinfo.cmdline_params = [seedname] + list(cmdline_params)
        codeinfo.code_uuid = self.inputs.code.uuid

        calcinfo.codes_info = [codeinfo]

        # Retrieve by default the .castep file and the bands file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(seedname + ".castep")
        calcinfo.retrieve_list.append(seedname + ".bands")

        settings_retrieve_list = self.settings_dict.pop(
            "ADDITIONAL_RETRIEVE_LIST", [])
        calcinfo.retrieve_list.extend(settings_retrieve_list)

        calcinfo.retrieve_temporary_list = []
        calcinfo.retrieve_temporary_list.extend(
            self.settings_dict.pop("ADDITIONAL_RETRIEVE_TEMPORARY_LIST", []))

        calculation_mode = self.param_file.get("task", "singlepoint")

        # If we are doing geometryoptimisation retrieved the geom file and -out.cell file
        # dictionary for task specific file retrieve
        task_extra = self.retrieve_dict.get(calculation_mode.lower(), [])
        for suffix in task_extra:
            settings_retrieve_list.append(seedname + suffix)

        # Retrieve output cell  file if requested
        if self.param_file.get("write_cell_structure"):
            settings_retrieve_list.append(seedname + "-out.cell")

        calcinfo.retrieve_list += settings_retrieve_list
        calcinfo.retrieve_list += self._default_retrieve_list

        # Remove parser options in the setting dictionary
        # At the moment parser options are not used here

        if self.settings_dict:
            raise InputValidationError(
                "The following keys have been found in "
                "the settings input node, but were not understood: {}".format(
                    ",".join(list(self.settings_dict.keys()))))

        return calcinfo
Exemplo n.º 8
0
    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.CalcInfo` instance
        """
        # assert that the potential and structure have the same kind elements
        if [k.symbol for k in self.inputs.structure.kinds] != self.inputs.potential.kind_elements:
            raise ValidationError("the structure and potential are not compatible (different kind elements)")

        # Setup potential
        potential_txt = self.inputs.potential.get_potential_file()

        # Setup structure
        structure_txt, struct_transform = generate_lammps_structure(
            self.inputs.structure, self.inputs.potential.atom_style)

        with open(tempfolder.get_abs_path(self.options.cell_transform_filename), 'w+b') as handle:
            np.save(handle, struct_transform)

        if "parameters" in self.inputs:
            parameters = self.inputs.parameters
        else:
            parameters = Dict()
        pdict = parameters.get_dict()

        # Check lammps version date in parameters
        lammps_date = convert_date_string(
            pdict.get("lammps_version", '11 Aug 2017'))

        # Setup input parameters
        input_txt = self._generate_input_function(
            parameters=parameters,
            potential_obj=self.inputs.potential,
            structure_filename=self._INPUT_STRUCTURE,
            trajectory_filename=self.options.trajectory_name,
            info_filename=self.options.info_filename,
            restart_filename=self.options.restart_filename,
            add_thermo_keywords=pdict.get("thermo_keywords", []),
            version_date=lammps_date)

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        with open(input_filename, 'w') as infile:
            infile.write(input_txt)

        self.validate_parameters(parameters, self.inputs.potential)

        # prepare extra files if needed
        self.prepare_extra_files(tempfolder, self.inputs.potential)

        # =========================== dump to file =============================

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

        if potential_txt is not None:
            potential_filename = tempfolder.get_abs_path(
                self.inputs.potential.potential_filename)
            with open(potential_filename, 'w') as infile:
                infile.write(potential_txt)

        # ============================ calcinfo ================================

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = self._cmdline_params
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.withmpi = False  # Set lammps openmpi environment properly
        codeinfo.stdout_name = self._stdout_name

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.retrieve_list = self._retrieve_list + [
            self.options.output_filename,
            self.options.cell_transform_filename]
        calcinfo.retrieve_temporary_list = self._retrieve_temporary_list
        calcinfo.codes_info = [codeinfo]

        return calcinfo