Exemplo n.º 1
0
def cmd_import(filename, dry_run, fleurinp):
    """
    Import a `StructureData` from a Fleur input file.

    FILENAME is the name/path of the inp.xml file to use.

    If you want to import a structure from any file type you can use
    'verdi data structure import -ase <filename>' instead.
    """
    from aiida_fleur.data.fleurinp import FleurinpData

    if not filename.endswith('.xml'):
        echo.echo_critical(
            'Error: Currently, only StructureData from a inp.xml file can be extracted.'
        )
    fleurinpd = FleurinpData(files=[filename])
    if not fleurinp or dry_run:
        structure = fleurinpd.get_structuredata_ncf()
    else:
        structure = fleurinpd.get_structuredata()
    formula = structure.get_formula()

    if dry_run:
        echo.echo_success(f'parsed structure with formula {formula}')
    else:
        structure.store()
        echo.echo_success(
            f'parsed and stored StructureData<{structure.pk}> with formula {formula}, also stored FleurinpData<{fleurinpd.pk}>'
        )
Exemplo n.º 2
0
    def get_results_relax(self):
        """
        Generates results of the workchain.
        Creates a new structure data node which is an
        optimized structure.
        """

        if self.ctx.wf_dict.get('relaxation_type', 'atoms') is None:
            input_scf = AttributeDict(
                self.exposed_inputs(FleurScfWorkChain, namespace='scf'))
            if 'structure' in input_scf:
                structure = input_scf.structure
            elif 'fleurinp' in input_scf:
                structure = input_scf.fleurinp.get_structuredata_ncf()
            else:
                pass
            self.ctx.final_structure = structure
            self.ctx.final_cell = structure.cell
            # The others are already put to None
            return

        try:
            relax_out = self.ctx.scf_res.outputs.last_fleur_calc_output
            last_fleur = find_nested_process(self.ctx.scf_res, FleurCalc)[-1]
            retrieved_node = last_fleur.outputs.retrieved
        except NotExistent:
            return self.exit_codes.ERROR_NO_SCF_OUTPUT

        relax_out = relax_out.get_dict()

        try:
            total_energy = relax_out['energy']
            total_energy_units = relax_out['energy_units']
            atomtype_info = relax_out['relax_atomtype_info']
        except KeyError:
            return self.exit_codes.ERROR_NO_RELAX_OUTPUT

        self.ctx.total_energy_last = total_energy
        self.ctx.total_energy_units = total_energy_units
        self.ctx.atomtype_info = atomtype_info

        fleurinp = FleurinpData(files=['inp.xml', 'relax.xml'],
                                node=retrieved_node)
        structure = fleurinp.get_structuredata_ncf()

        self.ctx.final_structure = structure
Exemplo n.º 3
0
    def parse(self, **kwargs):
        """
        Takes inp.xml generated by inpgen calculation and created an FleurinpData node.

        :return: a dictionary of AiiDA nodes to be stored in the database.
        """

        try:
            output_folder = self.retrieved
        except NotExistent:
            self.logger.error('No retrieved folder found')
            return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER

        # check what is inside the folder
        list_of_files = output_folder.list_object_names()
        self.logger.info('file list {}'.format(list_of_files))

        errorfile = FleurinputgenCalculation._ERROR_FILE_NAME
        if errorfile in list_of_files:
            try:
                with output_folder.open(errorfile, 'r') as error_file:
                    error_file_lines = error_file.read()
            except IOError:
                self.logger.error(
                    'Failed to open error file: {}.'.format(errorfile))
                return self.exit_codes.ERROR_OPENING_OUTPUTS
            # if not empty, has_error equals True, parse error.
            if error_file_lines:
                self.logger.error(
                    "The following was written to the error file {} : \n '{}'"
                    ''.format(errorfile, error_file_lines))

        inpxml_file = FleurinputgenCalculation._INPXML_FILE_NAME
        if inpxml_file not in list_of_files:
            self.logger.error("XML inp not found '{}'".format(inpxml_file))
            return self.exit_codes.ERROR_NO_INPXML

        for file1 in self._default_files:
            if file1 not in list_of_files:
                self.logger.error(
                    "'{}' file not found in retrived folder, it was probably "
                    'not created by inpgen'.format(file1))
                return self.exit_codes.ERROR_MISSING_RETRIEVED_FILES

        try:
            fleurinp = FleurinpData(files=[inpxml_file], node=output_folder)
        except InputValidationError as ex:
            self.logger.error('FleurinpData initialization failed: {}'.format(
                str(ex)))
            return self.exit_codes.ERROR_FLEURINPDATA_INPUT_NOT_VALID
        except ValidationError as ex:
            self.logger.error('FleurinpData validation failed: {}'.format(
                str(ex)))
            return self.exit_codes.ERROR_FLEURINPDATA_NOT_VALID

        self.logger.info('FleurinpData initialized')
        self.out('fleurinpData', fleurinp)
