def test_magres(): import numpy as np from ase.io import read, write from ase.build import bulk from ase.calculators.singlepoint import SinglePointDFTCalculator # Test with fictional data si2 = bulk('Si') ms = np.ones((2, 3, 3)) si2.set_array('ms', ms) efg = np.repeat([[[1, 0, 0], [0, 1, 0], [0, 0, -2]]], 2, axis=0) si2.set_array('efg', efg) calc = SinglePointDFTCalculator(si2) calc.results['sus'] = np.eye(3) * 2 si2.set_calculator(calc) si2.info['magres_units'] = { 'ms': 'ppm', 'efg': 'au', 'sus': '10^-6.cm^3.mol^-1' } write('si2_test.magres', si2) si2 = read('si2_test.magres') assert (np.trace(si2.get_array('ms')[0]) == 3) assert (np.all(np.isclose(si2.get_array('efg')[:, 2, 2], -2))) assert (np.all(np.isclose(si2.calc.results['sus'], np.eye(3) * 2)))
def build(self, lines: _CHUNK) -> Atoms: """Apply outcar chunk parsers, and build an atoms object""" self.update_parser_headers() # Ensure header is in sync results = self.parse(lines) symbols = self.header['symbols'] constraint = self.header.get('constraint', None) atoms_kwargs = dict(symbols=symbols, constraint=constraint) # Find some required properties in the parsed results. # Raise ParseError if they are not present for prop in ('positions', 'cell'): try: atoms_kwargs[prop] = results.pop(prop) except KeyError: raise ParseError( 'Did not find required property {} during parse.'.format( prop)) atoms = Atoms(**atoms_kwargs) kpts = results.pop('kpts', None) calc = SinglePointDFTCalculator(atoms, **results) if kpts is not None: calc.kpts = kpts calc.name = 'vasp' atoms.calc = calc return atoms
def parse_gto_chunk(chunk): atoms = None forces = None energy = None dipole = None quadrupole = None for theory in ['tce', 'ccsd', 'mp2', 'mf']: matches = _e_gto[theory].findall(chunk) if matches: energy = float(matches[-1].replace('D', 'E')) * Hartree break gradblocks = _gto_grad.findall(chunk) if gradblocks: gradblock = gradblocks[-1].strip().split('\n') natoms = len(gradblock) symbols = [] pos = np.zeros((natoms, 3)) forces = np.zeros((natoms, 3)) for i, line in enumerate(gradblock): line = line.strip().split() symbols.append(line[1]) pos[i] = [float(x) for x in line[2:5]] forces[i] = [-float(x) for x in line[5:8]] pos *= Bohr forces *= Hartree / Bohr atoms = Atoms(symbols, positions=pos) dipole, quadrupole = _get_multipole(chunk) kpts = _get_gto_kpts(chunk) atoms_new = _parse_geomblock(chunk) if atoms_new is not None: atoms = atoms_new if atoms is None: return # SinglePointDFTCalculator doesn't support quadrupole moment currently calc = SinglePointDFTCalculator( atoms=atoms, energy=energy, forces=forces, dipole=dipole, # quadrupole=quadrupole, ) calc.kpts = kpts atoms.calc = calc return atoms
def test_singlepoint_dft_calc(): import numpy as np from ase.calculators.singlepoint import (SinglePointDFTCalculator, arrays_to_kpoints) from ase.build import bulk rng = np.random.RandomState(17) nspins, nkpts, nbands = shape = 2, 4, 5 eps = 2 * rng.rand(*shape) occ = rng.rand(*shape) weights = rng.rand(nkpts) kpts = arrays_to_kpoints(eps, occ, weights) atoms = bulk('Au') calc = SinglePointDFTCalculator(atoms) calc.kpts = kpts assert calc.get_number_of_spins() == nspins assert calc.get_spin_polarized() assert np.allclose(calc.get_k_point_weights(), weights) for s in range(nspins): for k in range(nkpts): eps1 = calc.get_eigenvalues(kpt=k, spin=s) occ1 = calc.get_occupation_numbers(kpt=k, spin=s) assert np.allclose(eps1, eps[s, k]) assert np.allclose(occ1, occ[s, k])
def parse_pw_chunk(chunk): atoms = _parse_geomblock(chunk) if atoms is None: return energy = None efermi = None forces = None stress = None matches = _nwpw_energy.findall(chunk) if matches: energy = float(matches[-1].replace('D', 'E')) * Hartree matches = _fermi_energy.findall(chunk) if matches: efermi = float(matches[-1].replace('D', 'E')) * Hartree gradblocks = _nwpw_grad.findall(chunk) if not gradblocks: gradblocks = _paw_grad.findall(chunk) if gradblocks: gradblock = gradblocks[-1].strip().split('\n') natoms = len(gradblock) symbols = [] forces = np.zeros((natoms, 3)) for i, line in enumerate(gradblock): line = line.strip().split() symbols.append(line[1]) forces[i] = [float(x) for x in line[3:6]] forces *= Hartree / Bohr if atoms.cell: stress = _get_stress(chunk, atoms.cell) ibz_kpts, kpts = _get_pw_kpts(chunk) # NWChem does not calculate an energy extrapolated to the 0K limit, # so right now, energy and free_energy will be the same. calc = SinglePointDFTCalculator(atoms=atoms, energy=energy, efermi=efermi, free_energy=energy, forces=forces, stress=stress, ibzkpts=ibz_kpts) calc.kpts = kpts atoms.calc = calc return atoms
def test_dos(): from ase.atoms import Atoms from ase.calculators.singlepoint import SinglePointDFTCalculator from ase.calculators.singlepoint import SinglePointKPoint from ase.dft.dos import DOS atoms = Atoms('H') eFermi = [0, 1] kpts = [SinglePointKPoint(1, 0, 0), SinglePointKPoint(1, 1, 0)] kpts[0].eps_n = [-2, -1, 1] kpts[0].f_n = [1, 0, 0] kpts[1].eps_n = [-2.5, -1.5, 0.5] kpts[1].f_n = [1, 0, 0] calc = SinglePointDFTCalculator(atoms, efermi=eFermi) calc.kpts = kpts DOS(calc)
def read_wann2kc_out(fileobj): """Reads Wannier to KC output files. Parameters ---------- fileobj : file|str A file like object or filename Yields ------ structure : Atoms The next structure from the index slice. The Atoms has a SinglePointCalculator attached with any results parsed from the file. """ if isinstance(fileobj, basestring): fileobj = open(fileobj, 'rU') # work with a copy in memory for faster random access flines = fileobj.readlines() # For the moment, provide an empty atoms object structure = Atoms() # Extract calculation results walltime = None job_done = False for line in flines: if 'JOB DONE' in line: job_done = True if 'KC_WANN :' in line: time_str = line.split()[-2] walltime = time_to_float(time_str) # Return an empty calculator object with ths solitary result 'job done' calc = SinglePointDFTCalculator(structure) calc.results['job_done'] = job_done calc.results['walltime'] = walltime structure.calc = calc yield structure
def read_koopmans_screen_out(fileobj): """Reads Koopmans Screen output files. Will probably raise errors for broken or incomplete files. Parameters ---------- fileobj : file|str A file like object or filename Yields ------ structure : Atoms The next structure from the index slice. The Atoms has a SinglePointCalculator attached with any results parsed from the file. """ if isinstance(fileobj, basestring): fileobj = open(fileobj, 'rU') # work with a copy in memory for faster random access flines = fileobj.readlines() # For the moment, provide an empty atoms object structure = Atoms() # Extract calculation results job_done = False walltime = None alphas = [[]] orbital_data = {'self-Hartree': []} for i_line, line in enumerate(flines): if 'relaxed' in line: splitline = line.split() alphas[-1].append(float(splitline[-5])) orbital_data['self-Hartree'].append( float(splitline[-1]) * units.Ry) if 'JOB DONE' in line: job_done = True if 'KC_WANN :' in line: time_str = line.split()[-2] walltime = time_to_float(time_str) # Put everything together calc = SinglePointDFTCalculator(structure) calc.results['job_done'] = job_done calc.results['walltime'] = walltime calc.results['alphas'] = alphas calc.results['orbital_data'] = orbital_data structure.calc = calc yield structure
def read_gpw(filename): try: reader = ulm.open(filename) except ulm.InvalidULMFileError: return read_old_gpw(filename) atoms = read_atoms(reader.atoms, _try_except=False) wfs = reader.wave_functions kpts = wfs.get('kpts') if kpts is None: ibzkpts = None bzkpts = None bz2ibz = None else: ibzkpts = kpts.ibzkpts bzkpts = kpts.get('bzkpts') bz2ibz = kpts.get('bz2ibz') if reader.version >= 3: efermi = reader.wave_functions.fermi_levels.mean() else: efermi = reader.occupations.fermilevel atoms.calc = SinglePointDFTCalculator(atoms, efermi=efermi, ibzkpts=ibzkpts, bzkpts=bzkpts, bz2ibz=bz2ibz, **reader.results.asdict()) if kpts is not None: atoms.calc.kpts = [] spin = 0 for eps_kn, f_kn in zip(wfs.eigenvalues, wfs.occupations): kpt = 0 for weight, eps_n, f_n in zip(kpts.weights, eps_kn, f_kn): atoms.calc.kpts.append( SinglePointKPoint(weight, spin, kpt, eps_n, f_n)) kpt += 1 spin += 1 return atoms
def read_old_gpw(filename): from gpaw.io.tar import Reader r = Reader(filename) positions = r.get('CartesianPositions') * Bohr numbers = r.get('AtomicNumbers') cell = r.get('UnitCell') * Bohr pbc = r.get('BoundaryConditions') tags = r.get('Tags') magmoms = r.get('MagneticMoments') energy = r.get('PotentialEnergy') * Hartree if r.has_array('CartesianForces'): forces = r.get('CartesianForces') * Hartree / Bohr else: forces = None atoms = Atoms(positions=positions, numbers=numbers, cell=cell, pbc=pbc) if tags.any(): atoms.set_tags(tags) if magmoms.any(): atoms.set_initial_magnetic_moments(magmoms) magmom = magmoms.sum() else: magmoms = None magmom = None atoms.calc = SinglePointDFTCalculator(atoms, energy=energy, forces=forces, magmoms=magmoms, magmom=magmom) kpts = [] if r.has_array('IBZKPoints'): for w, kpt, eps_n, f_n in zip(r.get('IBZKPointWeights'), r.get('IBZKPoints'), r.get('Eigenvalues'), r.get('OccupationNumbers')): kpts.append(SinglePointKPoint(w, kpt[0], kpt[1], eps_n[0], f_n[0])) atoms.calc.kpts = kpts return atoms
from ase.build import bulk rng = np.random.RandomState(17) nspins, nkpts, nbands = shape = 2, 4, 5 eps = 2 * rng.rand(*shape) occ = rng.rand(*shape) weights = rng.rand(nkpts) kpts = arrays_to_kpoints(eps, occ, weights) atoms = bulk('Au') calc = SinglePointDFTCalculator(atoms) calc.kpts = kpts assert calc.get_number_of_spins() == nspins assert calc.get_spin_polarized() assert np.allclose(calc.get_k_point_weights(), weights) for s in range(nspins): for k in range(nkpts): eps1 = calc.get_eigenvalues(kpt=k, spin=s) occ1 = calc.get_occupation_numbers(kpt=k, spin=s) assert np.allclose(eps1, eps[s, k]) assert np.allclose(occ1, occ[s, k])
def read_magres(fd, include_unrecognised=False): """ Reader function for magres files. """ blocks_re = re.compile(r'[\[<](?P<block_name>.*?)[>\]](.*?)[<\[]/' + r'(?P=block_name)[\]>]', re.M | re.S) """ Here are defined the various functions required to parse different blocks. """ def tensor33(x): return np.squeeze(np.reshape(x, (3, 3))).tolist() def tensor31(x): return np.squeeze(np.reshape(x, (3, 1))).tolist() def get_version(file_contents): """ Look for and parse the magres file format version line """ lines = file_contents.split('\n') match = re.match(r'\#\$magres-abinitio-v([0-9]+).([0-9]+)', lines[0]) if match: version = match.groups() version = tuple(vnum for vnum in version) else: version = None return version def parse_blocks(file_contents): """ Parse series of XML-like deliminated blocks into a list of (block_name, contents) tuples """ blocks = blocks_re.findall(file_contents) return blocks def parse_block(block): """ Parse block contents into a series of (tag, data) records """ def clean_line(line): # Remove comments and whitespace at start and ends of line line = re.sub('#(.*?)\n', '', line) line = line.strip() return line name, data = block lines = [clean_line(line) for line in data.split('\n')] records = [] for line in lines: xs = line.split() if len(xs) > 0: tag = xs[0] data = xs[1:] records.append((tag, data)) return (name, records) def check_units(d): """ Verify that given units for a particular tag are correct. """ allowed_units = {'lattice': 'Angstrom', 'atom': 'Angstrom', 'ms': 'ppm', 'efg': 'au', 'efg_local': 'au', 'efg_nonlocal': 'au', 'isc': '10^19.T^2.J^-1', 'isc_fc': '10^19.T^2.J^-1', 'isc_orbital_p': '10^19.T^2.J^-1', 'isc_orbital_d': '10^19.T^2.J^-1', 'isc_spin': '10^19.T^2.J^-1', 'isc': '10^19.T^2.J^-1', 'sus': '10^-6.cm^3.mol^-1', 'calc_cutoffenergy': 'Hartree', } if d[0] in d and d[1] == allowed_units[d[0]]: pass else: raise RuntimeError('Unrecognized units: %s %s' % (d[0], d[1])) return d def parse_magres_block(block): """ Parse magres block into data dictionary given list of record tuples. """ name, records = block # 3x3 tensor def ntensor33(name): return lambda d: {name: tensor33([float(x) for x in data])} # Atom label, atom index and 3x3 tensor def sitensor33(name): return lambda d: {'atom': {'label': data[0], 'index': int(data[1])}, name: tensor33([float(x) for x in data[2:]])} # 2x(Atom label, atom index) and 3x3 tensor def sisitensor33(name): return lambda d: {'atom1': {'label': data[0], 'index': int(data[1])}, 'atom2': {'label': data[2], 'index': int(data[3])}, name: tensor33([float(x) for x in data[4:]])} tags = {'ms': sitensor33('sigma'), 'sus': ntensor33('S'), 'efg': sitensor33('V'), 'efg_local': sitensor33('V'), 'efg_nonlocal': sitensor33('V'), 'isc': sisitensor33('K'), 'isc_fc': sisitensor33('K'), 'isc_spin': sisitensor33('K'), 'isc_orbital_p': sisitensor33('K'), 'isc_orbital_d': sisitensor33('K'), 'units': check_units} data_dict = {} for record in records: tag, data = record if tag not in data_dict: data_dict[tag] = [] data_dict[tag].append(tags[tag](data)) return data_dict def parse_atoms_block(block): """ Parse atoms block into data dictionary given list of record tuples. """ name, records = block # Lattice record: a1, a2 a3, b1, b2, b3, c1, c2 c3 def lattice(d): return tensor33([float(x) for x in data]) # Atom record: label, index, x, y, z def atom(d): return {'species': data[0], 'label': data[1], 'index': int(data[2]), 'position': tensor31([float(x) for x in data[3:]])} def symmetry(d): return ' '.join(data) tags = {'lattice': lattice, 'atom': atom, 'units': check_units, 'symmetry': symmetry} data_dict = {} for record in records: tag, data = record if tag not in data_dict: data_dict[tag] = [] data_dict[tag].append(tags[tag](data)) return data_dict def parse_generic_block(block): """ Parse any other block into data dictionary given list of record tuples. """ name, records = block data_dict = {} for record in records: tag, data = record if tag not in data_dict: data_dict[tag] = [] data_dict[tag].append(data) return data_dict """ Actual parser code. """ block_parsers = {'magres': parse_magres_block, 'atoms': parse_atoms_block, 'calculation': parse_generic_block, } file_contents = fd.read() # This works as a validity check version = get_version(file_contents) if version is None: # This isn't even a .magres file! raise RuntimeError('File is not in standard Magres format') blocks = parse_blocks(file_contents) data_dict = {} for block_data in blocks: block = parse_block(block_data) if block[0] in block_parsers: block_dict = block_parsers[block[0]](block) data_dict[block[0]] = block_dict else: # Throw in the text content of blocks we don't recognise if include_unrecognised: data_dict[block[0]] = block_data[1] # Now the loaded data must be turned into an ASE Atoms object # First check if the file is even viable if 'atoms' not in data_dict: raise RuntimeError('Magres file does not contain structure data') # Allowed units handling. This is redundant for now but # could turn out useful in the future magres_units = {'Angstrom': ase.units.Ang} # Lattice parameters? if 'lattice' in data_dict['atoms']: try: u = dict(data_dict['atoms']['units'])['lattice'] except KeyError: raise RuntimeError('No units detected in file for lattice') u = magres_units[u] cell = np.array(data_dict['atoms']['lattice'][0]) * u pbc = True else: cell = None pbc = False # Now the atoms symbols = [] positions = [] indices = [] labels = [] if 'atom' in data_dict['atoms']: try: u = dict(data_dict['atoms']['units'])['atom'] except KeyError: raise RuntimeError('No units detected in file for atom positions') u = magres_units[u] # Now we have to account for the possibility of there being CASTEP # 'custom' species amongst the symbols custom_species = None for a in data_dict['atoms']['atom']: spec_custom = a['species'].split(':', 1) if len(spec_custom) > 1 and custom_species is None: # Add it to the custom info! custom_species = list(symbols) symbols.append(spec_custom[0]) positions.append(a['position']) indices.append(a['index']) labels.append(a['label']) if custom_species is not None: custom_species.append(a['species']) atoms = Atoms(cell=cell, pbc=pbc, symbols=symbols, positions=positions) # Add custom species if present if custom_species is not None: atoms.new_array('castep_custom_species', np.array(custom_species)) # Add the spacegroup, if present and recognizable if 'symmetry' in data_dict['atoms']: try: spg = Spacegroup(data_dict['atoms']['symmetry'][0]) except: # Not found spg = Spacegroup(1) # Most generic one atoms.info['spacegroup'] = spg # Set up the rest of the properties as arrays atoms.new_array('indices', np.array(indices)) atoms.new_array('labels', np.array(labels)) # Now for the magres specific stuff li_list = list(zip(labels, indices)) def create_magres_array(name, order, block): if order == 1: u_arr = [None] * len(li_list) elif order == 2: u_arr = [[None] * (i + 1) for i in range(len(li_list))] else: raise ValueError( 'Invalid order value passed to create_magres_array') for s in block: # Find the atom index/indices if order == 1: # First find out which atom this is at = (s['atom']['label'], s['atom']['index']) try: ai = li_list.index(at) except ValueError: raise RuntimeError('Invalid data in magres block') # Then add the relevant quantity u_arr[ai] = s[mn] else: at1 = (s['atom1']['label'], s['atom1']['index']) at2 = (s['atom2']['label'], s['atom2']['index']) ai1 = li_list.index(at1) ai2 = li_list.index(at2) # Sort them ai1, ai2 = sorted((ai1, ai2), reverse=True) u_arr[ai1][ai2] = s[mn] return np.array(u_arr) if 'magres' in data_dict: if 'units' in data_dict['magres']: atoms.info['magres_units'] = dict(data_dict['magres']['units']) for u in atoms.info['magres_units']: # This bit to keep track of tags u0 = u.split('_')[0] if u0 not in _mprops: raise RuntimeError('Invalid data in magres block') mn, order = _mprops[u0] if order > 0: u_arr = create_magres_array(mn, order, data_dict['magres'][u]) atoms.new_array(u, u_arr) else: # atoms.info['magres_data'] = atoms.info.get('magres_data', # {}) # # We only take element 0 because for this sort of data # # there should be only that # atoms.info['magres_data'][u] = data_dict['magres'][u][0][mn] if atoms.calc is None: calc = SinglePointDFTCalculator(atoms) atoms.set_calculator(calc) atoms.calc.results[u] = data_dict['magres'][u][0][mn] if 'calculation' in data_dict: atoms.info['magresblock_calculation'] = data_dict['calculation'] if include_unrecognised: for b in data_dict: if b not in block_parsers: atoms.info['magresblock_' + b] = data_dict[b] return atoms
from ase.atoms import Atoms from ase.calculators.singlepoint import SinglePointDFTCalculator from ase.calculators.singlepoint import SinglePointKPoint from ase.dft.dos import DOS atoms = Atoms('H') eFermi = [0, 1] kpts = [SinglePointKPoint(1, 0, 0), SinglePointKPoint(1, 1, 0)] kpts[0].eps_n = [-2, -1, 1] kpts[0].f_n = [1, 0, 0] kpts[1].eps_n = [-2.5, -1.5, 0.5] kpts[1].f_n = [1, 0, 0] calc = SinglePointDFTCalculator(atoms, efermi=eFermi) calc.kpts = kpts dos = DOS(calc)
import numpy as np from ase.io import read, write from ase.build import bulk from ase.calculators.singlepoint import SinglePointDFTCalculator # Test with fictional data si2 = bulk('Si') ms = np.ones((2, 3, 3)) si2.set_array('ms', ms) efg = np.repeat([[[1, 0, 0], [0, 1, 0], [0, 0, -2]]], 2, axis=0) si2.set_array('efg', efg) calc = SinglePointDFTCalculator(si2) calc.results['sus'] = np.eye(3) * 2 si2.set_calculator(calc) si2.info['magres_units'] = { 'ms': 'ppm', 'efg': 'au', 'sus': '10^-6.cm^3.mol^-1' } write('si2_test.magres', si2) si2 = read('si2_test.magres') assert (np.trace(si2.get_array('ms')[0]) == 3) assert (np.all(np.isclose(si2.get_array('efg')[:, 2, 2], -2))) assert (np.all(np.isclose(si2.calc.results['sus'], np.eye(3) * 2)))
def calc_fcs( phono3py, calc, unitcell_f='Unknown', cp_files=None, sym_fc=True, fc_calc=None, r_cut=None, ): """ fc_calc: None or 'alm' r_cut: None or float. Use hiPhive if provided. """ # Check if structure is lower triangular cell for c in ((0, 1), (0, 2), (1, 2)): if phono3py.primitive.get_cell()[c[0], c[1]] != 0. and calc == 'lmp': raise ValueError('Please provide lower triangular cell.') # phono3py.generate_displacements() fc2_snd = phono3py.get_phonon_supercells_with_displacements() fc3_snd = phono3py.get_supercells_with_displacements() fc2_job_name = '{}-x{}{}{}_d0.010_sym{}-fc2'.format( calc, *np.diag(phono3py.get_phonon_supercell_matrix()), phono3py._is_symmetry, ) fc3_job_name = '{}-x{}{}{}_d0.030_sym{}-fc3'.format( calc, *np.diag(phono3py.get_supercell_matrix()), phono3py._is_symmetry, ) fc2_npy_name = '{}-forces.npy'.format(fc2_job_name) fc3_npy_name = '{}-forces.npy'.format(fc3_job_name) calc_dir = 'calcs' fc2_path = '{}/{}'.format(calc_dir, fc2_job_name) fc3_path = '{}/{}'.format(calc_dir, fc3_job_name) # from phonopy.interface.vasp import write_vasp call('mkdir -p {}/poscars'.format(fc2_path), shell=True) write_vasp('{}/poscars/SPOSCAR'.format(fc2_path), phono3py.get_phonon_supercell()) for i in range(len(fc2_snd)): write_vasp('{}/poscars/POSCAR-{:03d}'.format(fc2_path, i + 1), fc2_snd[i]) # call('mkdir -p {}/poscars'.format(fc3_path), shell=True) write_vasp('{}/poscars/SPOSCAR'.format(fc3_path), phono3py.get_supercell()) for i in range(len(fc3_snd)): write_vasp('{}/poscars/POSCAR-{:05d}'.format(fc3_path, i + 1), fc3_snd[i]) try: fc2_forces = np.load(fc2_npy_name) except: calc_fc2 = True print('\n*** NOTE) Failed to load {} file. ***\n'.format(fc2_npy_name)) else: calc_fc2 = False print('\n=== NOTE) Loaded: {} ===\n'.format(fc2_npy_name)) if calc_fc2: print('=== NOTE) Starting fc2 calculations! ===\n') fc2_forces = [] for i in range(len(fc2_snd)): folder = 'disp-{:03d}'.format(i + 1) wdir = '{}/{}'.format(fc2_path, folder) budir = '{}/bu-{}'.format(fc2_path, folder) call('rm -rf {}'.format(budir), shell=True) call('mv {} {}'.format(wdir, budir), shell=True) call('mkdir -p {}'.format(wdir), shell=True) write_vasp('{}/POSCAR'.format(wdir), fc2_snd[i]) fc2_forces.append(_calc_forces(wdir, calc, cp_files)) print(' == Progress: {}/{}'.format(i + 1, len(fc2_snd))) np.save(fc2_npy_name, fc2_forces) try: fc3_forces = np.load(fc3_npy_name) except: calc_fc3 = True print('\n*** NOTE) Failed to load {} file. ***\n'.format(fc3_npy_name)) else: calc_fc3 = False print('\n=== NOTE) Loaded: {} ===\n'.format(fc3_npy_name)) if calc_fc3: print('=== NOTE) Starting fc3 calculations! ===\n') fc3_forces = [] for i in range(len(fc3_snd)): folder = 'disp-{:05d}'.format(i + 1) wdir = '{}/{}'.format(fc3_path, folder) budir = '{}/bu-{}'.format(fc3_path, folder) call('rm -rf {}'.format(budir), shell=True) call('mv {} {}'.format(wdir, budir), shell=True) call('mkdir -p {}'.format(wdir), shell=True) write_vasp('{}/POSCAR'.format(wdir), fc3_snd[i]) fc3_forces.append(_calc_forces(wdir, calc, cp_files)) print(' == Progress: {}/{}'.format(i + 1, len(fc3_snd))) np.save(fc3_npy_name, fc3_forces) # phono3py.phonon_forces = np.array(fc2_forces) phono3py.forces = np.array(fc3_forces) # phono3py.produce_fc3( symmetrize_fc3r=sym_fc, fc_calculator=fc_calc, ) phono3py.produce_fc2( symmetrize_fc2=sym_fc, fc_calculator=fc_calc, ) if r_cut: # from ase.io import read from ase.calculators.singlepoint import SinglePointDFTCalculator fc2_disp_ds = phono3py.get_phonon_displacement_dataset()['first_atoms'] fc2_sposcar = read('{}/poscars/SPOSCAR'.format(fc2_path)) fc2_supers = [] for i in range(len(fc2_disp_ds)): displacements = np.zeros(fc2_sposcar.get_positions().shape, dtype=float) displacements[fc2_disp_ds[i] ['number']] += fc2_disp_ds[i]['displacement'] fc2_supers.append(fc2_sposcar.copy()) fc2_supers[-1].new_array( 'displacements', displacements, ) fc2_supers[-1]._calc = SinglePointDFTCalculator(fc2_supers[-1]) fc2_supers[-1]._calc.results['forces'] = fc2_disp_ds[i]['forces'] # rotational sum rule from hiphive import ForceConstants, ClusterSpace, StructureContainer cs = ClusterSpace(fc2_sposcar, [r_cut]) sc = StructureContainer(cs) for s in fc2_supers: sc.add_structure(s) from hiphive.fitting import Optimizer opt = Optimizer(sc.get_fit_data(), train_size=1.0) opt.train() print(opt) parameters = opt.parameters from hiphive import ForceConstantPotential, enforce_rotational_sum_rules parameters_rot = enforce_rotational_sum_rules(cs, parameters, ['Huang', 'Born-Huang']) fcp_rot = ForceConstantPotential(cs, parameters_rot) fcs = fcp_rot.get_force_constants(fc2_sposcar).get_fc_array(order=2) phono3py.set_fc2(fcs) # # Not implemented yet in hiPhive # fc3_disp_ds = phono3py.get_displacement_dataset()['first_atoms'] # fc3_sposcar = read('{}/poscars/SPOSCAR'.format(fc3_path)) # fc3_supers = [] # for i in range(len(fc3_disp_ds)): # displacements_1st = np.zeros(fc3_sposcar.get_positions().shape, dtype=float) # displacements_1st[fc3_disp_ds[i]['number']] += fc3_disp_ds[i]['displacement'] # for j in range(len(fc3_disp_ds[i]['second_atoms'])): # displacements_2nd = np.zeros(fc3_sposcar.get_positions().shape, dtype=float) # displacements_2nd[fc3_disp_ds[i]['second_atoms'][j]['number']] += fc3_disp_ds[i]['second_atoms'][j]['displacement'] # displacements = displacements_1st + displacements_2nd # fc3_supers.append(fc3_sposcar.copy()) # fc3_supers[-1].new_array( # 'displacements', # displacements, # ) # fc3_supers[-1]._calc = SinglePointDFTCalculator(fc3_supers[-1]) # fc3_supers[-1]._calc.results['forces'] = fc3_disp_ds[i]['second_atoms'][j]['forces'] return phono3py
def read_gpaw_text(fileobj, index=-1): if isinstance(fileobj, str): fileobj = open(fileobj, "rU") notfound = [] def index_startswith(lines, string): if string in notfound: raise ValueError for i, line in enumerate(lines): if line.startswith(string): return i notfound.append(string) raise ValueError lines = fileobj.readlines() images = [] while True: try: i = lines.index("Unit Cell:\n") except ValueError: pass else: cell = [] pbc = [] for line in lines[i + 3 : i + 6]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == "yes") else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == "yes") try: i = lines.index("Positions:\n") except ValueError: break symbols = [] positions = [] for line in lines[i + 1 :]: words = line.split() if len(words) != 5: break n, symbol, x, y, z = words symbols.append(symbol.split(".")[0]) positions.append([float(x), float(y), float(z)]) if len(symbols): atoms = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) else: atoms = Atoms(cell=cell, pbc=pbc) lines = lines[i + 5 :] try: ii = index_startswith(lines, "Reference Energy:") Eref = float(lines[ii].split()[-1]) except ValueError: Eref = None ene = { # key position "Kinetic:": 1, "Potential:": 2, "XC:": 4, } try: i = lines.index("-------------------------\n") except ValueError: e = None else: for key in ene: pos = ene[key] ene[key] = None line = lines[i + pos] try: assert line.startswith(key) ene[key] = float(line.split()[-1]) except ValueError: pass line = lines[i + 9] assert line.startswith("Zero Kelvin:") e = float(line.split()[-1]) try: ii = index_startswith(lines, "Fermi Level") except ValueError: eFermi = None else: try: eFermi = float(lines[ii].split()[2]) except ValueError: # we have two Fermi levels fields = lines[ii].split() def strip(string): for rubbish in "[],": string = string.replace(rubbish, "") return string eFermi = [float(strip(fields[2])), float(strip(fields[3]))] # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, " Band Eigenvalues Occupancy") except ValueError: pass try: ii2 = index_startswith(lines, " Band Eigenvalues Occupancy") except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while len(words) > 2: vals.append([float(word) for word in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(1, 0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(1, 1, 0)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, "Total Charge:") except ValueError: q = None else: q = float(lines[ii].split()[2]) # read dipole moment try: ii = index_startswith(lines, "Dipole Moment:") except ValueError: dipole = None else: line = lines[ii].replace("]", "").replace("[", "") dipole = np.array([float(c) for c in line.split()[-3:]]) try: ii = index_startswith(lines, "Local Magnetic Moments") except ValueError: magmoms = None else: magmoms = [] for i in range(ii + 1, ii + 1 + len(atoms)): iii, magmom = lines[i].split()[:2] magmoms.append(float(magmom)) try: ii = lines.index("Forces in eV/Ang:\n") except ValueError: f = None else: f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError), m: raise IOError("Malformed GPAW log file: %s" % m) if len(images) > 0 and e is None: break if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_initial_charges([q / n] * n) if e is not None or f is not None: calc = SinglePointDFTCalculator( atoms, energy=e, forces=f, dipole=dipole, magmoms=magmoms, eFermi=eFermi, Eref=Eref ) if kpts is not None: calc.kpts = kpts atoms.set_calculator(calc) images.append(atoms) lines = lines[i:]
def read_gpaw_text(fileobj, index=-1): if isinstance(fileobj, str): fileobj = open(fileobj) def index_startswith(lines, string): for i, line in enumerate(lines): if line.startswith(string): return i raise ValueError lines = fileobj.readlines() images = [] while True: try: i = lines.index('Unit Cell:\n') except ValueError: pass else: cell = [] pbc = [] for line in lines[i + 3:i + 6]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') try: i = lines.index('Positions:\n') except ValueError: break atoms = Atoms(cell=cell, pbc=pbc) for line in lines[i + 1:]: words = line.split() if len(words) != 5: break n, symbol, x, y, z = words symbol = symbol.split('.')[0] atoms.append(Atom(symbol, [float(x), float(y), float(z)])) lines = lines[i + 5:] try: i = lines.index('-------------------------\n') except ValueError: e = None else: line = lines[i + 9] assert line.startswith('Zero Kelvin:') e = float(line.split()[-1]) try: ii = index_startswith(lines, 'Fermi Level:') except ValueError: eFermi = None else: try: eFermi = float(lines[ii].split()[2]) except ValueError: # we have two Fermi levels fields = lines[ii].split() def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[2])), float(strip(fields[3]))] try: ii = index_startswith(lines, 'Total Charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) try: ii = index_startswith(lines, 'Local Magnetic Moments') except ValueError: magmoms = None else: magmoms = [] for i in range(ii + 1, ii + 1 + len(atoms)): iii, magmom = lines[i].split()[:2] magmoms.append(float(magmom)) try: ii = lines.index('Forces in eV/Ang:\n') except ValueError: f = None else: f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError), m: raise IOError('Malformed GPAW log file: %s' % m) if len(images) > 0 and e is None: break if e is not None or f is not None: calc = SinglePointDFTCalculator(e, f, None, magmoms, atoms, eFermi) atoms.set_calculator(calc) if q is not None: n = len(atoms) atoms.set_charges([q / n] * n) images.append(atoms) lines = lines[i:]
def read_gpaw_out(fileobj, index): if isinstance(fileobj, str): fileobj = open(fileobj, 'rU') notfound = [] def index_startswith(lines, string): if string in notfound: raise ValueError for i, line in enumerate(lines): if line.startswith(string): return i notfound.append(string) raise ValueError def index_pattern(lines, pattern): repat = re.compile(pattern) if pattern in notfound: raise ValueError for i, line in enumerate(lines): if repat.match(line): return i notfound.append(pattern) raise ValueError def read_forces(lines, ii): f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError) as m: raise IOError('Malformed GPAW log file: %s' % m) return f, i lines = fileobj.readlines() images = [] while True: try: i = lines.index('Unit Cell:\n') except ValueError: pass else: cell = [] pbc = [] for line in lines[i + 3:i + 6]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') try: i = lines.index('Positions:\n') except ValueError: break symbols = [] positions = [] for line in lines[i + 1:]: words = line.split() if len(words) != 5: break n, symbol, x, y, z = words symbols.append(symbol.split('.')[0]) positions.append([float(x), float(y), float(z)]) if len(symbols): atoms = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) else: atoms = Atoms(cell=cell, pbc=pbc) lines = lines[i + 5:] try: ii = index_startswith(lines, 'Reference Energy:') Eref = float(lines[ii].split()[-1]) except ValueError: Eref = None try: ii = index_pattern(lines, '\d+ k-point') word = lines[ii].split() kx = int(word[2]) ky = int(word[4]) kz = int(word[6]) bz_kpts = (kx, ky, kz) ibz_kpts = int(lines[ii + 1].split()[0]) except (ValueError, TypeError): bz_kpts = None ibz_kpts = None ene = { # key position 'Kinetic:': 1, 'Potential:': 2, 'XC:': 4} try: i = lines.index('-------------------------\n') except ValueError: e = None else: for key in ene: pos = ene[key] ene[key] = None line = lines[i + pos] try: assert line.startswith(key) ene[key] = float(line.split()[-1]) except ValueError: pass line = lines[i + 9] assert line.startswith('Zero Kelvin:') e = float(line.split()[-1]) try: ii = index_startswith(lines, 'Fermi Level') except ValueError: eFermi = None else: try: eFermi = float(lines[ii].split()[2]) except ValueError: # we have two Fermi levels fields = lines[ii].split() def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[2])), float(strip(fields[3]))] # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, ' Band Eigenvalues Occupancy') except ValueError: pass try: ii2 = index_startswith(lines, ' Band Eigenvalues Occupancy') except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while(len(words) > 2): vals.append([float(w) for w in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(1, 0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(1, 1, 0)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, 'Total Charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) # read dipole moment try: ii = index_startswith(lines, 'Dipole Moment:') except ValueError: dipole = None else: line = lines[ii].replace(']', '').replace('[', '') dipole = np.array([float(c) for c in line.split()[-3:]]) try: ii = index_startswith(lines, 'Local Magnetic Moments') except ValueError: magmoms = None else: magmoms = [] for i in range(ii + 1, ii + 1 + len(atoms)): iii, magmom = lines[i].split()[:2] magmoms.append(float(magmom)) try: ii = lines.index('Forces in eV/Ang:\n') except ValueError: f = None else: f, i = read_forces(lines, ii) try: ii = index_startswith(lines, 'vdW correction:') except ValueError: pass else: line = lines[ii + 1] assert line.startswith('Energy:') e = float(line.split()[-1]) f, i = read_forces(lines, ii + 3) if len(images) > 0 and e is None: break if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_initial_charges([q / n] * n) if e is not None or f is not None: calc = SinglePointDFTCalculator(atoms, energy=e, forces=f, dipole=dipole, magmoms=magmoms, eFermi=eFermi, Eref=Eref, bz_kpts=bz_kpts, ibz_kpts=ibz_kpts) calc.name = 'gpaw' if kpts is not None: calc.kpts = kpts atoms.set_calculator(calc) if magmoms is not None: atoms.set_initial_magnetic_moments(magmoms) images.append(atoms) lines = lines[i:] if len(images) == 0: raise IOError('Corrupted GPAW-text file!') return images[index]
def get_atoms(structure, **kwargs): """ Returns ASE Atoms object from pymatgen structure or molecule. Args: structure: pymatgen.core.structure.Structure or pymatgen.core.structure.Molecule **kwargs: other keyword args to pass into the ASE Atoms constructor Returns: ASE Atoms object """ if not structure.is_ordered: raise ValueError("ASE Atoms only supports ordered structures") if not ase_loaded: raise ImportError( "AseAtomsAdaptor requires the ASE package.\nUse `pip install ase` or `conda install ase -c conda-forge`" ) # Construct the base ASE Atoms object symbols = [str(site.specie.symbol) for site in structure] positions = [site.coords for site in structure] if hasattr(structure, "lattice"): cell = structure.lattice.matrix pbc = True else: cell = None pbc = None atoms = Atoms(symbols=symbols, positions=positions, pbc=pbc, cell=cell, **kwargs) # Set the site magmoms in the ASE Atoms object # Note: ASE distinguishes between initial and converged # magnetic moment site properties, whereas pymatgen does not. Therefore, we # have to distinguish between these two when constructing the Structure/Molecule. # The mapping selected here is: # ASE initial magmom <--> Pymatgen "magmom" # ASE final magmom <--> Pymatgen "final_magmom" # ASE initial charge <--> Pymatgen "charge" # ASE final charge <--> Pymatgen "final_charge" if "magmom" in structure.site_properties: initial_magmoms = structure.site_properties["magmom"] atoms.set_initial_magnetic_moments(initial_magmoms) if "charge" in structure.site_properties: initial_charges = structure.site_properties["charge"] atoms.set_initial_charges(initial_charges) if "final_magmom" in structure.site_properties: magmoms = structure.site_properties["final_magmom"] else: magmoms = None if "final_charge" in structure.site_properties: charges = structure.site_properties["final_charge"] else: charges = None if magmoms or charges: if magmoms and charges: calc = SinglePointDFTCalculator( atoms, **{ "magmoms": magmoms, "charges": charges }) elif magmoms: calc = SinglePointDFTCalculator(atoms, **{"magmoms": magmoms}) elif charges: calc = SinglePointDFTCalculator(atoms, **{"charges": charges}) atoms.calc = calc # Get the oxidation states from the structure oxi_states = [ getattr(site.specie, "oxi_state", None) for site in structure ] # Read in selective dynamics if present. Note that the ASE FixAtoms class fixes (x,y,z), so # here we make sure that [False, False, False] or [True, True, True] is set for the site selective # dynamics property. As a consequence, if only a subset of dimensions are fixed, this won't get passed to ASE. if "selective_dynamics" in structure.site_properties: fix_atoms = [] for site in structure: site_prop = site.properties["selective_dynamics"] if site_prop not in [[True, True, True], [False, False, False]]: raise ValueError( "ASE FixAtoms constraint does not support selective dynamics in only some dimensions." "Remove the selective dynamics and try again if you do not need them." ) is_fixed = bool(~np.all(site.properties["selective_dynamics"])) fix_atoms.append(is_fixed) else: fix_atoms = None # Set the selective dynamics with the FixAtoms class. if fix_atoms is not None: atoms.set_constraint(FixAtoms(mask=fix_atoms)) # Add any remaining site properties to the ASE Atoms object for prop in structure.site_properties: if prop not in [ "magmom", "charge", "final_magmom", "final_charge", "selective_dynamics" ]: atoms.set_array(prop, np.array(structure.site_properties[prop])) if np.any(oxi_states): atoms.set_array("oxi_states", np.array(oxi_states)) return atoms
def read_pw_out(fileobj, index=-1, results_required=True): """Reads Quantum ESPRESSO output files. The atomistic configurations as well as results (energy, force, stress, magnetic moments) of the calculation are read for all configurations within the output file. Will probably raise errors for broken or incomplete files. Parameters ---------- fileobj : file|str A file like object or filename index : slice The index of configurations to extract. results_required : bool If True, atomistic configurations that do not have any associated results will not be included. This prevents double printed configurations and incomplete calculations from being returned as the final configuration with no results data. Yields ------ structure : Atoms The next structure from the index slice. The Atoms has a SinglePointCalculator attached with any results parsed from the file. """ if isinstance(fileobj, str): fileobj = open(fileobj, 'rU') # work with a copy in memory for faster random access pwo_lines = fileobj.readlines() # TODO: index -1 special case? # Index all the interesting points indexes = { _PW_START: [], _PW_END: [], _PW_CELL: [], _PW_POS: [], _PW_MAGMOM: [], _PW_FORCE: [], _PW_TOTEN: [], _PW_STRESS: [], _PW_FERMI: [], _PW_HIGHEST_OCCUPIED: [], _PW_HIGHEST_OCCUPIED_LOWEST_FREE: [], _PW_KPTS: [], _PW_BANDS: [], _PW_BANDSTRUCTURE: [], _PW_ELECTROSTATIC_EMBEDDING: [], _PW_NITER: [], _PW_DONE: [], _PW_WALLTIME: [] } for idx, line in enumerate(pwo_lines): for identifier in indexes: if identifier in line: indexes[identifier].append(idx) # Configurations are either at the start, or defined in ATOMIC_POSITIONS # in a subsequent step. Can deal with concatenated output files. all_config_indexes = sorted(indexes[_PW_START] + indexes[_PW_POS]) # Slice only requested indexes # setting results_required argument stops configuration-only # structures from being returned. This ensures the [-1] structure # is one that has results. Two cases: # - SCF of last configuration is not converged, job terminated # abnormally. # - 'relax' and 'vc-relax' re-prints the final configuration but # only 'vc-relax' recalculates. if results_required: results_indexes = sorted(indexes[_PW_TOTEN] + indexes[_PW_FORCE] + indexes[_PW_STRESS] + indexes[_PW_MAGMOM] + indexes[_PW_BANDS] + indexes[_PW_ELECTROSTATIC_EMBEDDING] + indexes[_PW_BANDSTRUCTURE]) # Prune to only configurations with results data before the next # configuration results_config_indexes = [] for config_index, config_index_next in zip( all_config_indexes, all_config_indexes[1:] + [len(pwo_lines)]): if any([ config_index < results_index < config_index_next for results_index in results_indexes ]): results_config_indexes.append(config_index) # slice from the subset image_indexes = results_config_indexes[index] else: image_indexes = all_config_indexes[index] # Extract initialisation information each time PWSCF starts # to add to subsequent configurations. Use None so slices know # when to fill in the blanks. pwscf_start_info = dict((idx, None) for idx in indexes[_PW_START]) if isinstance(image_indexes, int): image_indexes = [image_indexes] for image_index in image_indexes: # Find the nearest calculation start to parse info. Needed in, # for example, relaxation where cell is only printed at the # start. if image_index in indexes[_PW_START]: prev_start_index = image_index else: # The greatest start index before this structure prev_start_index = [ idx for idx in indexes[_PW_START] if idx < image_index ][-1] # add structure to reference if not there if pwscf_start_info[prev_start_index] is None: pwscf_start_info[prev_start_index] = parse_pwo_start( pwo_lines, prev_start_index) # Get the bounds for information for this structure. Any associated # values will be between the image_index and the following one, # EXCEPT for cell, which will be 4 lines before if it exists. for next_index in all_config_indexes: if next_index > image_index: break else: # right to the end of the file next_index = len(pwo_lines) # Get the structure # Use this for any missing data prev_structure = pwscf_start_info[prev_start_index]['atoms'] if image_index in indexes[_PW_START]: structure = prev_structure.copy() # parsed from start info else: if _PW_CELL in pwo_lines[image_index - 5]: # CELL_PARAMETERS would be just before positions if present cell, cell_alat = get_cell_parameters(pwo_lines[image_index - 5:image_index]) else: cell = prev_structure.cell cell_alat = pwscf_start_info[prev_start_index]['alat'] # give at least enough lines to parse the positions # should be same format as input card n_atoms = len(prev_structure) positions_card = get_atomic_positions( pwo_lines[image_index:image_index + n_atoms + 1], n_atoms=n_atoms, cell=cell, alat=cell_alat) # convert to Atoms object symbols = [ label_to_symbol(position[0]) for position in positions_card ] tags = [label_to_tag(position[0]) for position in positions_card] positions = [position[1] for position in positions_card] constraint_idx = [position[2] for position in positions_card] constraint = get_constraint(constraint_idx) structure = Atoms(symbols=symbols, positions=positions, cell=cell, constraint=constraint, pbc=True, tags=tags) # Extract calculation results # Energy energy = None for energy_index in indexes[_PW_TOTEN]: if image_index < energy_index < next_index: energy = float( pwo_lines[energy_index].split()[-2]) * units['Ry'] # Electrostatic enbedding energy elec_embedding_energy = None for eee_index in indexes[_PW_ELECTROSTATIC_EMBEDDING]: if image_index < eee_index < next_index: elec_embedding_energy = float( pwo_lines[eee_index].split()[-2]) * units['Ry'] # Number of iterations n_iterations = None for niter_index in indexes[_PW_NITER]: if image_index < niter_index < next_index: n_iterations = int( pwo_lines[niter_index].split('#')[1].split()[0]) # Forces forces = None for force_index in indexes[_PW_FORCE]: if image_index < force_index < next_index: # Before QE 5.3 'negative rho' added 2 lines before forces # Use exact lines to stop before 'non-local' forces # in high verbosity if not pwo_lines[force_index + 2].strip(): force_index += 4 else: force_index += 2 # assume contiguous forces = [[float(x) for x in force_line.split()[-3:]] for force_line in pwo_lines[force_index:force_index + len(structure)]] forces = np.array(forces) * units['Ry'] / units['Bohr'] # Stress stress = None for stress_index in indexes[_PW_STRESS]: if image_index < stress_index < next_index: sxx, sxy, sxz = pwo_lines[stress_index + 1].split()[:3] _, syy, syz = pwo_lines[stress_index + 2].split()[:3] _, _, szz = pwo_lines[stress_index + 3].split()[:3] stress = np.array([sxx, syy, szz, syz, sxz, sxy], dtype=float) # sign convention is opposite of ase stress *= -1 * units['Ry'] / (units['Bohr']**3) # Magmoms magmoms = None for magmoms_index in indexes[_PW_MAGMOM]: if image_index < magmoms_index < next_index: magmoms = [ float(mag_line.split('=')[-1]) for mag_line in pwo_lines[magmoms_index + 1:magmoms_index + 1 + len(structure)] ] # Fermi level / highest occupied level and lowest unoccupied level efermi = None lumo_ene = None for fermi_index in indexes[_PW_FERMI]: if image_index < fermi_index < next_index: efermi = float(pwo_lines[fermi_index].split()[-2]) if efermi is None: for ho_index in indexes[_PW_HIGHEST_OCCUPIED]: if image_index < ho_index < next_index: efermi = float(pwo_lines[ho_index].split()[-1]) if efermi is None: for holf_index in indexes[_PW_HIGHEST_OCCUPIED_LOWEST_FREE]: if image_index < holf_index < next_index: efermi = float(pwo_lines[holf_index].split()[-2]) lumo_ene = float(pwo_lines[holf_index].split()[-1]) # K-points ibzkpts = None weights = None kpoints_warning = "Number of k-points >= 100: " + \ "set verbosity='high' to print them." for kpts_index in indexes[_PW_KPTS]: nkpts = int(pwo_lines[kpts_index].split()[4]) kpts_index += 2 if pwo_lines[kpts_index].strip() == kpoints_warning: continue # QE prints the k-points in units of 2*pi/alat # with alat defined as the length of the first # cell vector cell = structure.get_cell() alat = np.linalg.norm(cell[0]) ibzkpts = [] weights = [] for i in range(nkpts): L = pwo_lines[kpts_index + i].split() weights.append(float(L[-1])) coord = np.array([L[-6], L[-5], L[-4].strip('),')], dtype=float) coord *= 2 * np.pi / alat coord = kpoint_convert(cell, ckpts_kv=coord) ibzkpts.append(coord) ibzkpts = np.array(ibzkpts) weights = np.array(weights) # Bands kpts = None kpoints_warning = "Number of k-points >= 100: " + \ "set verbosity='high' to print the bands." for bands_index in indexes[_PW_BANDS] + indexes[_PW_BANDSTRUCTURE]: if image_index < bands_index < next_index: bands_index += 2 if pwo_lines[bands_index].strip() == kpoints_warning: continue assert ibzkpts is not None spin, bands, eigenvalues = 0, [], [[], []] while True: L = pwo_lines[bands_index].replace('-', ' -').split() if len(L) == 0: if len(bands) > 0: eigenvalues[spin].append(bands) bands = [] elif L == ['occupation', 'numbers']: # Skip the lines with the occupation numbers bands_index += len(eigenvalues[spin][0]) // 8 + 1 elif L[0] == 'k' and L[1].startswith('='): pass elif 'SPIN' in L: if 'DOWN' in L: spin += 1 else: try: bands.extend(map(float, L)) except ValueError: break bands_index += 1 if spin == 1: assert len(eigenvalues[0]) == len(eigenvalues[1]) # assert len(eigenvalues[0]) == len(ibzkpts), \ # (np.shape(eigenvalues), len(ibzkpts)) kpts = [] for s in range(spin + 1): for w, k, e in zip(weights, ibzkpts, eigenvalues[s]): kpt = SinglePointKPoint(w, s, k, eps_n=e) kpts.append(kpt) # Convergence job_done = False for done_index in indexes[_PW_DONE]: if image_index < done_index < next_index: job_done = True # Walltime walltime = None for wt_index in indexes[_PW_WALLTIME]: if image_index < wt_index < next_index: walltime = time_to_float(pwo_lines[wt_index].split()[-2]) # Put everything together calc = SinglePointDFTCalculator(structure, energy=energy, forces=forces, stress=stress, magmoms=magmoms, efermi=efermi, ibzkpts=ibzkpts) calc.results['homo_energy'] = efermi calc.results['lumo_energy'] = lumo_ene calc.results['electrostatic embedding'] = elec_embedding_energy calc.results['iterations'] = n_iterations calc.results['job done'] = job_done calc.results['walltime'] = walltime calc.kpts = kpts structure.calc = calc yield structure
def read_gpaw_out(fileobj, index): notfound = [] def index_startswith(lines, string): if not isinstance(string, str): # assume it's a list for entry in string: try: return index_startswith(lines, entry) except ValueError: pass raise ValueError if string in notfound: raise ValueError for i, line in enumerate(lines): if line.startswith(string): return i notfound.append(string) raise ValueError def index_pattern(lines, pattern): repat = re.compile(pattern) if pattern in notfound: raise ValueError for i, line in enumerate(lines): if repat.match(line): return i notfound.append(pattern) raise ValueError def read_forces(lines, ii): f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError) as m: raise IOError('Malformed GPAW log file: %s' % m) return f, i lines = [line.lower() for line in fileobj.readlines()] images = [] while True: try: i = index_startswith(lines, 'reference energy:') Eref = float(lines[i].split()[-1]) except ValueError: Eref = None try: i = lines.index('unit cell:\n') except ValueError: pass else: if lines[i + 2].startswith(' -'): del lines[i + 2] # old format cell = [] pbc = [] for line in lines[i + 2:i + 5]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') try: i = lines.index('positions:\n') except ValueError: break symbols = [] positions = [] for line in lines[i + 1:]: words = line.split() if len(words) < 5: break n, symbol, x, y, z = words[:5] symbols.append(symbol.split('.')[0].title()) positions.append([float(x), float(y), float(z)]) if len(symbols): atoms = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) else: atoms = Atoms(cell=cell, pbc=pbc) lines = lines[i + 5:] try: ii = index_pattern(lines, '\\d+ k-point') word = lines[ii].split() kx = int(word[2]) ky = int(word[4]) kz = int(word[6]) bz_kpts = (kx, ky, kz) ibz_kpts = int(lines[ii + 1].split()[0]) except (ValueError, TypeError, IndexError): bz_kpts = None ibz_kpts = None try: i = index_startswith(lines, 'energy contributions relative to') except ValueError: e = energy_contributions = None else: energy_contributions = {} for line in lines[i + 2:i + 8]: fields = line.split(':') energy_contributions[fields[0]] = float(fields[1]) line = lines[i + 10] assert (line.startswith('zero kelvin:') or line.startswith('extrapolated:')) e = float(line.split()[-1]) try: ii = index_pattern(lines, '(fixed )?fermi level(s)?:') except ValueError: eFermi = None else: fields = lines[ii].split() try: def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[-2])), float(strip(fields[-1]))] except ValueError: eFermi = float(fields[-1]) # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, ' band eigenvalues occupancy') except ValueError: pass try: ii2 = index_startswith(lines, ' band eigenvalues occupancy') except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while (len(words) > 2): vals.append([float(w) for w in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(1, 0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(1, 1, 0)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, 'total charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) # read dipole moment try: ii = index_startswith(lines, 'dipole moment:') except ValueError: dipole = None else: line = lines[ii] for x in '()[],': line = line.replace(x, '') dipole = np.array([float(c) for c in line.split()[2:5]]) try: ii = index_startswith(lines, 'local magnetic moments') except ValueError: magmoms = None else: magmoms = [] for j in range(ii + 1, ii + 1 + len(atoms)): magmom = lines[j].split()[-1].rstrip(')') magmoms.append(float(magmom)) try: ii = lines.index('forces in ev/ang:\n') except ValueError: f = None else: f, i = read_forces(lines, ii) try: ii = index_startswith(lines, 'vdw correction:') except ValueError: pass else: line = lines[ii + 1] assert line.startswith('energy:') e = float(line.split()[-1]) f, i = read_forces(lines, ii + 3) if len(images) > 0 and e is None: break if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_initial_charges([q / n] * n) if magmoms is not None: atoms.set_initial_magnetic_moments(magmoms) if e is not None or f is not None: calc = SinglePointDFTCalculator(atoms, energy=e, forces=f, dipole=dipole, magmoms=magmoms, efermi=eFermi, bzkpts=bz_kpts, ibzkpts=ibz_kpts) calc.eref = Eref calc.name = 'gpaw' if energy_contributions is not None: calc.energy_contributions = energy_contributions if kpts is not None: calc.kpts = kpts atoms.calc = calc images.append(atoms) lines = lines[i:] if len(images) == 0: raise IOError('Corrupted GPAW-text file!') return images[index]
def read_vasp_xml(filename='vasprun.xml', index=-1): """Parse vasprun.xml file. Reads unit cell, atom positions, energies, forces, and constraints from vasprun.xml file """ import numpy as np import xml.etree.ElementTree as ET from ase import Atoms from ase.constraints import FixAtoms, FixScaled from ase.calculators.singlepoint import (SinglePointDFTCalculator, SinglePointKPoint) from ase.units import GPa from collections import OrderedDict tree = ET.iterparse(filename, events=['start', 'end']) atoms_init = None calculation = [] ibz_kpts = None kpt_weights = None parameters = OrderedDict() try: for event, elem in tree: if event == 'end': if elem.tag == 'kpoints': for subelem in elem.iter(tag='generation'): kpts_params = OrderedDict() parameters['kpoints_generation'] = kpts_params for par in subelem.iter(): if par.tag in ['v', 'i']: parname = par.attrib['name'].lower() kpts_params[parname] = __get_xml_parameter(par) kpts = elem.findall("varray[@name='kpointlist']/v") ibz_kpts = np.zeros((len(kpts), 3)) for i, kpt in enumerate(kpts): ibz_kpts[i] = [float(val) for val in kpt.text.split()] kpt_weights = elem.findall('varray[@name="weights"]/v') kpt_weights = [float(val.text) for val in kpt_weights] elif elem.tag == 'parameters': for par in elem.iter(): if par.tag in ['v', 'i']: parname = par.attrib['name'].lower() parameters[parname] = __get_xml_parameter(par) elif elem.tag == 'atominfo': species = [] for entry in elem.find("array[@name='atoms']/set"): species.append(entry[0].text.strip()) natoms = len(species) elif (elem.tag == 'structure' and elem.attrib.get('name') == 'initialpos'): cell_init = np.zeros((3, 3), dtype=float) for i, v in enumerate( elem.find("crystal/varray[@name='basis']")): cell_init[i] = np.array( [float(val) for val in v.text.split()]) scpos_init = np.zeros((natoms, 3), dtype=float) for i, v in enumerate( elem.find("varray[@name='positions']")): scpos_init[i] = np.array( [float(val) for val in v.text.split()]) constraints = [] fixed_indices = [] for i, entry in enumerate( elem.findall("varray[@name='selective']/v")): flags = (np.array( entry.text.split() == np.array(['F', 'F', 'F']))) if flags.all(): fixed_indices.append(i) elif flags.any(): constraints.append(FixScaled(cell_init, i, flags)) if fixed_indices: constraints.append(FixAtoms(fixed_indices)) atoms_init = Atoms(species, cell=cell_init, scaled_positions=scpos_init, constraint=constraints, pbc=True) elif elem.tag == 'dipole': dblock = elem.find('v[@name="dipole"]') if dblock is not None: dipole = np.array( [float(val) for val in dblock.text.split()]) elif event == 'start' and elem.tag == 'calculation': calculation.append(elem) except ET.ParseError as parse_error: if atoms_init is None: raise parse_error if calculation[-1].find('energy') is None: calculation = calculation[:-1] if not calculation: yield atoms_init if calculation: if isinstance(index, int): steps = [calculation[index]] else: steps = calculation[index] else: steps = [] for step in steps: # Workaround for VASP bug, e_0_energy contains the wrong value # in calculation/energy, but calculation/scstep/energy does not # include classical VDW corrections. So, first calculate # e_0_energy - e_fr_energy from calculation/scstep/energy, then # apply that correction to e_fr_energy from calculation/energy. lastscf = step.findall('scstep/energy')[-1] try: lastdipole = step.findall('scstep/dipole')[-1] except: lastdipole = None de = (float(lastscf.find('i[@name="e_0_energy"]').text) - float(lastscf.find('i[@name="e_fr_energy"]').text)) free_energy = float(step.find('energy/i[@name="e_fr_energy"]').text) energy = free_energy + de cell = np.zeros((3, 3), dtype=float) for i, vector in enumerate( step.find('structure/crystal/varray[@name="basis"]')): cell[i] = np.array([float(val) for val in vector.text.split()]) scpos = np.zeros((natoms, 3), dtype=float) for i, vector in enumerate( step.find('structure/varray[@name="positions"]')): scpos[i] = np.array([float(val) for val in vector.text.split()]) forces = None fblocks = step.find('varray[@name="forces"]') if fblocks is not None: forces = np.zeros((natoms, 3), dtype=float) for i, vector in enumerate(fblocks): forces[i] = np.array( [float(val) for val in vector.text.split()]) stress = None sblocks = step.find('varray[@name="stress"]') if sblocks is not None: stress = np.zeros((3, 3), dtype=float) for i, vector in enumerate(sblocks): stress[i] = np.array( [float(val) for val in vector.text.split()]) stress *= -0.1 * GPa stress = stress.reshape(9)[[0, 4, 8, 5, 2, 1]] dipole = None if lastdipole is not None: dblock = lastdipole.find('v[@name="dipole"]') if dblock is not None: dipole = np.zeros((1, 3), dtype=float) dipole = np.array([float(val) for val in dblock.text.split()]) dblock = step.find('dipole/v[@name="dipole"]') if dblock is not None: dipole = np.zeros((1, 3), dtype=float) dipole = np.array([float(val) for val in dblock.text.split()]) efermi = step.find('dos/i[@name="efermi"]') if efermi is not None: efermi = float(efermi.text) kpoints = [] for ikpt in range(1, len(ibz_kpts) + 1): kblocks = step.findall( 'eigenvalues/array/set/set/set[@comment="kpoint %d"]' % ikpt) if kblocks is not None: for spin, kpoint in enumerate(kblocks): eigenvals = kpoint.findall('r') eps_n = np.zeros(len(eigenvals)) f_n = np.zeros(len(eigenvals)) for j, val in enumerate(eigenvals): val = val.text.split() eps_n[j] = float(val[0]) f_n[j] = float(val[1]) if len(kblocks) == 1: f_n *= 2 kpoints.append( SinglePointKPoint(kpt_weights[ikpt - 1], spin, ikpt, eps_n, f_n)) if len(kpoints) == 0: kpoints = None atoms = atoms_init.copy() atoms.set_cell(cell) atoms.set_scaled_positions(scpos) atoms.set_calculator( SinglePointDFTCalculator(atoms, energy=energy, forces=forces, stress=stress, free_energy=free_energy, ibzkpts=ibz_kpts, efermi=efermi, dipole=dipole)) atoms.calc.name = 'vasp' atoms.calc.kpts = kpoints atoms.calc.parameters = parameters yield atoms
def _read_outcar_frame(lines, header_data): from ase.calculators.singlepoint import (SinglePointDFTCalculator, SinglePointKPoint) mag_x = None mag_y = None mag_z = None magmoms = None magmom = None stress = None efermi = None symbols = header_data['symbols'] constraints = header_data['constraints'] natoms = header_data['natoms'] # nkpts = header_data['nkpts'] nbands = header_data['nbands'] kpt_weights = header_data['kpt_weights'] ibzkpts = header_data['ibzkpts'] atoms = Atoms(symbols=symbols, pbc=True, constraint=constraints) cl = _outcar_check_line # Aliasing spinc = 0 # Spin component kpts = [] forces = np.zeros((natoms, 3)) positions = np.zeros((natoms, 3)) f_n = np.zeros(nbands) # kpt occupations eps_n = np.zeros(nbands) # kpt eigenvalues # Parse each atoms object for n, line in enumerate(lines): line = line.strip() if 'direct lattice vectors' in line: cell = [] for i in range(3): parts = cl(lines[n + i + 1]).split() cell += [list(map(float, parts[0:3]))] atoms.set_cell(cell) elif 'magnetization (x)' in line: # Magnetization in both collinear and non-collinear nskip = 4 # Skip some lines mag_x = [float(cl(lines[n + i + nskip]).split()[-1]) for i in range(natoms)] # XXX: !!!Uncomment these lines when non-collinear spin is supported!!! # Remember to check that format fits! # elif 'magnetization (y)' in line: # # Non-collinear spin # nskip = 4 # Skip some lines # mag_y = [float(cl(lines[n + i + nskip]).split()[-1]) # for i in range(natoms)] # elif 'magnetization (z)' in line: # # Non-collinear spin # nskip = 4 # Skip some lines # mag_z = [float(cl(lines[n + i + nskip]).split()[-1]) # for i in range(natoms)] elif 'number of electron' in line: parts = cl(line).split() if len(parts) > 5 and parts[0].strip() != "NELECT": i = parts.index('magnetization') + 1 magmom = parts[i:] if len(magmom) == 1: # Collinear spin magmom = float(magmom[0]) # !Uncomment these lines when non-collinear spin is supported! # Remember to check that format fits! # else: # # Non-collinear spin # # Make a (3,) dim array # magmom = np.array(list(map(float, magmom))) elif 'in kB ' in line: stress = -np.asarray([float(a) for a in cl(line).split()[2:]]) stress = stress[[0, 1, 2, 4, 5, 3]] * 1e-1 * ase.units.GPa elif 'POSITION ' in line: nskip = 2 for i in range(natoms): parts = list(map(float, cl(lines[n + i + nskip]).split())) positions[i] = parts[0:3] forces[i] = parts[3:6] atoms.set_positions(positions, apply_constraint=False) elif 'E-fermi :' in line: parts = line.split() efermi = float(parts[2]) elif 'spin component' in line: # Update spin component for kpts # Make spin be in [0, 1], VASP writes 1 or 2 tmp = int(line.split()[-1]) - 1 if tmp < spinc: # if NWRITE=3, we write KPTS after every electronic step, # so we just reset it, since we went from spin=2 to spin=1 # in the same ionic step. # XXX: Only read it at last electronic step kpts = [] spinc = tmp elif 'k-point ' in line: if 'plane waves' in line: # Can happen if we still have part of header continue # Parse all kpts and bands parts = line.split() ikpt = int(parts[1]) - 1 # Make kpt idx start from 0 w = kpt_weights[ikpt] nskip = 2 for i in range(nbands): parts = lines[n + i + nskip].split() eps_n[i] = float(parts[1]) f_n[i] = float(parts[2]) kpts.append(SinglePointKPoint(w, spinc, ikpt, eps_n=eps_n, f_n=f_n)) elif _OUTCAR_SCF_DELIM in line: # Last section before next ionic step nskip = 2 parts = cl(lines[n + nskip]).strip().split() energy_free = float(parts[4]) # Force consistent nskip = 4 parts = cl(lines[n + nskip]).strip().split() energy_zero = float(parts[6]) # Extrapolated to 0 K # For debugging # assert len(kpts) == 0 or len(kpts) == (spinc + 1) * nkpts if mag_x is not None: if mag_y is not None: # Non-collinear assert len(mag_x) == len(mag_y) == len(mag_z) magmoms = np.zeros((len(atoms), 3)) magmoms[:, 0] = mag_x magmoms[:, 1] = mag_y magmoms[:, 2] = mag_z else: # Collinear magmoms = np.array(mag_x) atoms.set_calculator( SinglePointDFTCalculator(atoms, energy=energy_zero, free_energy=energy_free, ibzkpts=ibzkpts, forces=forces, efermi=efermi, magmom=magmom, magmoms=magmoms, stress=stress)) atoms.calc.name = 'vasp' atoms.calc.kpts = kpts return atoms
def read_koopmans_cp_out(fileobj, index=-1, results_required=True): """Reads Quantum ESPRESSO output files. The atomistic configurations as well as results (energy, force, stress, magnetic moments) of the calculation are read for all configurations within the output file. Will probably raise errors for broken or incomplete files. Parameters ---------- fileobj : file|str A file like object or filename index : slice The index of configurations to extract. results_required : bool If True, atomistic configurations that do not have any associated results will not be included. This prevents double printed configurations and incomplete calculations from being returned as the final configuration with no results data. Yields ------ structure : Atoms The next structure from the index slice. The Atoms has a SinglePointCalculator attached with any results parsed from the file. """ if isinstance(fileobj, basestring): fileobj = open(fileobj, 'rU') # work with a copy in memory for faster random access cpo_lines = fileobj.readlines() # For the moment, provide an empty atoms object structure = Atoms() # Extract calculation results energy = None odd_energy = None lumo_energy = None homo_energy = None mp1_energy = None mp2_energy = None lambda_ii = None eigenvalues = [] job_done = False orbital_data = { 'charge': [], 'centres': [], 'spreads': [], 'self-Hartree': [] } walltime = None convergence = {'filled': [], 'empty': []} convergence_key = 'filled' i_spin_orbital_data = None for i_line, line in enumerate(cpo_lines): # Energy if _CP_TOTEN in line: energy = float(line.split()[-3]) * units.Hartree if _CP_LAMBDA in line and lambda_ii is None: lambda_ii = float(line.split()[-1]) * units.Hartree # Bands if _CP_BANDS in line: if 'Empty' not in line: eigenvalues.append([]) j_line = i_line + 2 while len(cpo_lines[j_line].strip()) > 0: eigenvalues[-1] += safe_string_to_list_of_floats( cpo_lines[j_line]) j_line += 1 if 'odd energy' in line: odd_energy = float(line.split()[3]) * units.Hartree if 'H**O Eigenvalue (eV)' in line and '*' not in cpo_lines[i_line + 2]: homo_energy = float(cpo_lines[i_line + 2]) if 'LUMO Eigenvalue (eV)' in line and '*' not in cpo_lines[i_line + 2]: lumo_energy = float(cpo_lines[i_line + 2]) if 'Makov-Payne 1-order energy' in line: mp1_energy = float(line.split()[4]) * units.Hartree if 'Makov-Payne 2-order energy' in line: mp2_energy = float(line.split()[4]) * units.Hartree if 'JOB DONE' in line: job_done = True # Start of block of orbitals for a given spin channel if 'Orb -- Charge ---' in line or 'Orb -- Empty Charge' in line: i_spin_orbital_data = int(line.split()[-1]) - 1 for key in orbital_data: if len(orbital_data[key]) < i_spin_orbital_data + 1: orbital_data[key].append([]) # Orbital information if line.startswith(('OCC', 'EMP')): if 'NaN' in line: continue line = line.replace('********', ' 0.000') values = [ float(line[i - 4:i + 4]) for i, c in enumerate(line) if c == '.' ] orbital_data['charge'][i_spin_orbital_data].append(values[0]) orbital_data['centres'][i_spin_orbital_data].append( [x * units.Bohr for x in values[1:4]]) orbital_data['spreads'][i_spin_orbital_data].append(values[4] * units.Bohr**2) orbital_data['self-Hartree'][i_spin_orbital_data].append(values[5]) # Tracking convergence if 'PERFORMING CONJUGATE GRADIENT MINIMIZATION OF EMPTY STATES' in line: convergence_key = 'empty' if 'iteration = ' in line and 'eff iteration = ' in line: values = [l.split()[0] for l in line.split('=')[1:]] [it, eff_it, etot] = values[:3] entry = { 'iteration': int(it), 'eff iteration': int(eff_it), 'Etot': float(etot) * units.Hartree } if len(values) == 4: entry['delta_E'] = float(values[3]) * units.Hartree convergence[convergence_key].append(entry) if 'wall time' in line: time_str = line.split(',')[1].strip().rstrip('wall time') walltime = time_to_float(time_str) # Put everything together calc = SinglePointDFTCalculator(structure, energy=energy) # , # forces=forces, stress=stress, # magmoms=magmoms, efermi=efermi, # ibzkpts=ibzkpts) calc.results['energy'] = energy calc.results['odd_energy'] = odd_energy calc.results['homo_energy'] = homo_energy calc.results['lumo_energy'] = lumo_energy calc.results['mp1_energy'] = mp1_energy calc.results['mp2_energy'] = mp2_energy calc.results['eigenvalues'] = eigenvalues calc.results['lambda_ii'] = lambda_ii calc.results['orbital_data'] = orbital_data calc.results['convergence'] = convergence calc.results['job_done'] = job_done calc.results['walltime'] = walltime structure.calc = calc yield structure
def read_gpaw_text(fileobj, index=-1): if isinstance(fileobj, str): fileobj = open(fileobj) def index_startswith(lines, string): for i, line in enumerate(lines): if line.startswith(string): return i raise ValueError lines = fileobj.readlines() images = [] while True: try: i = lines.index('Unit Cell:\n') except ValueError: pass else: cell = [] pbc = [] for line in lines[i + 3:i + 6]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') try: i = lines.index('Positions:\n') except ValueError: break atoms = Atoms(cell=cell, pbc=pbc) for line in lines[i + 1:]: words = line.split() if len(words) != 5: break n, symbol, x, y, z = words symbol = symbol.split('.')[0] atoms.append(Atom(symbol, [float(x), float(y), float(z)])) lines = lines[i + 5:] try: i = lines.index('-------------------------\n') except ValueError: e = None else: line = lines[i + 9] assert line.startswith('Zero Kelvin:') e = float(line.split()[-1]) try: ii = index_startswith(lines, 'Fermi Level:') except ValueError: eFermi = None else: try: eFermi = float(lines[ii].split()[2]) except ValueError: # we have two Fermi levels fields = lines[ii].split() def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[2])), float(strip(fields[3])) ] # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, ' Band Eigenvalues Occupancy') except ValueError: pass try: ii2 = index_startswith(lines, ' Band Eigenvalues Occupancy') except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while(len(words) > 2): vals.append([float(word) for word in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(0, 1)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, 'Total Charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) try: ii = index_startswith(lines, 'Local Magnetic Moments') except ValueError: magmoms = None else: magmoms = [] for i in range(ii + 1, ii + 1 + len(atoms)): iii, magmom = lines[i].split()[:2] magmoms.append(float(magmom)) try: ii = lines.index('Forces in eV/Ang:\n') except ValueError: f = None else: f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError), m: raise IOError('Malformed GPAW log file: %s' % m) if len(images) > 0 and e is None: break if e is not None or f is not None: calc = SinglePointDFTCalculator(e, f, None, magmoms, atoms, eFermi) if kpts is not None: calc.kpts = kpts atoms.set_calculator(calc) if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_charges([q / n] * n) images.append(atoms) lines = lines[i:]
def read_gpaw_text(fileobj, index=-1): if isinstance(fileobj, str): fileobj = open(fileobj, 'rU') notfound = [] def index_startswith(lines, string): if string in notfound: raise ValueError for i, line in enumerate(lines): if line.startswith(string): return i notfound.append(string) raise ValueError lines = fileobj.readlines() images = [] while True: try: i = lines.index('Unit Cell:\n') except ValueError: pass else: cell = [] pbc = [] for line in lines[i + 3:i + 6]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') try: i = lines.index('Positions:\n') except ValueError: break symbols = [] positions = [] for line in lines[i + 1:]: words = line.split() if len(words) != 5: break n, symbol, x, y, z = words symbols.append(symbol.split('.')[0]) positions.append([float(x), float(y), float(z)]) if len(symbols): atoms = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) else: atoms = Atoms(cell=cell, pbc=pbc) lines = lines[i + 5:] ene = { # key position 'Kinetic:': 1, 'Potential:': 2, 'XC:': 4 } try: i = lines.index('-------------------------\n') except ValueError: e = None else: for key in ene: pos = ene[key] ene[key] = None line = lines[i + pos] try: assert line.startswith(key) ene[key] = float(line.split()[-1]) except ValueError: pass line = lines[i + 9] assert line.startswith('Zero Kelvin:') e = float(line.split()[-1]) try: ii = index_startswith(lines, 'Fermi Level') except ValueError: eFermi = None else: try: eFermi = float(lines[ii].split()[2]) except ValueError: # we have two Fermi levels fields = lines[ii].split() def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[2])), float(strip(fields[3]))] # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, ' Band Eigenvalues Occupancy') except ValueError: pass try: ii2 = index_startswith(lines, ' Band Eigenvalues Occupancy') except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while (len(words) > 2): vals.append([float(word) for word in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(1, 0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(1, 1, 0)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, 'Total Charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) # read dipole moment try: ii = index_startswith(lines, 'Dipole Moment:') except ValueError: dipole = None else: line = lines[ii].replace(']', '').replace('[', '') dipole = np.array([float(c) for c in line.split()[-3:]]) try: ii = index_startswith(lines, 'Local Magnetic Moments') except ValueError: magmoms = None else: magmoms = [] for i in range(ii + 1, ii + 1 + len(atoms)): iii, magmom = lines[i].split()[:2] magmoms.append(float(magmom)) try: ii = lines.index('Forces in eV/Ang:\n') except ValueError: f = None else: f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError), m: raise IOError('Malformed GPAW log file: %s' % m) if len(images) > 0 and e is None: break if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_initial_charges([q / n] * n) if e is not None or f is not None: calc = SinglePointDFTCalculator(atoms, energy=e, forces=f, dipole=dipole, magmoms=magmoms, eFermi=eFermi) if kpts is not None: calc.kpts = kpts atoms.set_calculator(calc) images.append(atoms) lines = lines[i:]
syms = '' y = s.readline().split() while len(y) > 0: nf = len(y) pos.append([float(x) for x in y[nf - 4:nf - 1]]) syms += y[1].strip('0123456789') y = s.readline().split() pos = np.array(pos) * alat natoms = len(pos) # create atoms object with coordinates and unit cell # as specified in the initial ionic step in log atoms = Atoms(syms, pos, cell=cell * alat, pbc=(1, 1, 1)) # Attach calculator object to atoms. calc = SinglePointDFTCalculator(atoms) atoms.set_calculator(calc) # Get total energy at first ionic step and store it in the calculator. en = get_total_energy(s) if en is not None: calc.results['energy'] = en else: print('no total energy found', file=stderr) exit(3) # Write to .traj file traj = Trajectory(argv[2], 'w') traj.write(atoms) # Append the following images. a = s.readline()
def read_gpaw_out(fileobj, index): # -> Union[Atoms, List[Atoms]]: """Read text output from GPAW calculation.""" lines = [line.lower() for line in fileobj.readlines()] blocks = [] i1 = 0 for i2, line in enumerate(lines): if line == 'positions:\n': if i1 > 0: blocks.append(lines[i1:i2]) i1 = i2 blocks.append(lines[i1:]) images: List[Atoms] = [] for lines in blocks: try: i = lines.index('unit cell:\n') except ValueError: pass else: if lines[i + 2].startswith(' -'): del lines[i + 2] # old format cell: List[Union[float, List[float]]] = [] pbc = [] for line in lines[i + 2:i + 5]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') symbols = [] positions = [] magmoms = [] for line in lines[1:]: words = line.split() if len(words) < 5: break n, symbol, x, y, z = words[:5] symbols.append(symbol.split('.')[0].title()) positions.append([float(x), float(y), float(z)]) if len(words) > 5: mom = float(words[-1].rstrip(')')) magmoms.append(mom) if len(symbols): atoms = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) else: atoms = Atoms(cell=cell, pbc=pbc) try: ii = index_pattern(lines, '\\d+ k-point') word = lines[ii].split() kx = int(word[2]) ky = int(word[4]) kz = int(word[6]) bz_kpts = (kx, ky, kz) ibz_kpts = int(lines[ii + 1].split()[0]) except (ValueError, TypeError, IndexError): bz_kpts = None ibz_kpts = None try: i = index_startswith(lines, 'energy contributions relative to') except ValueError: e = energy_contributions = None else: energy_contributions = {} for line in lines[i + 2:i + 8]: fields = line.split(':') energy_contributions[fields[0]] = float(fields[1]) line = lines[i + 10] assert (line.startswith('zero kelvin:') or line.startswith('extrapolated:')) e = float(line.split()[-1]) try: ii = index_pattern(lines, '(fixed )?fermi level(s)?:') except ValueError: eFermi = None else: fields = lines[ii].split() try: def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[-2])), float(strip(fields[-1]))] except ValueError: eFermi = float(fields[-1]) # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, ' band eigenvalues occupancy') except ValueError: pass try: ii2 = index_startswith(lines, ' band eigenvalues occupancy') except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while(len(words) > 2): vals.append([float(w) for w in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(1, 0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(1, 1, 0)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, 'total charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) # read dipole moment try: ii = index_startswith(lines, 'dipole moment:') except ValueError: dipole = None else: line = lines[ii] for x in '()[],': line = line.replace(x, '') dipole = np.array([float(c) for c in line.split()[2:5]]) try: ii = index_startswith(lines, 'local magnetic moments') except ValueError: pass else: magmoms = [] for j in range(ii + 1, ii + 1 + len(atoms)): magmom = lines[j].split()[-1].rstrip(')') magmoms.append(float(magmom)) try: ii = lines.index('forces in ev/ang:\n') except ValueError: f = None else: f, i = read_forces(lines, ii, atoms) try: parameters = {} ii = index_startswith(lines, 'vdw correction:') except ValueError: name = 'gpaw' else: name = lines[ii - 1].strip() # save uncorrected values parameters.update({ 'calculator': 'gpaw', 'uncorrected_energy': e, }) line = lines[ii + 1] assert line.startswith('energy:') e = float(line.split()[-1]) f, i = read_forces(lines, ii + 3, atoms) if len(images) > 0 and e is None: break if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_initial_charges([q / n] * n) if magmoms: atoms.set_initial_magnetic_moments(magmoms) else: magmoms = None if e is not None or f is not None: calc = SinglePointDFTCalculator(atoms, energy=e, forces=f, dipole=dipole, magmoms=magmoms, efermi=eFermi, bzkpts=bz_kpts, ibzkpts=ibz_kpts) calc.name = name calc.parameters = parameters if energy_contributions is not None: calc.energy_contributions = energy_contributions if kpts is not None: calc.kpts = kpts atoms.calc = calc images.append(atoms) if len(images) == 0: raise IOError('Corrupted GPAW-text file!') return images[index]
def read_koopmans_ham_out(fileobj): """Reads Koopmans Ham output files. Will probably raise errors for broken or incomplete files. Parameters ---------- fileobj : file|str A file like object or filename Yields ------ structure : Atoms The next structure. The Atoms has a SinglePointCalculator attached with any results parsed from the file. """ if isinstance(fileobj, basestring): fileobj = open(fileobj, 'rU') # work with a copy in memory for faster random access flines = fileobj.readlines() # For the moment, provide an empty atoms object structure = Atoms() # Extract calculation results job_done = False walltime = None kpts = [] eigenvalues = [] ks_eigenvalues_on_grid = [] ki_eigenvalues_on_grid = [] for i_line, line in enumerate(flines): if 'KC interpolated eigenvalues at k=' in line: kpts.append([float(x) for x in line.split()[-3:]]) eigenvalues.append([]) j_line = i_line + 2 while True: line2 = flines[j_line].strip() if len(line2) == 0: break eigenvalues[-1] += [float(x) for x in line2.split()] j_line += 1 if 'INFO: KI[2nd] HAMILTONIAN CALCULATION ik=' in line: ks_eigenvalues_on_grid.append([]) ki_eigenvalues_on_grid.append([]) if line.startswith(' KS '): ks_eigenvalues_on_grid[-1] += safe_string_to_list_of_floats( line.replace('KS', '')) if line.startswith(' KI '): ki_eigenvalues_on_grid[-1] += safe_string_to_list_of_floats( line.replace('KI', '')) if 'JOB DONE' in line: job_done = True if 'KC_WANN :' in line: time_str = line.split()[-2] walltime = time_to_float(time_str) # Put everything together calc = SinglePointDFTCalculator(structure) calc.results['job_done'] = job_done calc.results['walltime'] = walltime calc.results['eigenvalues'] = eigenvalues calc.results['ks_eigenvalues_on_grid'] = ks_eigenvalues_on_grid calc.results['ki_eigenvalues_on_grid'] = ki_eigenvalues_on_grid structure.calc = calc yield structure
def xml2atoms(xml_elem): # symbols = [el.items()[0][1] for el in xml_elem.find('atomic_species').findall('species')] # # nat = int(xml_elem.find('atomic_structure').items()[0][1]) # alat = float(xml_elem.find('atomic_structure').items()[1][1]) atoms = [] for item in xml_elem.find('atomic_structure').find( 'atomic_positions').findall('atom'): coords = np.array(item.text.split(), dtype=np.float) * units['Bohr'] atom = Atom(symbol=item.items()[0][1], position=coords) atoms.append(atom) a1 = np.array( xml_elem.find('atomic_structure').find('cell').find('a1').text.split(), dtype=np.float) a2 = np.array( xml_elem.find('atomic_structure').find('cell').find('a2').text.split(), dtype=np.float) a3 = np.array( xml_elem.find('atomic_structure').find('cell').find('a3').text.split(), dtype=np.float) cell = np.array([a1, a2, a3]) * units['Bohr'] atoms = Atoms(atoms, cell=cell, pbc=True) # ------------------------------------------------------------------------------------------ # Extract calculation results # Energy energy = 2 * float( xml_elem.find('total_energy').find('etot').text) * units['Ry'] # Forces forces = [] if xml_elem.find('forces') is not None: for item in xml_elem.find('forces').text.strip().split('\n'): forces.append(np.fromstring(item.strip(), sep=' ', dtype=np.float)) forces = np.array(forces) * units['Ry'] / units['Bohr'] # Stress stress = None # Magmoms magmoms = None # Fermi level / highest occupied level efermi = None if xml_elem.find('band_structure') is not None: efermi = 2 * float( xml_elem.find('band_structure').find( 'fermi_energy').text) * units['Ry'] # # K-points ibzkpts = None # weights = None # kpoints_warning = "Number of k-points >= 100: " + \ # "set verbosity='high' to print them." # # for kpts_index in indexes[_PW_KPTS]: # nkpts = int(pwo_lines[kpts_index].split()[4]) # kpts_index += 2 # # if pwo_lines[kpts_index].strip() == kpoints_warning: # continue # # # QE prints the k-points in units of 2*pi/alat # # with alat defined as the length of the first # # cell vector # cell = structure.get_cell() # alat = np.linalg.norm(cell[0]) # ibzkpts = [] # weights = [] # for i in range(nkpts): # L = pwo_lines[kpts_index + i].split() # weights.append(float(L[-1])) # coord = np.array([L[-6], L[-5], L[-4].strip('),')], # dtype=float) # coord *= 2 * np.pi / alat # coord = kpoint_convert(cell, ckpts_kv=coord) # ibzkpts.append(coord) # ibzkpts = np.array(ibzkpts) # weights = np.array(weights) # # # Bands # kpts = None # kpoints_warning = "Number of k-points >= 100: " + \ # "set verbosity='high' to print the bands." # # for bands_index in indexes[_PW_BANDS] + indexes[_PW_BANDSTRUCTURE]: # if image_index < bands_index < next_index: # bands_index += 2 # # if pwo_lines[bands_index].strip() == kpoints_warning: # continue # # assert ibzkpts is not None # spin, bands, eigenvalues = 0, [], [[], []] # # while True: # L = pwo_lines[bands_index].replace('-', ' -').split() # if len(L) == 0: # if len(bands) > 0: # eigenvalues[spin].append(bands) # bands = [] # elif L == ['occupation', 'numbers']: # # Skip the lines with the occupation numbers # bands_index += len(eigenvalues[spin][0]) // 8 + 1 # elif L[0] == 'k' and L[1].startswith('='): # pass # elif 'SPIN' in L: # if 'DOWN' in L: # spin += 1 # else: # try: # bands.extend(map(float, L)) # except ValueError: # break # bands_index += 1 # # if spin == 1: # assert len(eigenvalues[0]) == len(eigenvalues[1]) # assert len(eigenvalues[0]) == len(ibzkpts), \ # (np.shape(eigenvalues), len(ibzkpts)) # # kpts = [] # for s in range(spin + 1): # for w, k, e in zip(weights, ibzkpts, eigenvalues[s]): # kpt = SinglePointKPoint(w, s, k, eps_n=e) # kpts.append(kpt) # ------------------------------------------------------------------------------------------ calc = SinglePointDFTCalculator(atoms, energy=energy, forces=forces, stress=stress, magmoms=magmoms, efermi=efermi, ibzkpts=ibzkpts) # calc.kpts = kpts atoms.calc = calc input_parameters = {} input_parameters['ecut'] = None if xml_elem.find('basis_set') is not None: input_parameters['ecut'] = 2 * float( xml_elem.find('basis_set').find('ecutwfc').text) input_parameters['input_dft'] = None if xml_elem.find('dft') is not None: input_parameters['input_dft'] = xml_elem.find('dft').find( 'functional').text.lower() input_parameters['k_points'] = None if xml_elem.find('band_structure') is not None: k_points = xml_elem.find('band_structure').find( 'starting_k_points').find('monkhorst_pack').items() k_points = [int(item[1]) for item in k_points] input_parameters['k_points'] = k_points input_parameters['fft_grid'] = None if xml_elem.find('basis_set') is not None: fft_points = xml_elem.find('basis_set').find('fft_grid').items() fft_points = [int(item[1]) for item in fft_points] input_parameters['fft_grid'] = fft_points return atoms, input_parameters
def read_gpaw_out(fileobj, index): notfound = [] def index_startswith(lines, string): if not isinstance(string, basestring): # assume it's a list for entry in string: try: return index_startswith(lines, entry) except ValueError: pass raise ValueError if string in notfound: raise ValueError for i, line in enumerate(lines): if line.startswith(string): return i notfound.append(string) raise ValueError def index_pattern(lines, pattern): repat = re.compile(pattern) if pattern in notfound: raise ValueError for i, line in enumerate(lines): if repat.match(line): return i notfound.append(pattern) raise ValueError def read_forces(lines, ii): f = [] for i in range(ii + 1, ii + 1 + len(atoms)): try: x, y, z = lines[i].split()[-3:] f.append((float(x), float(y), float(z))) except (ValueError, IndexError) as m: raise IOError('Malformed GPAW log file: %s' % m) return f, i lines = [line.lower() for line in fileobj.readlines()] images = [] while True: try: i = lines.index('unit cell:\n') except ValueError: pass else: if lines[i + 2].startswith(' -'): del lines[i + 2] # old format cell = [] pbc = [] for line in lines[i + 2:i + 5]: words = line.split() if len(words) == 5: # old format cell.append(float(words[2])) pbc.append(words[1] == 'yes') else: # new format with GUC cell.append([float(word) for word in words[3:6]]) pbc.append(words[2] == 'yes') try: i = lines.index('positions:\n') except ValueError: break symbols = [] positions = [] for line in lines[i + 1:]: words = line.split() if len(words) != 5: break n, symbol, x, y, z = words symbols.append(symbol.split('.')[0].title()) positions.append([float(x), float(y), float(z)]) if len(symbols): atoms = Atoms(symbols=symbols, positions=positions, cell=cell, pbc=pbc) else: atoms = Atoms(cell=cell, pbc=pbc) lines = lines[i + 5:] try: ii = index_startswith(lines, 'reference energy:') Eref = float(lines[ii].split()[-1]) except ValueError: Eref = None try: ii = index_pattern(lines, '\d+ k-point') word = lines[ii].split() kx = int(word[2]) ky = int(word[4]) kz = int(word[6]) bz_kpts = (kx, ky, kz) ibz_kpts = int(lines[ii + 1].split()[0]) except (ValueError, TypeError, IndexError): bz_kpts = None ibz_kpts = None try: i = index_startswith(lines, 'energy contributions relative to') except ValueError: e = None else: line = lines[i + 10] assert (line.startswith('zero kelvin:') or line.startswith('extrapolated:')) e = float(line.split()[-1]) try: ii = index_pattern(lines, '(fixed )?fermi level(s)?:') except ValueError: eFermi = None else: fields = lines[ii].split() try: def strip(string): for rubbish in '[],': string = string.replace(rubbish, '') return string eFermi = [float(strip(fields[-2])), float(strip(fields[-1]))] except ValueError: eFermi = float(fields[-1]) # read Eigenvalues and occupations ii1 = ii2 = 1e32 try: ii1 = index_startswith(lines, ' band eigenvalues occupancy') except ValueError: pass try: ii2 = index_startswith(lines, ' band eigenvalues occupancy') except ValueError: pass ii = min(ii1, ii2) if ii == 1e32: kpts = None else: ii += 1 words = lines[ii].split() vals = [] while(len(words) > 2): vals.append([float(w) for w in words]) ii += 1 words = lines[ii].split() vals = np.array(vals).transpose() kpts = [SinglePointKPoint(1, 0, 0)] kpts[0].eps_n = vals[1] kpts[0].f_n = vals[2] if vals.shape[0] > 3: kpts.append(SinglePointKPoint(1, 1, 0)) kpts[1].eps_n = vals[3] kpts[1].f_n = vals[4] # read charge try: ii = index_startswith(lines, 'total charge:') except ValueError: q = None else: q = float(lines[ii].split()[2]) # read dipole moment try: ii = index_startswith(lines, 'dipole moment:') except ValueError: dipole = None else: line = lines[ii] for x in '()[],': line = line.replace(x, '') dipole = np.array([float(c) for c in line.split()[2:5]]) try: ii = index_startswith(lines, 'local magnetic moments') except ValueError: magmoms = None else: magmoms = [] for j in range(ii + 1, ii + 1 + len(atoms)): magmom = lines[j].split()[-1] magmoms.append(float(magmom)) try: ii = lines.index('forces in ev/ang:\n') except ValueError: f = None else: f, i = read_forces(lines, ii) try: ii = index_startswith(lines, 'vdw correction:') except ValueError: pass else: line = lines[ii + 1] assert line.startswith('energy:') e = float(line.split()[-1]) f, i = read_forces(lines, ii + 3) if len(images) > 0 and e is None: break if q is not None and len(atoms) > 0: n = len(atoms) atoms.set_initial_charges([q / n] * n) if magmoms is not None: atoms.set_initial_magnetic_moments(magmoms) if e is not None or f is not None: calc = SinglePointDFTCalculator(atoms, energy=e, forces=f, dipole=dipole, magmoms=magmoms, efermi=eFermi, bzkpts=bz_kpts, ibzkpts=ibz_kpts) calc.eref = Eref calc.name = 'gpaw' if kpts is not None: calc.kpts = kpts atoms.set_calculator(calc) images.append(atoms) lines = lines[i:] if len(images) == 0: raise IOError('Corrupted GPAW-text file!') return images[index]
def read(filename, index=None, format=None): """Read Atoms object(s) from file. filename: str Name of the file to read from. index: int or slice If the file contains several configurations, the last configuration will be returned by default. Use index=n to get configuration number n (counting from zero). format: str Used to specify the file-format. If not given, the file-format will be guessed by the *filetype* function. Known formats: ========================= ============= format short name ========================= ============= GPAW restart-file gpw Dacapo netCDF output file dacapo Old ASE netCDF trajectory nc Virtual Nano Lab file vnl ASE pickle trajectory traj ASE bundle trajectory bundle GPAW text output gpaw-text CUBE file cube XCrySDen Structure File xsf Dacapo text output dacapo-text XYZ-file xyz VASP POSCAR/CONTCAR file vasp VASP OUTCAR file vasp_out SIESTA STRUCT file struct_out ABINIT input file abinit V_Sim ascii file v_sim Protein Data Bank pdb CIF-file cif FHI-aims geometry file aims FHI-aims output file aims_out VTK XML Image Data vti VTK XML Structured Grid vts VTK XML Unstructured Grid vtu TURBOMOLE coord file tmol TURBOMOLE gradient file tmol-gradient exciting input exi AtomEye configuration cfg WIEN2k structure file struct DftbPlus input file dftb CASTEP geom file cell CASTEP output file castep CASTEP trajectory file geom ETSF format etsf.nc DFTBPlus GEN format gen CMR db/cmr-file db CMR db/cmr-file cmr LAMMPS dump file lammps EON reactant.con file eon Gromacs coordinates gro Gaussian com (input) file gaussian Gaussian output file gaussian_out Quantum espresso in file esp_in Quantum espresso out file esp_out Extended XYZ file extxyz NWChem input file nw ========================= ============= """ if isinstance(filename, str) and ('.json@' in filename or '.db@' in filename or filename.startswith('pg://') and '@' in filename): filename, index = filename.rsplit('@', 1) if index.isdigit(): index = int(index) else: if isinstance(filename, str): p = filename.rfind('@') if p != -1: try: index = string2index(filename[p + 1:]) except ValueError: pass else: filename = filename[:p] if isinstance(index, str): index = string2index(index) if format is None: format = filetype(filename) if format.startswith('gpw'): import gpaw r = gpaw.io.open(filename, 'r') positions = r.get('CartesianPositions') * Bohr numbers = r.get('AtomicNumbers') cell = r.get('UnitCell') * Bohr pbc = r.get('BoundaryConditions') tags = r.get('Tags') magmoms = r.get('MagneticMoments') energy = r.get('PotentialEnergy') * Hartree if r.has_array('CartesianForces'): forces = r.get('CartesianForces') * Hartree / Bohr else: forces = None atoms = Atoms(positions=positions, numbers=numbers, cell=cell, pbc=pbc) if tags.any(): atoms.set_tags(tags) if magmoms.any(): atoms.set_initial_magnetic_moments(magmoms) else: magmoms = None atoms.calc = SinglePointDFTCalculator(atoms, energy=energy, forces=forces, magmoms=magmoms) kpts = [] if r.has_array('IBZKPoints'): for w, kpt, eps_n, f_n in zip(r.get('IBZKPointWeights'), r.get('IBZKPoints'), r.get('Eigenvalues'), r.get('OccupationNumbers')): kpts.append( SinglePointKPoint(w, kpt[0], kpt[1], eps_n[0], f_n[0])) atoms.calc.kpts = kpts return atoms if format in ['json', 'db', 'postgresql']: from ase.db.core import connect, dict2atoms if index == slice(None, None): index = None images = [ dict2atoms(d) for d in connect(filename, format).select(index) ] if len(images) == 1: return images[0] else: return images if index is None: index = -1 if format == 'castep': from ase.io.castep import read_castep return read_castep(filename, index) if format == 'castep_cell': import ase.io.castep return ase.io.castep.read_cell(filename, index) if format == 'castep_geom': import ase.io.castep return ase.io.castep.read_geom(filename, index) if format == 'exi': from ase.io.exciting import read_exciting return read_exciting(filename, index) if format in ['xyz', 'extxyz']: from ase.io.extxyz import read_xyz return read_xyz(filename, index) if format == 'traj': from ase.io.trajectory import read_trajectory return read_trajectory(filename, index) if format == 'bundle': from ase.io.bundletrajectory import read_bundletrajectory return read_bundletrajectory(filename, index) if format == 'cube': from ase.io.cube import read_cube return read_cube(filename, index) if format == 'nc': from ase.io.netcdf import read_netcdf return read_netcdf(filename, index) if format == 'gpaw-text': from ase.io.gpawtext import read_gpaw_text return read_gpaw_text(filename, index) if format == 'dacapo-text': from ase.io.dacapo import read_dacapo_text return read_dacapo_text(filename) if format == 'dacapo': from ase.io.dacapo import read_dacapo return read_dacapo(filename) if format == 'xsf': from ase.io.xsf import read_xsf return read_xsf(filename, index) if format == 'vasp': from ase.io.vasp import read_vasp return read_vasp(filename) if format == 'vasp_out': from ase.io.vasp import read_vasp_out return read_vasp_out(filename, index) if format == 'abinit': from ase.io.abinit import read_abinit return read_abinit(filename) if format == 'v_sim': from ase.io.v_sim import read_v_sim return read_v_sim(filename) if format == 'mol': from ase.io.mol import read_mol return read_mol(filename) if format == 'pdb': from ase.io.pdb import read_pdb return read_pdb(filename, index) if format == 'cif': from ase.io.cif import read_cif return read_cif(filename, index) if format == 'struct': from ase.io.wien2k import read_struct return read_struct(filename) if format == 'struct_out': from ase.io.siesta import read_struct return read_struct(filename) if format == 'vti': from ase.io.vtkxml import read_vti return read_vti(filename) if format == 'vts': from ase.io.vtkxml import read_vts return read_vts(filename) if format == 'vtu': from ase.io.vtkxml import read_vtu return read_vtu(filename) if format == 'aims': from ase.io.aims import read_aims return read_aims(filename) if format == 'aims_out': from ase.io.aims import read_aims_output return read_aims_output(filename, index) if format == 'iwm': from ase.io.iwm import read_iwm return read_iwm(filename) if format == 'Cmdft': from ase.io.cmdft import read_I_info return read_I_info(filename) if format == 'tmol': from ase.io.turbomole import read_turbomole return read_turbomole(filename) if format == 'tmol-gradient': from ase.io.turbomole import read_turbomole_gradient return read_turbomole_gradient(filename) if format == 'cfg': from ase.io.cfg import read_cfg return read_cfg(filename) if format == 'dftb': from ase.io.dftb import read_dftb return read_dftb(filename) if format == 'sdf': from ase.io.sdf import read_sdf return read_sdf(filename) if format == 'etsf': from ase.io.etsf import ETSFReader return ETSFReader(filename).read_atoms() if format == 'gen': from ase.io.gen import read_gen return read_gen(filename) if format == 'cmr': from ase.io.cmr_io import read_db return read_db(filename, index) if format == 'lammps': from ase.io.lammpsrun import read_lammps_dump return read_lammps_dump(filename, index) if format == 'eon': from ase.io.eon import read_reactant_con return read_reactant_con(filename) if format == 'gromacs': from ase.io.gromacs import read_gromacs return read_gromacs(filename) if format == 'gaussian': from ase.io.gaussian import read_gaussian return read_gaussian(filename) if format == 'gaussian_out': from ase.io.gaussian import read_gaussian_out return read_gaussian_out(filename, index) if format == 'esp_in': from ase.io.espresso import read_espresso_in return read_espresso_in(filename) if format == 'esp_out': from ase.io.espresso import read_espresso_out return read_espresso_out(filename, index) if format == 'nw': from ase.io.nwchem import read_nwchem_input return read_nwchem_input(filename) raise RuntimeError('File format descriptor ' + format + ' not recognized!')
def calc_phonon( calculator, phonon, acoustic_sum_rule=True, rot_sum_rule=False, r_cut=None, F_0_correction=False, verbose=False, ase_calc=None, cp_files=None, subscript=None, fc_calc=None, ): """ calc -- Specify calculator. One of these. [vasp, lmp, amp, amp_tf, amp_tf_bunch] phonon -- Phonopy phonon object. """ # Check if structure is lower triangular cell # for c in ((0,1), (0,2), (1,2)): # if phonon._primitive.get_cell()[c[0],c[1]] != 0. and calculator == 'lmp': # raise ValueError('Please provide lower triangular cell.') import sys if verbose: np.set_printoptions(threshold=sys.maxsize) if fc_calc == 'alm': disp = phonon.get_displacements() delta = np.linalg.norm(disp[0][0]) disp = np.concatenate([[np.zeros(disp.shape[1:])], disp], axis=0) else: delta = np.linalg.norm(phonon.get_displacements()[0][1:4]) disp = [[0, 0, 0, 0]] + phonon.get_displacements() job_name = '{}-x{}{}{}_d{:5.3f}_sym{}'.format( calculator, *np.diag(phonon.get_supercell_matrix()), delta, phonon._is_symmetry, ) if subscript is not None: job_name += '_s' + str(subscript) # Define names npy_name = '{}-fc2-forces.npy'.format(job_name) if phonon._nac_params is not None: nac = True else: nac = False pckl_name = '{}-RSR{}-rcut{}-NAC{}-fc2.bin'.format(job_name, rot_sum_rule, r_cut, nac) calc_dir = './calcs/{}'.format(job_name) # Environment preset call(['rm -rf ' + calc_dir + '/poscars'], shell=True) call(['mkdir -p ' + calc_dir + '/poscars'], shell=True) call(['cp SPOSCAR POSCAR-000'], shell=True) call(['mv POSCAR-* SPOSCAR ' + calc_dir + '/poscars/'], shell=True) # Load saved pickle file print('') try: forces = np.load(npy_name) if forces is None: raise ValueError(' Error:: npy file is not containing forces info') except: print( '<< CAUTION >> Fail to load npy file. << CAUTION >>' .center(120)) print(('<< CAUTION >>' + ':: Expected file name ::'.center(43) + '<< CAUTION >>').center(120)) print(('<< CAUTION >>' + npy_name.center(43) + '<< CAUTION >>').center(120)) do_calc = True else: print('>>>>>>> Pickle file "{}" has been loaded. <<<<<<<<'.format( npy_name).center(120)) do_calc = False print('') if do_calc: if calculator == 'vasp': calc = calc_vasp elif calculator == 'lmp': calc = calc_lmp elif calculator == 'ase_calc': calc = calc_ase_calc elif calculator == 'amp_tf': calc = calc_amp_tf elif calculator == 'amp_tf_bunch': calc = calc_amp_tf_bunch else: raise ValueError( 'Unknown calculator ({}) has been provided.'.format( calculator)) print(">>>>>>> {} calculation will be carried out. <<<<<<<<".format( calculator).center(120)) forces = calc(phonon, disp, calc_dir, F_0_correction, ase_calc, cp_files) np.save(npy_name, forces) if verbose: print('\n\n' + 'forces' + '\n' + str(forces)) phonon.set_forces(forces) # Produce fc phonon.produce_force_constants(fc_calculator=fc_calc) if acoustic_sum_rule: phonon.symmetrize_force_constants() if r_cut: if rot_sum_rule: # from ase.io import read from ase.calculators.singlepoint import SinglePointDFTCalculator sposcar = read(calc_dir + '/poscars/SPOSCAR') supers = [] for i in range(len(forces)): supers.append(sposcar.copy()) displacements = np.zeros(sposcar.get_positions().shape, dtype=float) displacements[disp[i + 1][0]] += disp[i + 1][1:] supers[-1].new_array( 'displacements', displacements, ) supers[-1]._calc = SinglePointDFTCalculator(supers[-1]) supers[-1]._calc.results['forces'] = forces[i] # rotational sum rule from hiphive import ForceConstants, ClusterSpace, StructureContainer cs = ClusterSpace(sposcar, [r_cut]) sc = StructureContainer(cs) for s in supers: sc.add_structure(s) from hiphive.fitting import Optimizer opt = Optimizer(sc.get_fit_data(), train_size=1.0) opt.train() print(opt) parameters = opt.parameters from hiphive import ForceConstantPotential, enforce_rotational_sum_rules parameters_rot = enforce_rotational_sum_rules( cs, parameters, ['Huang', 'Born-Huang']) fcp_rot = ForceConstantPotential(cs, parameters_rot) fcs = fcp_rot.get_force_constants(sposcar).get_fc_array(order=2) phonon.set_force_constants(fcs) else: phonon.set_force_constants_zero_with_radius(r_cut) if verbose: print('\n\ndisplacement_dataset =>\n\n') print(phonon.get_displacement_dataset()) print('\n\nforce_constants =>\n\n') print(phonon.get_force_constants()) import pickle as pckl pckl.dump(phonon, open(pckl_name, 'wb'), protocol=2) return phonon