def parse_bands(self, bands): """Parse bands from fort.25 file""" if not bands: raise ValueError("Sorry, didn't find bands info in fort.25") from aiida.plugins import DataFactory # to get BandsData node first we need to get k-points path and set KpointsData shrink = self.node.inputs.parameters.dict.band['shrink'] path = bands["path"] k_number = bands["n_k"] # for path construction we're getting geometry from fort.9 with self.node.inputs.wavefunction.open() as f: fort9_name = f.name geometry_parser = Fort9(fort9_name) cell = geometry_parser.get_cell(scale=True) path_description = construct_kpoints_path(cell, path, shrink, k_number) structure = DataFactory('structure')(ase=geometry_parser.get_ase()) # and now find k-points along the path k_points = get_explicit_kpoints_path( structure, path_description)['explicit_kpoints'] # ...and finally populate bands data bands_data = DataFactory('array.bands')() bands_data.set_kpointsdata(k_points) bands_data.set_bands(bands["bands_up"]) # TODO: Deal with bands_down? bands_down_data = None if bands["bands_down"] is not None: bands_down_data = DataFactory('array.bands')() bands_down_data.set_kpointsdata(k_points) bands_down_data.set_bands(bands["bands_down"]) return bands_data, bands_down_data
def test_pass(): parser = Fort9(file_name) cell, positions, numbers = parser.get_cell() assert cell.shape == (3, 3) assert positions.shape == (2, 3) assert sorted(numbers.tolist()) == [8, 12] assert parser.get_ao_number() == 18
def _set_default_parameters(self, parameters): """Set defaults to calculation parameters""" parameters_dict = parameters.get_dict() from aiida_crystal_dft.io.f9 import Fort9 with self.inputs.wavefunction.open() as f: file_name = f.name wf = Fort9(file_name) if 'band' in parameters_dict: # automatic generation of k-point path if 'bands' not in parameters_dict['band']: self.logger.info( 'Proceeding with automatic generation of k-points path') structure = wf.get_structure() shrink, points, path = get_shrink_kpoints_path(structure) parameters_dict['band']['shrink'] = shrink parameters_dict['band']['bands'] = path # automatic generation of first and last band if 'first' not in parameters_dict['band']: parameters_dict['band']['first'] = 1 if 'last' not in parameters_dict['band']: parameters_dict['band']['last'] = wf.get_ao_number() if 'dos' in parameters_dict: # automatic generation of projections in case no projections are given # TODO: explicit asking for automatic projections if ('projections_atoms' not in parameters_dict['dos'] and 'projections_orbitals' not in parameters_dict['dos']): self.logger.info( 'Proceeding with automatic generation of dos atomic projections' ) parameters_dict['dos'][ 'projections_atoms'] = get_dos_projections_atoms( wf.get_atomic_numbers()) # automatic generation of first and last band if 'first' not in parameters_dict['dos']: parameters_dict['dos']['first'] = 1 if 'last' not in parameters_dict['dos']: parameters_dict['dos']['last'] = wf.get_ao_number() return get_data_class('dict')(dict=parameters_dict)
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
def test_tof98(): name = os.path.join(TEST_DIR, "output_files", "optimise", "fort.9") parser = Fort9(name) print(parser._data)
def test_issue_30(): name = os.path.join(TEST_DIR, "input_files", "issue_30", "fort.9") parser = Fort9(name) assert parser.get_ao_number() == 71
def test_fail(): with pytest.raises(ValueError): Fort9("invalid_file_name.9")