def test_bandsexport_single_kp(self): """ Plot band for single k-point (issue #2462). """ kpnts = KpointsData() kpnts.set_kpoints([[0., 0., 0.]]) bands = BandsData() bands.set_kpointsdata(kpnts) bands.set_bands([[1.0, 2.0]]) bands.store() # matplotlib options = [str(bands.id), '--format', 'mpl_singlefile'] res = self.cli_runner.invoke(cmd_bands.bands_export, options, catch_exceptions=False) self.assertIn( b'p.scatter', res.stdout_bytes, 'The string p.scatter was not found in the bands mpl export') # gnuplot with self.cli_runner.isolated_filesystem(): options = [str(bands.id), '--format', 'gnuplot', '-o', 'bands.gnu'] self.cli_runner.invoke(cmd_bands.bands_export, options, catch_exceptions=False) with open('bands.gnu', 'r') as gnu_file: res = gnu_file.read() self.assertIn( 'vectors nohead', res, 'The string "vectors nohead" was not found in the gnuplot script' )
def test_fleurinp_modifier_set_kpointsdata(create_fleurinp): """Test if setting a kpoints list to a fleurinp data node works""" from aiida.orm import KpointsData fleurinp_tmp = create_fleurinp(inpxmlfilefolder) fleurinp_tmp.store() # needed? struc = fleurinp_tmp.get_structuredata_ncf() kps = KpointsData() kps.set_cell(struc.cell) kps.pbc = struc.pbc kpoints_pos = [[0.0, 0.0, 0.0], [0.0, 0.5, 0.0], [0.5, 0.0, 0.0], [0.5, 0.0, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0]] kpoints_weight = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # Fleur renormalizes kps.set_kpoints(kpoints_pos, cartesian=False, weights=kpoints_weight) kps.store() # needed, because node has to be loaded... #print(fleurinp_tmp) fm = FleurinpModifier(fleurinp_tmp) fm.set_kpointsdata(kps) fm.show(validate=True, display=False) fm.freeze() # check if kpoint node is input into modification # uuid of node show also work fm = FleurinpModifier(fleurinp_tmp) fm.set_kpointsdata(kps.uuid) fm.freeze()
def test_get_kpoints(self): """Test the `get_kpoints` method.""" kpt = KpointsData() kpt.set_cell_from_structure(self.structure) kpoints = [ [0., 0., 0.], [0.5, 0.5, 0.5], ] cartesian_kpoints = [ [0., 0., 0.], [np.pi / self.alat, np.pi / self.alat, np.pi / self.alat], ] kpt.set_kpoints(kpoints) self.assertEqual( np.abs(kpt.get_kpoints() - np.array(kpoints)).sum(), 0.) self.assertEqual( np.abs( kpt.get_kpoints(cartesian=True) - np.array(cartesian_kpoints)).sum(), 0.) # Check also after storing kpt.store() kpt2 = load_node(kpt.pk) self.assertEqual( np.abs(kpt2.get_kpoints() - np.array(kpoints)).sum(), 0.) self.assertEqual( np.abs( kpt2.get_kpoints(cartesian=True) - np.array(cartesian_kpoints)).sum(), 0.)
def _legacy_get_explicit_kpoints_path(structure, **kwargs): """ Call the get_explicit_kpoints_path of the legacy implementation :param structure: a StructureData node :param float kpoint_distance: parameter controlling the distance between kpoints. Distance is given in crystal coordinates, i.e. the distance is computed in the space of b1, b2, b3. The distance set will be the closest possible to this value, compatible with the requirement of putting equispaced points between two special points (since extrema are included). :param bool cartesian: if set to true, reads the coordinates eventually passed in value as cartesian coordinates :param float epsilon_length: threshold on lengths comparison, used to get the bravais lattice info :param float epsilon_angle: threshold on angles comparison, used to get the bravais lattice info """ args_recognized = ['value', 'kpoint_distance', 'cartesian', 'epsilon_length', 'epsilon_angle'] args_unknown = set(kwargs).difference(args_recognized) if args_unknown: raise ValueError('unknown arguments {}'.format(args_unknown)) point_coords, path, bravais_info, explicit_kpoints, labels = legacy.get_explicit_kpoints_path( # pylint: disable=unbalanced-tuple-unpacking cell=structure.cell, pbc=structure.pbc, **kwargs ) kpoints = KpointsData() kpoints.set_cell(structure.cell) kpoints.set_kpoints(explicit_kpoints) kpoints.labels = labels parameters = { 'bravais_info': bravais_info, 'point_coords': point_coords, 'path': path, } return {'parameters': Dict(dict=parameters), 'explicit_kpoints': kpoints}
def get_kpointsdata_ncf(self, name=None, index=None, only_used=False): """ This routine returns an AiiDA :class:`~aiida.orm.KpointsData` type produced from the ``inp.xml`` file. This only works if the kpoints are listed in the in inpxml. This is NOT a calcfunction and does not keep the provenance! :param name: str, optional, if given only the kpoint set with the given name is returned :param index: int, optional, if given only the kpoint set with the given index is returned :returns: :class:`~aiida.orm.KpointsData` node """ from aiida.orm import KpointsData from masci_tools.util.xml.xml_getters import get_kpoints_data # HINT, TODO:? in this routine, the 'cell' you might get in an other way # exp: StructureData.cell, but for this you have to make a structureData Node, # which might take more time for structures with lots of atoms. # then just parsing the cell from the inp.xml # as in the routine get_structureData xmltree, schema_dict = self.load_inpxml() if name is None and index is None: kpoints, weights, cell, pbc = get_kpoints_data(xmltree, schema_dict, only_used=only_used) else: kpoints, weights, cell, pbc = get_kpoints_data(xmltree, schema_dict, name=name, index=index, only_used=only_used) if isinstance(kpoints, dict): kpoints_data = {} for (label, kpoints_set), weights_set in zip(kpoints.items(), weights.values()): kps = KpointsData() kps.set_cell(cell) kps.pbc = pbc kps.set_kpoints(kpoints_set, cartesian=False, weights=weights_set) #kpoints_data.add_link_from(self, label='fleurinp.kpts', link_type=LinkType.CREATE) kps.label = 'fleurinp.kpts' kpoints_data[label] = kps else: kpoints_data = KpointsData() kpoints_data.set_cell(cell) kpoints_data.pbc = pbc kpoints_data.set_kpoints(kpoints, cartesian=False, weights=weights) #kpoints_data.add_link_from(self, label='fleurinp.kpts', link_type=LinkType.CREATE) kpoints_data.label = 'fleurinp.kpts' return kpoints_data
def connect_structure_bands(strct): # pylint: disable=unused-argument alat = 4. cell = np.array([ [alat, 0., 0.], [0., alat, 0.], [0., 0., alat], ]) kpnts = KpointsData() kpnts.set_cell(cell) kpnts.set_kpoints([[0., 0., 0.], [0.1, 0.1, 0.1]]) bands = BandsData() bands.set_kpointsdata(kpnts) bands.set_bands([[1.0, 2.0], [3.0, 4.0]]) return bands
def connect_structure_bands(structure): alat = 4. cell = np.array([ [alat, 0., 0.], [0., alat, 0.], [0., 0., alat], ]) k = KpointsData() k.set_cell(cell) k.set_kpoints([[0., 0., 0.], [0.1, 0.1, 0.1]]) b = BandsData() b.set_kpointsdata(k) b.set_bands([[1.0, 2.0], [3.0, 4.0]]) return b
def get_explicit_kpoints_path(structure, parameters): """ Return the kpoint path for band structure (in scaled and absolute coordinates), given a crystal structure, using the paths proposed in the various publications (see description of the 'recipe' input parameter). The parameters are the same as get get_explicit_k_path in __init__, but here all structures are input and returned as AiiDA structures rather than tuples, and similarly k-points-related information as a AiiDA KpointsData class. :param structure: The AiiDA StructureData for which we want to obtain the suggested path. :param parameters: A dictionary whose key-value pairs are passed as additional kwargs to the ``seekpath.get_explicit_k_path`` function. :return: A dictionary with four nodes: - ``explicit_kpoints``: a KpointsData with the (explicit) kpoints (with labels set). - ``parameters``: a Dict, whose content is the same dictionary as returned by the ``seekpath.get_explicit_k_path`` function (see `seekpath documentation <https://seekpath.readthedocs.io/>`_), except that: - ``conv_lattice``, ``conv_positions``, ``conv_types`` are removed and replaced by the ``conv_structure`` output node - ``primitive_lattice``, ``primitive_positions``, ``primitive_types`` are removed and replaced by the `primitive_structure` output node - ``reciprocal_primitive_lattice``, ``explicit_kpoints_abs``, ``explicit_kpoints_rel`` and ``explicit_kpoints_labels`` are removed and replaced by the ``explicit_kpoints`` output node - ``primitive_structure``: A StructureData with the primitive structure - ``conv_structure``: A StructureData with the primitive structure """ # pylint: disable=too-many-locals from aiida.tools.data.structure import spglib_tuple_to_structure, structure_to_spglib_tuple structure_tuple, kind_info, kinds = structure_to_spglib_tuple(structure) result = {} rawdict = seekpath.get_explicit_k_path(structure=structure_tuple, **parameters) # Replace primitive structure with AiiDA StructureData primitive_lattice = rawdict.pop('primitive_lattice') primitive_positions = rawdict.pop('primitive_positions') primitive_types = rawdict.pop('primitive_types') primitive_tuple = (primitive_lattice, primitive_positions, primitive_types) primitive_structure = spglib_tuple_to_structure(primitive_tuple, kind_info, kinds) # Replace conv structure with AiiDA StructureData conv_lattice = rawdict.pop('conv_lattice') conv_positions = rawdict.pop('conv_positions') conv_types = rawdict.pop('conv_types') conv_tuple = (conv_lattice, conv_positions, conv_types) conv_structure = spglib_tuple_to_structure(conv_tuple, kind_info, kinds) # Remove reciprocal_primitive_lattice, recalculated by kpoints class rawdict.pop('reciprocal_primitive_lattice') kpoints_abs = rawdict.pop('explicit_kpoints_abs') kpoints_labels = rawdict.pop('explicit_kpoints_labels') # set_kpoints expects labels like [[0,'X'],[34,'L'],...], so generate it here skipping empty labels labels = [[idx, label] for idx, label in enumerate(kpoints_labels) if label] kpoints = KpointsData() kpoints.set_cell_from_structure(primitive_structure) kpoints.set_kpoints(kpoints_abs, cartesian=True, labels=labels) result['parameters'] = Dict(dict=rawdict) result['explicit_kpoints'] = kpoints result['primitive_structure'] = primitive_structure result['conv_structure'] = conv_structure return result
def test_inp_gen_cell(gen_instance, sto_calc_inputs): """ Test generation of the inputs """ gen_instance.inputs = sto_calc_inputs gen_instance.prepare_inputs() assert 'symmetry_generate' in gen_instance.cell_file assert "POSITIONS_ABS" in gen_instance.cell_file assert "LATTICE_CART" in gen_instance.cell_file assert isinstance(gen_instance.cell_file["cell_constraints"], list) assert 'C9' in gen_instance.cell_file['SPECIES_POT'][0] # Test extra-kpoints from aiida.orm import KpointsData kpn1 = KpointsData() kpn1.set_kpoints_mesh((4, 4, 4)) gen_instance._include_extra_kpoints(kpn1, 'phonon', { 'task': ('phonon', ), 'need_weights': False }) assert 'phonon_kpoint_mp_grid' in gen_instance.cell_file kpn1.set_kpoints_mesh(( 4, 4, 4, ), (0.25, 0.25, 0.25)) gen_instance._include_extra_kpoints(kpn1, 'phonon', { 'task': ('phonon', ), 'need_weights': False }) assert 'phonon_kpoint_mp_offset' in gen_instance.cell_file # Explicit kpoints, with/without the weights kpn2 = KpointsData() kpn_points = [[0, 0, 0], [0.5, 0.5, 0.5]] kpn_weights = [0.3, 0.6] kpn2.set_kpoints(kpn_points, weights=kpn_weights) gen_instance._include_extra_kpoints(kpn2, 'bs', { 'task': ('bandstructure', ), 'need_weights': True }) assert len(gen_instance.cell_file['BS_KPOINT_LIST'][0].split()) == 4 kpn2 = KpointsData() kpn_points = [[0, 0, 0], [0.5, 0.5, 0.5]] kpn2.set_kpoints(kpn_points) gen_instance._include_extra_kpoints(kpn2, 'bs', { 'task': ('bandstructure', ), 'need_weights': True }) assert len(gen_instance.cell_file['BS_KPOINT_LIST'][0].split()) == 4 assert float(gen_instance.cell_file['BS_KPOINT_LIST'][0].split()[3]) == 0.5 # No weights gen_instance._include_extra_kpoints(kpn2, 'bs', { 'task': ('bandstructure', ), 'need_weights': False }) assert len(gen_instance.cell_file['BS_KPOINT_LIST'][0].split()) == 3 assert 'BS_KPOINT_LIST' in gen_instance.cell_file
def launch_calculation(code, structure, pseudo_family, kpoints_mesh, ecutwfc, ecutrho, hubbard_u, hubbard_v, hubbard_file_pk, starting_magnetization, smearing, max_num_machines, max_wallclock_seconds, with_mpi, daemon, parent_folder, dry_run, mode, unfolded_kpoints): """Run a PwCalculation.""" from aiida.orm import Dict, KpointsData from aiida.plugins import CalculationFactory from aiida_quantumespresso.utils.resources import get_default_options cutoff_wfc, cutoff_rho = pseudo_family.get_recommended_cutoffs( structure=structure, unit='Ry') parameters = { 'CONTROL': { 'calculation': mode, }, 'SYSTEM': { 'ecutwfc': ecutwfc or cutoff_wfc, 'ecutrho': ecutrho or cutoff_rho, } } if mode in CALCS_REQUIRING_PARENT and not parent_folder: raise click.BadParameter( f"calculation '{mode}' requires a parent folder", param_hint='--parent-folder') try: hubbard_file = validate.validate_hubbard_parameters( structure, parameters, hubbard_u, hubbard_v, hubbard_file_pk) except ValueError as exception: raise click.BadParameter(str(exception)) try: validate.validate_starting_magnetization(structure, parameters, starting_magnetization) except ValueError as exception: raise click.BadParameter(str(exception)) try: validate.validate_smearing(parameters, smearing) except ValueError as exception: raise click.BadParameter(str(exception)) if unfolded_kpoints: unfolded_list = kpoints_mesh.get_kpoints_mesh(print_list=True) kpoints_mesh = KpointsData() kpoints_mesh.set_kpoints(unfolded_list) inputs = { 'code': code, 'structure': structure, 'pseudos': pseudo_family.get_pseudos(structure=structure), 'kpoints': kpoints_mesh, 'parameters': Dict(dict=parameters), 'metadata': { 'options': get_default_options(max_num_machines, max_wallclock_seconds, with_mpi), } } if parent_folder: inputs['parent_folder'] = parent_folder if hubbard_file: inputs['hubbard_file'] = hubbard_file if dry_run: if daemon: # .submit() would forward to .run(), but it's better to stop here, # since it's a bit unexpected and the log messages output to screen # would be confusing ("Submitted PwCalculation<None> to the daemon") raise click.BadParameter( 'cannot send to the daemon if in dry_run mode', param_hint='--daemon') inputs['metadata']['store_provenance'] = False inputs['metadata']['dry_run'] = True launch.launch_process(CalculationFactory('quantumespresso.pw'), daemon, **inputs)
def get_explicit_kpoints(kpoints): """Convert from a mesh to an explicit list""" from aiida.orm import KpointsData kpt = KpointsData() kpt.set_kpoints(kpoints.get_kpoints_mesh(print_list=True)) return kpt
def change_fleurinp(self): """ create a new fleurinp from the old with certain parameters """ # TODO allow change of kpoint mesh?, tria? wf_dict = self.ctx.wf_dict if self.ctx.scf_needed: try: fleurin = self.ctx.scf.outputs.fleurinp except NotExistent: error = 'Fleurinp generated in the SCF calculation is not found.' self.control_end_wc(error) return self.exit_codes.ERROR_SCF_CALCULATION_FAILED else: if 'fleurinp' not in self.inputs: fleurin = get_fleurinp_from_remote_data(self.inputs.remote) else: fleurin = self.inputs.fleurinp # how can the user say he want to use the given kpoint mesh, ZZ nkpts : False/0 fleurmode = FleurinpModifier(fleurin) fchanges = wf_dict.get('inpxml_changes', []) # apply further user dependend changes if fchanges: try: fleurmode.add_task_list(fchanges) except (ValueError, TypeError) as exc: error = ( 'ERROR: Changing the inp.xml file failed. Tried to apply inpxml_changes' f', which failed with {exc}. I abort, good luck next time!' ) self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED kpath = wf_dict['kpath'] explicit = wf_dict['kpoints_explicit'] distance = wf_dict['kpoints_distance'] nkpts = wf_dict['kpoints_number'] listname = wf_dict['klistname'] if explicit is not None: try: fleurmode.set_kpointlist(**explicit) except (ValueError, TypeError) as exc: error = ( 'ERROR: Changing the inp.xml file failed. Tried to apply kpoints_explicit' f', which failed with {exc}. I abort, good luck next time!' ) self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED if listname is None: if wf_dict.get('mode') == 'band': listname = 'path-2' if nkpts is None and distance is None: nkpts = 500 if 'kpoints' in self.inputs: fleurmode.set_kpointsdata(self.inputs.kpoints, switch=True) if kpath == 'auto': if fleurin.inp_version >= '0.32' and listname is not None: fleurmode.switch_kpointset(listname) elif isinstance(kpath, dict): if fleurin.inp_version < '0.32': if distance is not None: raise ValueError( 'set_kpath only supports specifying the number of points for the kpoints' ) fleurmode.set_kpath(kpath, nkpts) else: raise ValueError( 'set_kpath is only supported for inputs up to Max4') elif kpath == 'seek': #Use aiida functionality struc = fleurin.get_structuredata() if distance is not None: output = get_explicit_kpoints_path(struc, reference_distance=distance) else: output = get_explicit_kpoints_path(struc) primitive_struc = output['primitive_structure'] #check if primitive_structure and input structure are identical: maxdiff_cell = sum( abs(np.array(primitive_struc.cell) - np.array(struc.cell))).max() if maxdiff_cell > 3e-9: self.report(f'Error in cell : {maxdiff_cell}') self.report( 'WARNING: The structure data from the fleurinp is not the primitive structure type, which is mandatory in some cases' ) output['explicit_kpoints'].store() fleurmode.set_kpointsdata(output['explicit_kpoints'], switch=True) elif kpath == 'skip': return else: #Use ase struc = fleurin.get_structuredata() path = bandpath(kpath, cell=struc.cell, npoints=nkpts, density=distance) special_points = path.special_points labels = [] for label, special_kpoint in special_points.items(): for index, kpoint in enumerate(path.kpts): if sum(abs(np.array(special_kpoint) - np.array(kpoint))).max() < 1e-12: labels.append((index, label)) labels = sorted(labels, key=lambda x: x[0]) kpts = KpointsData() kpts.set_cell(struc.cell) kpts.pbc = struc.pbc weights = np.ones(len(path.kpts)) / len(path.kpts) kpts.set_kpoints(kpoints=path.kpts, cartesian=False, weights=weights, labels=labels) kpts.store() fleurmode.set_kpointsdata(kpts, switch=True) sigma = wf_dict['sigma'] emin = wf_dict['emin'] emax = wf_dict['emax'] if fleurin.inp_version < '0.32': if wf_dict.get('mode') == 'dos': fleurmode.set_inpchanges({'ndir': -1}) if wf_dict.get('mode') == 'dos': change_dict = { 'dos': True, 'minEnergy': emin, 'maxEnergy': emax, 'sigma': sigma } else: change_dict = { 'band': True, 'minEnergy': emin, 'maxEnergy': emax, 'sigma': sigma } fleurmode.set_inpchanges(change_dict) 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 except ValueError as exc: error = ( 'ERROR: input, user wanted inp.xml changes could not be applied.' f'The following error was raised {exc}') self.control_end_wc(error) return self.exit_codes.ERROR_CHANGING_FLEURINPUT_FAILED fleurinp_new = fleurmode.freeze() self.ctx.fleurinp_banddos = fleurinp_new
def sto_spectral_inputs(sto_calc_inputs, db_test_app): kpoints = KpointsData() kpoints.set_kpoints([[0.0, 0.5, 0.5], [0.0, 0.0, 0.0]]) sto_calc_inputs.spectral_kpoints = kpoints return sto_calc_inputs
def get_kpointsdata_ncf(self): """ This routine returns an AiiDA :class:`~aiida.orm.KpointsData` type produced from the ``inp.xml`` file. This only works if the kpoints are listed in the in inpxml. This is NOT a calcfunction and does not keep the provenance! :returns: :class:`~aiida.orm.KpointsData` node """ from aiida.orm import KpointsData # HINT, TODO:? in this routine, the 'cell' you might get in an other way # exp: StructureData.cell, but for this you have to make a structureData Node, # which might take more time for structures with lots of atoms. # then just parsing the cell from the inp.xml # as in the routine get_structureData # Disclaimer: this routine needs some xpath expressions. # these are hardcoded here, therefore maintainance might be needed, # if you want to circumvent this, you have # to get all the paths from somewhere. ####### # all hardcoded xpaths used and attributes names: bravaismatrix_bulk_xpath = '/fleurInput/cell/bulkLattice/bravaisMatrix/' bravaismatrix_film_xpath = '/fleurInput/cell/filmLattice/bravaisMatrix/' kpointlist_xpath = '/fleurInput/calculationSetup/bzIntegration/kPointList/' kpoint_tag = 'kPoint' kpointlist_attrib_posscale = 'posScale' kpointlist_attrib_weightscale = 'weightScale' #kpointlist_attrib_count = 'count' kpoint_attrib_weight = 'weight' row1_tag_name = 'row-1' row2_tag_name = 'row-2' row3_tag_name = 'row-3' ######## if 'inp.xml' not in self.files: print( 'cannot get a KpointsData because fleurinpdata has no inp.xml file yet' ) # TODO what to do in this case? return False # else read in inpxml if self._schema_file_path: # Schema there, parse with schema xmlschema_doc = etree.parse(self._schema_file_path) xmlschema = etree.XMLSchema(xmlschema_doc) parser = etree.XMLParser(attribute_defaults=True, encoding='utf-8') with self.open(path='inp.xml', mode='r') as inpxmlfile: tree = etree.parse(inpxmlfile, parser) tree.xinclude() # remove comments from inp.xml comments = tree.xpath('//comment()') for c in comments: p = c.getparent() p.remove(c) if not xmlschema.validate(tree): raise ValueError( 'Input file is not validated against the schema.') else: # schema not there, parse without print('parsing inp.xml without XMLSchema') with self.open(path='inp.xml', mode='r') as inpxmlfile: tree = etree.parse(inpxmlfile) tree.xinclude() # remove comments from inp.xml comments = tree.xpath('//comment()') for c in comments: p = c.getparent() p.remove(c) root = tree.getroot() # get cell matrix from inp.xml cell = None row1 = root.xpath(bravaismatrix_bulk_xpath + row1_tag_name) # [0].text.split() if row1: # bulk calculation row1 = row1[0].text.split() row2 = root.xpath(bravaismatrix_bulk_xpath + row2_tag_name)[0].text.split() row3 = root.xpath(bravaismatrix_bulk_xpath + row3_tag_name)[0].text.split() # TODO? allow math? for i, cor in enumerate(row1): row1[i] = float(cor) * BOHR_A for i, cor in enumerate(row2): row2[i] = float(cor) * BOHR_A for i, cor in enumerate(row3): row3[i] = float(cor) * BOHR_A cell = [row1, row2, row3] # set boundary conditions pbc1 = [True, True, True] elif root.xpath(bravaismatrix_film_xpath + row1_tag_name): # film calculation row1 = root.xpath(bravaismatrix_film_xpath + row1_tag_name)[0].text.split() row2 = root.xpath(bravaismatrix_film_xpath + row2_tag_name)[0].text.split() row3 = root.xpath(bravaismatrix_film_xpath + row3_tag_name)[0].text.split() for i, cor in enumerate(row1): row1[i] = float(cor) * BOHR_A for i, cor in enumerate(row2): row2[i] = float(cor) * BOHR_A for i, cor in enumerate(row3): row3[i] = float(cor) * BOHR_A # row3 = [0, 0, 0]#? TODO:what has it to be in this case? cell = [row1, row2, row3] pbc1 = [True, True, False] if cell is None: print('Could not extract Bravias matrix out of inp.xml. Is the ' 'Bravias matrix explicitly given? i.e Latnam definition ' 'not supported.') return None # get kpoints only works if kpointlist in inp.xml kpoints = root.xpath(kpointlist_xpath + kpoint_tag) if kpoints: posscale = root.xpath(kpointlist_xpath + '@' + kpointlist_attrib_posscale) weightscale = root.xpath(kpointlist_xpath + '@' + kpointlist_attrib_weightscale) #count = root.xpath(kpointlist_xpath + '@' + kpointlist_attrib_count) kpoints_pos = [] kpoints_weight = [] for kpoint in kpoints: kpoint_pos = kpoint.text.split() for i, kval in enumerate(kpoint_pos): kpoint_pos[i] = float(kval) / float(posscale[0]) kpoint_weight = float( kpoint.get(kpoint_attrib_weight)) / float( weightscale[0]) kpoints_pos.append(kpoint_pos) kpoints_weight.append(kpoint_weight) totalw = 0 for weight in kpoints_weight: totalw = totalw + weight kps = KpointsData() kps.set_cell(cell) kps.pbc = pbc1 kps.set_kpoints(kpoints_pos, cartesian=False, weights=kpoints_weight) #kps.add_link_from(self, label='fleurinp.kpts', link_type=LinkType.CREATE) kps.label = 'fleurinp.kpts' # return {label: kps} return kps else: # TODO parser other kpoints formats, if they fit in an AiiDA node print('No kpoint list in inp.xml') return None
def band_parser_legacy(band_dat, band_kpt, special_points, structure): # pylint: disable=too-many-locals """ Parsers the bands output data, along with the special points retrieved from the input kpoints to construct a BandsData object which is then returned. Cannot handle discontinuities in the kpath, if two points are assigned to same spot only one will be passed. Used for wannier90 < 3.0 :param band_dat: list of str with each str stores one line of aiida_band.dat file :param band_kpt: list of str with each str stores one line of aiida_band.kpt file :param special_points: special points to add labels to the bands a dictionary in the form expected in the input as described in the wannier90 documentation :return: BandsData object constructed from the input params, and a list contains warnings. """ import numpy as np from aiida.orm import BandsData from aiida.orm import KpointsData warnings = [] warnings.append(( "Note: no file named SEEDNAME_band.labelinfo.dat found. " "You are probably using a version of Wannier90 before 3.0. " "There, the labels associated with each k-points were not printed in output " "and there were also cases in which points were not calculated " "(see issue #195 on the Wannier90 GitHub page). " "I will anyway try to do my best to assign labels, " "but the assignment might be wrong " "(especially if there are path discontinuities).")) # imports the data out_kpt = np.genfromtxt(band_kpt, skip_header=1, usecols=(0, 1, 2)) out_dat = np.genfromtxt(band_dat, usecols=1) # reshaps the output bands out_dat = out_dat.reshape(len(out_kpt), (len(out_dat) // len(out_kpt)), order="F") # finds expected points of discontinuity kpath = special_points['path'] cont_break = [(i, (kpath[i - 1][1], kpath[i][0])) for i in range(1, len(kpath)) if kpath[i - 1][1] != kpath[i][0]] # finds the special points special_points_dict = special_points['point_coords'] # We set atol to 1e-5 because in the kpt file the coords are printed with fixed precision labels = [ (i, k) for k in special_points_dict for i in range(len(out_kpt)) if all( np.isclose(special_points_dict[k], out_kpt[i], rtol=0, atol=1.e-5)) ] labels.sort() # Checks and appends labels if discontinuity appends = [] for x in cont_break: # two cases the break is before or the break is after # if the break is before if labels[x[0]][1] != x[1][0]: # checks to see if the discontinuity was already there if labels[x[0] - 1] == x[1][0]: continue insert_point = x[0] new_label = x[1][0] kpoint = labels[x[0]][0] - 1 appends += [[insert_point, new_label, kpoint]] # if the break is after if labels[x[0]][1] != x[1][1]: # checks to see if the discontinuity was already there if labels[x[0] + 1] == x[1][1]: continue insert_point = x[0] + 1 new_label = x[1][1] kpoint = labels[x[0]][0] + 1 appends += [[insert_point, new_label, kpoint]] appends.sort() for i, append in enumerate(appends): labels.insert(append[0] + i, (append[2], six.text_type(append[1]))) bands = BandsData() k = KpointsData() k.set_cell_from_structure(structure) k.set_kpoints(out_kpt, cartesian=False) bands.set_kpointsdata(k) bands.set_bands(out_dat, units='eV') bands.labels = labels return bands, warnings
def band_parser(band_dat, band_kpt, band_labelinfo, structure): # pylint: disable=too-many-locals """ Parsers the bands output data to construct a BandsData object which is then returned. Used for wannier90 >= 3.0 :param band_dat: list of str with each str stores one line of aiida_band.dat file :param band_kpt: list of str with each str stores one line of aiida_band.kpt file :param band_labelinfo: list of str with each str stores one line in aiida_band.labelinfo.dat file :return: BandsData object constructed from the input params """ import numpy as np from aiida.orm import BandsData from aiida.orm import KpointsData warnings = [] # imports the data out_kpt = np.genfromtxt(band_kpt, skip_header=1, usecols=(0, 1, 2)) out_dat = np.genfromtxt(band_dat, usecols=1) # reshaps the output bands out_dat = out_dat.reshape(len(out_kpt), (len(out_dat) // len(out_kpt)), order="F") labels_dict = {} for line_idx, line in enumerate(band_labelinfo, start=1): if not line.strip(): continue try: # label, idx, xval, kx, ky, kz = line.split() label, idx, _, _, _, _ = line.split() except ValueError: warnings.append( ('Wrong number of items in line {} of the labelinfo file - ' 'I will not assign that label')).format(line_idx) continue try: idx = int(idx) except ValueError: warnings.append(( "Invalid value for the index in line {} of the labelinfo file, " "it's not an integer - I will not assign that label" )).format(line_idx) continue # I use a dictionary because there are cases in which there are # two lines for the same point (e.g. when I do a zero-length path, # from a point to the same point, just to have that value) # Note the -1 because in fortran indices are 1-based, in Python are # 0-based labels_dict[idx - 1] = label labels = [(key, labels_dict[key]) for key in sorted(labels_dict)] bands = BandsData() k = KpointsData() k.set_cell_from_structure(structure) k.set_kpoints(out_kpt, cartesian=False) bands.set_kpointsdata(k) bands.set_bands(out_dat, units='eV') bands.labels = labels return bands, warnings