Пример #1
0
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)))
Пример #2
0
    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
Пример #3
0
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])
Пример #5
0
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
Пример #6
0
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)
Пример #7
0
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
Пример #8
0
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
Пример #9
0
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
Пример #10
0
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
Пример #11
0
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])

Пример #12
0
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
Пример #13
0
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)
Пример #14
0
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)))
Пример #15
0
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
Пример #16
0
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:]
Пример #17
0
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:]
Пример #18
0
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]
Пример #19
0
    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
Пример #20
0
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
Пример #21
0
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]
Пример #22
0
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
Пример #23
0
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
Пример #24
0
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
Пример #25
0
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:]
Пример #26
0
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()
Пример #28
0
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]
Пример #29
0
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
Пример #30
0
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
Пример #31
0
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]
Пример #32
0
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!')
Пример #33
0
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