Exemplo n.º 4
0
def cmd_param_import(filename, dry_run, fleurinp, show):
    """
    Extract FLAPW parameters from a Fleur input file and store as Dict in the db.

    FILENAME is the name/path of the inp.xml file to use.
    """
    from aiida_fleur.data.fleurinp import FleurinpData

    if not filename.endswith('.xml'):
        echo.echo_critical('Error: Currently, we can only extract information from an inp.xml file.')
    fleurinpd = FleurinpData(files=[filename])
    if not fleurinp or dry_run:
        parameters = fleurinpd.get_parameterdata_ncf()
    else:
        parameters = fleurinpd.get_parameterdata(fleurinpd)

    if dry_run:
        echo.echo_success('parsed FLAPW parameters')
    else:
        parameters.store()
        echo.echo_success(f'parsed and stored FLAPW parameters<{parameters.pk}>  <{parameters.uuid}>')

    if show:
        echo.echo_dictionary(parameters.get_dict())
Exemplo n.º 5
0
    def parse_with_retrieved(self, retrieved):
        """
        Receives in input a dictionary of retrieved nodes.
        Does all the logic here. Checks presents of files.
        Calls routines to parse them and returns parameter nodes and sucess.

        :return successful: Bool, if overall parsing was successful or not
        :return new_nodes_list: list of tuples of two (linkname, Dataobject),
                                nodes to be stored by AiiDA

        """

        ####### init some variables ######

        successful = True

        has_xml_outfile = False
        has_dos_file = False
        has_bands_file = False
        has_new_xmlinp_file = False

        dos_file = None
        band_file = None
        new_nodes_list = []

        ######### Check presents of files ######

        # select the folder object
        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()
        self.logger.info("file list {}".format(list_of_files))

        # has output xml file, otherwise error
        if self._calc._OUTXML_FILE_NAME not in list_of_files:
            successful = False
            self.logger.error("XML out not found '{}'".format(
                self._calc._OUTXML_FILE_NAME))
        else:
            has_xml_outfile = True

        # check if all files expected are there for the calculation
        #print self._should_retrieve
        for filel in self._should_retrieve:
            if filel not in list_of_files:
                successful = False
                self.logger.warning(
                    "'{}' file not found in retrived folder, it"
                    " was probable not created by fleur".format(filel))

        # check if something was written to the error file
        if self._calc._ERROR_FILE_NAME in list_of_files:
            errorfile = os.path.join(out_folder.get_abs_path('.'),
                                     self._calc._ERROR_FILE_NAME)
            # read
            error_file_lines = ''
            try:
                with open(errorfile, 'r') as efile:
                    error_file_lines = efile.read(
                    )  # Note: read(), not readlines()
            except IOError:
                self.logger.error(
                    "Failed to open error file: {}.".format(errorfile))

            # if not empty, has_error equals True, parse error.
            if error_file_lines:
                self.logger.warning(
                    "The following was written into std error and piped to {} : \n {}"
                    "".format(self._calc._ERROR_FILE_NAME, error_file_lines))

                if 'OK' in error_file_lines:  # if judft-error # TODO maybe change.
                    successful = True
                else:
                    successful = False

        if successful == False:
            return successful, ()

        #what about other files?
        #check input dict

        if self._calc._DOS_FILE_NAME in list_of_files:
            has_dos = True
        if self._calc._BAND_FILE_NAME in list_of_files:
            has_bands = True

        #if a new inp.xml file was created (new stucture)
        if self._calc._NEW_XMlINP_FILE_NAME in list_of_files:
            self.logger.error("new inp.xml file found in retrieved folder")
            has_new_xmlinp_file = True
        # add files which should also be there in addition to default_files.

        ################################
        ####### Parse the files ########

        if has_xml_outfile:
            # get outfile path and call xml out parser
            outxmlfile = os.path.join(out_folder.get_abs_path('.'),
                                      self._calc._OUTXML_FILE_NAME)
            simpledata, complexdata, parser_info, success = parse_xmlout_file(
                outxmlfile)

            # Call routines for output node creation
            if simpledata:
                outputdata = dict(simpledata.items() + parser_info.items())
                outxml_params = ParameterData(dict=outputdata)
                link_name = self.get_linkname_outparams(
                )  # accessible via c.res
                new_nodes_list.append((link_name, outxml_params))

            if complexdata:
                parameter_data = dict(complexdata.items() +
                                      parser_info.items())
                outxml_params_complex = ParameterData(dict=parameter_data)
                link_name = self.get_linkname_outparams_complex()
                new_nodes_list.append((link_name, outxml_params_complex))

            #greate new fleurinpData object if needed

            #fleurinp_Data = FleurinpData(files= [inpxmlfile])
            #, symoutfile, enparafile])
            #self.logger.info('FleurinpData initialized')
            #self.logger.info
            #link_name_fleurinp = 'fleurinpData'

            # return it to the execmanager / maybe later not
            #new_nodes_list.append((link_name_fleurinp, fleurinp_Data))

            # load old fleurinpdata

            # if structure changed, create new fleurinpdata of new inp.xml file.
            # and parse the structure

        # optional parse other files

        # DOS
        if has_dos_file:
            dos_file = os.path.join(out_folder.get_abs_path('.'),
                                    self._calc._DOS_FILE_NAME)
            #if dos_file is not None:
            try:
                with open(dos_file, 'r') as dosf:
                    dos_lines = dosf.read()  # Note: read() and not readlines()
            except IOError:
                raise FleurOutputParsingError(
                    "Failed to open DOS file: {}.".format(dos_file))
            dos_data = parse_dos_file(dos_lines)  #, number_of_atom_types)

            # save array

        # Bands
        if has_bands_file:
            # TODO be carefull there might be two files.
            band_file = os.path.join(out_folder.get_abs_path('.'),
                                     self._calc._BAND_FILE_NAME)

            #if band_file is not None:
            try:
                with open(band_file, 'r') as bandf:
                    bands_lines = bandf.read(
                    )  # Note: read() and not readlines()
            except IOError:
                raise FleurOutputParsingError(
                    "Failed to open bandstructure file: {}."
                    "".format(band_file))
            bands_data = parse_bands_file(bands_lines)

            # save array
        if has_new_xmlinp_file:
            new_inpxmlfile = os.path.join(out_folder.get_abs_path('.'),
                                          self._calc._NEW_XMlINP_FILE_NAME)
            new_fleurinpData = FleurinpData()
            new_fleurinpData.set_file(new_inpxmlfile, dst_filename='inp.xml')
            self.logger.info('New FleurinpData initialized')
            link_name = 'fleurinpData'  #self.get_linkname_outparams()# accessible via c.res
            new_nodes_list.append((link_name, new_fleurinpData))

        # Spectra

        return successful, new_nodes_list
