Пример #1
0
    def __init__(self, absolute_path=None):
        super().__init__(absolute_path)
        self.tags.add("lmpdat")
        self._multiple_dihedrals = False

        self.atoms = Atoms([])
        self._xyz_lo_hi = None  # [xlo, xhi, ylo, yhi, zlo, zhi]

        if self.absolute_path is not None:
            self.read_lmpdat()
Пример #2
0
    def __init__(self, absolute_path=None):
        """Initiates an Xyz object.
        If absolute_path is not None, reads the xyz file."""

        super().__init__(absolute_path)
        self.tags.add("xyz")
        self.atoms = Atoms([])

        if self.absolute_path is not None:
            self.read_xyz()
Пример #3
0
def read_vasp(filename, symbols=None):
    file = open(filename)

    lines = file.readlines()

    line1 = [x for x in lines[0].split()]
    if is_exist_symbols(line1):
        symbols = line1

    scale = float(lines[1])

    cell = []
    for i in range(2, 5):
        cell.append([float(x) for x in lines[i].split()[:3]])
    cell = np.array(cell) * scale

    try:
        num_atoms = np.array([int(x) for x in lines[5].split()])
        line_at = 6
    except ValueError:
        symbols = [x for x in lines[5].split()]
        num_atoms = np.array([int(x) for x in lines[6].split()])
        line_at = 7

    expaned_symbols = expand_symbols(num_atoms, symbols)

    if lines[line_at][0].lower() == 's':
        line_at += 1

    is_scaled = True
    if (lines[line_at][0].lower() == 'c' or lines[line_at][0].lower() == 'k'):
        is_scaled = False

    line_at += 1

    positions = []
    for i in range(line_at, line_at + num_atoms.sum()):
        positions.append([float(x) for x in lines[i].split()[:3]])

    if is_scaled:
        atoms = Atoms(symbols=expaned_symbols,
                      cell=cell,
                      scaled_positions=positions)
    else:
        atoms = Atoms(symbols=expaned_symbols, cell=cell, positions=positions)

    return atoms
Пример #4
0
    def __init__(self,
                 absolute_path=None,
                 ignore_types=None):  # ignore_types is for internal use
        super().__init__(absolute_path=absolute_path)

        self.number_of_particles = None
        self.has_velocity = True
        self.atoms = Atoms([])
        self.entry_count = None
        self.auxiliary = []

        if ignore_types is None:
            self.ignore_types = []
        else:
            self.ignore_types = ignore_types

        if self.absolute_path is not None:
            self.read()
Пример #5
0
def parse_scf(outputfile):
    'Obtain material system information'
    unit_lvs = []
    unit_rlvs = []
    mass = []
    symbol = []
    position = []
    file = open(outputfile, 'r')
    lines = file.readlines()
    for index, line in enumerate(lines):
        if 'bravais-lattice index' in line:
            ibrav = int(line.split()[3])
        if 'lattice parameter' in line:
            lattice_constant = float(line.split()[4])
        if 'number of atoms/cell' in line:
            natom = int(line.split()[4])
        if 'number of atomic types' in line:
            ntype = int(line.split()[5])
        if 'crystal axes' in line:
            for i in range(0, 3):
                unit_lvs.append(
                    [float(f) for f in lines[index + 1 + i].split()[3:6]])
        #unit_lvs = unit_lvs * lattice_constant
        if 'reciprocal axes:' in line:
            for i in range(0, 3):
                unit_rlvs.append(
                    [float(f) for f in lines[index + 1 + i].split()[3:6]])
        #unit_rlvs = unit_rlvs * 2 * math.pi / lattice_constant
        if 'mass' in line:
            for i in range(0, ntype):
                symbol.append(lines[index + 1 + i].split()[0])
                mass.append(float(lines[index + 1 + i].split()[2]))
        if 'positions' in line:
            for i in range(0, natom):
                position.append(
                    [float(f) for f in lines[index + 1 + i].split()[6:9]])

    unitcell = Atoms(ntype, symbol, mass, natom, position, unit_lvs)
    unitcell.print_info()
    return unitcell
    def findsym(self):
        def show_symmetry(symmetry):
            for i in range(symmetry['rotations'].shape[0]):
                print("  --------------- %4d ---------------" % (i + 1))
                rot = symmetry['rotations'][i]
                trans = symmetry['translations'][i]
                print("  rotation:")
                for x in rot:
                    print("     [%2d %2d %2d]" % (x[0], x[1], x[2]))
                print("  translation:")
                print("     (%8.5f %8.5f %8.5f)" %
                      (trans[0], trans[1], trans[2]))

        atom_in = Atoms(symbols=self.symbols_in,
                        cell=list(self.lattice),
                        scaled_positions=self.positions_in,
                        pbc=True)
        print("[get_spacegroup]")
        print("  Spacegroup of " + self.seedname +
              " is %s." % spglib.get_spacegroup(atom_in))
        self.symmetry = spglib.get_symmetry(atom_in)
        self.nsymm = self.symmetry['rotations'].shape[0]
        show_symmetry(self.symmetry)
Пример #7
0
import sys
from pyspglib import spglib
import numpy as np

try:
    from atoms import Atoms
except ImportError:
    print "Atoms class is necessary."
    print "You can use atoms.py in the test/ directory."
    sys.exit(1)

silicon = Atoms(symbols=['Si'] * 8,
                cell=[(4, 0, 0), (0, 4, 0), (0, 0, 4)],
                scaled_positions=[(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5),
                                  (0.5, 0.5, 0), (0.25, 0.25, 0.25),
                                  (0.25, 0.75, 0.75), (0.75, 0.25, 0.75),
                                  (0.75, 0.75, 0.25)],
                pbc=True)

silicon_prim = Atoms(symbols=['Si'] * 2,
                     cell=[(0, 2, 2), (2, 0, 2), (2, 2, 0)],
                     scaled_positions=[(0, 0, 0), (0.25, 0.25, 0.25)],
                     pbc=True)

