Ejemplo n.º 1
0
    def prepare_for_submission(self, folder):
        #create box.npy, coord.npy, force.npy, energy.npy and stress.npy (if present)
        mother_folder = None
        write_dict = self.inputs.param.get_dict()
        if not 'systems' in write_dict:
            write_dict['systems'] = ['raw']
        if not 'set_prefix' in write_dict:
            write_dict['set_prefix'] = 'set'
        if not 'save_ckpt' in write_dict:
            write_dict['save_ckpt'] = 'model.ckpt'
        if not 'disp_file' in write_dict:
            write_dict['disp_file'] = 'lcurve.out'
        if 'restart_calculation_folder' in self.inputs:
            mother_folder = self.inputs.restart_calculation_folder

        symlink = []
        copy_list = []
        cmdline_params = [self.options.input_filename]
        if 'traj' in self.inputs:
            force = self.inputs.traj.get_array('forces')
            box = self.inputs.traj.get_array('cells')
            coord = self.inputs.traj.get_array('positions')
            energy = self.inputs.traj.get_array('scf_total_energy')
            #TODO: stress and scf_total_energy generic names for traj arrays
            nstep = force.shape[0]
            nfolders = int(nstep / int(self.inputs.nline_per_set))
            for i in range(nfolders):
                startidx = i * int(self.inputs.nline_per_set)
                stopidx = (i + 1) * int(
                    self.inputs.nline_per_set) if i + 1 < nfolders else nstep
                size = stopidx - startidx
                subfoldername = '{}/{}.{}'.format(write_dict['systems'][0],
                                                  write_dict['set_prefix'],
                                                  str(i).zfill(3))
                subfolder = folder.get_subfolder(subfoldername, create=True)

                def save_sliced_arr(fname, arr):
                    with subfolder.open(fname, mode='wb',
                                        encoding=None) as handle:
                        np.save(
                            handle, arr[startidx:stopidx].reshape(size, -1)
                            if len(arr.shape) > 1 else arr[startidx:stopidx])

                save_sliced_arr('box.npy', box)
                save_sliced_arr('coord.npy', coord)
                save_sliced_arr('energy.npy', energy)
                save_sliced_arr('force.npy', force)
            #write types of atoms
            def create_id(traj):
                l = []
                sp = {}
                nidx = 0
                for s in traj.symbols:
                    idx = sp.setdefault(s, nidx)
                    if idx == nidx: nidx = nidx + 1
                    l.append(idx)
                return l

            with folder.open(write_dict['systems'][0] + '/type.raw',
                             'w') as handle:
                np.savetxt(handle, create_id(self.inputs.traj))
        elif mother_folder is not None:
            #make symlink
            for system in write_dict['systems']:
                symlink.append(
                    (mother_folder.computer.uuid,
                     mother_folder.get_remote_path() + '/' + system, system))
            #copy checkpoint data
            copy_list.append(
                (mother_folder.computer.uuid, mother_folder.get_remote_path() +
                 '/' + write_dict['save_ckpt'] + '*', '.'))
            write_dict['load_ckpt'] = write_dict['save_ckpt']
            write_dict['restart'] = True
            #restart commandline option (the only one that is working for real?)
            cmdline_params.append('--restart={}'.format(
                write_dict['load_ckpt']))
        else:
            #error: where is the data??
            return self.exit_codes.ERROR_NO_TRAINING_DATA
        with folder.open(self.options.input_filename, 'w') as handle:
            json.dump(write_dict, handle)
        codeinfo = CodeInfo()
        codeinfo.code_uuid = self.inputs.code.uuid
        codeinfo.stdout_name = self.options.output_filename
        codeinfo.cmdline_params = cmdline_params

        calcinfo = CalcInfo()
        calcinfo.codes_info = [codeinfo]
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = copy_list
        calcinfo.remote_symlink_list = symlink

        #or self.metadata.options.output_filename?
        #calcinfo.retrieve_list = [
        #            (self.options.output_filename,'.',1),
        #            (write_dict['save_ckpt']+'*','.',1),
        #            (write_dict['disp_file'],'.',1)
        #          ]
        calcinfo.retrieve_list = [
            self.options.input_filename, self.options.output_filename,
            write_dict['save_ckpt'] + '*', write_dict['disp_file']
        ]

        return calcinfo
    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.
        """
        # pylint: disable=too-many-locals,too-many-statements,too-many-branches
        from aiida.common.utils import validate_list_of_string_tuples
        from aiida.common.exceptions import ValidationError

        code = self.inputs.code
        template = self.inputs.template.get_dict()

        try:
            parameters = self.inputs.parameters.get_dict()
        except AttributeError:
            parameters = {}

        input_file_template = template.pop('input_file_template', '')
        input_file_name = template.pop('input_file_name', None)
        output_file_name = template.pop('output_file_name', None)
        cmdline_params_tmpl = template.pop('cmdline_params', [])
        input_through_stdin = template.pop('input_through_stdin', False)
        files_to_copy = template.pop('files_to_copy', [])
        retrieve_temporary_files = template.pop('retrieve_temporary_files', [])

        if template:
            raise exceptions.InputValidationError(
                'The following keys could not be used in the template node: {}'.format(template.keys()))

        try:
            validate_list_of_string_tuples(files_to_copy, tuple_length=2)
        except ValidationError as exc:
            raise exceptions.InputValidationError('invalid file_to_copy format: {}'.format(exc))

        local_copy_list = []
        remote_copy_list = []

        for link_name, dest_rel_path in files_to_copy:
            try:
                fileobj = self.inputs.files[link_name]
            except AttributeError:
                raise exceptions.InputValidationError('You are asking to copy a file link {}, '
                                                      'but there is no input link with such a name'.format(link_name))
            if isinstance(fileobj, orm.SinglefileData):
                local_copy_list.append((fileobj.uuid, fileobj.filename, dest_rel_path))
            elif isinstance(fileobj, orm.RemoteData):  # can be a folder
                remote_copy_list.append((fileobj.computer.uuid, fileobj.get_remote_path(), dest_rel_path))
            else:
                raise exceptions.InputValidationError(
                    'If you ask to copy a file link {}, '
                    'it must be either a SinglefileData or a RemoteData; it is instead of type {}'.format(
                        link_name, fileobj.__class__.__name__))

        if input_file_name is not None and not input_file_template:
            raise exceptions.InputValidationError(
                'If you give an input_file_name, you must also specify a input_file_template')

        if input_through_stdin and input_file_name is None:
            raise exceptions.InputValidationError(
                'If you ask for input_through_stdin you have to specify a input_file_name')

        input_content = input_file_template.format(**parameters)
        if input_file_name:
            folder.create_file_from_filelike(io.StringIO(input_content), input_file_name, 'w', encoding='utf8')
        else:
            if input_file_template:
                self.logger.warning('No input file name passed, but a input file template is present')

        cmdline_params = [i.format(**parameters) for i in cmdline_params_tmpl]

        calcinfo = CalcInfo()
        calcinfo.retrieve_list = []
        calcinfo.retrieve_temporary_list = []

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = cmdline_params

        if input_through_stdin:
            codeinfo.stdin_name = input_file_name

        if output_file_name:
            codeinfo.stdout_name = output_file_name
            calcinfo.retrieve_list.append(output_file_name)

        if retrieve_temporary_files:
            calcinfo.retrieve_temporary_list = retrieve_temporary_files

        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 3
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.
        
        :param tempfolder: 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_inputdata_dict (without the Code!)
        """
        local_copy_list = []
        remote_copy_list = []

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "No code specified for this calculation")

        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError(
                "No parameters specified for this calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError(
                "parameters is not of type ParameterData")

        # Settings can be undefined, and defaults to an empty dictionary
        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")
            # Settings converted to uppercase
            settings_dict = _uppercase_dict(settings.get_dict(),
                                            dict_name='settings')

        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'),
                                           None)

        if parent_calc_folder is not None:
            if not isinstance(parent_calc_folder, self._parent_folder_type):
                if not isinstance(self._parent_folder_type, tuple):
                    possible_types = [self._parent_folder_type.__name__]
                else:
                    possible_types = [
                        t.__name__ for t in self._parent_folder_type
                    ]
                raise InputValidationError("parent_calc_folder, if specified,"
                                           "must be of type {}".format(
                                               " or ".join(possible_types)))

        following_text = self._get_following_text(inputdict, settings)

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

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

        # I put the first-level keys as uppercase (i.e., namelist and card names)
        # and the second-level keys as lowercase
        # (deeper levels are unchanged)
        input_params = _uppercase_dict(parameters.get_dict(),
                                       dict_name='parameters')
        input_params = {
            k: _lowercase_dict(v, dict_name=k)
            for k, v in input_params.iteritems()
        }

        # set default values. NOTE: this is different from PW/CP
        for blocked in self._blocked_keywords:
            namelist = blocked[0].upper()
            key = blocked[1].lower()
            value = blocked[2]

            if namelist in input_params:
                if key in input_params[namelist]:
                    raise InputValidationError(
                        "You cannot specify explicitly the '{}' key in the '{}' "
                        "namelist.".format(key, namelist))

            # set to a default
            if not input_params[namelist]:
                input_params[namelist] = {}
            input_params[namelist][key] = value

        # =================== NAMELISTS AND CARDS ========================
        try:
            namelists_toprint = settings_dict.pop('NAMELISTS')
            if not isinstance(namelists_toprint, list):
                raise InputValidationError(
                    "The 'NAMELISTS' value, if specified in the settings input "
                    "node, must be a list of strings")
        except KeyError:  # list of namelists not specified; do automatic detection
            namelists_toprint = self._default_namelists

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        with open(input_filename, 'w') as infile:
            for namelist_name in namelists_toprint:
                infile.write("&{0}\n".format(namelist_name))
                # namelist content; set to {} if not present, so that we leave an
                # empty namelist
                namelist = input_params.pop(namelist_name, {})
                for k, v in sorted(namelist.iteritems()):
                    infile.write(get_input_data_text(k, v))
                infile.write("/\n")

            # Write remaning text now, if any
            infile.write(following_text)

        # Check for specified namelists that are not expected
        if input_params:
            raise InputValidationError(
                "The following namelists are specified in input_params, but are "
                "not valid namelists for the current type of calculation: "
                "{}".format(",".join(input_params.keys())))

        # copy remote output dir, if specified
        if parent_calc_folder is not None:
            if isinstance(parent_calc_folder, RemoteData):
                parent_calc_out_subfolder = settings_dict.pop(
                    'PARENT_CALC_OUT_SUBFOLDER', self._INPUT_SUBFOLDER)
                remote_copy_list.append(
                    (parent_calc_folder.get_computer().uuid,
                     os.path.join(parent_calc_folder.get_remote_path(),
                                  parent_calc_out_subfolder),
                     self._OUTPUT_SUBFOLDER))
            elif isinstance(parent_calc_folder, FolderData):
                local_copy_list.append(
                    (parent_calc_folder.get_abs_path(self._INPUT_SUBFOLDER),
                     self._OUTPUT_SUBFOLDER))
            elif isinstance(parent_calc_folder, SinglefileData):
                filename = parent_calc_folder.get_file_abs_path()
                local_copy_list.append((filename, os.path.basename(filename)))

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = settings_dict.pop('CMDLINE', [])
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        # Retrieve by default the output file and the xml file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST',
                                                   [])
        calcinfo.retrieve_list += settings_retrieve_list
        calcinfo.retrieve_list += self._internal_retrieve_list

        calcinfo.retrieve_singlefile_list = self._retrieve_singlefile_list

        if settings_dict:
            try:
                Parserclass = self.get_parserclass()
                parser = Parserclass(self)
                parser_opts = parser.get_parser_settings_key()
                settings_dict.pop(parser_opts)
            except (
                    KeyError, AttributeError
            ):  # the key parser_opts isn't inside the dictionary, or it is set to None
                raise InputValidationError(
                    "The following keys have been found in "
                    "the settings input node, but were not understood: {}".
                    format(",".join(settings_dict.keys())))

        return calcinfo
Ejemplo n.º 4
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        from aiida.orm.data.cif import CifData
        from aiida.orm.data.parameter import ParameterData
        from aiida_codtools.calculations import commandline_params_from_dict
        import shutil

        try:
            cif = inputdict.pop(self.get_linkname('cif'))
        except KeyError:
            raise InputValidationError(
                "no CIF file is specified for deposition")
        if not isinstance(cif, CifData):
            raise InputValidationError("cif is not of type CifData")

        parameters = inputdict.pop(self.get_linkname('parameters'), None)
        if parameters is None:
            parameters = ParameterData(dict={})
        if not isinstance(parameters, ParameterData):
            raise InputValidationError(
                "parameters is not of type ParameterData")

        code = inputdict.pop(self.get_linkname('code'), None)
        if code is None:
            raise InputValidationError("No code found in input")

        parameters_dict = parameters.get_dict()

        deposit_file_rel = "deposit.cif"
        deposit_file_abs = tempfolder.get_abs_path(deposit_file_rel)
        shutil.copy(cif.get_file_abs_path(), deposit_file_abs)

        input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE)
        with open(input_filename, 'w') as f:
            f.write("{}\n".format(deposit_file_rel))
            f.flush()

        config_file_abs = tempfolder.get_abs_path(self._CONFIG_FILE)
        with open(config_file_abs, 'w') as f:
            for k in self._config_keys:
                if k in parameters_dict.keys():
                    f.write("{}={}\n".format(k, parameters_dict.pop(k)))
            f.flush()

        commandline_params = self._default_commandline_params
        commandline_params.extend(
            commandline_params_from_dict(parameters_dict))

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        # The command line parameters should be generated from 'parameters'
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE, self._DEFAULT_ERROR_FILE
        ]
        calcinfo.retrieve_singlefile_list = []

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = commandline_params
        codeinfo.stdin_name = self._DEFAULT_INPUT_FILE
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.stderr_name = self._DEFAULT_ERROR_FILE
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 5
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        try:
            parameters_data = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this calculation")

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("no structure is specified for this calculation")

        try:
            data_sets = inputdict.pop(self.get_linkname('data_sets'))
        except KeyError:
            raise InputValidationError("no data_set is specified for this calculation")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("no code is specified for this calculation")

        try:
            nac_data = inputdict.pop(self.get_linkname('nac_data'))
        except KeyError:
            nac_data = None


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

        # =================== prepare the python input files =====================

        cell_txt = structure_to_poscar(structure)
        input_txt = parameters_to_input_file(parameters_data)
        force_sets_txt = get_FORCE_SETS_txt(data_sets)

        # For future use (not actually used, test only)
        if nac_data is not  None:
            born_txt = get_BORN_txt(structure, parameters_data, nac_data)
            nac_filename = tempfolder.get_abs_path(self._INPUT_NAC)
            with open(nac_filename, 'w') as infile:
                infile.write(born_txt)

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

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

        cell_filename = tempfolder.get_abs_path(self._INPUT_CELL)
        with open(cell_filename, 'w') as infile:
            infile.write(cell_txt)

        force_sets_filename = tempfolder.get_abs_path(self._INPUT_FORCE_SETS)
        with open(force_sets_filename, 'w') as infile:
            infile.write(force_sets_txt)

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

        local_copy_list = []
        remote_copy_list = []
        #    additional_retrieve_list = settings_dict.pop("ADDITIONAL_RETRIEVE_LIST",[])

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        # Retrieve files
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = [self._INPUT_FILE_NAME, '--writefc']
        codeinfo.code_uuid = code.uuid
        codeinfo.withmpi = False
        calcinfo.codes_info = [codeinfo]
        return calcinfo