Exemplo n.º 6
0
    def parse_with_retrieved(self, retrieved):
        """
        Receives as input a dictionary of the retrieved nodes from an inpgen run.
        Does all the logic here.

        :return: a dictionary of AiiDA nodes for storing in the database.
        """

        successful = True
        has_xml_inpfile = False
        #has_error = False

        # select the folder object
        # Check that the retrieved folder is there
        try:
            out_folder = retrieved[self._calc._get_linkname_retrieved()]
        except KeyError:
            self.logger.error("No retrieved folder found")
            return False, ()

        # check what is inside the folder
        list_of_files = out_folder.get_folder_list()
        self.logger.info("file list {}".format(list_of_files))

        if self._calc._INPXML_FILE_NAME not in list_of_files:
            successful = False
            self.logger.error("XML inp not found '{}'".format(
                self._calc._INPXML_FILE_NAME))
        else:
            has_xml_inpfile = True

        for file1 in self._default_files:
            if file1 not in list_of_files:
                successful = False
                self.logger.warning(
                    "'{}' file not found in retrived folder, it was probable "
                    "not created by inpgen".format(file1))
        # TODO what about other files?

        # TODO parse out file of inpgen
        #output_data = ParameterData(dict=out_dict)
        #link_name = self.get_linkname_outparams()
        #new_nodes_list = [(link_name, output_data)]
        #return successful,new_nodes_list

        new_nodes_list = []
        if self._calc._ERROR_FILE_NAME in list_of_files:
            errorfile = os.path.join(out_folder.get_abs_path('.'),
                                     self._calc._ERROR_FILE_NAME)
            # read
            error_file_lines = ''
            try:
                with open(errorfile, 'r') as efile:
                    error_file_lines = efile.read(
                    )  # Note: read(),not readlines()
            except IOError:
                self.logger.error(
                    "Failed to open error file: {}.".format(errorfile))
            # if not empty, has_error equals True, parse error.
            if error_file_lines:
                self.logger.error(
                    "The following was written to the error file {} : \n '{}'"
                    "".format(self._calc._ERROR_FILE_NAME, error_file_lines))
                #has_error = True
                successful = False
                return successful, ()

        if has_xml_inpfile:
            # read xmlinp file into an etree
            inpxmlfile = os.path.join(out_folder.get_abs_path('.'),
                                      self._calc._INPXML_FILE_NAME)
            #tree = etree.parse(inpxmlfile)
            #root = tree.getroot()

            # convert etree into python dictionary
            #inpxml_params_dict = inpxml_todict(tree.getroot(), inpxmlstructure)
            #self.inpxmlstructure)#tags_several)#.xpath('/fleurInput')[0])

            # convert the dictionary into an AiiDA object
            #Some values, errors and co?
            #inpxml_params = ParameterData(dict=inpxml_params_dict)
            #link_name = self.get_linkname_outparams()
            # this will be accesible with res
            #new_nodes_list.append((link_name, inpxml_params))

            #check if inpgen was invokes with other options
            fleurinp_data = FleurinpData(files=[inpxmlfile])
            # if kpoints
            # fleurinp_data.set_kpoints
            #, symoutfile, enparafile])
            self.logger.info('FleurinpData initialized')
            #self.logger.info
            link_name_fleurinp = 'fleurinpData'
            # return it to the execmanager
            new_nodes_list.append((link_name_fleurinp, fleurinp_data))

        return successful, new_nodes_list
