def parse(self, retrieved_temporary_folder=None, **kwargs): """ Parse outputs, store results in database. :param retrieved_temporary_folder: a FolderData returned from the calculation :returns: a tuple with two values ``(bool, node_list)``, where: * ``bool``: variable to tell if the parsing succeeded * ``node_list``: list of new nodes to be stored in the db (as a list of tuples ``(link_name, node)``) """ # Check that the retrieved folder is there try: folder = self.retrieved except NotExistent: return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER # parse file here with folder.open("fort.25") as f: parser = Fort25(f) result = parser.parse() self.add_node(self._linkname_bands, result.get("BAND", None), self.parse_bands) self.add_node(self._linkname_dos, result.get("DOSS", None), self.parse_dos)
def test_read_bands(): file_name = os.path.join(TEST_DIR, "output_files", "mgo_sto3g", "fort.25") parser = Fort25(file_name) result = parser.parse() assert result["BAND"] bands = result["BAND"] assert bands["n_bands"] == 14 assert bands["n_k"] == [7, 2, 8, 6, 5, 3] assert bands["bands_up"].shape == (31, 14)
def test_read_spinpolarized_dos(): file_name = os.path.join(TEST_DIR, "output_files", "spinpolarized.fort.25") parser = Fort25(file_name) result = parser.parse() assert result["DOSS"] dos = result["DOSS"] assert dos["e_fermi"] == -0.122904 assert len(dos["e"]) == 25002 assert dos["dos_up"].shape == (1, 25002) assert dos["dos_down"].shape == (1, 25002)
def test_read_negative_path_bands(): file_name = os.path.join(TEST_DIR, "output_files", "negative_band_path.fort.25") parser = Fort25(file_name) result = parser.parse() assert result["BAND"] bands = result["BAND"] assert bands["n_bands"] == 86 assert bands["n_k"] == [8, 5] assert bands["bands_up"].shape == (13, 86)
def test_read_broken_path_bands(): file_name = os.path.join(TEST_DIR, "output_files", "lif_broken_band_path.fort.25") parser = Fort25(file_name) result = parser.parse() assert result["BAND"] bands = result["BAND"] assert bands["n_bands"] == 25 assert bands["n_k"] == [7, 2, 8, 6, 5, 3] assert bands["bands_up"].shape == (31, 25)
def test_read_dos(): file_name = os.path.join(TEST_DIR, "output_files", "mgo_sto3g", "fort.25") parser = Fort25(file_name) result = parser.parse() assert result["DOSS"] dos = result["DOSS"] assert dos["e_fermi"] == -0.146404 assert len(dos["e"]) == 302 assert dos["e"][0] != 0. assert dos["dos_up"].shape == (3, 302) assert dos["dos_down"] is None
def run_properties_direct(wf_path, input_dict): """ This procedure runs properties outside of AiiDA graph and scheduler """ assert wf_path.endswith('fort.9') assert 'band' in input_dict and 'dos' in input_dict assert 'first' not in input_dict['dos'] and 'first' not in input_dict[ 'band'] assert 'last' not in input_dict['dos'] and 'last' not in input_dict['band'] print('Working with %s' % wf_path) work_folder = os.path.join( config.get('local', 'data_dir'), '_'.join([ 'props', datetime.now().strftime('%Y%m%d_%H%M%S'), ''.join([random.choice(string.ascii_lowercase) for _ in range(4)]) ])) os.makedirs(work_folder, exist_ok=False) shutil.copy(wf_path, work_folder) shutil.copy(os.path.join(os.path.dirname(wf_path), 'fort.34'), work_folder) # save structure wf = Fort9(os.path.join(work_folder, 'fort.9')) # automatic generation of k-point path #structure = wf.get_structure() # NB fort.9 may produce slightly different structure, so use fort.34 f34 = f34_input.read(os.path.join(os.path.dirname(wf_path), 'fort.34')) structure = f34.to_aiida() shrink, _, kpath = get_shrink_kpoints_path(structure) last_state = wf.get_ao_number() input_dict['band']['shrink'] = shrink input_dict['band']['bands'] = kpath # automatic generation of first and last state input_dict['band']['first'] = 1 input_dict['band']['last'] = last_state input_dict['dos']['first'] = 1 input_dict['dos']['last'] = last_state d3_content = str(D3(input_dict)) inp = open(os.path.join(work_folder, 'INPUT'), "w") inp.write(d3_content) inp.close() start_time = time.time() p = subprocess.Popen( exec_cmd % (work_folder, EXEC_PATH, os.path.join(work_folder, 'OUTPUT')), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) try: p.wait(timeout=EXEC_TIMEOUT) except subprocess.TimeoutExpired: kill(p.pid) print("Killed as too time-consuming") print("Done in %1.2f sc" % (time.time() - start_time)) if p.returncode != 0: return None, 'PROPERTIES failed, see %s' % work_folder if not os.path.exists(os.path.join(work_folder, 'BAND.DAT')) \ or not os.path.exists(os.path.join(work_folder, 'DOSS.DAT')) \ or not os.path.exists(os.path.join(work_folder, 'fort.25')): return None, 'No PROPERTIES outputs' edata = Fort25(os.path.join(work_folder, 'fort.25')).parse() assert sum(edata['DOSS']['e']) == 0 # all zeros, FIXME? print('>N DOSS: %s' % len(edata['DOSS']['dos'][0])) path = edata['BAND']['path'] k_number = edata['BAND']['n_k'] #cell = wf.get_cell(scale=True) # for path construction we're getting geometry from fort.9 # NB fort.9 may produce slightly different structure, so use fort.34 cell = f34.abc, f34.positions, f34.atomic_numbers path_description = construct_kpoints_path(cell, path, shrink, k_number) # find k-points along the path k_points = get_explicit_kpoints_path(structure, path_description)['explicit_kpoints'] # pass through the internal AiiDA repr, FIXME? bands_data = DataFactory('array.bands')() bands_data.set_kpointsdata(k_points) bands_data.set_bands(edata['BAND']['bands']) edata['BAND']['bands'] = bands_data.get_bands() k_points = bands_data.get_kpoints().tolist() print('>N KPOINTS: %s' % len(k_points)) print('>N BANDS: %s' % len(edata['BAND']['bands'][0])) edata['BAND']['bands'] -= edata['DOSS']['e_fermi'] edata['BAND']['bands'] *= Hartree edata['DOSS']['dos'] -= edata['DOSS']['e_fermi'] edata['DOSS']['dos'] *= Hartree # get rid of the negative DOS artifacts edata['DOSS']['dos'][edata['DOSS']['dos'] < 0] = 0 e_min, e_max = np.amin(edata['BAND']['bands']), np.amax( edata['BAND']['bands']) dos_energies = np.linspace(e_min, e_max, num=len(edata['DOSS']['dos'][0])) stripes = edata['BAND']['bands'].transpose().copy() if is_conductor(stripes): indirect_gap, direct_gap = None, None else: indirect_gap, direct_gap = get_band_gap_info(stripes) # save only the range of the interest E_MIN, E_MAX = -15, 20 stripes = stripes[(stripes[:, 0] > E_MIN) & (stripes[:, 0] < E_MAX)] dos = [] for n, i in enumerate(dos_energies): # FIXME use numpy advanced slicing if E_MIN < i < E_MAX: dos.append(edata['DOSS']['dos'][0][n]) dos_energies = dos_energies[(dos_energies > E_MIN) & (dos_energies < E_MAX)] return { # - gaps 'direct_gap': direct_gap, 'indirect_gap': indirect_gap, # - dos values 'dos': np.round(np.array(dos), 3).tolist(), 'levels': np.round(dos_energies, 3).tolist(), # - bands values 'k_points': k_points, 'stripes': np.round(stripes, 3).tolist(), # - auxiliary 'work_folder': work_folder, 'units': 'eV' }, None