Ejemplo n.º 6
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        in_nodes = self._verify_inlinks(inputdict)
        params, structure, code, settings, local_copy_list, \
            parent_calc_folder = in_nodes

        # write cp2k input file
        inp = Cp2kInput(params)
        inp.add_keyword("GLOBAL/PROJECT", self._PROJECT_NAME)
        if structure is not None:
            struct_fn = tempfolder.get_abs_path(self._COORDS_FILE_NAME)
            structure.export(struct_fn, fileformat="xyz")
            for i, a in enumerate('ABC'):
                val = '{:<15} {:<15} {:<15}'.format(*structure.cell[i])
                inp.add_keyword('FORCE_EVAL/SUBSYS/CELL/' + a, val)
            topo = "FORCE_EVAL/SUBSYS/TOPOLOGY"
            inp.add_keyword(topo + "/COORD_FILE_NAME", self._COORDS_FILE_NAME)
            inp.add_keyword(topo + "/COORD_FILE_FORMAT", "XYZ")
        inp_fn = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        with open(inp_fn, "w") as f:
            f.write(inp.render())

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

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

        # file lists
        calcinfo.remote_symlink_list = []
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [
            self._OUTPUT_FILE_NAME, self._RESTART_FILE_NAME
        ]
        calcinfo.retrieve_list += settings.pop('additional_retrieve_list', [])

        # symlinks
        if parent_calc_folder is not None:
            comp_uuid = parent_calc_folder.get_computer().uuid
            remote_path = parent_calc_folder.get_remote_path()
            symlink = (comp_uuid, remote_path, self._PARENT_CALC_FOLDER_NAME)
            calcinfo.remote_symlink_list.append(symlink)

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

        return calcinfo
Ejemplo n.º 7
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        Create input files.

            :param tempfolder: aiida.common.folders.Folder subclass where
                the plugin should put all its files.
            :param inputdict: dictionary of the input nodes as they would
                be returned by get_inputs_dict
        """
        # Check inputdict
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this "
                                       "calculation")

        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this "
                                       "calculation")
        if not isinstance(parameters, DiffParameters):
            raise InputValidationError("parameters not of type "
                                       "DiffParameters")

        try:
            file1 = inputdict.pop(self.get_linkname('file1'))
        except KeyError:
            raise InputValidationError("Missing file1")
        if not isinstance(file1, SinglefileData):
            raise InputValidationError("file1 not of type SinglefileData")

        try:
            file2 = inputdict.pop(self.get_linkname('file2'))
        except KeyError:
            raise InputValidationError("Missing file2")
        if not isinstance(file2, SinglefileData):
            raise InputValidationError("file2 not of type SinglefileData")

        if inputdict:
            raise ValidationError("Unknown inputs besides DiffParameters")

        # Prepare CodeInfo object for aiida
        codeinfo = CodeInfo()
        codeinfo.code_uuid = code.uuid
        codeinfo.cmdline_params = parameters.cmdline_params(
            file1_name=file1.filename, file2_name=file2.filename)
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME

        # Prepare CalcInfo object for aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME]
        calcinfo.local_copy_list = [
            [file1.get_file_abs_path(), file1.filename],
            [file2.get_file_abs_path(), file2.filename],
        ]
        calcinfo.codes_info = [codeinfo]

        return calcinfo
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.
        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        ### ------------------------------------------------------
        ###  Input check

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "No code specified for this calculation")

        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError(
                "No parameters specified for this calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError(
                "parameters is not of type ParameterData")

        try:
            parent_slab_folder = inputdict.pop(
                self.get_linkname('parent_slab_folder'))
        except KeyError:
            raise InputValidationError(
                "No parent_slab_folder specified for this calculation")
        if not isinstance(parent_slab_folder, RemoteData):
            raise InputValidationError(
                "parent_slab_folder is not of type RemoteData")
        try:
            parent_mol_folder = inputdict.pop(
                self.get_linkname('parent_mol_folder'))
        except KeyError:
            raise InputValidationError(
                "No parent_mol_folder specified for this calculation")
        if not isinstance(parent_mol_folder, RemoteData):
            raise InputValidationError(
                "parent_mol_folder is not of type RemoteData")

        try:
            settings = inputdict.pop(self.get_linkname('settings'))
        except KeyError:
            raise InputValidationError(
                "No settings specified for this calculation")
        if not isinstance(settings, ParameterData):
            raise InputValidationError("settings is not of type ParameterData")
        settings_dict = settings.get_dict()

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

        ###  End of input check
        ### ------------------------------------------------------

        # create code info
        codeinfo = CodeInfo()
        codeinfo.code_uuid = code.uuid

        cmdline = []
        for key in parameters.dict:
            cmdline += [key]
            if parameters.dict[key] != '':
                if isinstance(parameters.dict[key], list):
                    cmdline += parameters.dict[key]
                else:
                    cmdline += [parameters.dict[key]]

        codeinfo.cmdline_params = cmdline

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

        # file lists
        calcinfo.remote_symlink_list = []
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []

        calcinfo.retrieve_list = settings_dict.pop('additional_retrieve_list',
                                                   [])

        # symlinks
        if parent_slab_folder is not None:
            comp_uuid = parent_slab_folder.get_computer().uuid
            remote_path = parent_slab_folder.get_remote_path()
            symlink = (comp_uuid, remote_path, "parent_slab_folder")
            calcinfo.remote_symlink_list.append(symlink)
        if parent_mol_folder is not None:
            comp_uuid = parent_mol_folder.get_computer().uuid
            remote_path = parent_mol_folder.get_remote_path()
            symlink = (comp_uuid, remote_path, "parent_mol_folder")
            calcinfo.remote_symlink_list.append(symlink)

        return calcinfo


# EOF
Ejemplo n.º 9
0
    def prepare_for_submission(self, folder):
        """
        This is the routine to be called when you want to create
        the input files for the inpgen with the plug-in.

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

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

        # first check existence of structure and if 1D, 2D, 3D
        structure = self.inputs.structure

        # check existence of parameters (optional)
        if 'parameters' in self.inputs:
            parameters = self.inputs.parameters
        else:
            parameters = None

        if parameters is None:
            # use default
            parameters_dict = {}
        else:
            parameters_dict = _lowercase_dict(parameters.get_dict(),
                                              dict_name='parameters')

        code = self.inputs.code

        # check existence of settings (optional)
        if 'settings' in self.inputs:
            settings = self.inputs.settings
        else:
            settings = None

        if settings is None:
            settings_dict = {}
        else:
            settings_dict = settings.get_dict()

        # check for for allowed keys, ignore unknown keys but warn.
        for key in settings_dict.keys():
            if key not in self._settings_keys:
                # TODO warning
                self.logger.info(
                    'settings dict key %s for Fleur calculation'
                    'not recognized, only %s are allowed.', key,
                    str(self._settings_keys))

        #######################################
        #### WRITE ALL CARDS IN INPUT FILE ####

        with folder.open(self._INPUT_FILE_NAME, 'w') as input_file:
            write_inpgen_file_aiida_struct(structure,
                                           input_file,
                                           input_params=parameters_dict,
                                           settings=settings_dict)

        # create a JUDFT_WARN_ONLY file in the calculation folder
        with io.StringIO('/n') as handle:
            warn_only_filename = self._JUDFT_WARN_ONLY_INFO_FILE_NAME
            folder.create_file_from_filelike(handle,
                                             filename=warn_only_filename,
                                             mode='w')

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # Retrieve per default only out file and inp.xml file?
        retrieve_list = []
        retrieve_list.append(self._INPXML_FILE_NAME)
        retrieve_list.append(self._OUTPUT_FILE_NAME)
        retrieve_list.append(self._SHELLOUT_FILE_NAME)
        retrieve_list.append(self._ERROR_FILE_NAME)
        retrieve_list.append(self._STRUCT_FILE_NAME)
        retrieve_list.append(self._INPUT_FILE_NAME)

        # user specific retrieve
        add_retrieve = settings_dict.get('additional_retrieve_list', [])
        for file1 in add_retrieve:
            retrieve_list.append(file1)

        remove_retrieve = settings_dict.get('remove_from_retrieve_list', [])
        for file1 in remove_retrieve:
            if file1 in retrieve_list:
                retrieve_list.remove(file1)

        calcinfo.retrieve_list = []
        for file1 in retrieve_list:
            calcinfo.retrieve_list.append(file1)

        codeinfo = CodeInfo()
        # , "-electronConfig"] # TODO? let the user decide -electronconfig?

        # We support different inpgen and fleur version via reading the version from the code node extras
        code_extras = code.extras
        code_version = code_extras.get('version', 32)
        if int(code_version) < 32:
            # run old inpgen
            cmdline_params = ['-explicit']
        else:
            cmdline_params = [
                '-explicit', '-inc', '+all', '-f',
                '{}'.format(self._INPUT_FILE_NAME)
            ]

        # user specific commandline_options
        for command in settings_dict.get('cmdline', []):
            cmdline_params.append(command)
        codeinfo.cmdline_params = (list(cmdline_params))

        codeinfo.code_uuid = code.uuid
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._SHELLOUT_FILE_NAME  # shell output will be piped in file
        codeinfo.stderr_name = self._ERROR_FILE_NAME  # std error too

        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 10