Exemplo n.º 7
0
    def change_fleurinp(self):
        """
        This routine sets somethings in the fleurinp file before running a fleur
        calculation.
        """
        self.report('INFO: run change_fleurinp')

        if self.ctx.scf_needed:  # use fleurinp from scf wc
            try:
                fleurin = self.ctx.reference.outputs.fleurinp
            except NotExistent:
                error = 'Fleurinp generated in the reference calculation is not found.'
                self.control_end_wc(error)
                return self.exit_codes.ERROR_REFERENCE_CALCULATION_FAILED
        else:
            if 'fleurinp' in self.inputs:  # use the given fleurinp
                fleurin = self.inputs.fleurinp
            else:  # or generate a new one from inp.xml located in the remote folder
                remote_node = self.inputs.remote
                for link in remote_node.get_incoming().all():
                    if isinstance(link.node, CalcJobNode):
                        parent_calc_node = link.node
                retrieved_node = parent_calc_node.get_outgoing().get_node_by_label('retrieved')
                fleurin = FleurinpData(files=['inp.xml'], node=retrieved_node)

        # copy inpchanges from wf parameters
        fchanges = self.ctx.wf_dict.get('inpxml_changes', [])
        # create forceTheorem tags
        fchanges.extend([('create_tag', {
            'xpath': '/fleurInput',
            'newelement': 'forceTheorem'
        }), ('create_tag', {
            'xpath': '/fleurInput/forceTheorem',
            'newelement': 'spinSpiralDispersion'
        })])

        for i, vectors in enumerate(self.ctx.wf_dict['q_vectors']):

            fchanges.append(('create_tag', {
                'xpath': '/fleurInput/forceTheorem/spinSpiralDispersion',
                'newelement': 'q'
            }))
            fchanges.append(('xml_set_text_occ', {
                'xpathn': '/fleurInput/forceTheorem/spinSpiralDispersion/q',
                'text': ' '.join(six.moves.map(str, vectors)),
                'create': False,
                'occ': i
            }))

        changes_dict = {'itmax': 1, 'l_noco': True, 'ctail': False, 'l_ss': True}
        fchanges.append(('set_inpchanges', {'change_dict': changes_dict}))

        # change beta parameter
        for key, val in six.iteritems(self.ctx.wf_dict.get('beta')):
            fchanges.append(('set_atomgr_att_label', {
                'attributedict': {
                    'nocoParams': [('beta', val)]
                },
                'atom_label': key
            }))

        if fchanges:  # change inp.xml file
            fleurmode = FleurinpModifier(fleurin)
            avail_ac_dict = fleurmode.get_avail_actions()

            # apply further user dependend changes
            for change in fchanges:
                function = change[0]
                para = change[1]
                method = avail_ac_dict.get(function, None)
                if not method:
                    error = ("ERROR: Input 'inpxml_changes', function {} "
                             'is not known to fleurinpmodifier class, '
                             'please check/test your input. I abort...'
                             ''.format(function))
                    self.control_end_wc(error)
                    return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

                else:  # apply change
                    method(**para)

            # validate
            try:
                fleurmode.show(display=False, validate=True)
            except etree.DocumentInvalid:
                error = ('ERROR: input, user wanted inp.xml changes did not validate')
                self.control_end_wc(error)
                return self.exit_codes.ERROR_INVALID_INPUT_FILE

            # apply
            out = fleurmode.freeze()
            self.ctx.fleurinp = out
            return
        else:  # otherwise do not change the inp.xml
            self.ctx.fleurinp = fleurin
            return
