Source code for sisl.io.fhiaims._geometry

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
"""
Sile object for reading/writing FHI-aims geometry files
"""
import numpy as np

from ..sile import sile_raise_write, sile_fh_open, add_sile
from ..sile import SileError

from .sile import SileFHIaims

from sisl._internal import set_module
from sisl import Geometry, SuperCell


__all__ = ["inSileFHIaims"]


@set_module("sisl.io.fhiaims")
class inSileFHIaims(SileFHIaims):
    """ FHI-aims geometry file object """

[docs] @sile_fh_open() def write_supercell(self, sc, fmt=".8f"): """ Writes the supercell to the contained file Parameters ---------- sc : SuperCell the supercell to be written fmt : str, optional used format for the precision of the data """ sile_raise_write(self) _fmt = f"lattice_vector {{:{fmt}}} {{:{fmt}}} {{:{fmt}}}\n" self._write(_fmt.format(*sc.cell[0])) self._write(_fmt.format(*sc.cell[1])) self._write(_fmt.format(*sc.cell[2]))
[docs] @sile_fh_open() def write_geometry(self, geometry, fmt=".8f", as_frac=False, velocity=None, moment=None): """ Writes the geometry to the contained file Parameters ---------- geometry : Geometry the geometry to be written fmt : str, optional used format for the precision of the data as_frac : bool, optional whether coordinates are written as fractional coordinates velocity: array_like, optional also write the velocity fields in [Ang/ps] moment : array_like, optional also write an initial moment for each atom """ # Check that we can write to the file sile_raise_write(self) self.write_supercell(geometry.sc, fmt) if as_frac: xyz = geometry.fxyz prefix = "atom_frac" else: xyz = geometry.xyz prefix = "atom" _fmt = f"{prefix} {{1:{fmt}}} {{2:{fmt}}} {{3:{fmt}}} {{0:s}}\n" _fmtv = f"velocity {{:{fmt}}} {{:{fmt}}} {{:{fmt}}}\n" _fmtm = f"initial_moment {{:{fmt}}}\n" for ia, atom in enumerate(geometry.atoms): s = {"fa": "Ds"}.get(atom.symbol, atom.symbol) self._write(_fmt.format(s, *xyz[ia])) if velocity is not None: self._write(_fmtv.format(*velocity[ia])) if moment is not None: self._write(_fmtm.format(moment[ia]))
[docs] @sile_fh_open() def read_supercell(self): """ Reads supercell object from the file """ self.fh.seek(0) # read until "lattice_vector" is found cell = [] for line in self: if line.startswith("lattice_vector"): cell.append([float(f) for f in line.split()[1:]]) return SuperCell(cell)
[docs] @sile_fh_open() def read_geometry(self, velocity=False, moment=False): """ Reads Geometry object from the file Parameters ---------- velocity: bool, optional also return the velocities in the file, if not present, it will return a 0 array moment: bool, optional also return the moments specified in the file, if not present, it will return a 0 array Returns ------- Geometry : geometry found in file velocity : array_like array of velocities in Ang/ps for each atom, will only be returned if `velocity` is true moment : array_like array of initial moments of each atom, will only be returned if `moment` is true """ sc = self.read_supercell() self.fh.seek(0) sp = [] xyz = [] v = [] m = [] def ensure_length(l, length, add): if length < 0: raise SileError("Found a velocity/initial_moment entry before an atom entry?") while len(l) < length: l.append(add) for line in self: line = line.split() if line[0] == "atom": xyz.append([float(f) for f in line[1:4]]) elif line[0] == "atom_frac": xyz.append([float(f) for f in line[1:4]] @ sc.cell) elif line[0] == "velocity": # ensure xyz and v are same length ensure_length(v, len(xyz) - 1, [0, 0, 0]) v.append([float(f) for f in line[1:4]]) continue elif line[0] == "initial_moment": # ensure xyz and v are same length ensure_length(m, len(xyz) - 1, 0) m.append(float(line[1])) continue else: continue # we found an atom sp.append(line[4]) ret = (Geometry(xyz, atoms=sp, sc=sc), ) if not velocity and not moment: return ret[0] if velocity: ret = ret + (np.array(v),) if moment: ret = ret + (np.array(m),) return ret
[docs] def read_velocity(self): """ Reads velocity in the file """ return self.read_geometry(velocity=True)[1]
[docs] def read_moment(self): """ Reads initial moment in the file """ return self.read_geometry(moment=True)[1]
def ArgumentParser(self, p=None, *args, **kwargs): """ Returns the arguments that is available for this Sile """ newkw = Geometry._ArgumentParser_args_single() newkw.update(kwargs) return self.read_geometry().ArgumentParser(p, *args, **newkw) add_sile("geometry.in", inSileFHIaims, case=False, gzip=True)