rutile = Atoms(symbols=['Si'] * 2 + ['O'] * 4,
               cell=[(4, 0, 0), (0, 4, 0), (0, 0, 3)],
               scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5), (0.3, 0.3, 0.0),
                                 (0.7, 0.7, 0.0), (0.2, 0.8, 0.5),
                                 (0.8, 0.2, 0.5)],
               pbc=True)
Пример #8
0
    for vec, axis in zip(lattice, ("a", "b", "c")):
        print("%s %10.5f %10.5f %10.5f" % (tuple(axis,) + tuple(vec)))

def show_cell(lattice, positions, numbers):
    show_lattice(lattice)
    print("Atomic points:")
    for p, s in zip(positions, numbers):
        print("%2d %10.5f %10.5f %10.5f" % ((s,) + tuple(p)))

silicon_ase = Atoms(symbols=['Si'] * 8,
                    cell=[(4, 0, 0),
                          (0, 4, 0),
                          (0, 0, 4)],
                    scaled_positions=[(0, 0, 0),
                                      (0, 0.5, 0.5),
                                      (0.5, 0, 0.5),
                                      (0.5, 0.5, 0),
                                      (0.25, 0.25, 0.25),
                                      (0.25, 0.75, 0.75),
                                      (0.75, 0.25, 0.75),
                                      (0.75, 0.75, 0.25)],
                    pbc=True)