Exemplo n.º 8
0
    def change_fleurinp(self):
        """
        This routine sets somethings in the fleurinp file before running a fleur
        calculation.
        """
        if self.ctx.scf_needed:
            try:
                fleurin = self.ctx.reference.outputs.fleurinp
            except NotExistent:
                error = 'Fleurinp generated in the reference calculation is not found.'
                self.control_end_wc(error)
                return self.exit_codes.ERROR_REFERENCE_CALCULATION_FAILED
        else:
            if 'fleurinp' in self.inputs:
                fleurin = self.inputs.fleurinp
            else:
                # In this case only remote is given
                # fleurinp data has to be generated from the remote inp.xml file
                remote_node = self.inputs.remote
                for link in remote_node.get_incoming().all():
                    if isinstance(link.node, CalcJobNode):
                        parent_calc_node = link.node
                retrieved_node = parent_calc_node.get_outgoing(
                ).get_node_by_label('retrieved')
                fleurin = FleurinpData(files=['inp.xml'], node=retrieved_node)

        # copy default changes
        fchanges = self.ctx.wf_dict.get('inpxml_changes', [])

        # add forceTheorem tag into inp.xml
        fchanges.extend([
            ('create_tag', {
                'xpath': '/fleurInput',
                'newelement': 'forceTheorem'
            }),
            ('create_tag', {
                'xpath': '/fleurInput/forceTheorem',
                'newelement': 'MAE'
            }),
            ('xml_set_attribv_occ', {
                'xpathn':
                '/fleurInput/forceTheorem/MAE',
                'attributename':
                'theta',
                'attribv':
                ' '.join(six.moves.map(str,
                                       self.ctx.wf_dict.get('sqas_theta')))
            }),
            ('xml_set_attribv_occ', {
                'xpathn':
                '/fleurInput/forceTheorem/MAE',
                'attributename':
                'phi',
                'attribv':
                ' '.join(six.moves.map(str, self.ctx.wf_dict.get('sqas_phi')))
            }),
            ('set_inpchanges', {
                'change_dict': {
                    'itmax': 1,
                    'l_soc': True
                }
            }),
        ])

        if fchanges:  # change inp.xml file
            fleurmode = FleurinpModifier(fleurin)
            avail_ac_dict = fleurmode.get_avail_actions()

            # apply further user dependend changes
            for change in fchanges:
                function = change[0]
                para = change[1]
                method = avail_ac_dict.get(function, None)
                if not method:
                    error = ("ERROR: Input 'inpxml_changes', function {} "
                             'is not known to fleurinpmodifier class, '
                             'please check/test your input. I abort...'
                             ''.format(function))
                    self.control_end_wc(error)
                    return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

                else:  # apply change
                    method(**para)

            # validate?
            try:
                fleurmode.show(display=False, validate=True)
            except etree.DocumentInvalid:
                error = (
                    'ERROR: input, user wanted inp.xml changes did not validate'
                )
                self.report(error)
                return self.exit_codes.ERROR_INVALID_INPUT_FILE

            # apply
            out = fleurmode.freeze()
            self.ctx.fleurinp = out
            return
        else:  # otherwise do not change the inp.xml
            self.ctx.fleurinp = fleurin
            return