0
    def prepare_for_submission(self, folder):
        """
        This is the routine to be called when you make a FLEUR calculation.
        This routine checks the inputs and modifies copy lists accordingly.
        The standard files to be copied are given here.

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

        local_copy_list = []
        remote_copy_list = []
        remote_symlink_list = []
        mode_retrieved_filelist = []
        filelist_tocopy_remote = []
        settings_dict = {}

        has_fleurinp = False
        has_parent = False
        fleurinpgen = False
        copy_remotely = True
        with_hdf5 = False

        code = self.inputs.code

        codesdesc = code.description
        # TODO: ggf also check settings
        # In code description we write with what libs the code was compiled
        # we look for certain keywords in the description
        # also ggf, to be back comportable, the plugin should know the version number
        if codesdesc is not None:
            if 'hdf5' in codesdesc:
                with_hdf5 = True
            elif 'Hdf5' in codesdesc:
                with_hdf5 = True
            elif 'HDF5' in codesdesc:
                with_hdf5 = True
            else:
                with_hdf5 = False
        # a Fleur calc can be created from a fleurinpData alone
        # (then no parent is needed) all files are in the repo, but usually it is
        # a child of a inpgen calc or an other fleur calc (some or all files are
        # in a remote source). if the User has not changed something, the
        # calculation does not need theoretical a new FleurinpData it could use
        # the one from the parent, but the plug-in desgin is in a way that it has
        # to be there and it just copies files if changes occurred..

        if 'fleurinpdata' in self.inputs:
            fleurinp = self.inputs.fleurinpdata
        else:
            fleurinp = None

        if fleurinp is None:
            has_fleurinp = False
        else:
            has_fleurinp = True

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

        if parent_calc_folder is None:
            has_parent = False
            if not has_fleurinp:
                raise InputValidationError(
                    'No parent calculation found and no fleurinp data '
                    'given, need either one or both for a '
                    "'fleurcalculation'.")
        else:
            # extract parent calculation
            parent_calcs = parent_calc_folder.get_incoming(
                node_class=CalcJob).all()
            n_parents = len(parent_calcs)
            if n_parents != 1:
                raise UniquenessError(
                    'Input RemoteData is child of {} '
                    'calculation{}, while it should have a single parent'
                    ''.format(n_parents, '' if n_parents == 0 else 's'))
            parent_calc = parent_calcs[0].node
            parent_calc_class = parent_calc.process_class
            has_parent = True

            # check that it is a valid parent
            # self._check_valid_parent(parent_calc)

            # if inpgen calc do
            # check if folder from db given, or get folder from rep.
            # Parent calc does not has to be on the same computer.

            if parent_calc_class is FleurCalculation:
                new_comp = self.node.computer
                old_comp = parent_calc.computer
                if new_comp.uuid != old_comp.uuid:
                    # don't copy files, copy files locally
                    copy_remotely = False
            elif parent_calc_class is FleurinputgenCalculation:
                fleurinpgen = True
                new_comp = self.node.computer
                old_comp = parent_calc.computer
                if new_comp.uuid != old_comp.uuid:
                    # don't copy files, copy files locally
                    copy_remotely = False
            else:
                raise InputValidationError(
                    "parent_calc, must be either an 'inpgen calculation' or"
                    " a 'fleur calculation'.")

        # check existence of settings (optional)
        if 'settings' in self.inputs:
            settings = self.inputs.settings
        else:
            settings = None

        if settings is None:
            settings_dict = {}
        else:
            settings_dict = settings.get_dict()

        # check for for allowed keys, ignore unknown keys but warn.
        for key in settings_dict.keys():
            if key not in self._settings_keys:
                self.logger.warning(
                    'settings dict key %s for Fleur calculation'
                    'not recognized, only %s are allowed.'
                    '', key, str(self._settings_keys))

        # TODO: Detailed check of FleurinpData
        # if certain files are there in fleurinpData
        # from where to copy

        # file copy stuff TODO check in fleur input
        if has_fleurinp:
            # add files belonging to fleurinp into local_copy_list
            allfiles = fleurinp.files
            for file1 in allfiles:
                local_copy_list.append((fleurinp.uuid, file1, file1))
            modes = fleurinp.get_fleur_modes()

            # add files to mode_retrieved_filelist
            if modes['band']:
                mode_retrieved_filelist.append(self._BAND_FILE_NAME)
                mode_retrieved_filelist.append(self._BAND_GNU_FILE_NAME)
                if with_hdf5:
                    mode_retrieved_filelist.append(self._BANDDOS_FILE_NAME)
            if modes['dos']:
                mode_retrieved_filelist.append(self._DOS_FILE_NAME)
                if with_hdf5:
                    mode_retrieved_filelist.append(self._BANDDOS_FILE_NAME)
            if modes['relax']:
                # if l_f="T" retrieve relax.xml
                mode_retrieved_filelist.append(self._RELAX_FILE_NAME)
            if modes['ldau']:
                if with_hdf5:
                    mode_retrieved_filelist.append(
                        self._NMMPMAT_HDF5_FILE_NAME)
                else:
                    mode_retrieved_filelist.append(self._NMMPMAT_FILE_NAME)
            if modes['greensf']:
                if with_hdf5:
                    mode_retrieved_filelist.append(
                        self._GREENSF_HDF5_FILE_NAME)
            if modes['cf_coeff']:
                if with_hdf5:
                    mode_retrieved_filelist.append(self._CFDATA_HDF5_FILE_NAME)
                else:
                    self.logger.warning(
                        'CF calculation without HDF5 not supported '
                        'for automatic file retrieval.')
            if modes['force_theorem'] or modes['cf_coeff']:
                if 'remove_from_retrieve_list' not in settings_dict:
                    settings_dict['remove_from_retrieve_list'] = []
                if with_hdf5:
                    settings_dict['remove_from_retrieve_list'].append(
                        self._CDN_LAST_HDF5_FILE_NAME)
                else:
                    settings_dict['remove_from_retrieve_list'].append(
                        self._CDN1_FILE_NAME)

            # if noco, ldau, gw...
            # TODO: check from where it was copied, and copy files of its parent
            # if needed

        if has_parent:
            # copy necessary files
            # TODO: check first if file exist and throw a warning if not
            outfolder_uuid = parent_calc.outputs.retrieved.uuid
            self.logger.info('out folder path %s', outfolder_uuid)

            outfolder_filenames = [
                x.name for x in parent_calc.outputs.retrieved.list_objects()
            ]
            has_nmmpmat_file = self._NMMPMAT_FILE_NAME in outfolder_filenames
            if (self._NMMPMAT_FILE_NAME in outfolder_filenames or \
                self._NMMPMAT_HDF5_FILE_NAME in outfolder_filenames):
                if has_fleurinp:
                    if 'n_mmp_mat' in fleurinp.files:
                        self.logger.warning(
                            'Ignoring n_mmp_mat from fleurinp. '
                            'There is already an n_mmp_mat file '
                            'for the parent calculation')
                        local_copy_list.remove(
                            (fleurinp.uuid, 'n_mmp_mat', 'n_mmp_mat'))

            if fleurinpgen and (not has_fleurinp):
                for file1 in self._copy_filelist_inpgen:
                    local_copy_list.append(
                        (outfolder_uuid, os.path.join(file1),
                         os.path.join(file1)))
            elif not fleurinpgen and (not has_fleurinp):  # fleurCalc
                # need to copy inp.xml from the parent calc
                if with_hdf5:
                    copylist = self._copy_scf_hdf
                elif has_nmmpmat_file:
                    copylist = self._copy_scf_ldau_nohdf
                else:
                    copylist = self._copy_scf
                for file1 in copylist:
                    local_copy_list.append(
                        (outfolder_uuid, file1[0], file1[1]))
                # TODO: get inp.xml from parent fleurinpdata; otherwise it will be doubled in rep
            elif fleurinpgen and has_fleurinp:
                # everything is taken care of
                pass
            elif not fleurinpgen and has_fleurinp:
                # inp.xml will be copied from fleurinp
                if with_hdf5:
                    copylist = self._copy_scf_noinp_hdf
                elif has_nmmpmat_file:
                    copylist = self._copy_scf_ldau_noinp_nohdf
                else:
                    copylist = self._copy_scf_noinp
                for file1 in copylist:
                    local_copy_list.append(
                        (outfolder_uuid, file1[0], file1[1]))

            # TODO: not on same computer -> copy needed files from repository
            # if they are not there throw an error
            if copy_remotely:  # on same computer.
                filelist_tocopy_remote = filelist_tocopy_remote + self._copy_filelist_scf_remote
                # from settings, user specified
                # TODO: check if list?
                for file1 in settings_dict.get('additional_remotecopy_list',
                                               []):
                    filelist_tocopy_remote.append(file1)

                for file1 in settings_dict.get('remove_from_remotecopy_list',
                                               []):
                    if file1 in filelist_tocopy_remote:
                        filelist_tocopy_remote.remove(file1)

                for file1 in filelist_tocopy_remote:
                    remote_copy_list.append(
                        (parent_calc_folder.computer.uuid,
                         os.path.join(parent_calc_folder.get_remote_path(),
                                      file1), self._get_output_folder))

                self.logger.info('remote copy file list %s',
                                 str(remote_copy_list))

        # create a JUDFT_WARN_ONLY file in the calculation folder
        with io.StringIO('/n') as handle:
            warn_only_filename = self._JUDFT_WARN_ONLY_INFO_FILE_NAME
            folder.create_file_from_filelike(handle,
                                             filename=warn_only_filename,
                                             mode='w')

        ########## MAKE CALCINFO ###########

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        #cmdline_params = settings_dict.pop('CMDLINE', [])
        # calcinfo.cmdline_params = (list(cmdline_params)
        #                           + ["-in", self._INPUT_FILE_NAME])

        self.logger.info('local copy file list %s', str(local_copy_list))

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # Retrieve by default the output file and the xml file
        retrieve_list = []
        retrieve_list.append(self._OUTXML_FILE_NAME)
        if has_fleurinp:
            allfiles = fleurinp.files
            for file1 in allfiles:
                if file1.endswith('.xml'):
                    retrieve_list.append(file1)
        else:
            retrieve_list.append(self._INPXML_FILE_NAME)
        retrieve_list.append(self._SHELLOUTPUT_FILE_NAME)
        retrieve_list.append(self._ERROR_FILE_NAME)
        retrieve_list.append(self._USAGE_FILE_NAME)
        # retrieve_list.append(self._TIME_INFO_FILE_NAME)
        # retrieve_list.append(self._OUT_FILE_NAME)
        if with_hdf5:
            retrieve_list.append(self._CDN_LAST_HDF5_FILE_NAME)
        else:
            retrieve_list.append(self._CDN1_FILE_NAME)

        for mode_file in mode_retrieved_filelist:
            if mode_file not in retrieve_list:
                retrieve_list.append(mode_file)
        self.logger.info('retrieve_list: %s', str(retrieve_list))

        # user specific retrieve
        add_retrieve = settings_dict.get('additional_retrieve_list', [])
        self.logger.info('add_retrieve: %s', str(add_retrieve))
        for file1 in add_retrieve:
            retrieve_list.append(file1)

        remove_retrieve = settings_dict.get('remove_from_retrieve_list', [])
        for file1 in remove_retrieve:
            if file1 in retrieve_list:
                retrieve_list.remove(file1)

        calcinfo.retrieve_list = []
        for file1 in retrieve_list:
            calcinfo.retrieve_list.append(file1)

        codeinfo = CodeInfo()
        # should look like: codepath -xmlInput < inp.xml > shell.out 2>&1
        walltime_sec = self.node.get_attribute('max_wallclock_seconds')
        cmdline_params = []  # , "-wtime", "{}".format(walltime_sec)]"-xml"

        cmdline_params.append('-minimalOutput')

        if with_hdf5:
            cmdline_params.append('-last_extra')
            cmdline_params.append('-no_send')

        if walltime_sec:
            walltime_min = int(max(1, walltime_sec / 60))
            cmdline_params.append('-wtime')
            cmdline_params.append('{}'.format(int(walltime_min)))

        # user specific commandline_options
        for command in settings_dict.get('cmdline', []):
            cmdline_params.append(command)

        codeinfo.cmdline_params = list(cmdline_params)
        # + ["<", self._INPXML_FILE_NAME,
        # ">", self._SHELLOUTPUT_FILE_NAME, "2>&1"]
        codeinfo.code_uuid = code.uuid
        codeinfo.withmpi = self.node.get_attribute('withmpi')
        codeinfo.stdin_name = None  # self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._SHELLOUTPUT_FILE_NAME
        #codeinfo.join_files = True
        codeinfo.stderr_name = self._ERROR_FILE_NAME

        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 11
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.
        
        :param tempfolder: 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_inputdata_dict (without the Code!)
        """
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "No code specified for this calculation")

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

        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError(
                "No parameters specified for this calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError(
                "parameters is not of type ParameterData")

        try:
            qpoints = inputdict.pop(self.get_linkname('qpoints'))
        except KeyError:
            raise InputValidationError(
                "No qpoints specified for this calculation")
        if not isinstance(qpoints, KpointsData):
            raise InputValidationError("qpoints is not of type KpointsData")

        # Settings can be undefined, and defaults to an empty dictionary.
        # They will be used for any input that doen't fit elsewhere.
        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")
            # Settings converted to uppercase
            settings_dict = _uppercase_dict(settings.get_dict(),
                                            dict_name='settings')

        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'),
                                           None)
        if parent_calc_folder is None:
            raise InputValidationError(
                "No parent calculation found, needed to "
                "compute phonons")
        # TODO: to be a PwCalculation is not sufficient: it could also be a nscf
        # calculation that is invalid for phonons

        if not isinstance(parent_calc_folder, RemoteData):
            raise InputValidationError("parent_calc_folder, if specified,"
                                       "must be of type RemoteData")

        restart_flag = False
        # extract parent calculation
        parent_calcs = parent_calc_folder.get_inputs(node_type=JobCalculation)
        n_parents = len(parent_calcs)
        if n_parents != 1:
            raise UniquenessError("Input RemoteData is child of {} "
                                  "calculation{}, while it should have "
                                  "a single parent".format(
                                      n_parents,
                                      "" if n_parents == 0 else "s"))
        parent_calc = parent_calcs[0]
        # check that it is a valid parent
        self._check_valid_parent(parent_calc)

        if not isinstance(parent_calc, PwCalculation):
            restart_flag = True

        # Also, the parent calculation must be on the same computer
        new_comp = self.get_computer()
        old_comp = parent_calc.get_computer()
        if (not new_comp.uuid == old_comp.uuid):
            raise InputValidationError(
                "PhCalculation must be launched on the same computer"
                " of the parent: {}".format(old_comp.get_name()))

        # put by default, default_parent_output_folder = ./out
        try:
            default_parent_output_folder = parent_calc._OUTPUT_SUBFOLDER
        except AttributeError:
            try:
                default_parent_output_folder = parent_calc._get_output_folder()
            except AttributeError:
                raise InputValidationError("Parent of PhCalculation  does not "
                                           "have a default output subfolder")
        #os.path.join(
        #                   parent_calc.OUTPUT_SUBFOLDER,
        #                  '{}.save'.format(parent_calc.PREFIX))
        parent_calc_out_subfolder = settings_dict.pop(
            'PARENT_CALC_OUT_SUBFOLDER', default_parent_output_folder)

        # Here, there should be no other inputs
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

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

        # I put the first-level keys as uppercase (i.e., namelist and card names)
        # and the second-level keys as lowercase
        # (deeper levels are unchanged)
        input_params = _uppercase_dict(parameters.get_dict(),
                                       dict_name='parameters')
        input_params = {
            k: _lowercase_dict(v, dict_name=k)
            for k, v in input_params.iteritems()
        }

        prepare_for_d3 = settings_dict.pop('PREPARE_FOR_D3', False)
        if prepare_for_d3:
            self._blocked_keywords += [('INPUTPH', 'fildrho'),
                                       ('INPUTPH', 'drho_star%open'),
                                       ('INPUTPH', 'drho_star%ext'),
                                       ('INPUTPH', 'drho_star%dir')]

        # I remove unwanted elements (for the moment, instead, I stop; to change when
        # we setup a reasonable logging)
        for nl, flag in self._blocked_keywords:
            if nl in input_params:
                if flag in input_params[nl]:
                    raise InputValidationError(
                        "You cannot specify explicitly the '{}' flag in the '{}' "
                        "namelist or card.".format(flag, nl))

        # Set some variables (look out at the case! NAMELISTS should be uppercase,
        # internal flag names must be lowercase)
        if 'INPUTPH' not in input_params:
            raise InputValidationError(
                "No namelist INPUTPH found in input"
            )  # I cannot decide what to do in the calculation
        input_params['INPUTPH']['outdir'] = self._OUTPUT_SUBFOLDER
        input_params['INPUTPH']['iverbosity'] = 1  # in human language 1=high
        input_params['INPUTPH']['prefix'] = self._PREFIX
        input_params['INPUTPH'][
            'fildyn'] = self._OUTPUT_DYNAMICAL_MATRIX_PREFIX
        if prepare_for_d3:
            input_params['INPUTPH']['fildrho'] = self._DRHO_PREFIX
            input_params['INPUTPH']['drho_star%open'] = True
            input_params['INPUTPH']['drho_star%ext'] = self._DRHO_STAR_EXT
            input_params['INPUTPH']['drho_star%dir'] = self._FOLDER_DRHO

        # qpoints part
        try:
            mesh, offset = qpoints.get_kpoints_mesh()

            if any([i != 0. for i in offset]):
                raise NotImplementedError(
                    "Computation of phonons on a mesh with"
                    " non zero offset is not implemented, at the level of ph.x"
                )

            input_params["INPUTPH"]["ldisp"] = True
            input_params["INPUTPH"]["nq1"] = mesh[0]
            input_params["INPUTPH"]["nq2"] = mesh[1]
            input_params["INPUTPH"]["nq3"] = mesh[2]

            postpend_text = None

        except AttributeError:
            # this is the case where no mesh was set. Maybe it's a list
            try:
                list_of_points = qpoints.get_kpoints(cartesian=True)
            except AttributeError as e:
                # In this case, there are no info on the qpoints at all
                raise InputValidationError(
                    "Neither a qpoints mesh or a valid "
                    "list of qpoints was found in input", e.message)
            # change to 2pi/a coordinates
            lattice_parameter = numpy.linalg.norm(qpoints.cell[0])
            list_of_points *= lattice_parameter / (2. * numpy.pi)
            # add here the list of point coordinates
            if len(list_of_points) > 1:
                input_params["INPUTPH"]["qplot"] = True
                input_params["INPUTPH"]["ldisp"] = True
                postpend_text = "{}\n".format(len(list_of_points))
                for points in list_of_points:
                    postpend_text += "{}  {}  {}  1\n".format(*points)
                # Note: the weight is fixed to 1, because ph.x calls these
                # things weights but they are not such. If they are going to
                # exist with the meaning of weights, they will be supported
            else:
                input_params["INPUTPH"]["ldisp"] = False
                postpend_text = ""
                for points in list_of_points:
                    postpend_text += "{}  {}  {}\n".format(*points)

        # =================== NAMELISTS ========================

        # customized namelists, otherwise not present in the distributed ph code
        try:
            namelists_toprint = settings_dict.pop('NAMELISTS')
            if not isinstance(namelists_toprint, list):
                raise InputValidationError(
                    "The 'NAMELISTS' value, if specified in the settings input "
                    "node, must be a list of strings")
        except KeyError:  # list of namelists not specified in the settings; do automatic detection
            namelists_toprint = self._compulsory_namelists

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

        # create a folder for the dynamical matrices
        if not restart_flag:  # if it is a restart, it will be copied over
            tempfolder.get_subfolder(self._FOLDER_DYNAMICAL_MATRIX,
                                     create=True)

        with open(input_filename, 'w') as infile:
            infile.write('AiiDA calculation\n')
            for namelist_name in namelists_toprint:
                infile.write("&{0}\n".format(namelist_name))
                # namelist content; set to {} if not present, so that we leave an
                # empty namelist
                namelist = input_params.pop(namelist_name, {})
                for k, v in sorted(namelist.iteritems()):
                    infile.write(get_input_data_text(k, v))
                infile.write("/\n")

            # add list of qpoints if required
            if postpend_text is not None:
                infile.write(postpend_text)

            #TODO: write nat_todo

        if input_params:
            raise InputValidationError(
                "The following namelists are specified in input_params, but are "
                "not valid namelists for the current type of calculation: "
                "{}".format(",".join(input_params.keys())))

        # copy the parent scratch
        symlink = settings_dict.pop('PARENT_FOLDER_SYMLINK',
                                    _default_symlink_usage)  # a boolean
        if symlink:
            # I create a symlink to each file/folder in the parent ./out
            tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True)

            remote_symlink_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              parent_calc_out_subfolder,
                              "*"), self._OUTPUT_SUBFOLDER))

            # I also create a symlink for the ./pseudo folder
            # TODO: suppress this when the recover option of QE will be fixed
            # (bug when trying to find pseudo file)
            remote_symlink_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              self._get_pseudo_folder()),
                 self._get_pseudo_folder()))
            #pass
        else:
            # here I copy the whole folder ./out
            remote_copy_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              parent_calc_out_subfolder),
                 self._OUTPUT_SUBFOLDER))
            # I also copy the ./pseudo folder
            # TODO: suppress this when the recover option of QE will be fixed
            # (bug when trying to find pseudo file)
            remote_copy_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              self._get_pseudo_folder()),
                 self._get_pseudo_folder()))

        if restart_flag:  # in this case, copy in addition also the dynamical matrices
            if symlink:
                remote_symlink_list.append(
                    (parent_calc_folder.get_computer().uuid,
                     os.path.join(parent_calc_folder.get_remote_path(),
                                  self._FOLDER_DYNAMICAL_MATRIX),
                     self._FOLDER_DYNAMICAL_MATRIX))

            else:
                # copy the dynamical matrices
                remote_copy_list.append(
                    (parent_calc_folder.get_computer().uuid,
                     os.path.join(parent_calc_folder.get_remote_path(),
                                  self._FOLDER_DYNAMICAL_MATRIX), '.'))
                # no need to copy the _ph0, since I copied already the whole ./out folder

        # here we may create an aiida.EXIT file
        create_exit_file = settings_dict.pop('ONLY_INITIALIZATION', False)
        if create_exit_file:
            exit_filename = tempfolder.get_abs_path('{}.EXIT'.format(
                self._PREFIX))
            with open(exit_filename, 'w') as f:
                f.write('\n')

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        cmdline_params = settings_dict.pop('CMDLINE', [])

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = (list(cmdline_params) +
                                   ["-in", self._INPUT_FILE_NAME])
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        # Retrieve by default the output file and the xml file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        calcinfo.retrieve_list.append(self._FOLDER_DYNAMICAL_MATRIX)
        calcinfo.retrieve_list.append(
            os.path.join(self._OUTPUT_SUBFOLDER, '_ph0',
                         '{}.phsave'.format(self._PREFIX),
                         self._OUTPUT_XML_TENSOR_FILE_NAME))

        extra_retrieved = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', [])
        for extra in extra_retrieved:
            calcinfo.retrieve_list.append(extra)

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

        return calcinfo