silicon = ([(4, 0, 0),
            (0, 4, 0),
            (0, 0, 4)],
           [(0, 0, 0),
            (0, 0.5, 0.5),
            (0.5, 0, 0.5),
            (0.5, 0.5, 0),
            (0.25, 0.25, 0.25),
Пример #9
0
class Xyz(File):
    """Class for xyz files."""
    def __init__(self, absolute_path=None):
        """Initiates an Xyz object.
        If absolute_path is not None, reads the xyz file."""

        super().__init__(absolute_path)
        self.tags.add("xyz")
        self.atoms = Atoms([])

        if self.absolute_path is not None:
            self.read_xyz()

    def read_xyz(self):
        """
        Reads info from xyz file, whose path was given as
        absolute_path when the object was instantiated.

        Raises
        ------
        ValueError
            If the xyz file has extra lines between atoms.
            If a Lattice is found that has the wrong number of parameters.
        TypeError
            If non-numeric values are found for an atom's position.

        """
        self._check_read()

        lines = iter(self.content)
        line = next(lines)
        n_atoms = 0
        while True:
            try:
                n_atoms = int(line.split()[0])
            except TypeError:
                line = next(lines)
                continue
            else:
                break

        lattice_indexes = self._find("Lattice")
        must_invent_cell = False
        if len(lattice_indexes) > 0:
            lattice_index = lattice_indexes[0]
            lattice = find_between(self.content[lattice_index], '"', '"')
            try:
                xx, xy, xz, yx, yy, yz, zx, zy, zz = tuple(lattice.split())
            except ValueError:
                raise ValueError("Lattice in xyz file is bad")
            self.atoms.cell = [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]]
        else:  # if no "Lattice" is found, atoms.cell is invented below
            lattice_index = 0
            must_invent_cell = True

        for line in self.content[lattice_index + 1:]:
            if not line[0].isalpha():
                continue
            try:
                s, x, y, z = tuple(line.split())
            except ValueError:
                continue
                # raise ValueError("xyz file has a bad format, avoid extra lines")
            try:
                xyz = [float(x), float(y), float(z)]
            except TypeError:
                raise TypeError("bad positions in file: {} {} {}".format(
                    x, y, z))

            atom = Atom(atom_type=s, position=xyz)
            self.atoms.add_atom(atom)

        if len(self.atoms) != n_atoms:
            print("WARNING: {} atoms declared in file, {} atoms found in file".
                  format(n_atoms, len(self.atoms)))

        if must_invent_cell:
            gap = 10  # angstroms
            min_x = min(atom.position[0] for atom in self.atoms)
            max_x = max(atom.position[0] for atom in self.atoms)
            min_y = min(atom.position[1] for atom in self.atoms)
            max_y = max(atom.position[1] for atom in self.atoms)
            min_z = min(atom.position[2] for atom in self.atoms)
            max_z = max(atom.position[2] for atom in self.atoms)
            xx = max_x - min_x + gap
            yy = max_y - min_y + gap
            zz = max_z - min_z + gap
            self.atoms.cell = [[xx, 0, 0], [0, yy, 0], [0, 0, zz]]

    def write_xyz(self, filename, real_types=False, with_classification=False):
        """
        Writes xyz file with info present in the Xyz object.

        Parameters
        ----------
        filename : str
            Path to output xyz file.
        real_types : bool, optional
            If real types should be used instead of types
            (e.g. C instead of C2). Standard is False.
        with_classification : bool, optional
            If atom classification is wanted as a comment after every line.
            Standard is False.

        """

        with open(filename, "w") as F:
            F.write(str(len(self.atoms)))
            F.write('\n')

            if self.atoms.cell is not None:
                F.write('Lattice="')
                F.write(' '.join([str(p) for p in self.atoms.cell[0]]) + ' ')
                F.write(' '.join([str(p) for p in self.atoms.cell[1]]) + ' ')
                F.write(' '.join([str(p)
                                  for p in self.atoms.cell[2]]) + '"' + '\n')
            else:
                F.write('\n')

            if not with_classification:
                for atom in self.atoms:
                    F.write(atom.__str__(real_type=real_types) + '\n')
            else:
                for atom in self.atoms:
                    F.write(
                        atom.__str__(real_type=real_types) + '\t# ' +
                        atom.classification + '\n')

    def write_simple_cif(self,
                         filename,
                         struct_name,
                         comment=None,
                         centralize=True):
        """
        Writes a simple cif file. Meant to be used for 1D structures.

        Parameters
        ----------
        filename : str
            Path to output cif file.
        struct_name : str
            Name of the structure, to be included in the file info.
        comment : str, optional
            Comment to the structure, to be included in the file info.
            Standard comment is 'simple cif for 1D nanostructure'.
        centralize : bool, optional
            If the atomic positions should be centralized in the cell.
            Standard is True.

        Notes
        -----
        This is a very simple cif writing for theoretical structures.
        It's not meant to be used for complete crystallography information.

        """

        self._check_read()
        if not self.atoms.atoms:
            self.read_xyz()

        # arguments checking
        struct_name = struct_name.replace(" ", "")
        if comment is None:
            comment = "simple cif for 1D nanostructure"

        with open(filename, "w") as F:

            F.write("data_" + struct_name + "\n\n")

            F.write("_publ_section_comment" + "\n" + ";" + "\n" + comment +
                    "\n" + ";" + "\n\n")

            cell_x = self.atoms.cell[0][0]
            cell_y = self.atoms.cell[1][1]
            cell_z = self.atoms.cell[2][2]

            F.write("_cell_length_a " + str(round(cell_x, 4)) + "(0)" + "\n")
            F.write("_cell_length_b " + str(round(cell_y, 4)) + "(0)" + "\n")
            F.write("_cell_length_c " + str(round(cell_z, 4)) + "(0)" + "\n")
            F.write("_cell_angle_alpha 90.0000(0)" + "\n")
            F.write("_cell_angle_beta 90.0000(0)" + "\n")
            F.write("_cell_angle_gamma 90.0000(0)" + "\n\n")

            F.write("_symmetry_space_group_name_H-M 'P 1'" + "\n")
            F.write("_symmetry_Int_Tables_number 1" + "\n")
            F.write("_symmetry_cell_setting triclinic" + "\n\n")

            F.write("loop_" + "\n")
            F.write("_atom_site_label" + "\n")
            F.write("_atom_site_type_symbol" + "\n")
            F.write("_atom_site_occupancy" + "\n")
            F.write("_atom_site_fract_x" + "\n")
            F.write("_atom_site_fract_y" + "\n")
            F.write("_atom_site_fract_z" + "\n")

            if centralize:
                self.atoms.translate_to_cell_center()

            counter = dict()
            for atom in self.atoms:

                atom_type = str(atom.type)
                if atom_type in counter.keys():
                    counter[atom_type] += 1
                else:
                    counter[atom_type] = 1

                F.write(atom_type + str(counter[atom_type]) + " " +
                        atom.type.real + " 1.0000 " +
                        str(round(atom.position[0] / cell_x, 4)) + " " +
                        str(round(atom.position[1] / cell_y, 4)) + " " +
                        str(round(atom.position[2] / cell_z, 4)) + "\n")
Пример #10
0
class Cfg(File):
    """Class for LAMMPS cfg files."""

    # usual line: "mass type x y z *etc" where len(x,y,z,*etc) == entry_count

    def __init__(self,
                 absolute_path=None,
                 ignore_types=None):  # ignore_types is for internal use
        super().__init__(absolute_path=absolute_path)

        self.number_of_particles = None
        self.has_velocity = True
        self.atoms = Atoms([])
        self.entry_count = None
        self.auxiliary = []

        if ignore_types is None:
            self.ignore_types = []
        else:
            self.ignore_types = ignore_types

        if self.absolute_path is not None:
            self.read()

    def read(self):

        index_start = self._find("Number of particles")[0]
        index_auxiliary = None
        index_atoms = None
        self.number_of_particles = int(self.content[index_start].split()[-1])

        h0_11, h0_12, h0_13, h0_21, h0_22, h0_23, h0_31, h0_32, h0_33 = 0, 0, 0, 0, 0, 0, 0, 0, 0

        if len(self._find(".NO_VELOCITY.")) == 1:
            self.has_velocity = False

        if len(self._find("A = 1 Angstrom")) == 0:
            print(
                "WARNING: distance units in cfg file may not be in Angstroms!")

        for (index, line) in enumerate(self.content[index_start:],
                                       index_start):
            if line.startswith("H0"):
                if "H0(1,1)" in line:
                    h0_11 = float(line.split()[-2])
                elif "H0(1,2)" in line:
                    h0_12 = float(line.split()[-2])
                elif "H0(1,3)" in line:
                    h0_13 = float(line.split()[-2])
                elif "H0(2,1)" in line:
                    h0_21 = float(line.split()[-2])
                elif "H0(2,2)" in line:
                    h0_22 = float(line.split()[-2])
                elif "H0(2,3)" in line:
                    h0_23 = float(line.split()[-2])
                elif "H0(3,1)" in line:
                    h0_31 = float(line.split()[-2])
                elif "H0(3,2)" in line:
                    h0_32 = float(line.split()[-2])
                elif "H0(3,3)" in line:
                    h0_33 = float(line.split()[-2])
            elif "entry_count" in line:
                self.entry_count = int(line.split()[-1])
                n_standard_args = 6 if self.has_velocity else 3
                for _ in range(self.entry_count - n_standard_args):
                    self.auxiliary.append(None)
                index_auxiliary = index + 1
                break
            else:
                continue

        self.atoms.cell = [[h0_11, h0_12, h0_13], [h0_21, h0_22, h0_23],
                           [h0_31, h0_32, h0_33]]

        for (index, line) in enumerate(self.content[index_auxiliary:],
                                       index_auxiliary):
            if line.startswith("auxiliary"):
                i = int(find_between(line, "[", "]"))
                _, __, auxiliary = tuple(line.split())
                self.auxiliary[i] = auxiliary
            else:
                index_atoms = index
                break

        for i in range(index_atoms, len(self.content), 3):
            typ = clear_end(self.content[i + 1], [" ", "\n", "\t"])
            if typ in self.ignore_types:
                continue
            mass = float(self.content[i + 0])
            etc = dict()
            if self.has_velocity:
                raise TypeError("cfg with velocities! not implemented yet!")
            else:
                x, y, z, *args = tuple(self.content[i + 2].split())
                atom = Atom(atom_type=typ,
                            position=[float(x), float(y),
                                      float(z)])
                atom.position = np.matmul(self.atoms.cell, atom.position)
                atom.type.mass = mass
                for (index, arg) in enumerate(args):
                    etc[self.auxiliary[index]] = arg  # string
                atom.etc = etc
                self.atoms.add_atom(atom)

        if self.number_of_particles != len(
                self.atoms) and not self.ignore_types:
            print("WARNING: file says {} atoms, but only {} were found".format(
                self.number_of_particles, len(self.atoms)))

    def write_xyz(self, path, real_types=False):
        xyz = Xyz()
        xyz.atoms = self.atoms
        xyz.write_xyz(path, real_types=real_types)
Пример #11
0
class LmpDat(File):
    """Class for LAMMPS Data files.
    Contains topological information for input.
    May contain force field parameters."""
    def __init__(self, absolute_path=None):
        super().__init__(absolute_path)
        self.tags.add("lmpdat")
        self._multiple_dihedrals = False

        self.atoms = Atoms([])
        self._xyz_lo_hi = None  # [xlo, xhi, ylo, yhi, zlo, zhi]

        if self.absolute_path is not None:
            self.read_lmpdat()

    def read_lmpdat(self):
        pass

    def get_xyz(self, xyz_file: str):
        """
        Gets info from xyz file, and lattice if there is any.

        Parameters
        ----------
        xyz_file : str
            Path to xyz file.

        """

        # makes a dummy Xyz object
        _xyz = Xyz(xyz_file)

        # uses the dummy Xyz object to get info from xyz file
        if len(self.atoms) > 0:
            print("WARNING: erasing current {} atoms".format(len(self.atoms)))
        self.atoms = _xyz.atoms
        print("Reading {} atoms from xyz file".format(len(self.atoms)))

        # deals with the cell
        self.cell_to_lo_hi()

    def cell_to_lo_hi(self):
        xlo = min(atom.position[0] for atom in self.atoms)
        ylo = min(atom.position[1] for atom in self.atoms)
        zlo = min(atom.position[2] for atom in self.atoms)
        extra_spacing = 5  # angstroms
        xhi = max(atom.position[0] for atom in self.atoms) + extra_spacing
        yhi = max(atom.position[1] for atom in self.atoms) + extra_spacing
        zhi = max(atom.position[2] for atom in self.atoms) + extra_spacing
        try:  # if self.atoms.cell is not None
            xhi = xlo + self.atoms.cell[0][0]
            yhi = ylo + self.atoms.cell[1][1]
            zhi = zlo + self.atoms.cell[2][2]
        except TypeError:  # if self.atoms.cell is None
            print("WARNING: no Lattice found in xyz file; "
                  "if the system is periodic, this is BAD")
        finally:
            self._xyz_lo_hi = [xlo, xhi, ylo, yhi, zlo, zhi]

    def get_params(self, params_file: str):
        """
        Gets info from parameters file (force field parameters).

        Parameters
        ----------
        params_file : str
            Path to parameters file.

        Raises
        ------
        TypeError
            If any parameter in the file isn't a number.

        Notes
        -----
        The expected file format isn't native to LAMMPS.
        Instead, it can be written by e.g. a CharmmGeneral object.
        The file should look like this:

        "
        Atom Types

        C1	-0.18	0.06	3.59923	0.01	3.38542
        C2	0.0	    0.06	3.59923	0.01	3.38542

        Bond Types

        C1:C1	195.0	1.53
        C1:C2	195.0	1.53

        Angle Types

        C1:C2:C1	 58.0	109.5	11.16	2.561
        C1:C1:C2     35.0	111.4	22.53	2.179

        Dihedral Types

        C1:C2:C1:C1	0.14	3	0	1.0

        Improper Types

        # none
        "

        """

        if not self.atoms.bonds:
            print("WARNING: topology not computed yet")

        # makes a dummy generic File for parameters
        _params_file = File(params_file)

        atom_types_index = _params_file._find("Atom Types")
        bond_types_index = _params_file._find("Bond Types")
        angle_types_index = _params_file._find("Angle Types")
        dihedral_types_index = _params_file._find("Dihedral Types")
        improper_types_index = _params_file._find("Improper Types")

        # each of the titles above must appear exactly once
        # note that the area below the title may be left empty

        for lis in [
                atom_types_index, bond_types_index, angle_types_index,
                dihedral_types_index, improper_types_index
        ]:
            if (len(lis) > 1) or (len(lis) == 0):
                print("WARNING: bad params file")

        atom_types_index = atom_types_index[0]
        bond_types_index = bond_types_index[0]
        angle_types_index = angle_types_index[0]
        dihedral_types_index = dihedral_types_index[0]
        improper_types_index = improper_types_index[0]

        # checks if there are multiple dihedrals
        self._multiple_dihedrals = False
        types = []
        for line in _params_file.content[dihedral_types_index +
                                         1:improper_types_index]:
            try:
                if line[0].isalpha():
                    typ, *etc = tuple(line.split())
                    if typ in types:
                        self._multiple_dihedrals = True
                    types.append(typ)
            except IndexError:
                continue

        # Atom Types

        index = 1
        for line in _params_file.content[atom_types_index +
                                         1:bond_types_index]:

            try:
                if line[0].isalpha():
                    typ, *charge_and_params = tuple(line.split())
                    if typ not in AtomType.instances_dict.keys():
                        AtomType(typ)  # instantiates it
                    charge, *params = charge_and_params
                    params_nums = []

                    # just takes strings into the right numeric types
                    # if the str "1" becomes the float 1.0, LAMMPS may complain
                    for param in params:
                        try:
                            if "." in param:
                                param_num = float(param)
                            else:
                                param_num = int(param)
                        except TypeError:
                            raise TypeError(
                                "all Atom Type parameters must be numbers, "
                                "at least one is not")
                        except ValueError:  # if param=None
                            param_num = None
                        params_nums.append(param_num)

                    AtomType.instances_dict[typ].index = index
                    AtomType.instances_dict[typ].charge = charge
                    AtomType.instances_dict[typ].params = params_nums  # list
                    index += 1
            except IndexError:
                continue

        # Bond Types

        index = 1
        for line in _params_file.content[bond_types_index +
                                         1:angle_types_index]:

            try:
                if line[0].isalpha():
                    typ, *params = tuple(line.split())
                    if typ not in BondType.instances_dict.keys():
                        BondType(typ)  # instantiates it
                    params_nums = []

                    # just takes strings into the right numeric types
                    # if the str "1" becomes the float 1.0, LAMMPS may complain
                    for param in params:
                        try:
                            if "." in param:
                                param_num = float(param)
                            else:
                                param_num = int(param)
                        except TypeError:
                            raise TypeError(
                                "all Bond Type parameters must be numbers, "
                                "at least one is not")
                        except ValueError:  # if param is None
                            param_num = None
                        params_nums.append(param_num)

                    BondType.instances_dict[typ].index = index
                    BondType.instances_dict[typ].params = params_nums  # list
                    index += 1
            except IndexError:
                continue

        # Angle Types

        index = 1
        for line in _params_file.content[angle_types_index +
                                         1:dihedral_types_index]:

            try:
                if line[0].isalpha():
                    typ, *params = tuple(line.split())
                    if typ not in AngleType.instances_dict.keys():
                        AngleType(typ)  # instantiates it
                    params_nums = []

                    # just takes strings into the right numeric types
                    # if the str "1" becomes the float 1.0, LAMMPS may complain
                    for param in params:
                        try:
                            if "." in param:
                                param_num = float(param)
                            else:
                                param_num = int(param)
                        except TypeError:
                            raise TypeError(
                                "all Angle Type parameters must be numbers, "
                                "at least one is not")
                        except ValueError:  # if param=None
                            param_num = None
                        params_nums.append(param_num)

                    AngleType.instances_dict[typ].index = index
                    AngleType.instances_dict[typ].params = params_nums  # list
                    index += 1
            except IndexError:
                continue

        # Dihedral Types

        index = 1
        for line in _params_file.content[dihedral_types_index +
                                         1:improper_types_index]:

            try:
                if line[0].isalpha():
                    typ, *params = tuple(line.split())
                    if typ not in DihedralType.instances_dict.keys():
                        DihedralType(typ)  # instantiates it
                    params_nums = []

                    # just takes strings into the right numeric types
                    # if the str "1" becomes the float 1.0, LAMMPS may complain
                    for param in params:
                        try:
                            if "." in param:
                                param_num = float(param)
                            else:
                                param_num = int(param)
                        except TypeError:
                            raise TypeError(
                                "all Dihedral Type parameters must be numbers, "
                                "at least one is not")
                        except ValueError:  # if param=None
                            param_num = None
                        params_nums.append(param_num)

                    if not self._multiple_dihedrals:
                        DihedralType.instances_dict[typ].index = index
                        DihedralType.instances_dict[
                            typ].params = params_nums  # list
                    else:  # if self._multiple_dihedrals
                        try:
                            DihedralType.instances_dict[typ].index.append(
                                index)
                            DihedralType.instances_dict[typ].params.append(
                                params_nums)
                        except AttributeError:  # first params of each dihedral
                            DihedralType.instances_dict[typ].index = []
                            DihedralType.instances_dict[typ].params = []
                            DihedralType.instances_dict[typ].index.append(
                                index)
                            DihedralType.instances_dict[typ].params.append(
                                params_nums)
                    index += 1
            except IndexError:
                continue

        # Improper Types

        index = 1
        for line in _params_file.content[improper_types_index + 1:]:

            try:
                if line[0].isalpha():
                    typ, *params = tuple(line.split())
                    if typ not in ImproperType.instances_dict.keys():
                        ImproperType(typ)
                    params_nums = []

                    # just takes strings into the right numeric types
                    # if the str "1" becomes the float 1.0, LAMMPS may complain
                    for param in params:
                        try:
                            if "." in param:
                                param_num = float(param)
                            else:
                                param_num = int(param)
                        except TypeError:
                            raise TypeError(
                                "all Improper Type parameters must be numbers, "
                                "at least one is not")
                        except ValueError:  # if param=None
                            param_num = None
                        params_nums.append(param_num)

                    ImproperType.instances_dict[typ].index = index
                    ImproperType.instances_dict[
                        typ].params = params_nums  # list
                    index += 1
            except IndexError:
                continue

        # moves charge from AtomType to each Atom
        self._set_charges()

        # re-indexes types leaving extra types (in .par but not in .xyz) behind
        self.atoms.re_index_types()

        # GAMBIARRA
        # but should not be a problem if .par is right
        self.delete_impropers_without_parameters()

    def delete_impropers_without_parameters(self):

        impropers = self.atoms.impropers[:]
        i = 1
        for improper in impropers:
            if improper.type.params is None:
                self.atoms.impropers.remove(improper)
            else:
                improper.index = i
                i += 1

        improper_types = self.atoms.improper_types[:]
        i = 1
        for improper_type in improper_types:
            if improper_type.params is None:
                self.atoms.improper_types.remove(improper_type)
            else:
                improper_type.index = i
                i += 1

    def _set_charges(self):
        for atom in self.atoms:
            atom.charge = atom.type.charge

    def multiply_dihedral_coeffs(self):
        """
        Turns every dihedral in n dihedrals, where n is the number of
        terms in its series (e.g. a Fourier Series).

        Returns
        -------
        n_dihedrals : int
            Total number of dihedrals in self.atoms, computed
            after the multiplication.

        Notes
        -----
        The CHARMM parameters are given in this format.
        LAMMPS also has a nice sinusoidal form for dihedrals,
        making this format well suited.

        """

        if not self._multiple_dihedrals:
            raise TypeError("not self._multiple_dihedrals")
            # this means there's an internal problem

        for dihedral in self.atoms.dihedrals:
            try:
                dihedral.index = dihedral.type.index[:]
                # meaningless numbers, only the list's len matters
            except TypeError:
                raise TypeError("bad dihedral type {}, check .par file".format(
                    str(dihedral.type)))

        index = 1
        for dihedral in self.atoms.dihedrals:
            for i in range(len(dihedral.index)):
                dihedral.index[i] = index
                index += 1

        n_dihedrals = index - 1
        return n_dihedrals

    def write_lmpdat(self, filename, atom_style="full", comments=False):
        """
        Writes LAMMPS Data file with info present in this object
        i.e. topology and force field parameters previously read.

        Parameters
        ----------
        filename : str
            Path for output LAMMPS Data file.
            CARE: Will erase any existing file with this name.
        atom_style : {'full', ...}, optional
            Wanted atom_style output format.
        comments : bool, optional
            If comments are wanted in the output file,
            containing redundant info about atom types.

        Notes
        -----
        See LAMMPS documentation on atom_style:
        https://lammps.sandia.gov/doc/atom_style.html

        Examples
        --------
        Example for combining xyz file and par file to make lmpdat file:
        >> xyz = "/home/lasim/mydir/NAME.xyz"
        >> par = "/home/lasim/mydir/NAME.par"
        >> from files.lmp import LmpDat
        >> lmp = LmpDat()
        >> lmp.get_xyz(xyz)
        >> lmp.atoms.compute_topology()  # finds bonds, angles, etc
        >> lmp.get_params(par)  # AFTER computing topology
        >> lmp.write_lmpdat("/home/lasim/mydir/NAME.lmp")

        """

        # sets flags according to atom_style
        if atom_style == "full":
            atoms, bonds, angles, dihedrals, impropers = True, True, True, True, True
            molecule, charge = True, True
            parameters = True
        elif atom_style == "atomic":
            atoms, bonds, angles, dihedrals, impropers = True, False, False, False, False
            molecule, charge = False, False
            parameters = False
        elif atom_style == "charge":
            atoms, bonds, angles, dihedrals, impropers = True, False, False, False, False
            molecule, charge = False, True
            parameters = False
        else:  # to be expanded as needed
            raise TypeError("bad atom_style")

        number_of_dihedrals = len(self.atoms.dihedrals)
        if self._multiple_dihedrals:
            number_of_dihedrals = self.multiply_dihedral_coeffs()

        with open(filename, "w") as F:

            # HEADERS

            F.write("LAMMPS data file\n\n")

            if atoms:
                F.write(str(len(self.atoms.atoms)) + " atoms \n")
            if bonds:
                F.write(str(len(self.atoms.bonds)) + " bonds \n")
            if angles:
                F.write(str(len(self.atoms.angles)) + " angles \n")
            if dihedrals:
                F.write(str(number_of_dihedrals) + " dihedrals \n")
            if impropers:
                F.write(str(len(self.atoms.impropers)) + " impropers \n\n")

            if atoms:
                F.write(str(len(self.atoms.atom_types)) + " atom types \n")
            if bonds:
                F.write(str(len(self.atoms.bond_types)) + " bond types \n")
            if angles:
                F.write(str(len(self.atoms.angle_types)) + " angle types \n")
            if dihedrals and not self._multiple_dihedrals:
                F.write(
                    str(len(self.atoms.dihedral_types)) + " dihedral types \n")
            elif dihedrals and self._multiple_dihedrals:
                F.write(
                    str(
                        sum(
                            len(typ.index)
                            for typ in self.atoms.dihedral_types)) +
                    " dihedral types \n")
            if impropers:
                F.write(
                    str(len(self.atoms.improper_types)) +
                    " improper types \n\n")

            F.write(
                str(self._xyz_lo_hi[0]) + " " + str(self._xyz_lo_hi[1]) + " " +
                "xlo xhi \n")
            F.write(
                str(self._xyz_lo_hi[2]) + " " + str(self._xyz_lo_hi[3]) + " " +
                "ylo yhi \n")
            F.write(
                str(self._xyz_lo_hi[4]) + " " + str(self._xyz_lo_hi[5]) + " " +
                "zlo zhi \n\n")

            F.write("Masses \n\n")
            for typ in self.atoms.atom_types:
                F.write(
                    str(typ.index) + " " + str(typ.mass) + "  # " + str(typ) +
                    "\n")

            # STRUCTURES

            if atoms and self.atoms.atoms:
                molecule_flag = False
                F.write("\nAtoms \n\n")
                if molecule and charge:
                    for atom in self.atoms.atoms:
                        if atom.molecule.index is None:
                            atom.molecule.index = 1
                            molecule_flag = True
                        F.write(
                            str(atom.index) + " " + str(atom.molecule.index) +
                            " " + str(atom.type.index) + " " +
                            str(atom.charge) + " " +
                            " ".join(str(pos) for pos in atom.position) +
                            "  # " + str(atom.type) + "\n")
                elif charge:
                    for atom in self.atoms.atoms:
                        if atom.charge is None:
                            atom.charge = 0.0
                        F.write(
                            str(atom.index) + " " + str(atom.type.index) +
                            " " + str(atom.charge) + " " +
                            " ".join(str(pos) for pos in atom.position) +
                            "  # " + str(atom.type) + "\n")
                else:
                    for atom in self.atoms.atoms:
                        F.write(
                            str(atom.index) + " " + str(atom.type.index) +
                            " " + " ".join(str(pos) for pos in atom.position) +
                            "  # " + str(atom.type) + "\n")

                if molecule_flag:
                    print("WARNING: single molecule assumed!")

            if bonds and self.atoms.bonds:
                F.write("\nBonds \n\n")
                for bond in self.atoms.bonds:
                    if comments:
                        output = (str(bond.index) + " " +
                                  str(bond.type.index) + " " + " ".join(
                                      str(atom.index) for atom in bond.atoms) +
                                  "  # " + str(bond.type) + "\n")
                    else:
                        output = (
                            str(bond.index) + " " + str(bond.type.index) +
                            " " +
                            " ".join(str(atom.index)
                                     for atom in bond.atoms) + "\n")
                    F.write(output)

            if angles and self.atoms.angles:
                F.write("\nAngles \n\n")
                for angle in self.atoms.angles:
                    if comments:
                        output = (
                            str(angle.index) + " " + str(angle.type.index) +
                            " " +
                            " ".join(str(atom.index) for atom in angle.atoms) +
                            "  # " + str(angle.type) + "\n")
                    else:
                        output = (
                            str(angle.index) + " " + str(angle.type.index) +
                            " " +
                            " ".join(str(atom.index)
                                     for atom in angle.atoms) + "\n")
                    F.write(output)

            if dihedrals and self.atoms.dihedrals:
                F.write("\nDihedrals \n\n")
                for dihedral in self.atoms.dihedrals:
                    if not self._multiple_dihedrals:
                        if comments:
                            output = (str(dihedral.index) + " " +
                                      str(dihedral.type.index) + " " +
                                      " ".join(
                                          str(atom.index)
                                          for atom in dihedral.atoms) +
                                      "  # " + str(dihedral.type) + "\n")
                        else:
                            output = (str(dihedral.index) + " " +
                                      str(dihedral.type.index) + " " +
                                      " ".join(
                                          str(atom.index)
                                          for atom in dihedral.atoms) + "\n")
                        F.write(output)
                    else:  # if self._multiple_dihedrals
                        for i in range(len(dihedral.index)):
                            if comments:
                                output = (str(dihedral.index[i]) + " " +
                                          str(dihedral.type.index[i]) + " " +
                                          " ".join(
                                              str(atom.index)
                                              for atom in dihedral.atoms) +
                                          "  # " + str(dihedral.type) + "\n")
                            else:
                                output = (str(dihedral.index[i]) + " " +
                                          str(dihedral.type.index[i]) + " " +
                                          " ".join(
                                              str(atom.index)
                                              for atom in dihedral.atoms) +
                                          "\n")
                            F.write(output)

            if impropers and self.atoms.impropers:
                F.write("\nImpropers \n\n")
                for improper in self.atoms.impropers:
                    if comments:
                        output = (str(improper.index) + " " +
                                  str(improper.type.index) + " " + " ".join(
                                      str(atom.index)
                                      for atom in improper.atoms) + "  # " +
                                  str(improper.type) + "\n")
                    else:
                        output = (str(improper.index) + " " +
                                  str(improper.type.index) + " " + " ".join(
                                      str(atom.index)
                                      for atom in improper.atoms) + "\n")
                    F.write(output)

            # TYPES

            if parameters and atoms and self.atoms.atoms:
                F.write("\nPair Coeffs \n\n")
                for atom_type in self.atoms.atom_types:
                    F.write(
                        str(atom_type.index) + " " +
                        " ".join(str(param) for param in atom_type.params) +
                        "  # " + str(atom_type) + "\n")

            if bonds and self.atoms.bonds:
                F.write("\nBond Coeffs \n\n")
                for bond_type in self.atoms.bond_types:
                    F.write(
                        str(bond_type.index) + " " +
                        " ".join(str(param) for param in bond_type.params) +
                        "  # " + str(bond_type) + "\n")

            if angles and self.atoms.angles:
                F.write("\nAngle Coeffs \n\n")
                for angle_type in self.atoms.angle_types:
                    F.write(
                        str(angle_type.index) + " " +
                        " ".join(str(param) for param in angle_type.params) +
                        "  # " + str(angle_type) + "\n")

            if dihedrals and self.atoms.dihedrals:
                F.write("\nDihedral Coeffs \n\n")
                for dihedral_type in self.atoms.dihedral_types:
                    if not self._multiple_dihedrals:
                        F.write(
                            str(dihedral_type.index) + " " + " ".join(
                                str(param) for param in dihedral_type.params) +
                            "  # " + str(dihedral_type) + "\n")
                    else:  # if self._multiple_dihedrals
                        for i in range(len(dihedral_type.index)):
                            F.write(
                                str(dihedral_type.index[i]) + " " + " ".join(
                                    str(param)
                                    for param in dihedral_type.params[i]) +
                                "  # " + str(dihedral_type) + "\n")

            if impropers and self.atoms.impropers:
                F.write("\nImproper Coeffs \n\n")
                for improper_type in self.atoms.improper_types:
                    try:
                        F.write(
                            str(improper_type.index) + " " + " ".join(
                                str(param) for param in improper_type.params) +
                            "  # " + str(improper_type) + "\n")
                    except TypeError:
                        print(
                            "WARNING: improper {} without parameters!".format(
                                str(improper_type)))
def get_rot_trans(myposwan):
    Amat        = myposwan.Amat
    natom_pos   = myposwan.natom_pos     
    atoms_frac  = myposwan.atoms_frac    
    atoms_symbol= myposwan.atoms_symbol  
    natom_wan   = myposwan.natom_wan     
    atom_num    = myposwan.atom_num      

    crystal_ase = Atoms(symbols=atoms_symbol,cell=Amat.T, scaled_positions=atoms_frac.T,pbc=True)
   
    symmetry = spglib.get_symmetry(crystal_ase)
    ptgrp = spglib.get_pointgroup(symmetry['rotations'])
    
    nsymm = symmetry['rotations'].shape[0]
    
    rotmat = symmetry['rotations']
    rottrn = symmetry['translations']
    rmat0 = np.array(rotmat[0], dtype = np.float64)
    
    # get the number of ptrans
    nptrans = 0
    for i in range(nsymm):
        rmati = np.array(rotmat[i], dtype = np.float64)
        diff = abs(rmati-rmat0).sum()
        #print "i ", i+1, "diff", diff
        if diff < 1.0E-9: nptrans = nptrans + 1
    
    # get the number of distinct rotaions
    nrot = nsymm/nptrans

    print "--------------abstrac of symmetry------------------"
    print("Spacegroup of this cell is %s." % spglib.get_spacegroup(crystal_ase))
    print('Point group: ',ptgrp[0])
    print "number of total symmetry operations: ", nsymm
    print "number of distnct rot  ", nrot 
    print "nptrans per rotation", nptrans
    print "######### For details, see ./mysymmop.dat ########"
    print ""
    
    # check whether rotmat are put as typeI
    # still need to be tested. 
    err="""
    Opps, It seems that in spglib, the rotaions_matrix is not put as
    ----typeI-----
    rot1/ptran_11
    rot2/ptran_21  
    ...
    rotn/ptran_n1  
    ...
    ...
    ...
    rot1/ptran_1m 
    rot2/ptran_2m
    ...
    rotn/ptran_nm
    
    If put as above, I want to trans it as in vasp/OUTCAR
    
    ----typeII-----
    rot1/ptran_11
    rot1/ptran_12
    ...
    rot1/ptran_1m
    ...
    ...
    ...
    rotn/ptran_n1  
    rotn/ptran_n2  
    ...
    rotn/ptran_nm  
    
    """
    for isym in range(nrot):
        rmat0 = np.array(rotmat[isym], dtype = np.float64)
        diff = 0.0
        for iptr in range(nptrans): 
            numb = isym + iptr*nrot
            rmatt = np.array(rotmat[numb], dtype = np.float64)
            diff = diff + abs(rmatt-rmat0).sum() 
        if diff>1.0E-5: print err
        if diff>1.0E-5: sys.exit(0)
    
    # To change code less, we use type I and set nptrans=1
    nptrans = 1 
    wann_atom_rotmap=np.zeros((nsymm,nptrans,natom_wan), dtype=np.int32)
    symop = []
    f = open('mysymmop.dat', 'w')
    for isym in range(nsymm):
        print>>f, ("  --------------- %4d ---------------" % (isym + 1))
        rot = symmetry['rotations'][isym]
        trans = symmetry['translations'][isym]
        print>>f, ("  rotation:")
        for x in rot:
            print>>f, ("      %2d %2d %2d " % (x[0], x[1], x[2]))
        print>>f, ("  translation:")
        print>>f, ("      %8.5f %8.5f %8.5f " % (trans[0], trans[1], trans[2]))
        print>>f, ("  rotmap:")
        gtrans = trans
        ptrans = [np.zeros((3),dtype=np.float64)]
# rot map for POSCAR
        rotmap = []
        for iatom in range(natom_pos):    
            atoms_frac_new = np.dot(rotmat[isym],atoms_frac[:,iatom]) + rottrn[isym]
            # find equiv loc as in original cell
            for jatom in range(natom_pos):
               frac_diff = atoms_frac[:,jatom]-atoms_frac_new
               # determine the equivalent between two atoms before and after space group operation.
               if abs(frac_diff-np.array([round(i) for i in frac_diff],dtype=np.float64)).sum() < 1.0E-3: 
                   print>>f, "             ", iatom+1, "->", jatom+1
                   rotmap.append([iatom+1,jatom+1])
# rot map for wann.in. here 
        for iatom in range(natom_wan):    
            target = rotmap[ atom_num[iatom]-1 ][1]
            wann_atom_rotmap[isym,0,iatom]=atom_num.index(target)
        symop.append((rotmat[isym],gtrans,rotmap,ptrans))
        print>>f, "\n"
        print>>f, "\n"

    print>>f,"rotations as for atoms in wannier projection" 
    # rot map of atoms in wannier projection
    for isymm in range(nsymm):
        print >>f, "isymm", isymm+1, "---------"
        for iptr in range(nptrans): 
            print>>f, "trans", 0, gtrans
            for ii in range(natom_wan): 
                print>>f, "OUTCAR atom rot map:", atom_num[ii], "->", symop[isymm][2][atom_num[ii]-1][1], "=====>", "wannier atom rot map:", ii+1, "->", wann_atom_rotmap[isymm,iptr,ii]+1
    f.close()
    return nsymm, nptrans, symop, wann_atom_rotmap
Пример #13
0
def wRMSD(atom_1, atom_2, ali):
	# filter non-aligned atoms
	atom_1, atom_2 = filter (atom_1, atom_2, ali)
        #print('wRMSD()| pA len: %d   pB len: %d' % (len(atom_1.xyz), len(atom_2.xyz)))
	
	pro = [atom_1, atom_2]
	mmin = min(pro[0].count, pro[1].count)
	### STEP 1 ###
	for p in pro: # resize
		p.count = mmin
		p.xyz = np.resize(p.xyz, (mmin, 3)) # cut off extra atoms (shh)
		p.centerOrigin() # move centroid to Origin

	### STEP 2 ###
	# average Structure
	avgS = Atoms(np.zeros(pro[0].xyz.shape)) # initialize all 0s
	for p in pro:
		avgS.xyz += p.xyz
	avgS.xyz = avgS.xyz/len(pro) # average

	w = 1 # weights not used yet
	weight = np.array([1.0]*p.count)
	# calculate the Standard Deviation
	sd = np.float64(0)
	for p in pro:
		for atom in range(len(p.xyz)):
			n = np.linalg.norm(p.xyz[atom] - avgS.xyz[atom])
			sd += w * n * n
	
	# e is epsilon aka reaaaally small number
	eps = 1.0*np.power(10.0,-5.0)
	### STEP 3 ###

	while True:
		for p in pro:
			# Ri = from Horn's method
			# Si = Ri * Si
			r,t = horn(p.xyz, avgS.xyz, weight)
			#p.xyz = p.xyz*r + t
			temp = np.outer(np.ones(avgS.xyz.shape[0]), t)
			p.xyz = np.dot(p.xyz,r.T) + temp
			
		### STEP 4 ###
		# average Structure
		avgS.xyz = avgS.xyz*0 # initialize all 0s
		for p in pro:
			avgS.xyz += p.xyz
		avgS.xyz = avgS.xyz/len(pro) # average
		
		# calculate the Standard Deviation
		sdNew = np.float64(0)
		for p in pro:
			for atom in range(len(p.xyz)):
				n = np.linalg.norm(p.xyz[atom] - avgS.xyz[atom])
				sdNew += w * n * n
	
		### STEP 5 ###
		if (sd - sdNew) < eps:
			break # algorithm terminates
		else:
			sd = sdNew
	wrmsd = math.sqrt(sd / len(p.xyz))
        return wrmsd