Exemplo n.º 9
0
    def parse(self, **kwargs):
        """
        Takes inp.xml generated by inpgen calculation and created an FleurinpData node.

        :return: a dictionary of AiiDA nodes to be stored in the database.
        """

        try:
            output_folder = self.retrieved
        except NotExistent:
            self.logger.error('No retrieved folder found')
            return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER

        # check what is inside the folder
        list_of_files = output_folder.list_object_names()
        self.logger.info('file list {}'.format(list_of_files))

        errorfile = FleurinputgenCalculation._ERROR_FILE_NAME
        if errorfile in list_of_files:
            try:
                with output_folder.open(errorfile, 'r') as error_file:
                    error_file_lines = error_file.read()
            except IOError:
                self.logger.error(
                    'Failed to open error file: {}.'.format(errorfile))
                return self.exit_codes.ERROR_OPENING_OUTPUTS
            # if not empty, has_error equals True, prior fleur 32
            if error_file_lines:
                if isinstance(error_file_lines, type(b'')):
                    error_file_lines = error_file_lines.replace(b'\x00', b' ')
                else:
                    error_file_lines = error_file_lines.replace('\x00', ' ')
                if 'Run finished successfully' not in error_file_lines:
                    self.logger.warning(
                        'The following was written into std error and piped to {}'
                        ' : \n {}'.format(errorfile, error_file_lines))
                    self.logger.error('Inpgen calculation did not finish'
                                      ' successfully.')

        inpxml_file = FleurinputgenCalculation._INPXML_FILE_NAME
        if inpxml_file not in list_of_files:
            self.logger.error("XML inp not found '{}'".format(inpxml_file))
            return self.exit_codes.ERROR_NO_INPXML

        for file1 in self._default_files:
            if file1 not in list_of_files:
                self.logger.error(
                    "'{}' file not found in retrieved folder, it was probably "
                    'not created by inpgen'.format(file1))
                return self.exit_codes.ERROR_MISSING_RETRIEVED_FILES

        try:
            fleurinp = FleurinpData(files=[])
            fleurinp.set_file(inpxml_file, node=output_folder)
        except InputValidationError as ex:
            self.logger.error('FleurinpData initialization failed: {}'.format(
                str(ex)))
            if fleurinp.parser_info == {}:
                self.logger.error('Parser output: No Output produced')
            else:
                self.logger.error(
                    f'Parser output: {pprint.pformat(fleurinp.parser_info)}')
            return self.exit_codes.ERROR_FLEURINPDATA_INPUT_NOT_VALID
        except ValidationError as ex:
            self.logger.error('FleurinpData validation failed: {}'.format(
                str(ex)))
            return self.exit_codes.ERROR_FLEURINPDATA_NOT_VALID

        self.logger.info('FleurinpData initialized')
        self.out('fleurinpData', fleurinp)