Ejemplo n.º 12
0
    def _prepare_for_submission(self, tempfolder,
                                inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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!)
        """
        local_copy_list = []
        remote_copy_list = []
        remote_symlink_list = []

        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters is not of type ParameterData")

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("No structure specified for this calculation")
        if not isinstance(structure, StructureData):
            raise InputValidationError("structure is not of type StructureData")

        if self._use_kpoints:
            try:
                kpoints = inputdict.pop(self.get_linkname('kpoints'))
            except KeyError:
                raise InputValidationError("No kpoints specified for this calculation")
            if not isinstance(kpoints, KpointsData):
                raise InputValidationError("kpoints is not of type KpointsData")
        else:
            kpoints = None

        # Settings can be undefined, and defaults to an empty dictionary
        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError("settings, if specified, must be of "
                                           "type ParameterData")
            # Settings converted to uppercase
            settings_dict = _uppercase_dict(settings.get_dict(),
                                            dict_name='settings')

        pseudos = {}
        # I create here a dictionary that associates each kind name to a pseudo
        for link in inputdict.keys():
            if link.startswith(self._get_linkname_pseudo_prefix()):
                kindstring = link[len(self._get_linkname_pseudo_prefix()):]
                kinds = kindstring.split('_')
                the_pseudo = inputdict.pop(link)
                if not isinstance(the_pseudo, UpfData):
                    raise InputValidationError("Pseudo for kind(s) {} is not of "
                                               "type UpfData".format(",".join(kinds)))
                for kind in kinds:
                    if kind in pseudos:
                        raise InputValidationError("Pseudo for kind {} passed "
                                                   "more than one time".format(kind))
                    pseudos[kind] = the_pseudo

        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'), None)
        if parent_calc_folder is not None:
            if not isinstance(parent_calc_folder, RemoteData):
                raise InputValidationError("parent_calc_folder, if specified, "
                                           "must be of type RemoteData")

        vdw_table = inputdict.pop(self.get_linkname('vdw_table'), None)
        if vdw_table is not None:
            if not isinstance(vdw_table, SinglefileData):
                raise InputValidationError("vdw_table, if specified, "
                                           "must be of type SinglefileData")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this calculation")

        # Here, there should be no more parameters...
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(inputdict.keys()))

        # Check structure, get species, check peudos
        kindnames = [k.name for k in structure.kinds]
        if set(kindnames) != set(pseudos.keys()):
            err_msg = ("Mismatch between the defined pseudos and the list of "
                       "kinds of the structure. Pseudos: {}; kinds: {}".format(
                ",".join(pseudos.keys()), ",".join(list(kindnames))))
            raise InputValidationError(err_msg)

        ##############################
        # END OF INITIAL INPUT CHECK #
        ##############################
        # 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 (sometimes Quantum
        # Espresso codes crash if an empty folder is not already there
        tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True)

        # If present, add also the Van der Waals table to the pseudo dir
        # Note that the name of the table is not checked but should be the
        # one expected by QE.
        if vdw_table:
            local_copy_list.append(
                (
                vdw_table.get_file_abs_path(),
                os.path.join(self._PSEUDO_SUBFOLDER,
                    os.path.split(vdw_table.get_file_abs_path())[1])
                )
                )

        input_filecontent, local_copy_pseudo_list = self._generate_PWCPinputdata(parameters,settings_dict,pseudos,
                                                                                 structure,kpoints)
        local_copy_list += local_copy_pseudo_list

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        with open(input_filename, 'w') as infile:
            infile.write(input_filecontent)

        # operations for restart
        symlink = settings_dict.pop('PARENT_FOLDER_SYMLINK',
                                    self._default_symlink_usage)  # a boolean
        if symlink:
            if parent_calc_folder is not None:
                # I put the symlink to the old parent ./out folder
                remote_symlink_list.append(
                    (parent_calc_folder.get_computer().uuid,
                     os.path.join(parent_calc_folder.get_remote_path(),
                                  self._restart_copy_from),
                     self._restart_copy_to
                     ))
        else:
            # copy remote output dir, if specified
            if parent_calc_folder is not None:
                remote_copy_list.append(
                    (parent_calc_folder.get_computer().uuid,
                     os.path.join(parent_calc_folder.get_remote_path(),
                                  self._restart_copy_from),
                     self._restart_copy_to
                     ))

        # here we may create an aiida.EXIT file
        create_exit_file = settings_dict.pop('ONLY_INITIALIZATION', False)
        if create_exit_file:
            exit_filename = tempfolder.get_abs_path(
                '{}.EXIT'.format(self._PREFIX))
            with open(exit_filename, 'w') as f:
                f.write('\n')

        # Check if specific inputs for the ENVIRON module where specified
        environ_namelist = settings_dict.pop('ENVIRON', None)
        if environ_namelist is not None:
            if not isinstance(environ_namelist, dict):
                raise InputValidationError(
                    "ENVIRON namelist should be specified as a dictionary")
            # We first add the environ flag to the command-line options (if not already present)
            try:
                if '-environ' not in settings_dict['CMDLINE']:
                    settings_dict['CMDLINE'].append('-environ')
            except KeyError:
                settings_dict['CMDLINE'] = ['-environ']
            # To create a mapping from the species to an incremental fortran 1-based index
            # we use the alphabetical order as in the inputdata generation
            mapping_species = {sp_name: (idx+1) for idx, sp_name in 
                               enumerate(sorted([kind.name for kind in structure.kinds]))}
            environ_input_filename = tempfolder.get_abs_path(
                self._ENVIRON_INPUT_FILE_NAME)
            with open(environ_input_filename, 'w') as environ_infile:
                environ_infile.write("&ENVIRON\n")
                for k, v in sorted(environ_namelist.iteritems()):
                    environ_infile.write(
                        get_input_data_text(k, v, mapping=mapping_species))
                environ_infile.write("/\n")

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        cmdline_params = settings_dict.pop('CMDLINE', [])
        # we commented calcinfo.stin_name and added it here in cmdline_params
        # in this way the mpirun ... pw.x ... < aiida.in
        # is replaced by mpirun ... pw.x ... -in aiida.in
        # in the scheduler, _get_run_line, if cmdline_params is empty, it
        # simply uses < calcinfo.stin_name
        calcinfo.cmdline_params = (list(cmdline_params)
                                   + ["-in", self._INPUT_FILE_NAME])
        # calcinfo.stdin_name = self._INPUT_FILE_NAME
        # calcinfo.stdout_name = self._OUTPUT_FILE_NAME

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = (list(cmdline_params)
                                   + ["-in", self._INPUT_FILE_NAME])
        # calcinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # Retrieve by default the output file and the xml file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        calcinfo.retrieve_list.append(self._DATAFILE_XML)
        settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST',
                                                   [])

        if settings_dict.pop('ALSO_BANDS', False):
            # To retrieve also the bands data
            settings_retrieve_list.append([os.path.join(self._OUTPUT_SUBFOLDER,
                                                        self._PREFIX + '.save',
                                                        'K*[0-9]',
                                                        'eigenval*.xml'),
                                           '.',
                                           2])

        calcinfo.retrieve_list += settings_retrieve_list
        calcinfo.retrieve_list += self._internal_retrieve_list

        try:
            Parserclass = self.get_parserclass()
            parser = Parserclass(self)
            parser_opts = parser.get_parser_settings_key()
            settings_dict.pop(parser_opts)
        except (KeyError, AttributeError):
            # the key parser_opts isn't inside the dictionary
            pass

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

        return calcinfo
Ejemplo n.º 13
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        local_copy_list = []
        remote_copy_list = []

        # Process the settings dictionary first
        # Settings can be undefined, and defaults to an empty dictionary
        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")

            # Settings converted to UPPERCASE to standardize the usage and
            # avoid ambiguities
            settings_dict = _uppercase_dict(settings.get_dict(),
                                            dict_name='settings')

        # Parameters
        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this "
                                       "calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters is not of type "
                                       "ParameterData")

        # Singlefile
        singlefile = inputdict.pop(self.get_linkname('singlefile'), None)
        if singlefile is not None:
            if not isinstance(singlefile, SinglefileData):
                raise InputValidationError("singlefile, if specified,"
                                           "must be of type SinglefileData")

        # Parent calculation folder
        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'),
                                           None)
        if parent_calc_folder is not None:
            if not isinstance(parent_calc_folder, RemoteData):
                raise InputValidationError("parent_calc_folder, if specified,"
                                           "must be of type RemoteData")

        # Code
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "No code specified for this calculation")

        # Here, there should be no more input data
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

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

        input_params = parameters.get_dict()

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

        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)

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

            for k, v in sorted(input_params.iteritems()):
                infile.write(get_input_data_text(k, v))

        # = Additional files =====================================

        # Create the subfolder that will contain Gollum files
        tempfolder.get_subfolder(self._GFILES_SUBFOLDER, create=True)
        # Create the subfolder with the output data
        tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True)

        if singlefile is not None:
            lfile = singlefile.get_file_abs_path().split("path/", 1)[1]
            local_copy_list.append((singlefile.get_file_abs_path(),
                                    os.path.join(self._GFILES_SUBFOLDER,
                                                 lfile)))

        settings_local_copy_list = settings_dict.pop(
            'ADDITIONAL_LOCAL_COPY_LIST', [])
        if settings_local_copy_list is not None:
            for k in settings_local_copy_list:
                lfile = k.split("/")
                lf = './' + lfile[len(lfile) - 1]
                local_copy_list.append((unicode(k), unicode(lf)))

        # = Parent calculation folder ============================

        # 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 Gollum, partial.mat
        #
        # It will be copied to the current calculation's working folder

        if parent_calc_folder is not None:
            remote_copy_list.append(
                (parent_calc_folder.get_computer().uuid,
                 os.path.join(parent_calc_folder.get_remote_path(),
                              self._restart_copy_from), self._restart_copy_to))

        # = Calculation information and parameters ===============

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid

        cmdline_params = settings_dict.pop('CMDLINE', [])

        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 = self._INPUT_FILE_NAME
        calcinfo.stdout_name = self._OUTPUT_FILE_NAME
        calcinfo.messages_name = self._MESSAGES_FILE_NAME
        calcinfo.oc_name = self._OC_FILE_NAME
        calcinfo.ou_name = self._OU_FILE_NAME
        calcinfo.od_name = self._OD_FILE_NAME
        calcinfo.tt_name = self._TT_FILE_NAME
        calcinfo.tu_name = self._TU_FILE_NAME
        calcinfo.td_name = self._TD_FILE_NAME

        # = Code information object ==============================

        codeinfo = CodeInfo()
        #codeinfo.cmdline_params = list(cmdline_params)
        codeinfo.cmdline_params = [cmdline_params]
        #codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.messages_name = self._MESSAGES_FILE_NAME
        codeinfo.oc_name = self._OC_FILE_NAME
        codeinfo.ou_name = self._OU_FILE_NAME
        codeinfo.od_name = self._OD_FILE_NAME
        codeinfo.tt_name = self._TT_FILE_NAME
        codeinfo.tu_name = self._TU_FILE_NAME
        codeinfo.td_name = self._TD_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        # = Retrieve files =======================================

        # Retrieve by default: the output file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        calcinfo.retrieve_list.append(self._MESSAGES_FILE_NAME)
        calcinfo.retrieve_list.append(self._OC_FILE_NAME)
        calcinfo.retrieve_list.append(self._OU_FILE_NAME)
        calcinfo.retrieve_list.append(self._OD_FILE_NAME)
        calcinfo.retrieve_list.append(self._TT_FILE_NAME)
        calcinfo.retrieve_list.append(self._TU_FILE_NAME)
        calcinfo.retrieve_list.append(self._TD_FILE_NAME)

        # Any other files specified in the settings dictionary
        settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST',
                                                   [])
        calcinfo.retrieve_list += settings_retrieve_list

        # = Copy additional remote files =========================

        # Additional remote copy list for files like the EM or leads
        settings_remote_copy_list = settings_dict.pop(
            'ADDITIONAL_REMOTE_COPY_LIST', [])
        calcinfo.remote_copy_list += settings_remote_copy_list

        if settings_remote_copy_list and parent_calc_folder is None:
            raise ValueError("The definition of a parent calculation folder "
                             "is also needed when there is a remote copy list")
        for src_relative, dest_relative in settings_remote_copy_list:
            calcinfo.remote_copy_list.append([
                parent_calc_folder.get_computer().uuid, src_relative,
                dest_relative
            ])

        return calcinfo
Ejemplo n.º 14
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you make a fleur calculation
        Here should be checked if all the files are there to run fleur.
        And input files (inp.xml) can be modified.

        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        #   from aiida.common.utils import get_unique_filename, get_suggestion

        local_copy_list = []
        remote_copy_list = []
        remote_symlink_list = []
        mode_retrieved_filelist = []
        #filelocal_copy_list = []
        #filelist_tocopy = []
        filelist_tocopy_remote = []
        settings_dict = {}

        #fleur_calc = False
        #new_inp_file = False
        #ignore_mode = False
        has_fleurinp = False
        has_parent = False
        #restart_flag = False
        fleurinpgen = False
        copy_remotely = True

        ##########################################
        ############# INPUT CHECK ################
        ##########################################

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "No code specified for this calculation")

        # a Fleur calc can be created from a fleurinpData alone
        #(then no parent is needed) all files are in the repo, but usually it is
        # a child of a inpgen calc or an other fleur calc (some or all files are
        # in a remote source). if the User has not changed something, the
        #calculation does not need theoretical a new FleurinpData it could use
        #the one from the parent, but the plug-in desgin is in a way that it has
        # to be there and it just copies files if changes occured..

        fleurinp = inputdict.pop(self.get_linkname('fleurinpdata'), None)
        if fleurinp is None:
            #xml_inp_dict = {}
            has_fleurinp = False
        else:
            if not isinstance(fleurinp, FleurinpData):
                raise InputValidationError(
                    "The FleurinpData node given is not of type FleurinpData.")
            has_fleurinp = True
        parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'),
                                           None)
        #print parent_calc_folder
        if parent_calc_folder is None:
            has_parent = False
            if not has_fleurinp:
                raise InputValidationError(
                    "No parent calculation found and no fleurinp data "
                    "given, need either one or both for a "
                    "'fleurcalculation'.")
        else:  #
            if not isinstance(parent_calc_folder, RemoteData):
                raise InputValidationError("parent_calc_folder, if specified,"
                                           "must be of type RemoteData")

            # extract parent calculation
            parent_calcs = parent_calc_folder.get_inputs(
                node_type=JobCalculation)
            n_parents = len(parent_calcs)
            if n_parents != 1:
                raise UniquenessError(
                    "Input RemoteData is child of {} "
                    "calculation{}, while it should have a single parent"
                    "".format(n_parents, "" if n_parents == 0 else "s"))
            parent_calc = parent_calcs[0]
            has_parent = True
            #print parent_calc
            # check that it is a valid parent
            #self._check_valid_parent(parent_calc)

            # if inpgen calc do
            # check if folder from db given, or get folder from rep.
            # Parent calc does not has to be on the same computer.

            if isinstance(parent_calc, FleurCalculation):
                new_comp = self.get_computer()
                old_comp = parent_calc.get_computer()
                if new_comp.uuid != old_comp.uuid:
                    #dont copy files, copy files localy
                    copy_remotely = False
                    #raise InputValidationError(
                    #    "FleurCalculation must be launched on the same computer"
                    #    " of the parent: {}".format(old_comp.get_name()))
            elif isinstance(parent_calc, FleurinputgenCalculation):
                fleurinpgen = True
                new_comp = self.get_computer()
                old_comp = parent_calc.get_computer()
                if new_comp.uuid != old_comp.uuid:
                    #dont copy files, copy files localy
                    copy_remotely = False
            else:
                raise InputValidationError(
                    "parent_calc, must be either an 'inpgen calculation' or"
                    " a 'fleur calculation'.")

        # check existence of settings (optional)
        settings = inputdict.pop(self.get_linkname('settings'), None)
        #print('settings: {}'.format(settings))
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError(
                    "settings, if specified, must be of "
                    "type ParameterData")
            else:
                settings_dict = settings.get_dict()
        #check for for allowed keys, ignor unknown keys but warn.
        for key in settings_dict.keys():
            if key not in self._settings_keys:
                #TODO warrning
                self.logger.info("settings dict key {} for Fleur calculation"
                                 "not reconized, only {} are allowed."
                                 "".format(key, self._settings_keys))
        #print settings_dict
        # Here, there should be no other inputs
        if inputdict:
            raise InputValidationError("The following input data nodes are "
                                       "unrecognized: {}".format(
                                           inputdict.keys()))

        #TODO: Detailed check of FleurinpData
        # if certain files are there in fleurinpData.
        # from where to copy

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

        # file copy stuff TODO check in fleur input
        if has_fleurinp:
            self._DEFAULT_INPUT_FILE = fleurinp.get_file_abs_path(
                self._INPXML_FILE_NAME)

            #local_copy_list.append((
            #    fleurinp.get_file_abs_path(self._INPXML_FILE_NAME),
            #    self._INPXML_FILE_NAME))
            #copy ALL files from inp.xml
            allfiles = fleurinp.files
            for file1 in allfiles:
                local_copy_list.append(
                    (fleurinp.get_file_abs_path(file1), file1))
            modes = fleurinp.get_fleur_modes()

            # add files to mode_retrieved_filelist
            if modes['band']:
                mode_retrieved_filelist.append(self._BAND_FILE_NAME)
                mode_retrieved_filelist.append(self._BAND_GNU_FILE_NAME)
            if modes['dos']:
                mode_retrieved_filelist.append(self._DOS_FILE_NAME)
            if modes['forces']:
                print 'FORCES!!!'
                mode_retrieved_filelist.append(self._NEW_XMlINP_FILE_NAME)
                mode_retrieved_filelist.append(self._FORCE_FILE_NAME)
            if modes['ldau']:
                mode_retrieved_filelist.append(self._NMMPMAT_FILE_NAME)
            #if noco, ldau, gw...
            # TODO: check from where it was copied, and copy files of its parent
            # if needed
        #self.logger.info("@@@@@@@@@@@@@@@@@@@@@@@@has_parent {}".format(has_parent))

        if has_parent:
            # copy the right files #TODO check first if file, exist and throw
            # warning, now this will throw an error
            outfolderpath = parent_calc.out.retrieved.folder.abspath
            self.logger.info("out folder path {}".format(outfolderpath))

            #print outfolderpath
            if fleurinpgen and (not has_fleurinp):
                for file1 in self._copy_filelist_inpgen:
                    local_copy_list.append(
                        (os.path.join(outfolderpath, 'path',
                                      file1), os.path.join(file1)))
            elif not fleurinpgen and (not has_fleurinp):  # fleurCalc
                for file1 in self._copy_filelist_scf:
                    local_copy_list.append(
                        (os.path.join(outfolderpath, 'path',
                                      file1), os.path.join(file1)))
                filelist_tocopy_remote = filelist_tocopy_remote  # + self._copy_filelist_scf_remote
                #TODO get inp.xml from parent fleurinpdata, since otherwise it will be doubled in repo
            elif fleurinpgen and has_fleurinp:
                # everything is taken care of
                pass
            elif not fleurinpgen and has_fleurinp:
                # input file is already taken care of
                for file1 in self._copy_filelist_scf1:
                    local_copy_list.append(
                        (os.path.join(outfolderpath, 'path',
                                      file1), os.path.join(file1)))
                filelist_tocopy_remote = filelist_tocopy_remote  # + self._copy_filelist_scf_remote

            # TODO not on same computer -> copy needed files from repository,
            # if they are not there, throw error
            if copy_remotely:  # on same computer.
                #print('copy files remotely')

                # from fleurmodes
                if modes['pot8']:
                    filelist_tocopy_remote = filelist_tocopy_remote + self._copy_filelist_scf_remote
                    filelist_tocopy_remote.append(self._POT_FILE_NAME)
                #    #filelist_tocopy_remote.append(self._POT2_FILE_NAME)
                elif modes['dos']:
                    pass
                elif modes['band']:
                    pass
                else:
                    filelist_tocopy_remote = filelist_tocopy_remote + self._copy_filelist_scf_remote
                # from settings, user specified
                #TODO check if list?
                for file1 in settings_dict.get('additional_remotecopy_list',
                                               []):
                    filelist_tocopy_remote.append(file1)

                for file1 in settings_dict.get('remove_from_remotecopy_list',
                                               []):
                    if file1 in filelist_tocopy_remote:
                        filelist_tocopy_remote.remove(file1)

                for file1 in filelist_tocopy_remote:
                    remote_copy_list.append(
                        (parent_calc_folder.get_computer().uuid,
                         os.path.join(parent_calc_folder.get_remote_path(),
                                      file1), self._OUTPUT_FOLDER))
                #print remote_copy_list
                #self.logger.info("remote copy file list {}".format(remote_copy_list))

        ########## MAKE CALCINFO ###########

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        #cmdline_params = settings_dict.pop('CMDLINE', [])
        #calcinfo.cmdline_params = (list(cmdline_params)
        #                           + ["-in", self._INPUT_FILE_NAME])
        #print local_copy_list
        self.logger.info("local copy file list {}".format(local_copy_list))

        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list
        #(remotemachinename, remoteabspath, relativedestpath)
        calcinfo.remote_symlink_list = remote_symlink_list
        #calcinfo.stdout_name = self._OUTPUT_FILE_NAME

        # Retrieve by default the output file and the xml file
        retrieve_list = []
        retrieve_list.append(self._OUTXML_FILE_NAME)
        retrieve_list.append(self._INPXML_FILE_NAME)
        #calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        retrieve_list.append(self._SHELLOUTPUT_FILE_NAME)
        retrieve_list.append(self._CDN1_FILE_NAME)
        retrieve_list.append(self._ERROR_FILE_NAME)
        #calcinfo.retrieve_list.append(self._TIME_INFO_FILE_NAME)
        retrieve_list.append(self._OUT_FILE_NAME)
        #calcinfo.retrieve_list.append(self._INP_FILE_NAME)
        #calcinfo.retrieve_list.append(self._ENPARA_FILE_NAME)
        #calcinfo.retrieve_list.append(self._SYMOUT_FILE_NAME)
        #calcinfo.retrieve_list.append(self._KPTS_FILE_NAME)

        # if certain things are modefied, flags set,
        #other files should be retrieved, example DOS.x...
        #print "mode_retrieved_filelist", repr(mode_retrieved_filelist)
        for mode_file in mode_retrieved_filelist:
            retrieve_list.append(mode_file)
        #print('retrieve_list: {}'.format(retrieve_list))

        # user specific retrieve
        add_retrieve = settings_dict.get('additional_retrieve_list', [])
        #print('add_retrieve: {}'.format(add_retrieve))
        for file1 in add_retrieve:
            retrieve_list.append(file1)

        remove_retrieve = settings_dict.get('remove_from_retrieve_list', [])
        for file1 in remove_retrieve:
            if file1 in retrieve_list:
                retrieve_list.remove(file1)

        calcinfo.retrieve_list = []
        for file1 in retrieve_list:
            calcinfo.retrieve_list.append(file1)

        codeinfo = CodeInfo()
        # should look like: codepath -xmlInput < inp.xml > shell.out 2>&1
        walltime_sec = self.get_max_wallclock_seconds()
        #self.logger.info("!!!!!!!!!!!!!!!!!!! walltime_sec : {}"
        #                         "".format(walltime_sec))
        cmdline_params = ["-xml"]  #, "-wtime", "{}".format(walltime_sec)]
        #walltime_sec = self.get_max_wallclock_seconds()
        #print('walltime: {}'.format(walltime_sec))
        if walltime_sec:
            walltime_min = max(1, walltime_sec / 60)
            cmdline_params.append("-wtime")
            cmdline_params.append("{}".format(walltime_min))

        # user specific commandline_options
        for command in settings_dict.get('cmdline', []):
            cmdline_params.append(command)

        codeinfo.cmdline_params = list(cmdline_params)
        # + ["<", self._INPXML_FILE_NAME,
        # ">", self._SHELLOUTPUT_FILE_NAME, "2>&1"]
        codeinfo.code_uuid = code.uuid
        codeinfo.withmpi = self.get_withmpi()
        codeinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._SHELLOUTPUT_FILE_NAME
        #codeinfo.join_files = True
        codeinfo.stderr_name = self._ERROR_FILE_NAME

        calcinfo.codes_info = [codeinfo]
        '''
        # not needed in new version
        if fleurinpgen:# execute twice, as long start density stop
            codeinfo1 = CodeInfo()
            cmdline_params = ["-xmlInput"]
            codeinfo1.cmdline_params = list(cmdline_params)
            # + ["<", self._INPUT_FILE_NAME])#,
	        # ">",self._OUTPUT_FILE_NAME]
            codeinfo1.code_uuid = code.uuid
            codeinfo1.withmpi = self.get_withmpi()
            codeinfo1.stdin_name = self._INPUT_FILE_NAME
            codeinfo1.stdout_name = self._SHELLOUTPUT_FILE_NAME
            calcinfo.codes_info.append(codeinfo1)

        if settings_dict:
            raise InputValidationError("The following keys have been found in "
                "the settings input node, but were not understood: {}".format(
                ",".join(settings_dict.keys())))
        '''
        return calcinfo
Ejemplo n.º 15
0
    def _prepare_for_submission(self,tempfolder,inputdict):
        import numpy as np

        try:
            struct = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("no structure is specified for this calculation")
        if not isinstance(struct, StructureData):
            raise InputValidationError("struct is not of type StructureData")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("no code is specified for this calculation")

        atoms = struct.get_ase()

     
        parameters = inputdict.pop(self.get_linkname('parameters'), None)
        if parameters is None:
            parameters = ParameterData(dict={})
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters is not of type ParameterData")
        par = parameters.get_dict()

        charge= par.pop('CHARGE', '0')
        cpus=par.pop ('CPUS','1')
        mult= par.pop(' MULTIPLICITY', '1')
        basis = par.pop('BASIS','6-31G')
        jobtype = par.pop('JOB_TYPE','SP')
        dft_d=par.pop('DFT_D','FALSE')
        total=par.pop('MEM_TOTAL', '7500')
        method=par.pop('METHOD', 'HF')
        convergence=par.pop('SCF_CONVERGENCE', 'Tight')
        title=par.pop('TITLE', 'A generic title')
        cycles=par.pop('SCF_MAX_CYCLES', '50')
        integral=par.pop('INTEGRAL','Integral(Grid=UltraFine)') # Note this default will generated a pruned a grid with 99,590 points
        unrestricted=par.pop('UNRESTRICTED', 'R')
        add_cell = par.pop('add_cell',False)


        input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE)
        with open(input_filename,'w') as f:
            f.write('%Mem={}mb\n'.format(total))
            if method == 'PM6':
               f.write('#p {} {} \n'.format(method,jobtype))
            else:
               f.write('#p {}{}/{} {} {} SCF={}\n'.format(unrestricted,method,basis,jobtype,integral,convergence))
               if dft_d != 'FALSE':
                    f.write('EmpiricalDispersion={}\n'.format(dft_d))
            f.write('\n')
            f.write('{}\n'.format(title))
            f.write('\n')
            f.write('{} {} \n'.format(charge,mult))
            for i,atom_type in enumerate(atoms.get_chemical_symbols()):
                x='{0:.7f}'.format(float(atoms.get_positions()[i][0]))
                y='{0:.7f}'.format(float(atoms.get_positions()[i][1]))
                z='{0:.7f}'.format(float(atoms.get_positions()[i][2]))
                f.write(' {} {} {} {} \n'.format(atom_type,x,y,z))
            f.write('\n')
            f.flush()


        self._default_commandline_params = []

        commandline_params = self._default_commandline_params

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [self._DEFAULT_OUTPUT_FILE,
                                  self._DEFAULT_ERROR_FILE]
        calcinfo.retrieve_singlefile_list = []

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = commandline_params
        codeinfo.stdin_name = self._DEFAULT_INPUT_FILE
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.stderr_name = self._DEFAULT_ERROR_FILE
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 16
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        import numpy as np

        try:
            struct = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError(
                "no structure is specified for this calculation")
        if not isinstance(struct, StructureData):
            raise InputValidationError("struct is not of type StructureData")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "no code is specified for this calculation")

        atoms = struct.get_ase()

        lat_lengths = [
            (atoms.cell[0]**2).sum()**0.5,
            (atoms.cell[1]**2).sum()**0.5,
            (atoms.cell[2]**2).sum()**0.5,
        ]

        lat_angles = np.arccos([
            np.vdot(atoms.cell[1], atoms.cell[2]) / lat_lengths[1] /
            lat_lengths[2],
            np.vdot(atoms.cell[0], atoms.cell[2]) / lat_lengths[0] /
            lat_lengths[2],
            np.vdot(atoms.cell[0], atoms.cell[1]) / lat_lengths[0] /
            lat_lengths[1],
        ]) / np.pi * 180

        parameters = inputdict.pop(self.get_linkname('parameters'), None)
        if parameters is None:
            parameters = ParameterData(dict={})
        if not isinstance(parameters, ParameterData):
            raise InputValidationError(
                "parameters is not of type ParameterData")
        par = parameters.get_dict()

        abbreviation = par.pop('abbreviation', 'aiida_calc')
        title = par.pop('title', 'AiiDA NWChem calculation')
        basis = par.pop('basis', None)
        task = par.pop('task', 'scf')
        add_cell = par.pop('add_cell', True)

        if basis is None:
            basis = dict()
            for atom_type in set(atoms.get_chemical_symbols()):
                basis[atom_type] = 'library 6-31g'

        input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE)
        with open(input_filename, 'w') as f:
            f.write('start {}\ntitle "{}"\n\n'.format(abbreviation, title))
            f.write('geometry units au\n')
            if add_cell:
                f.write('  system crystal\n')
                f.write('    lat_a {}\n    lat_b {}\n    lat_c {}\n'.format(
                    *lat_lengths))
                f.write('    alpha {}\n    beta  {}\n    gamma {}\n'.format(
                    *lat_angles))
                f.write('  end\n')
            for i, atom_type in enumerate(atoms.get_chemical_symbols()):
                f.write('    {} {} {} {}\n'.format(
                    atom_type,
                    atoms.get_positions()[i][0],
                    atoms.get_positions()[i][1],
                    atoms.get_positions()[i][2]))
            f.write('end\nbasis\n')
            for atom_type, b in basis.iteritems():
                f.write('    {} {}\n'.format(atom_type, b))
            f.write('end\ntask {}\n'.format(task))
            f.flush()

        commandline_params = self._default_commandline_params

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [
            self._DEFAULT_OUTPUT_FILE, self._DEFAULT_ERROR_FILE
        ]
        calcinfo.retrieve_singlefile_list = []

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = commandline_params
        codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE
        codeinfo.stderr_name = self._DEFAULT_ERROR_FILE
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 17
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        inputs = dict(parameters=self.__prepare_parameters(inputdict),
                      force_field=self.__prepare_force_field(inputdict),
                      output=dict(population='progress.npy', append=False, best='best.yml'),
                      structures=[])

        species = inputs.get('force_field').get('species')
        copy_list = [(tempfolder.get_abs_path('aiida.yml'), '.')]
        
        tempfolder.get_subfolder('./data', create=True)
        
        formulas = {}
        for key in inputdict:
            if 'structure' in key:
                uuid = key.replace('structure_', '')
                pmg = inputdict.get(key).get_pymatgen()
                formula = pmg.formula.replace(' ', '')
                formulas.setdefault(formula, 0)
                filename = tempfolder.get_abs_path('./data/%s.%03d.npy' % (formula, formulas.get(formula)))
                formulas[formula] += 1
                
                with open(filename, 'wb') as file:
                    data = np.array([
                        (
                            species.index(str(site.specie)), 
                            0 if isinstance(site.specie, Element)
                            else site.specie.oxi_state, 
                            site.coords[0], 
                            site.coords[1], 
                            site.coords[2], 
                            forces[0], 
                            forces[1], 
                            forces[2]
                        )
                        for site, forces in zip(pmg, inputdict.get('forces_%s' % uuid).get_array('forces'))
                    ])
                    np.save(file, pmg.lattice.matrix)
                    np.save(file, data)
                    np.save(file, inputdict.get('energy_%s' % uuid).value)

                copy_list += [
                    (str(filename), './data')
                ]

        
        for formula, count in formulas.items():
            inputs.get('structures').append(dict(
                format=str('./data/%s.%%03d.npy' % formula),
                range=[0, count]
            ))
        
        with open(tempfolder.get_abs_path('aiida.yml'), 'w') as f:
            f.write(yaml.dump(inputs))

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = copy_list
        calcinfo.retrieve_list = [
            'progress.npy', 'best.yml'
        ]
        
        codeinfo = CodeInfo()
        codeinfo.code_uuid = inputdict.get('code').uuid
        codeinfo.cmdline_params = ['aiida.yml', 'genetic']
        codeinfo.stdout_name = 'aiida.stdout'
        codeinfo.stderr_name = 'aiida.stderr'

        calcinfo.codes_info = [codeinfo]

        import os

        for root, dirnames, filenames in os.walk(tempfolder.abspath):
            print root, dirnames, filenames
        
        return calcinfo
Ejemplo n.º 18
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        try:
            parameters_data = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            pass
            #raise InputValidationError("No parameters specified for this "
            #                           "calculation")
        if not isinstance(parameters_data, ParameterData):
            raise InputValidationError("parameters is not of type "
                                       "ParameterData")

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError(
                "no structure is specified for this calculation")

        try:
            trajectory = inputdict.pop(self.get_linkname('trajectory'))
        except KeyError:
            raise InputValidationError(
                "trajectory is specified for this calculation")

        try:
            force_constants = inputdict.pop(
                self.get_linkname('force_constants'))
        except KeyError:
            raise InputValidationError(
                "no force_constants is specified for this calculation")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError(
                "no code is specified for this calculation")

        time_step = trajectory.get_times()[1] - trajectory.get_times()[0]

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

        # =================== prepare the python input files =====================

        cell_txt = structure_to_poscar(structure)
        input_txt = parameters_to_input_file(parameters_data)
        force_constants_txt = get_FORCE_CONSTANTS_txt(force_constants)
        trajectory_txt = get_trajectory_txt(trajectory)

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

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

        cell_filename = tempfolder.get_abs_path(self._INPUT_CELL)
        with open(cell_filename, 'w') as infile:
            infile.write(cell_txt)

        force_constants_filename = tempfolder.get_abs_path(
            self._INPUT_FORCE_CONSTANTS)
        with open(force_constants_filename, 'w') as infile:
            infile.write(force_constants_txt)

        trajectory_filename = tempfolder.get_abs_path(self._INPUT_TRAJECTORY)
        with open(trajectory_filename, 'w') as infile:
            infile.write(trajectory_txt)

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

        local_copy_list = []
        remote_copy_list = []
        #    additional_retrieve_list = settings_dict.pop("ADDITIONAL_RETRIEVE_LIST",[])

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        # Retrieve files
        calcinfo.retrieve_list = [
            self._OUTPUT_FILE_NAME, self._OUTPUT_FORCE_CONSTANTS,
            self._OUTPUT_QUASIPARTICLES
        ]

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = [
            self._INPUT_FILE_NAME,
            self._INPUT_TRAJECTORY,
            '-ts',
            '{}'.format(time_step),
            '--silent',
            '-sfc',
            self._OUTPUT_FORCE_CONSTANTS,
            '-thm',  # '--resolution 0.01',
            '-psm',
            '2',
            '--normalize_dos',
            '-sdata'
        ]

        if 'temperature' in parameters_data.get_dict():
            codeinfo.cmdline_params.append('--temperature')
            codeinfo.cmdline_params.append('{}'.format(
                parameters_data.dict.temperature))

        if 'md_commensurate' in parameters_data.get_dict():
            if parameters_data.dict.md_commensurate:
                codeinfo.cmdline_params.append('--MD_commensurate')

        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.code_uuid = code.uuid
        codeinfo.withmpi = False
        calcinfo.codes_info = [codeinfo]
        return calcinfo
Ejemplo n.º 19
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        Create input files.

            :param tempfolder: aiida.common.folders.Folder subclass where
                the plugin should put all its files.
            :param inputdict: dictionary of the input nodes as they would
                be returned by get_inputs_dict
        """
        # Check inputdict
        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this "
                                       "calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters not of type "
                                       "ParameterData")
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this "
                                       "calculation")

        try:
            electronic_calc_folder = inputdict.pop('electronic_calc_folder', None)
        except:
            pass

        if inputdict:
            raise ValidationError("Unknown inputs besides ParameterData")

        # In this example, the input file is simply a json dict.
        # Adapt for your particular code!
        input_dict = parameters.get_dict()

        # Write input to file
        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        with open(input_filename, 'w') as infile:
            infile.write(input_render(input_dict))

        # Prepare CalcInfo to be returned to aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.remote_symlink_list = []
        calcinfo.retrieve_list = [
            self._OUTPUT_FILE_NAME,
            [self._ADDITIONAL_RETRIEVE_LIST, '.',0]
        ]

        # Electronic calc folder
        if electronic_calc_folder is not None:
            if not isinstance(electronic_calc_folder, RemoteData):
                msg = "electronic_calc_folder type not RemoteData"
                raise InputValidationError(msg)

            comp_uuid = electronic_calc_folder.get_computer().uuid
            remote_path = electronic_calc_folder.get_remote_path()+'/'+'aiida-ELECTRON_DENSITY-1_0.cube'
            symlink = (comp_uuid, remote_path, 'valence_density.cube')
            calcinfo.remote_symlink_list.append(symlink)

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

        return calcinfo