Exemplo n.º 10
0
    def change_fleurinp(self):
        """
        This routine sets somethings in the fleurinp file before running a fleur
        calculation.
        """
        self.report('INFO: run change_fleurinp')

        inputs = self.inputs

        # Has to never crash because corresponding check was done in validate function
        if self.ctx.fleurinp:  # something was already changed
            return
        elif 'fleurinp' in inputs:
            fleurin = self.inputs.fleurinp
        elif 'structure' in inputs:
            if not self.ctx['inpgen'].is_finished_ok:
                error = 'Inpgen calculation failed'
                self.control_end_wc(error)
                return self.exit_codes.ERROR_INPGEN_CALCULATION_FAILED
            fleurin = self.ctx['inpgen'].outputs.fleurinpData
        elif 'remote_data' in inputs:
            # In this case only remote_data for input structure is given
            # fleurinp data has to be generated from the remote inp.xml file to use change_fleurinp
            remote_node = self.inputs.remote_data
            for link in remote_node.get_incoming().all():
                if isinstance(link.node, CalcJobNode):
                    parent_calc_node = link.node
            retrieved_node = parent_calc_node.get_outgoing().get_node_by_label('retrieved')
            try:
                if self.ctx.wf_dict['use_relax_xml']:
                    fleurin = FleurinpData(files=['inp.xml', 'relax.xml'], node=retrieved_node)
                    self.report('INFO: generated FleurinpData from inp.xml and relax.xml')
                else:
                    raise ValueError
            except ValueError:
                fleurin = FleurinpData(files=['inp.xml'], node=retrieved_node)
                self.report('INFO: generated FleurinpData from inp.xml')
            fleurin.store()

        wf_dict = self.ctx.wf_dict
        force_dict = wf_dict.get('force_dict')
        converge_mode = wf_dict.get('mode')
        fchanges = wf_dict.get('inpxml_changes', [])

        fleurmode = FleurinpModifier(fleurin)

        # set proper convergence parameters in inp.xml
        if converge_mode == 'density':
            dist = wf_dict.get('density_converged')
            fleurmode.set_inpchanges({'itmax': self.ctx.default_itmax, 'minDistance': dist})
        elif converge_mode == 'force':
            force_converged = wf_dict.get('force_converged')
            dist = wf_dict.get('density_converged')
            fleurmode.set_inpchanges({
                'itmax': self.ctx.default_itmax,
                'minDistance': dist,
                'force_converged': force_converged,
                'l_f': True,
                'qfix': force_dict.get('qfix'),
                'forcealpha': force_dict.get('forcealpha'),
                'forcemix': force_dict.get('forcemix')
            })
        elif converge_mode == 'energy':
            dist = 0.0
            fleurmode.set_inpchanges({'itmax': self.ctx.default_itmax, 'minDistance': dist})

        avail_ac_dict = fleurmode.get_avail_actions()

        # apply further user dependend changes
        if fchanges:
            for change in fchanges:
                function = change[0]
                para = change[1]
                method = avail_ac_dict.get(function, None)
                if not method:
                    error = ("ERROR: Input 'inpxml_changes', function {} "
                             'is not known to fleurinpmodifier class, '
                             'please check/test your input. I abort...'
                             ''.format(function))
                    self.control_end_wc(error)
                    return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

                else:  # apply change
                    try:
                        method(**para)
                    except ValueError as vale:
                        error = ('ERROR: Changing the inp.xml file failed. Tried to apply {}'
                                 ', which failed with {}. I abort, good luck next time!'
                                 ''.format(change, vale))
                        self.control_end_wc(error)
                        return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED

        # validate?
        try:
            fleurmode.show(display=False, validate=True)
        except etree.DocumentInvalid:
            error = ('ERROR: input, user wanted inp.xml changes did not validate')
            self.report(error)
            return self.exit_codes.ERROR_INVALID_INPUT_FILE

        # apply
        out = fleurmode.freeze()
        self.ctx.fleurinp = out
        return
Exemplo n.º 11
0
# -*- coding: utf-8 -*-
"""Helper for regenerating inp.xml files
"""
from aiida import load_profile
load_profile()

from aiida.orm import load_node
from aiida.engine import run
from aiida.plugins import CalculationFactory
from aiida_fleur.data.fleurinp import FleurinpData

inpgenc = CalculationFactory('fleur.inpgen')
path = './inp.xml'

fleurinp = FleurinpData(inpxml=path)

struc = fleurinp.get_structuredata_ncf()
param = fleurinp.get_parameterdata_ncf()
inpgen_code = load_node()

runa = run(inpgenc, code=inpgen_code, structure=struc, calc_parameter=param)