Ejemplo n.º 20
0
    def prepare_for_submission(self, tempfolder):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: an aiida.common.folders.Folder subclass
                           where the plugin should put all its files.
        """
        settings = {}
        if "settings" in self.inputs:
            settings = self.inputs.settings.get_dict()

        # validate that the structures and observables have the same keys
        struct_keys = set(self.inputs.structures.keys())
        observe_keys = set(self.inputs.observables.keys())
        if struct_keys != observe_keys:
            raise InputValidationError(
                "The structures and observables do not match: {} != {}".format(
                    struct_keys, observe_keys
                )
            )

        # validate number of fitting variables vs number of observables
        if len(observe_keys) < self.inputs.potential.number_of_variables:
            raise InputValidationError(
                "The number of observables supplied ({}) "
                "is less than the number of variables required to be fit ({})".format(
                    len(observe_keys), self.inputs.potential.number_of_variables
                )
            )

        content_lines, snames = create_input_lines(
            self.inputs.potential,
            self.inputs.structures,
            self.inputs.observables,
            observables=self.create_observable_map(settings),
            delta=settings.get("gradient_delta", None),
            dump_file=self.metadata.options.output_dump_file_name,
        )

        with tempfolder.open(self.metadata.options.input_file_name, "w") as f:
            f.write(six.ensure_text("\n".join(content_lines)))

        with tempfolder.open("structure_names.json", "w") as handle:
            handle.write(six.ensure_text(json.dumps(snames)))

        # Prepare CodeInfo object for aiida,
        # describes how a code has to be executed
        code = self.inputs.code
        codeinfo = CodeInfo()
        codeinfo.code_uuid = code.uuid
        codeinfo.stdin_name = self.metadata.options.input_file_name
        codeinfo.stdout_name = self.metadata.options.output_main_file_name
        codeinfo.stderr_name = self.metadata.options.output_stderr_file_name
        codeinfo.withmpi = self.metadata.options.withmpi

        # Prepare CalcInfo object for aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.codes_info = [codeinfo]
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [
            self.metadata.options.output_main_file_name,
            self.metadata.options.output_stderr_file_name,
            self.metadata.options.output_dump_file_name,
        ]
        calcinfo.retrieve_temporary_list = []

        return calcinfo
Ejemplo n.º 21
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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 (with the Code!)
        """
        import StringIO

        from aiida.orm.data.parameter import ParameterData
        from aiida.orm.data.singlefile import SinglefileData
        from aiida.orm.data.remote import RemoteData
        from aiida.common.utils import validate_list_of_string_tuples
        from aiida.common.exceptions import ValidationError

        parameters_node = inputdict.pop('parameters', None)
        if parameters_node is None:
            parameters = {}
        else:
            if not isinstance(parameters_node, ParameterData):
                raise InputValidationError("'parameters' data is not of type ParameterData")
            parameters = dict(parameters_node.iterattrs())

        template_node = inputdict.pop('template', None)
        if template_node is None:
            raise InputValidationError("No 'template' input data")
        if not isinstance(template_node, ParameterData):
            raise InputValidationError("'template' data is not of type ParameterData")
        template = dict(template_node.iterattrs())

        input_file_template = template.pop('input_file_template', "")
        input_file_name = template.pop('input_file_name', None)
        output_file_name = template.pop('output_file_name', None)
        cmdline_params_tmpl = template.pop('cmdline_params', [])
        input_through_stdin = template.pop('input_through_stdin', False)
        files_to_copy = template.pop('files_to_copy', [])

        if template:
            raise InputValidationError("The following keys could not be "
                                       "used in the template node: {}".format(
                template.keys()))

        try:
            validate_list_of_string_tuples(files_to_copy, tuple_length=2)
        except ValidationError as e:
            raise InputValidationError("invalid file_to_copy format: {}".format(e.message))

        local_copy_list = []
        remote_copy_list = []

        for link_name, dest_rel_path in files_to_copy:
            try:
                fileobj = inputdict.pop(link_name)
            except KeyError:
                raise InputValidationError("You are asking to copy a file link {}, "
                                           "but there is no input link with such a name".format(link_name))
            if isinstance(fileobj, SinglefileData):
                local_copy_list.append((fileobj.get_file_abs_path(), dest_rel_path))
            elif isinstance(fileobj, RemoteData):  # can be a folder
                remote_copy_list.append(
                    (fileobj.get_computer().uuid, fileobj.get_remote_path(), dest_rel_path)
                )
            else:
                raise InputValidationError("If you ask to copy a file link {}, "
                                           "it must be either a SinglefileData or a RemoteData; it is instead of type {}".format(
                    link_name, fileobj.__class__.__name__))

        code = inputdict.pop('code', None)
        if code is None:
            raise InputValidationError("No code in input")

        if len(inputdict) > 0:
            raise InputValidationError("The input nodes with the following labels could not be "
                                       "used by the templatereplacer plugin: {}".format(
                inputdict.keys()))

        if input_file_name is not None and not input_file_template:
            raise InputValidationError("If you give an input_file_name, you "
                                       "must also specify a input_file_template")

        if input_through_stdin and input_file_name is None:
            raise InputValidationError("If you ask for input_through_stdin you have to "
                                       "specify a input_file_name")

        input_file = StringIO.StringIO(input_file_template.format(**parameters))
        if input_file_name:
            tempfolder.create_file_from_filelike(input_file, input_file_name)
        else:
            if input_file_template:
                self.logger.warning("No input file name passed, but a input file template is present")

        cmdline_params = [i.format(**parameters) for i in cmdline_params_tmpl]

        calcinfo = CalcInfo()
        calcinfo.retrieve_list = []

        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = cmdline_params
        if input_through_stdin is not None:
            codeinfo.stdin_name = input_file_name
        if output_file_name:
            codeinfo.stdout_name = output_file_name
            calcinfo.retrieve_list.append(output_file_name)
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
Ejemplo n.º 22
0
    def _prepare_for_submission(self,tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.

        :param tempfolder: 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_inputdata_dict (without the Code!)
        """

        try:
            potential_data = inputdict.pop(self.get_linkname('potential'))
        except KeyError:
            raise InputValidationError("No potential specified for this "
                                       "calculation")

        if not isinstance(potential_data, ParameterData):
            raise InputValidationError("potential is not of type "
                                       "ParameterData")

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("no structure is specified for this calculation")

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("no code is specified for this calculation")

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

        # =================== prepare the python input files =====================

        potential_object = LammpsPotential(potential_data, structure, potential_filename=self._INPUT_POTENTIAL)


        structure_txt = generate_LAMMPS_structure(structure)
        input_txt = generate_LAMMPS_input(potential_object,
                                          structure_file=self._INPUT_STRUCTURE,
                                          trajectory_file=self._OUTPUT_TRAJECTORY_FILE_NAME,)

        potential_txt = potential_object.get_potential_file()
        # =========================== 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)

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

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

        local_copy_list = []
        remote_copy_list = []
    #    additional_retrieve_list = settings_dict.pop("ADDITIONAL_RETRIEVE_LIST",[])

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = remote_copy_list

        # Retrieve files
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_TRAJECTORY_FILE_NAME)
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = ['-in', self._INPUT_FILE_NAME]
        codeinfo.code_uuid = code.uuid
        codeinfo.withmpi = False
        calcinfo.codes_info = [codeinfo]
        return calcinfo
Ejemplo n.º 23
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.datastructures.CalcInfo` instance
        """
        # Check inputdict
        parameters = self.inputs.parameters

        if 'structure' in self.inputs:
            structure = self.inputs.structure
            found_structure = True
        else:
            found_structure = False

        vca_structure = False
        if found_structure:
            # for VCA: check if input structure and parameter node define VCA structure
            vca_structure = vca_check(structure, parameters)

        code = self.inputs.code

        # check if a parent folder containing a potential file (out_potential) is given
        if 'parent_KKR' in self.inputs:
            parent_calc_folder = self.inputs.parent_KKR
            found_parent = True
        else:
            found_parent = False

        if found_parent:
            # check if parent is either Voronoi or previous KKR calculation
            overwrite_potential, parent_calc = self._check_valid_parent(
                parent_calc_folder)

            #cross check if no structure was given and extract structure from parent
            if found_structure and not vca_structure:
                raise InputValidationError(
                    "parent_KKR and structure found in input. "
                    "Can only use either parent_KKR or structure in input.")
            else:
                structure_remote_KKR, voro_parent = self.find_parent_structure(
                    parent_calc)
                if not vca_structure:
                    structure = structure_remote_KKR
                else:
                    # check consistency of input vca structure and structure  from remote KKR folder
                    # TODO check consistency
                    pass
        else:
            overwrite_potential = False
            if not found_structure:
                raise InputValidationError(
                    "Neither structure nor parent_KKR specified for this "
                    "calculation")

        # check if overwrite potential is given explicitly
        if 'potential_overwrite' in self.inputs:
            potfile_overwrite = self.inputs.potential_overwrite
            has_potfile_overwrite = True
        else:
            has_potfile_overwrite = False

        if has_potfile_overwrite:
            overwrite_potential = True
            if not found_structure:
                raise InputValidationError(
                    "Input structure needed for this calculation "
                    "(using 'potential_overwrite' input node)")

        ###################################
        # Check for 2D case
        twoDimcheck, msg = check_2Dinput_consistency(structure, parameters)
        if not twoDimcheck:
            raise InputValidationError(msg)

        # Prepare inputcard from Structure and input parameter data
        input_file = tempfolder.open(self._INPUT_FILE_NAME, u'w')
        try:
            use_alat_input = parameters.get_dict().get('use_input_alat', False)
            natom, nspin, newsosol, warnings_write_inputcard = generate_inputcard_from_structure(
                parameters,
                structure,
                input_file,
                isvoronoi=True,
                vca_structure=vca_structure,
                use_input_alat=use_alat_input)
        except ValueError as e:
            raise InputValidationError(
                "Input Dict not consistent: {}".format(e))

        # Decide what files to copy
        local_copy_list = []
        if overwrite_potential:
            # copy the right files #TODO check first if file, exists and throw
            # warning, now this will throw an error
            if found_parent and self._is_KkrCalc(parent_calc):
                outfolder = parent_calc.outputs.retrieved  # copy from remote folder
                copylist = [parent_calc._OUT_POTENTIAL]
            elif has_potfile_overwrite:
                outfolder = potfile_overwrite  # copy from potential sfd
                copylist = [potfile_overwrite.filename]
            else:
                copylist = []

            for file1 in copylist:
                filename = file1
                if (found_parent
                        or has_potfile_overwrite) and file1 == copylist[0]:
                    filename = self._POTENTIAL_IN_OVERWRITE
                local_copy_list.append((outfolder.uuid, file1, filename))

        # Prepare CalcInfo to be returned to aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = local_copy_list
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [
            self._OUTPUT_FILE_NAME, self._ATOMINFO, self._RADII,
            self._SHAPEFUN, self._VERTICES, self._INPUT_FILE_NAME
        ]

        # pass on overwrite potential if this was given in input
        # (KkrCalculation checks if this file is there and takes this file instead of _OUT_POTENTIAL_voronoi
        #  if given)
        if overwrite_potential:
            calcinfo.retrieve_list += [self._POTENTIAL_IN_OVERWRITE]
        else:
            calcinfo.retrieve_list += [self._OUT_POTENTIAL_voronoi]

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = []
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
    def _prepare_for_submission(self, tempfolder, inputdict):

        settings = inputdict.pop(self.get_linkname('settings'), None)
        if settings is None:
            settings_dict = {}
        else:
            if not isinstance(settings, ParameterData):
                raise InputValidationError("settings, if specified, must be of "
                                           "type ParameterData")
            settings_dict = settings.get_dict()

        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this calculation")

        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters is not of type ParameterData")

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid
        # Empty command line by default
        cmdline_params = settings_dict.pop('CMDLINE', [])

        #calcinfo.stdin_name = self._INPUT_FILE_NAME
        #calcinfo.stdout_name = self._OUTPUT_FILE_NAME

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = list(cmdline_params)
        ##calcinfo.stdin_name = self._INPUT_FILE_NAME
        codeinfo.stdout_name = self._OUTPUT_FILE_NAME
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]
        #
        #calcinfo.remote_copy_list = remote_copy_list
        #calcinfo.remote_symlink_list = remote_symlink_list

        calcinfo.local_copy_list = []

        # Retrieve by default the output file and the xml file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME)
        calcinfo.retrieve_list.append("info.xml")
        #calcinfo.retrieve_list.append(self._DATAFILE_XML)
        #settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', [])

        try:
            structure = inputdict.pop(self.get_linkname('structure'))
        except KeyError:
            raise InputValidationError("No structure specified for this calculation")
        if not isinstance(structure, StructureData):
            raise InputValidationError("structure is not of type StructureData")

        try:
            kpoints = inputdict.pop(self.get_linkname('kpoints'))
        except KeyError:
            raise InputValidationError("No kpoints specified for this calculation")
        if not isinstance(kpoints, KpointsData):
            raise InputValidationError("kpoints is not of type KpointsData")

        kmesh, koffset = kpoints.get_kpoints_mesh()
        
        lapw_basis_list = {}
        for link in inputdict.keys():
            if link.startswith("lapwbasis_"):
                kindstring = link[len("lapwbasis_"):]
                lapw_basis_list[kindstring] = inputdict.pop(link)

        import xml.etree.ElementTree as ET
        root = ET.Element("input")
        ET.SubElement(root, "title").text = "input file created with AiiDA"
        struct = ET.SubElement(root, "structure", attrib={'speciespath' : './', 'autormt' : 'true'})
        cryst = ET.SubElement(struct, "crystal", attrib={'scale' : '1.889725989'})

        from numpy import matrix
        lat_vec = matrix(structure.cell)
        inv_lat_vec = lat_vec.T.I;

        for vector in structure.cell:
            ET.SubElement(cryst, "basevect").text = " ".join(['%18.10f'%e for e in vector])

        for kind in structure.kinds:
            lapw_basis = lapw_basis_list[kind.symbol]
            calcinfo.local_copy_list.append((lapw_basis.get_file_abs_path(), lapw_basis.filename))

            s = ET.SubElement(struct, "species", attrib={'speciesfile' : lapw_basis.filename})
            for site in structure.sites:
                if site.kind_name == kind.name:
                    pos_cart = matrix(site.position)
                    pos_lat = inv_lat_vec * pos_cart.T
                    ET.SubElement(s, "atom", attrib={'coord' : " ".join(['%18.10f'%e for e in pos_lat])})
       
        parameters_dict = parameters.get_dict()
        groundstate_attrib = {}

        if 'groundstate' in parameters_dict:
            groundstate_attrib = parameters_dict['groundstate']
        groundstate_attrib['ngridk'] = " ".join(['%i'%e for e in kmesh])

#        ET.SubElement(root, "groundstate", attrib=groundstate_attrib)

        grnd = ET.SubElement(root, "groundstate", attrib=groundstate_attrib)
        solver_attrib = {}
        if 'solver' in parameters_dict:
            solver_attrib = parameters_dict['solver']
            ET.SubElement(grnd, "solver", attrib=solver_attrib)

        sirius_attrib = {}
        if 'sirius' in parameters_dict:
            sirius_attrib = parameters_dict['sirius']
            ET.SubElement(grnd, "sirius", attrib=sirius_attrib)

        libxc_attrib = {}
        if 'libxc' in parameters_dict:
            libxc_attrib = parameters_dict['libxc']
            ET.SubElement(grnd, "libxc", attrib=libxc_attrib)

        tree = ET.ElementTree(root)
        tree.write(tempfolder.get_abs_path("input.xml"))

        return calcinfo
Ejemplo n.º 25
0
    def prepare_for_submission(self, tempfolder):

        _dbs_accepted = {
            'gw0': 'ndb.QP',
            'HF_and_locXC': 'ndb.HF_and_locXC',
        }

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

        # Settings can be undefined, and defaults to an empty dictionary.
        # They will be used for any input that doen't fit elsewhere.

        settings = self.inputs.settings.get_dict()

        initialise = settings.pop('INITIALISE', None)
        if initialise is not None:
            if not isinstance(initialise, bool):
                raise InputValidationError("INITIALISE must be " " a boolean")

        copy_save = settings.pop('COPY_SAVE', None)
        if copy_save is not None:
            if not isinstance(copy_save, bool):
                raise InputValidationError("COPY_SAVE must be " " a boolean")

        copy_dbs = settings.pop('COPY_DBS', None)
        if copy_dbs is not None:
            if not isinstance(copy_dbs, bool):
                raise InputValidationError("COPY_DBS must be " " a boolean")

        restart_yambo = settings.pop('RESTART_YAMBO', None)
        if restart_yambo is not None:
            if not isinstance(restart_yambo, bool):
                raise InputValidationError("RESTART_YAMBO must be "
                                           " a boolean")

        parameters = self.inputs.parameters

        if not initialise:
            if not isinstance(parameters, Dict):
                raise InputValidationError("parameters is not of type Dict")

        parent_calc_folder = self.inputs.parent_folder

        main_code = self.inputs.code

        preproc_code = self.inputs.preprocessing_code

        parent_calc = take_calc_from_remote(parent_calc_folder)

        if parent_calc.process_type == 'aiida.calculations:yambo.yambo':
            yambo_parent = True
        else:
            yambo_parent = False

        # flags for yambo interfaces
        try:
            precode_param_dict = self.inputs.precode_parameters
        except:
            precode_param_dict = Dict(dict={})
        # check the precode parameters given in input
        input_cmdline = settings.pop('CMDLINE', None)
        import re
        precode_params_list = [
        ]  #['cd aiida.save'] ##.format(parent_calc_folder._PREFIX)
        pattern = re.compile(r"(^\-)([a-zA-Z])")
        for key, value in six.iteritems(precode_param_dict.get_dict()):
            if re.search(pattern, key) is not None:
                if key == '-O' or key == '-H' or key == '-h' or key == '-F':
                    raise InputValidationError(
                        "Precode flag {} is not allowed".format(str(key)))
                else:
                    if precode_param_dict[key] is True:
                        precode_params_list.append(str(key))
                    elif precode_param_dict[key] is False:
                        pass
                    else:
                        precode_params_list.append('{}'.format(str(key)))
                        precode_params_list.append('{}'.format(str(value)))
            else:
                raise InputValidationError(
                    "Wrong format of precode_parameters")
        # Adding manual cmdline input (e.g. for DB fragmentation)
        if input_cmdline is not None:
            precode_params_list = precode_params_list + input_cmdline

        # TODO: check that remote data must be on the same computer

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

        if not initialise:
            ###################################################
            # Prepare yambo input file
            ###################################################

            params_dict = parameters.get_dict()

            # extract boolean keys
            boolean_dict = {
                k: v
                for k, v in six.iteritems(params_dict) if isinstance(v, bool)
            }
            params_dict = {
                k: v
                for k, v in six.iteritems(params_dict)
                if k not in list(boolean_dict.keys())
            }

            # reorganize the dictionary and create a list of dictionaries with key, value and units
            parameters_list = []
            for k, v in six.iteritems(params_dict):

                if "_units" in k:
                    continue

                units_key = "{}_units".format(k)
                try:
                    units = params_dict[units_key]
                except KeyError:
                    units = None

                this_dict = {}
                this_dict['key'] = k
                this_dict['value'] = v
                this_dict['units'] = units

                parameters_list.append(this_dict)

            input_filename = tempfolder.get_abs_path(
                self.metadata.options.input_filename)

            with open(input_filename, 'w') as infile:
                infile.write(self.metadata.options.logostring)

                for k, v in six.iteritems(boolean_dict):
                    if v:
                        infile.write("{}\n".format(k))

                for this_dict in parameters_list:
                    key = this_dict['key']
                    value = this_dict['value']
                    units = this_dict['units']

                    if isinstance(value, list):
                        value_string = ''
                        try:
                            for v in value:
                                value_string += " | ".join([str(_) for _ in v
                                                            ]) + " |\n"
                        except:
                            value_string += " | ".join([str(_) for _ in value
                                                        ]) + " |\n"

                        the_string = "% {}\n {}".format(key, value_string)
                        the_string += "%"

                    else:
                        the_value = '"{}"'.format(value) if isinstance(
                            value, six.string_types) else '{}'.format(value)
                        the_string = "{} = {}".format(key, the_value)

                    if units is not None:
                        the_string += " {}".format(units)

                    infile.write(the_string + "\n")

        ############################################
        # set copy of the parent calculation
        ############################################

        try:
            parent_calc = parent_calc_folder.get_incoming().all_nodes()[
                -1]  #to load the node from a workchain...
        except:
            parent_calc = parent_calc_folder.get_incoming().get_node_by_label(
                'remote_folder')

        if yambo_parent:
            if copy_save:
                try:
                    remote_copy_list.append(
                        (parent_calc_folder.computer.uuid,
                         parent_calc_folder.get_remote_path() + "/SAVE/",
                         './SAVE/'))
                except:
                    remote_copy_list.append(
                        (parent_calc_folder.computer.uuid,
                         parent_calc_folder.get_remote_path() +
                         "out/aiida.save/SAVE/", './SAVE/'))
            else:
                try:
                    remote_symlink_list.append(
                        (parent_calc_folder.computer.uuid,
                         parent_calc_folder.get_remote_path() + "/SAVE/",
                         './SAVE/'))
                except:
                    remote_symlink_list.append(
                        (parent_calc_folder.computer.uuid,
                         parent_calc_folder.get_remote_path() +
                         "out/aiida.save/SAVE/", './SAVE/'))

            if copy_dbs:
                remote_copy_list.append(
                    (parent_calc_folder.computer.uuid,
                     parent_calc_folder.get_remote_path() + "/aiida.out/",
                     './aiida.out/'))
            if restart_yambo:
                remote_symlink_list.append(
                    (parent_calc_folder.computer.uuid,
                     parent_calc_folder.get_remote_path() + "/aiida.out/",
                     './aiida.out/'))
        else:
            remote_copy_list.append((
                parent_calc_folder.computer.uuid,
                os.path.join(parent_calc_folder.get_remote_path(),
                             PwCalculation._OUTPUT_SUBFOLDER, "aiida.save",
                             "*"),  ##.format(parent_calc_folder._PREFIX)
                "."))
        ############################################
        # set Calcinfo
        ############################################

        calcinfo = CalcInfo()

        calcinfo.uuid = self.uuid

        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = remote_copy_list
        calcinfo.remote_symlink_list = remote_symlink_list

        # Retrieve by default the output file and the xml file
        calcinfo.retrieve_list = []
        calcinfo.retrieve_list.append('r*')
        calcinfo.retrieve_list.append('l*')
        calcinfo.retrieve_list.append('o*')
        calcinfo.retrieve_list.append('LOG/l*_CPU_1')
        calcinfo.retrieve_list.append('LOG/l*_CPU_2')
        calcinfo.retrieve_list.append('*stderr*')  #standard errors
        extra_retrieved = []

        if initialise:
            #    extra_retrieved.append('SAVE/'+_dbs_accepted['ns.db1'])
            pass
        else:
            for dbs in _dbs_accepted.keys():
                db = boolean_dict.pop(dbs, False)
                if db:
                    extra_retrieved.append('aiida.out/' + _dbs_accepted[dbs])

        additional = settings.pop('ADDITIONAL_RETRIEVE_LIST', [])
        if additional:
            extra_retrieved.append(additional)

        for extra in extra_retrieved:
            calcinfo.retrieve_list.append(extra)

        from aiida.common.datastructures import CodeRunMode, CodeInfo

        # c1 = interface dft codes and yambo (ex. p2y or a2y)
        c1 = CodeInfo()
        c1.withmpi = True
        c1.cmdline_params = precode_params_list

        # c2 = yambo initialization
        c2 = CodeInfo()
        c2.withmpi = True
        c2.cmdline_params = []
        c2.code_uuid = main_code.uuid

        # if the parent calculation is a yambo calculation skip the interface (c1) and the initialization (c2)
        if yambo_parent:
            try:
                parent_settings = _uppercase_dict(
                    parent_calc.inputs.settings.get_dict(),
                    dict_name='parent settings')
                parent_initialise = parent_settings['INITIALISE']
            except KeyError:
                parent_initialise = False
            c1 = None
            if not parent_initialise:
                c2 = None
        else:
            c1.cmdline_params = precode_params_list
            c1.code_uuid = preproc_code.uuid

        # c3 = yambo calculation
        c3 = CodeInfo()
        c3.withmpi = True
        #c3.withmpi = self.get_withmpi()
        c3.cmdline_params = [
            "-F", self.metadata.options.input_filename, \
            '-J', self.metadata.options.output_filename, \
        ]
        c3.code_uuid = main_code.uuid

        if initialise:
            c2 = None
            c3 = None

        #logic of the execution
        #calcinfo.codes_info = [c1, c2, c3] if not yambo_parent else [c3]
        if yambo_parent:
            if not parent_initialise:
                calcinfo.codes_info = [c3]
            else:
                calcinfo.codes_info = [c2, c3]
        elif initialise:
            calcinfo.codes_info = [c1]
        else:
            calcinfo.codes_info = [c1, c2, c3]

        calcinfo.codes_run_mode = CodeRunMode.SERIAL

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

        return calcinfo