Пример #1
0
Файл: opls.py Проект: grhawk/ASE
    def read_labeled_xyz(self, fileobj, map={}):
        """Read xyz like file with labeled atoms."""
        if isinstance(fileobj, str):
            fileobj = open(fileobj)

        translate = dict(OPLSStructure.default_map.items() + map.items())

        lines = fileobj.readlines()
        L1 = lines[0].split()
        if len(L1) == 1:
            del lines[:2]
            natoms = int(L1[0])
        else:
            natoms = len(lines)
        types = []
        types_map = {}
        for line in lines[:natoms]:
            symbol, x, y, z = line.split()[:4]
            element, label = self.split_symbol(symbol, translate)
            if symbol not in types:
                types_map[symbol] = len(types)
                types.append(symbol)
            self.append(
                Atom(element,
                     [float(x), float(y), float(z)],
                     tag=types_map[symbol]))
            self.types = types
Пример #2
0
def add_atom_on_surfaces(surface,element="H", zmax=None, zmin= None, minimum_distance=0.7,
                         maximum_distance=1.4,max_trials=200):
    """
    This function will add an atom (specified by element) on a surface. Z axis must be perpendicular to x,y plane.
    :param surface: ase.atoms.Atoms object
    :param element: element to be added
    :param zmin and zmax: z_range, cartesian coordinates
    :param minimum_distance: to ensure a good structure returned
    :param maximum_distance: to ensure a good structure returned
    :param max_trials: maximum nuber of trials
    :return: atoms objects
    """
    cell=surface.get_cell()
    if np.power(cell[0:2, 2],2).sum() > 1.0e-6:
        raise RuntimeError("Currently, we only support orthorhombic cells")
    inspector=CheckAtoms(min_bond=minimum_distance,max_bond=maximum_distance)
    for _ in range(max_trials):
        x=np.random.uniform(low=0.0,high=cell[0][0])
        y=np.random.uniform(low=0.0,high=cell[1][1])
        z=np.random.uniform(low=zmin,high=zmax)
        t=surface.copy()
        t.append(Atom(symbol=element,position=[x,y,z],tag=1))
        if inspector.is_good(t, quickanswer=True):
            return t
    raise NoReasonableStructureFound("No good structure found at function add_atom_on_surfaces")
Пример #3
0
def main():
    args = sys.argv
    imgs = read(args[1], index="::40")
    #layers = find_layers(atoms.copy())
    traj = Trajectory('traj.traj','w')

    H_indices = random.sample([a.index for a in imgs[0] if a.symbol == 'H'],8)

    n_img = 0
    for atoms in imgs:
       nl=NeighborList([2.5/2]*len(atoms), self_interaction=False, bothways=True)
       nl.update(atoms)
       pair_selected = []
       for H_index in H_indices:
         nl_indices, nl_offsets = nl.get_neighbors(H_index)
         pair_selected.append([H_index, random.sample(nl_indices, 1)[0]])
       for HPd_dist in [1.0, 1.1, 1.2, 1.3, 1.4]:
          img = atoms.copy()
          for pair in pair_selected:
            H_index = pair[0]
            Pd_selected = pair[1]
            v = atoms[H_index].position - atoms[Pd_selected].position
            vn = v/np.linalg.norm(v)
            del img[H_index]
            img.append(Atom('H',atoms[Pd_selected].position + vn * HPd_dist))
          traj.write(img)
          print n_img
          n_img+=1
Пример #4
0
def read_gaussian(filename):
    """Reads a Gaussian input file"""
    f = open(filename, 'r')
    lines = f.readlines()
    f.close()

    atoms = Atoms()
    for n, line in enumerate(lines):
        if ('#' in line):
            i = 0
            while (lines[n + i + 5] != '\n'):
                info = lines[n + i + 5].split()
                if "Fragment" in info[0]:
                    info[0] = info[0].replace("(", " ")
                    info[0] = info[0].replace("=", " ")
                    info[0] = info[0].replace(")", " ")
                    fragment_line = info[0].split()
                    symbol = fragment_line[0]
                    tag = int(fragment_line[2]) - 1
                else:
                    symbol = info[0]
                    tag = 0
                position = [float(info[1]), float(info[2]), float(info[3])]
                atoms += Atom(symbol, position=position, tag=tag)
                i += 1
    return atoms
Пример #5
0
    def read_structures(self, content=None):
        """Read Structures from file and wirte them to self.structures"""
        from ase.atoms import Atoms
        from ase.atom import Atom
        images = []
        temp_items = content.split('Standard orientation')[1:]
        for item_i in temp_items:
            lines = [line for line in item_i.split('\n') if len(line) > 0]
            #first 5 lines are headers
            del lines[:5]
            images.append(Atoms())
            for line in lines:
                #if only - in line it is the end
                if set(line).issubset(set('- ')):
                    break
                tmp_line = line.strip().split()
                if not len(tmp_line) == 6:
                    raise RuntimeError(
                        'Length of line does not match structure!')

                #read atom
                try:
                    atN = int(tmp_line[1])
                    pos = tuple(float(x) for x in tmp_line[3:])
                except ValueError:
                    raise ValueError(
                        'Expected a line with three integers and three floats.'
                    )
                images[-1].append(Atom(atN, pos))
        self.structures = images
        return
Пример #6
0
    def setup(self):
        '''setup'''

        self.functional = self.inp.get('functional') or 'LDA'
        self.runtype = self.inp.get('runtype') or 'calc'

        self.eigensolver = self.inp.get('eigensolver') or 'cg'

        # this actually can't be none!
        _xyz = self.inp.get('xyz')

        if isinstance(_xyz, str):
            self.inputXYZ = _xyz
            self.atoms = read(self.inputXYZ)
        else:
            # support reading frm a dict (TODO: other type of objects - ?)
            from ase.atoms import Atoms
            from ase.atom import Atom

            self.atoms = \
             Atoms([Atom(a[0],(a[1],a[2],a[3])) for a in _xyz])

        # TODO: support multiple cell types
        self.atoms.cell = (self.inp['cell']['x'], self.inp['cell']['y'],
                           self.inp['cell']['z'])

        # Mixer setup - only "broyden" supported
        self.mixer = self.inp.get('mixer')

        if self.mixer is None:
            self.mixer = Mixer
        else:
            self.mixer = BroydenMixer

        # Custom ID: allow to trace parameter set using a custom id
        self.custom_id = self.inp.get('custom_id')

        # Periodic Boundary Conditions
        self.atoms.pbc = False

        # This should not be done always
        self.atoms.center()

        self.nbands = self.inp.get('nbands')

        self.gpts = None
        self.setup_gpts()

        self.max_iterations = self.inp.get('maxiter') or 333

        # Name: to be set by __str__ first time it is run
        self.name = None

        #
        self.logExtension = 'txt'
        self.dataExtension = 'gpw'

        # Timing / statistics
        self.lastElapsed = None
Пример #7
0
Файл: opls.py Проект: grhawk/ASE
 def colored(self, elements):
     res = Atoms()
     res.set_cell(self.get_cell())
     for atom in self:
         elem = self.types[atom.tag]
         if elem in elements:
             elem = elements[elem]
         res.append(Atom(elem, atom.position))
     return res
Пример #8
0
def get_structure(name):
    angle_w = math.radians(108)
    l_OH = 0.96
    p1 = numpy.array([sin(angle_w / 2), cos(angle_w / 2), 0])
    p2 = numpy.array([-sin(angle_w / 2), cos(angle_w / 2), 0])
    curr_dir = os.path.dirname(os.path.abspath(__file__))
    
    if "Zn" in name:
        f_name = os.path.join(curr_dir, "../data/Zn0.25V2O5(H2O)ICSD82328.cif")
    elif "Co" in name:
        f_name = os.path.join(curr_dir, "../data/Co0.25V2O5(H2O)ICSD50659.cif")
    else:
        return None
    mol = read(f_name)
    scaled_pos = mol.get_scaled_positions()
    ow = [(atom, i) for i, atom in enumerate(mol)\
          if (scaled_pos[i][-1] < 0.52) \
          and (scaled_pos[i][-1] > 0.48) \
          and (atom.symbol == "O")]
    metals = [atom for atom in mol if atom.symbol in ("Co", "Zn")]  # center of the octahedral
    # expand metals using unit cell
    cell = mol.cell
    m_pos = []
    for m in metals:
        for i in (-1, 0, 1):
            for j in range(3):
                m_pos.append(m.position + i * cell[j, :])  # toward direction j with repeat i
                # search for closet
    # Look for the smallest distance and place H in the plane
    for o, i in ow:
        dist = [norm(o.position - mp) for mp in m_pos]
        mp = m_pos[numpy.argmin(dist)]
        # print("Zn", mp, "O", o.position)
        vec = (o.position - mp) / norm(o.position - mp)  # unit vector from M->O
        r, theta, phi = cart_to_sph(vec)
        # print(vec, r, theta, phi)
        vec_xy = numpy.array([r * sin(theta) * cos(phi), r * sin(theta) * sin(phi), 0])
        vec_n = numpy.cross(vec_xy, vec)
        vec_n = vec_n / numpy.linalg.norm(vec_n)
        
        # print(vec, p1)
        for p in (p1, p2):
            vec_ph = p[0] * vec_n + p[1] * vec  # reconstruct in the vec, vec_n plane
            ph = o.position + vec_ph * l_OH
            h = Atom("H", ph)
            mol.append(h)

    # Add initial magmom
    symbols = numpy.array(mol.get_chemical_symbols())  # for comparison
    magmom = numpy.zeros(len(symbols))
    magmom[symbols == "V"] = 0.25
    magmom[symbols == "Co"] = 3.0
    mol.set_initial_magnetic_moments(magmom)
    return mol
Пример #9
0
def add_atom(atoms, chem_potentials, beta, random_state, resolution=None):
    """
    Perform a GCMC atomic addition

    Parameters
    ----------
    atoms: ase.Atoms object
        The atomic configuration
    chem_potentials: dict
        A dictionary of {"Chemical Symbol": mu} where mu is a float denoting
        the chemical potential
    beta: float
        The thermodynamic beta
    random_state: np.random.RandomState object
        The random state to be used
    resolution: float or ndarray, optional
        If used denote the resolution for the voxels

    Returns
    -------
    atoms or None:
        If the new configuration is accepted then the new atomic configuration
        is returned, else None

    """
    # make the proposed system
    atoms_prime = dc(atoms)

    # make new atom
    new_symbol = np.random.choice(list(chem_potentials.keys()))
    e0 = atoms.get_potential_energy()
    if resolution is None:
        new_position = np.random.uniform(0, np.max(atoms.get_cell(), 0))
    else:
        c = np.int32(np.ceil(np.diagonal(atoms.get_cell()) / resolution))
        qvr = np.random.choice(np.product(c))
        qv = np.asarray(np.unravel_index(qvr, c))
        new_position = (qv + random_state.uniform(0, 1, 3)) * resolution
    new_atom = Atom(new_symbol, np.asarray(new_position))

    # append new atom to system
    atoms_prime.append(new_atom)

    # get new energy
    delta_energy = atoms_prime.get_potential_energy() - e0
    # get chemical potential
    mu = chem_potentials[new_symbol]
    # calculate acceptance
    if np.random.random() < np.exp(
            min([0, -1. * beta * delta_energy + beta * mu])):
        return atoms_prime
    else:
        return None
Пример #10
0
def main():
    #config = ConfigParser.SafeConfigParser()
    config = ConfigParser.ConfigParser()
    config.read('config.ini')
    #print config
    main_paras = dict(config.items('main'))
    #print main_paras
    atoms = read(main_paras['structurefile'],
                 index=main_paras['structure_slice'],
                 format=main_paras['fileformat'])
    h_distances = np.array([0.6 + float(i) / 10.0 for i in range(10)])
    bondlength = 1.6
    traj = Trajectory('traj.traj', 'w')
    h_index = []
    for index in range(len(atoms[0])):
        if atoms[0][index].symbol == 'H':
            h_index.append(index)
    h_index.sort(reverse=True)
    for p in atoms:
        for index in h_index:
            p.pop(i=index)
        center = np.mean(p.get_positions(), axis=0)
        print center
        for atom in p:
            distance = np.linalg.norm(center - atom.position)
            if distance > 2.0:
                dot = atom.position + bondlength * (atom.position -
                                                    center) / distance
                perp_vector = perpendicular_vector(atom.position - center)
                unit_perp_vector = perp_vector / np.linalg.norm(perp_vector)
                for h_distance in h_distances:
                    image = p.copy()
                    image.append(
                        Atom('H', dot + h_distance * unit_perp_vector / 2.0))
                    image.append(
                        Atom('H', dot - h_distance * unit_perp_vector / 2.0))
                    #image=image.wrap(center=(0.5, 0.5, 0.5))
                    traj.write(image)
                break
Пример #11
0
def dict_atoms(d):
    atoms = Atoms([
        Atom(atom['symbol'],
             position=atom['position'],
             tag=atom['tag'],
             momentum=atom['momentum'],
             magmom=atom['magmom'],
             charge=atom['charge']) for atom in d['atoms']
    ],
                  cell=d['cell'],
                  pbc=d['pbc'],
                  info=d['info'],
                  constraint=[dict2constraint(c) for c in d['constraints']])
    return atoms
Пример #12
0
def read_cmdft(fileobj):
    lines = fileobj.readlines()
    del lines[0]
    finished = False
    s = Atoms()
    while not finished:
        w = lines.pop(0).split()
        if w[0].startswith('"'):
            position = Bohr * np.array([float(w[3]), float(w[4]), float(w[5])])
            s.append(Atom(w[0].replace('"', ''), position))
        else:
            finished = True

    yield s
Пример #13
0
def main():
    if not os.path.isdir('TMXR200X'):
        os.makedirs('TMXR200X')
    #for database in ['TM1R2006']:
    for database in database_files.keys():
        fh = open(database_files[database]['module'].lower() + '.py', 'w')
        fh.write('# Computer generated code! Hands off!\n')
        fh.write('# Generated: ' + str(datetime.date.today()) + '\n')
        fh.write('from numpy import array\n')
        fh.write('data = ')
        data = {}  # specification of molecules
        info = {}  # reference/calculation info
        # download structures
        file = database_files[database]['pdf']
        f = os.path.abspath(download_file(url_root, file, dir='TMXR200X'))
        f = pdftotext(f)
        geometries = read_geometries(f)
        # set number of unpaired electrons and charges
        no_unpaired_electrons = []
        charges = []
        for a in geometries:
            magmom = sum(a[1].get_initial_magnetic_moments())
            if magmom > 0.0:
                no_unpaired_electrons.append((a[0], magmom))
            charge = sum(a[1].get_charges())
            if abs(charge) > 0.0:
                charges.append((a[0], charge))
        data = format_data(database, geometries, no_unpaired_electrons,
                           charges)
        # all constituent atoms
        atoms = []
        for formula, geometry in geometries:
            atoms.extend(list(set(geometry.get_chemical_symbols())))
        atoms = list(set(atoms))
        atoms.sort()
        for atom in atoms:
            magmom = ground_state_magnetic_moments[atomic_numbers[atom]]
            data[atom] = {
                'database': database,
                'name': atom,
                'symbols': atom,
                'magmoms': [magmom],  # None or list
                'charges': None,  # None or list
                'positions': np.array([[0.0] * 3]),
            }
            Atom(atom, magmom=magmom)
        pprint.pprint(data, stream=fh)
        fh.close()
Пример #14
0
def read_gaussian(filename):
    """Reads a Gaussian input file"""
    f = open(filename, 'r')
    lines = f.readlines()
    f.close()

    atomsymbol = '\s*\D+\s*'
    atomnumber = '\s*\d+\s*'
    atomline = '.\s*((\D+)|(\d+))\s+[0-1]*\s*([-]*\d+\.\d+)\s+[-]*(\d+\.\d+)\s+[-]*(\d+\.\d+)'
    aline = re.compile(atomline)
    asym = re.compile(atomsymbol)
    anum = re.compile(atomnumber)

    atoms = Atoms()
    pbc = False
    cell = np.array([])

    for line in lines:
        p = aline.search(line)
        if p is not None:
            a = p.group().split()
            if asym.search(a[0]) is not None:
                symbol = a[0]
            elif anum.search(a[0]) is not None:
                atomicnum = int(a[0])
                symbol = chemical_symbols[atomicnum]
            if len(a) is 4: position = [float(a[1]), float(a[2]), float(a[3])]
            elif len(a) is 4:
                position = [float(a[2]), float(a[3]), float(a[4])]
            print(a)
            if symbol.find('Tv') == -1:
                atoms += Atom(symbol, position=position)
                isperiodic = False
            else:
                if not isperiodic:
                    cell = np.zeros([3, 3])
                    cell[0][:] = position
                    Ndim = 1
                    isperiodic = True
                else:

                    cell[Ndim][:] = position
                    Ndim += 1
    if isperiodic:
        pbc = [True] * Ndim + [False] * (3 - Ndim)
        atoms.set_pbc(pbc)
        atoms.set_cell(cell)
    return atoms
Пример #15
0
def read_gaussian(filename):
    """Reads a Gaussian input file"""
    f = open(filename, 'r')
    lines = f.readlines()
    f.close()

    atoms = Atoms()
    for n, line in enumerate(lines):
        if ('#' in line):
            i = 0
            while (lines[n + i + 5] != '\n'):
                info = lines[n + i + 5].split()
                symbol = info[0]
                position = [float(info[1]), float(info[2]), float(info[3])]
                atoms += Atom(symbol, position=position)
                i += 1
    return atoms
Пример #16
0
def read_ref_coords(system_name, filename="coords"):

    skip = True
    list_atoms = []
    with open(filename) as fp:
        for line in fp:
            if skip:
                skip = False
                continue
            temp = line.strip().split()
            list_atoms.append(
                Atom(temp[0],
                     (float(temp[1]), float(temp[2]), float(temp[3]))))

    system = Atoms(list_atoms)

    return system.get_atomic_numbers(), system.get_positions()
Пример #17
0
def read_geometry(filename, dir='.'):
    fh = open(os.path.join(dir, filename), 'rb')
    lines = list(filter(read_geometry_filter, fh.readlines()))
    # return geometry in ASE format
    geometry = []
    for line in lines:
        sline = line.split()
        # find chemical symbol (the symbols in the file are lowercase)
        symbol = sline[-1]
        for s in chemical_symbols:
            if symbol == s.lower():
                symbol = s
                break
        geometry.append(Atom(symbol=symbol, position=sline[:-1]))
    fh.close()
    atoms = Atoms(geometry)
    atoms.set_positions(atoms.get_positions()*Bohr) # convert to Angstrom
    return atoms
Пример #18
0
 def read_symbol(self, SYMBOL):
     # read NRLMOL SYMBOL input and convert it to ase.atoms object
     f = open(SYMBOL, 'r')
     ll = f.readlines()
     f.close()
     atoms = Atoms()
     for l in range(len(ll)):
         if ll[l].find('ALL') != -1 or ll[l].find('BHS') != -1:
             tmp = ll[l].split()
             # atom = px py pz s
             atom = tmp[0].split('-')[-1][0:3]
             px = float(tmp[2]) * Bohr
             py = float(tmp[3]) * Bohr
             pz = float(tmp[4]) * Bohr
             s = tmp[5]
             a = Atom(self.nrlmol2elements(atom), [px, py, pz])
             atoms.append(a)
     self.atoms = atoms
Пример #19
0
    def __getitem__(self, i):
        """Return a subset of the atoms.

        i -- scalar integer, list of integers, or slice object
        describing which atoms to return.

        If i is a scalar, return an Atom object. If i is a list or a
        slice, return an Atoms object with the same cell, pbc, and
        other associated info as the original Atoms object. The
        indices of the constraints will be shuffled so that they match
        the indexing in the subset returned.

        """
        if isinstance(i, int):
            natoms = len(self)
            if i < -natoms or i >= natoms:
                raise IndexError('Index out of range.')

            return Atom(atoms=self, index=i)

        import copy
        from ase.constraints import FixConstraint

        atoms = self.__class__(cell=self._cell, pbc=self._pbc)
        # TODO: Do we need to shuffle indices in adsorbate_info too?
        atoms.adsorbate_info = self.adsorbate_info

        atoms.arrays = {}
        for name, a in self.arrays.items():
            atoms.arrays[name] = a[i].copy()

        # Constraints need to be deepcopied, since we need to shuffle
        # the indices
        atoms.constraints = copy.deepcopy(self.constraints)
        condel = []
        for con in atoms.constraints:
            if isinstance(con, FixConstraint):
                try:
                    con.index_shuffle(i)
                except IndexError:
                    condel.append(con)
        for con in condel:
            atoms.constraints.remove(con)
        return atoms
Пример #20
0
def main():
    atoms = read('POSCAR')
    #    atoms.center()
    layers = find_layers(atoms.copy())
    inner_site = {}
    n_site = 0
    for key in layers.keys():
        new_sites, n_site = find_positions(layers[key][-1], n_site)
        if key == 0:
            outer_site = new_sites
            continue
        inner_site.update(new_sites)
    n_Pd = 147
    n_H = int(n_Pd * 0.4)
    n_inners = int(n_H * 0.5)
    #print inner_site.keys()
    #inners = random.sample(random.shuffle(inner_site.keys()), n_inners)
    #outers = random.sample(random.shuffle(outer_site.keys()), n_H - n_inners)
    inner_keys = inner_site.keys()
    outer_keys = outer_site.keys()
    #np.random.shuffle(inner_keys)
    #np.random.shuffle(outer_keys)
    #print inner_keys
    inners = random.sample(inner_keys, n_inners)
    outers = random.sample(outer_keys, n_H - n_inners)
    print outers
    print inners
    #print n_inners
    for key in inners:
        if inner_site[key][0] == 'bridge':
            atoms.append(
                Atom('H', inner_site[key][1] + inner_site[key][2] * 0.4))
        if inner_site[key][0] == 'hollow':
            if inner_site[key][3] > 0:
                atoms.append(
                    Atom('H', inner_site[key][1] + inner_site[key][2] * 0.6))
            else:
                atoms.append(
                    Atom('H', inner_site[key][1] - inner_site[key][2] * 0.6))
    for key in outers:
        if outer_site[key][0] == 'bridge':
            atoms.append(
                Atom('H', outer_site[key][1] + outer_site[key][2] * 0.4))
        if outer_site[key][0] == 'hollow':
            if outer_site[key][3] > 0:
                atoms.append(
                    Atom('H', outer_site[key][1] + outer_site[key][2] * 0.5))
            else:
                atoms.append(
                    Atom('H', outer_site[key][1] - outer_site[key][2] * 0.5))
    write('CONTCAR', atoms, format='vasp')
Пример #21
0
def parse_relax(label,
                write_traj=False,
                pbc=False,
                cell=None,
                chemical_symbols=[]):
    f = open(label + '.relax')
    #f = open(label + '.restart')
    text = f.read()
    # Parse out the steps
    if text == '':
        return None
    steps = text.split(':RELAXSTEP:')[1:]
    if write_traj == False:
        steps = [steps[-1]]
    else:
        traj = Trajectory(label + '.traj', mode='w')

    # Parse out the energies
    n_geometric = len(steps)
    s = os.popen('grep "Total free energy" ' + label + '.out')
    engs = s.readlines()[-n_geometric:]
    engs = [float(a.split()[-2]) * Hartree for a in engs]
    s.close()

    # build a traj file out of the steps
    for j, step in enumerate(steps):
        positions = step.split(':')[2].strip().split('\n')
        forces = step.split(':')[4].strip().split('\n')
        frc = np.empty((len(forces), 3))
        atoms = Atoms()
        for i, f in enumerate(forces):
            frc[i, :] = [float(a) * Hartree / Bohr for a in f.split()]
            atoms += Atom(chemical_symbols[i],
                          [float(a) * Bohr for a in positions[i].split()])

        atoms.set_calculator(
            SinglePointCalculator(atoms, energy=engs[j], forces=frc))
        atoms.set_pbc(pbc)
        atoms.cell = cell
        if write_traj == True:
            traj.write(atoms)
    atoms.set_calculator()
    return atoms
Пример #22
0
def read_I_info(fileobj, index=-1):
    if isinstance(fileobj, str):
        fileobj = open(fileobj)

    lines = fileobj.readlines()

    del lines[0]

    finished = False
    s = Atoms()
    while not finished:
        w = lines.pop(0).split()
        if w[0].startswith('"'):
            position = Bohr * np.array([float(w[3]), float(w[4]), float(w[5])])
            s.append(Atom(w[0].replace('"',''), position))
        else:
            finished = True

    return s
Пример #23
0
def read_dacapo_text(fileobj):
    if isinstance(fileobj, str):
        fileobj = open(fileobj)

    lines = fileobj.readlines()
    i = lines.index(' Structure:             A1           A2            A3\n')
    cell = np.array([[float(w) for w in line.split()[2:5]]
                     for line in lines[i + 1:i + 4]]).transpose()
    i = lines.index(' Structure:  >>         Ionic positions/velocities ' +
                    'in cartesian coordinates       <<\n')
    atoms = []
    for line in lines[i + 4:]:
        words = line.split()
        if len(words) != 9:
            break
        Z, x, y, z = words[2:6]
        atoms.append(Atom(int(Z), [float(x), float(y), float(z)]))

    atoms = Atoms(atoms, cell=cell.tolist())

    try:
        i = lines.index(
            ' DFT:  CPU time                           Total energy\n')
    except ValueError:
        pass
    else:
        column = lines[i + 3].split().index('selfcons') - 1
        try:
            i2 = lines.index(' ANALYSIS PART OF CODE\n', i)
        except ValueError:
            pass
        else:
            while i2 > i:
                if lines[i2].startswith(' DFT:'):
                    break
                i2 -= 1
            energy = float(lines[i2].split()[column])
            atoms.set_calculator(
                SinglePointCalculator(energy, None, None, None, atoms))

    return atoms
Пример #24
0
atoms.center()
view(atoms)
"""
# Si nano-dot

with open('Si29H36.ion', 'r') as f:
    txt = f.read()

Si = txt.split('Si')[1]
Si, H = Si.split('H')

atoms = Atoms()

for element, coord_set in zip(['Si', 'H'], [Si, H]):
    for line in coord_set.splitlines()[1:-1]:
        atoms += Atom(symbol=element,
                      position=[float(a) * Bohr for a in line.split()])
atoms.set_cell([21] * 3)
atoms.center()
add_to_dict(AseAtomsAdaptor.get_structure(atoms), 'Si_nanodot')

# PV=nRT @ 100 bar, 100 C
atoms = make_box_of_molecules(Atoms('He'), 75, [33.811] * 3)
add_to_dict(AseAtomsAdaptor.get_structure(atoms), 'He_box')

# water

# liquid water at room temp, 55.555 mol/L

water = molecule('H2O')
water.set_distance(0, 1, 1.0, fix=0)
water.set_distance(0, 2, 1.0, fix=0)
Пример #25
0
 def __init__(self, position, charge):
     Atom.__init__(self, position=position, charge=charge)
Пример #26
0
add_to_dict(AseAtomsAdaptor.get_structure(atoms), 'polyacetylene')

# MoS2

with open('MoS2') as f:
    txt = f.read()

header, Mo, S = txt.split(':')

MoS2 = Atoms()

for element, block in zip(['Mo', 'S'], [Mo, S]):
    b = block.splitlines()
    for line in b[1:-1]:
        MoS2 += Atom(position=[float(a) * Bohr for a in line.split()],
                     symbol=element)

MoS2.set_cell([27, 27, 6.017129910500000 * Bohr])
MoS2.center()
MoS2.rotate(90, 'y', rotate_cell=True)
#MoS2.set_cell([MoS2.cell[0] * -1, MoS2.cell[1], MoS2.cell[2]])
MoS2.set_cell([MoS2.cell[2], MoS2.cell[1], MoS2.cell[0] * -1])
MoS2.center()
#view(MoS2)
add_to_dict(AseAtomsAdaptor.get_structure(MoS2), 'MoS2_nanotube')

lens = []
for n, s in structures.items():
    lens.append(len(Structure.from_dict(s)))
    #print(len(Structure.from_dict(s)))
Пример #27
0
def make_srs_c8(names,sizes):

    #work out the expansion factor
    #dist0 = furthest_dummy(mol0)
    #dist1 = furthest_dummy(mol1)

    factor = sum(sizes) #dist0 + dist1

    factor = factor * 2

    a = 1.4142 * factor 
   
    #This is an interesting net, as specified, the chirality can go either way: there are 6 N adjacent to each carbon
    # each N, in turn can equally bond two different pairs of C
    # C -> triangles, N => midpoints
    #srs_c8 = crystal(['C', 'N'], [(0.25, 0.25, 0.25), (0.25, 0.0, 0.5)], spacegroup=211, #I432
    #               cellpar=[a, a, a, 90, 90, 90])
    # The confusion is removed by specifying extra 'F' atoms 
    srs_c8 = crystal(['C', 'N', 'F'], [(0.25, 0.25, 0.25), (0.25, 0.0, 0.5), (0.25, 0.625, 0.125)], spacegroup=211, #I432
                   cellpar=[a, a, a, 90, 90, 90])
    
    write('test.cif',srs_c8)
    
    eps = 0.05
    model_molecule={}
    n_obj = -1 #initialise to -1 such that it can be indexed at start of add
    n_tags = 0
    
    #First detect global bonding
    cov_rad=[]
    for atom in srs_c8:
        #cov_rad.append(covalent_radii[atom.number])
        cov_rad.append(factor / 4)
    
    print cov_rad
    
    nlist = NeighborList(cov_rad,skin=0.1,self_interaction=False,bothways=True)
    nlist.build(srs_c8)
    
    #To sort out tags, we need to label each bond
    nbond = 1
    bond_matrix = np.zeros( (len(srs_c8),len(srs_c8)) )
    pbc_bond_matrix = np.zeros( (len(srs_c8),len(srs_c8)) )
    
    bond_dict = {}
    
    for atom in srs_c8:
        print "---------------------"
        indices, offsets = nlist.get_neighbors(atom.index)
        for index,offset in zip(indices,offsets):
            print atom.index, index, atom.symbol, srs_c8[index].symbol, offset, srs_c8.get_distance(atom.index,index,mic=True)
            if atom.index < index:
                this_bond = [atom.index, index]
                for o in offset:
                    this_bond.append(o)
                bond = tuple(this_bond)
                print bond
                bond_dict[bond] = nbond
                #Now we need to find the same bond the other direction to get the offsets right
                indices2,offsets2 = nlist.get_neighbors(index)
                for i2,o2 in zip(indices2,offsets2):
                    if i2 == atom.index:
                        #print "sum of offsets = ", offset, o2, sum(offset + o2)
                        if sum(offset + o2) == 0: #same bond
                            this_bond = [index, atom.index]
                            for o in o2:
                                this_bond.append(o)
                            bond = tuple(this_bond)
                            print bond
                            bond_dict[bond] = nbond
                nbond +=1

    print "Bond dict:" 
    print nbond
    for k,v in sorted(bond_dict.items()):
        print k,v
    print "End Bond dict:" 
    #Want to delete bonds that don't have a F at the midpoint
    for k,v in sorted(bond_dict.items()):
        print "--------------------------"
        print k
        i1,i2,o1,o2,o3 = k
        if (srs_c8[i1].symbol == 'C' and srs_c8[i2].symbol == 'N') or (srs_c8[i1].symbol == 'N' and srs_c8[i2].symbol == 'C'):
            offset = [abs(o1),abs(o2),abs(o3)]
            position1 = srs_c8.positions[i1]
            position2 = srs_c8.positions[i2]
            position2_mic = srs_c8.positions[i2] + np.dot(offset, srs_c8.get_cell())
            midpoint = Atom()
            if any(o != 0 for o in offset):
                midpoint.position = srs_c8[i1].position + (position2_mic - srs_c8[i1].position)/2
                print position1, midpoint.position, position2
            else:
                midpoint.position = srs_c8[i1].position + (srs_c8[i2].position - srs_c8[i1].position)/2 
            match = False    
            for a2 in srs_c8:
                if a2.symbol == 'F':
                    if np.allclose(a2.position, midpoint.position):
                        print "Found a F"
                        match = True
                        continue
            if not match:
                print "deleting", k
                del bond_dict[k]
        else:
            print "not CN/NC, deleting", k
            del bond_dict[k]

    print "New Bond dict:"
    print len(bond_dict)
    for k,v in sorted(bond_dict.items()):
        i1,i2,o1,o2,o3 = k
        position1 = srs_c8.positions[i1]
        position2 = srs_c8.positions[i2]
        position2_mic = srs_c8.positions[i2] + np.dot([o1,o2,o3], srs_c8.get_cell())
        this_dist = np.linalg.norm(position1 - position2)
        this_dist_mic = np.linalg.norm(position1 - position2_mic)
        print k,v, this_dist,this_dist_mic
    print "End New Bond dict:"


    #Start with C (triangles) 
    for atom in srs_c8:
        if atom.symbol == 'C':
            print'======================================='
            print 'C Atom ',atom.index
            n_obj+=1
            model_molecule[n_obj] = Atoms()
            model_molecule[n_obj] += atom
            model_molecule[n_obj][0].original_index = atom.index
            model_molecule[n_obj][0].symbol = 'F' 
            indices, offsets = nlist.get_neighbors(atom.index)
            #Just checking the symbols here
            print indices
            print offsets
            symbols = ([srs_c8[index].symbol for index in indices])
            symbol_string = ''.join(sorted([srs_c8[index].symbol for index in indices]))
            #print symbol_string
            #for i,o in zip(indices, offsets):
            #    print i,o
            for index,offset in zip(indices,offsets):
                print atom.index, index, offset
                this_bond = [atom.index, index]
                for o in offset:
                    this_bond.append(o)
                bond = tuple(this_bond)
                #print bond_dict[bond]
                if srs_c8[index].symbol == 'N' and bond in bond_dict:
                    if any(o != 0 for o in offset):
                        #If we're going over a periodic boundary, we need to negate the tag
                        model_molecule[n_obj] += srs_c8[index]
                        model_molecule[n_obj].positions[-1] = srs_c8.positions[index] + np.dot(offset, srs_c8.get_cell())
                        model_molecule[n_obj][-1].tag = -bond_dict[bond]
                    else:
                        model_molecule[n_obj] += srs_c8[index]
                        model_molecule[n_obj][-1].tag = bond_dict[bond] 
                        model_molecule[n_obj].positions[-1] = srs_c8.positions[index] + np.dot(offset, srs_c8.get_cell())
    
    n_centers = n_obj
    #
    #
    ##Now we do the  N  (edges)
    for atom in srs_c8:
        if atom.symbol == 'N':
            #print'======================================='
            #print 'N Atom ',atom.index, " finding edges"
            n_obj+=1
            model_molecule[n_obj] = Atoms()
            model_molecule[n_obj] += atom
            indices, offsets = nlist.get_neighbors(atom.index)
            for index,offset in zip(indices,offsets):
                print index, offset, srs_c8[index].symbol
                this_bond = [atom.index, index]
                for o in offset:
                    this_bond.append(o)
                bond = tuple(this_bond)
                #if not bond_dict.has_key(bond):
                    #Then 
                if srs_c8[index].symbol == 'C' and bond in bond_dict:
                    if any(o != 0 for o in offset):
                        #If we're going over a periodic boundary, we need to negate the tag
                        model_molecule[n_obj] += srs_c8[index]
                        model_molecule[n_obj].positions[-1] = srs_c8.positions[index] + np.dot(offset, srs_c8.get_cell())
                        model_molecule[n_obj][-1].tag = -bond_dict[bond]
                    else:
                        model_molecule[n_obj] += srs_c8[index]
                        model_molecule[n_obj][-1].tag = bond_dict[bond] 
                        model_molecule[n_obj].positions[-1] = srs_c8.positions[index] + np.dot(offset, srs_c8.get_cell())
    
    
    #
    #
    #
    f = open('srs_c8.model','w')
    g = open('control-mofgen.txt','w')
    #Just for checking, now lets gather everything in the model_molecule dict into one big thing and print it
    #test_mol = Atoms()
    #for obj in model_molecule:
    #    test_mol += model_molecule[obj]
    
    #write('test_model.xyz',test_mol)
    
    #print n_centers, n_model, n_obj
    #Headers and cell
    f.write('%-20s %-3d\n' %('Number of objects =',n_obj+1))
    f.write('%-20s\n' %('build = systre'))
    f.write('%5s\n' %('Cell:'))
    f.write('%8.3f %8.3f %8.3f \n' %
              (srs_c8.get_cell()[0][0],
               srs_c8.get_cell()[0][1],
               srs_c8.get_cell()[0][2]))
    f.write('%8.3f %8.3f %8.3f \n' %
              (srs_c8.get_cell()[1][0],
               srs_c8.get_cell()[1][1],
               srs_c8.get_cell()[1][2]))
    f.write('%8.3f %8.3f %8.3f \n' %
              (srs_c8.get_cell()[2][0],
               srs_c8.get_cell()[2][1],
               srs_c8.get_cell()[2][2])) 
    
    g.write('%-20s\n' %('model = srs_c8'))

    #Now write stuff          
    for obj in xrange(n_centers+1):
        f.write('\n%-8s %-3d\n' %('Center: ', obj+1))
        f.write('%-3d\n' %(len(model_molecule[obj])))
        f.write('%-20s\n' %('type = triangle'))
        #process positions to make it a bit more ideal
        for atom in model_molecule[obj]:
            #if atom.symbol == 'C':
            if atom.index != 0:
                model_molecule[obj].set_distance(atom.index,0,1.0,fix=1)
        for atom in model_molecule[obj]:
            (x,y,z) = atom.position
            #print atom.symbol, atom.position, atom.tag
            if atom.tag:
                f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' % ('X', x, y, z, atom.tag))
                #f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' % (atom.symbol, x, y, z, atom.tag))
            else:
                f.write('%-2s %15.8f %15.8f %15.8f\n' % ('Q', x, y, z))
                #f.write('%-2s %15.8f %15.8f %15.8f\n' % (atom.symbol, x, y, z))
        g.write('%-9s %-50s\n' %('center =', names[0]))
    
    for obj in xrange(n_centers+1,n_obj+1):
        f.write('\n%-8s %-3d\n' %('Linker: ', obj-n_centers))
        f.write('%-3d\n' %(len(model_molecule[obj])))
        f.write('%-20s\n' %('type = linear'))
        #process positions to make it a bit more ideal
        for atom in model_molecule[obj]:
            #if atom.symbol == 'C': 
            if atom.index != 0:
                model_molecule[obj].set_distance(atom.index,0,1.0,fix=1)
        for atom in model_molecule[obj]:
            (x,y,z) = atom.position
            #print atom.symbol, atom.position, atom.tag
            if atom.tag:
                f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' % ('X', x, y, z, atom.tag))
                #f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' % (atom.symbol, x, y, z, atom.tag))
            else:
                f.write('%-2s %15.8f %15.8f %15.8f\n' % ('Q', x, y, z))
                #f.write('%-2s %15.8f %15.8f %15.8f\n' % (atom.symbol, x, y, z))
        g.write('%-9s %-50s\n' %('linker =', names[1]))
    
    #
    #
    test_mol = Atoms()
    for obj in model_molecule:
        test_mol += model_molecule[obj]
    #
    write('test_model2.xyz',test_mol)
Пример #28
0
sym_dict = {
    'carbon': 'C',
    'oxygen': 'O',
    'hydrogen': 'H',
    'lithium': 'Li',
    'fluorine': 'F',
    'phosphorus': 'P'
}

positions = positions.splitlines()[1:]

atoms = Atoms()

for line in positions:
    element, x, y, z = line.split()
    position = [float(a) * Bohr for a in [x, y, z]]
    atoms += Atom(symbol=sym_dict[element], position=position)
atoms.set_cell(lattice)
atoms.set_pbc([True] * 3)

add_to_dict(atoms, 'electrolyte', 273.15 + 23)

# iron interface

#atoms = read('interface.traj')
#add_to_dict(atoms, 'iron_interface', 273.15 + 23)

json.dump(structures, open('../../test_set/MD.json', 'w'))
json.dump(params_dict, open('../../test_set/MD_parameters.json', 'w'))
Пример #29
0
def read_geometries(filename, dir='.'):
    txt = os.path.join(dir, filename)
    fh = open(txt, 'rb')
    table = fh.read()
    firstsplit = '(in xyz format):'  # TM1R2006 and TM2R2007
    dataformat = 'xyz'
    if table.find('(Gaussian archive entries):') != -1:
        firstsplit = '(Gaussian archive entries):'  # TM3R2008
        dataformat = 'gaussian'
    table = table.split(firstsplit)
    table = table[1]
    # remove one or two digit numbers (page numbers/numbers of atoms in xyz format)
    table = re.sub('\n\d\d\n', '\n', table)
    table = re.sub('\n\d\n', '\n', table)
    # remove S + two digit numbers (page numbers)
    table = re.sub('\nS\d\d\n', '\n', table)
    # remove S + one digit (page numbers)
    table = re.sub('\nS\d\n', '\n', table)
    # remove empty lines
    # http://stackoverflow.com/questions/1140958/whats-a-quick-one-liner-to-remove-empty-lines-from-a-python-string
    table = os.linesep.join([s for s in table.splitlines() if s])
    geometries = []
    if dataformat == 'xyz':
        # split on new lines
        table = table.split('\n')
        # mark compound names with ':' tags
        for n, line in enumerate(table):
            if not (line.find('.') != -1):
                # remove method/basis set information
                table[n] = table[n].replace(' BP86/qzvp', '')
                table[n] = ':' + table[n] + ':'
        table = '\n'.join([s for s in table])
        # split into compounds
        # http://simonwillison.net/2003/Oct/26/reSplit/
        # http://stackoverflow.com/questions/647655/python-regex-split-and-special-character
        table = re.compile('(:.*:)').split(table)
        # remove empty elements
        table = [l.strip() for l in table]
        table = [l for l in table if len(l) > 1]
        # extract compounds
        for n in range(0, len(table), 2):
            compound = table[n].replace(':', '').replace(' ', '_')
            geometry = []
            for atom in table[n + 1].split('\n'):
                geometry.append(
                    Atom(symbol=atom.split()[0], position=atom.split()[1:]))
            atoms = Atoms(geometry)
            # set the charge and magnetic moment on the heaviest atom (better ideas?)
            heaviest = max([a.get_atomic_number() for a in atoms])
            heaviest_index = [a.get_atomic_number()
                              for a in atoms].index(heaviest)
            charge = 0.0
            if abs(charge) > 0.0:
                charges = [0.0 for a in atoms]
                charges[heaviest_index] = charge
                atoms.set_charges(charges)
            if compound in [  # see corresponding articles
                    'Ti(BH4)3',  # TM1R2006
                    'V(NMe2)4',  # TM1R2006
                    'Cu(acac)2',  # TM1R2006
                    'Nb(Cp)(C7H7)_Cs',  # TM2R2007
                    'CdMe_C3v',  # TM2R2007
            ]:
                multiplicity = 2.0
            else:
                multiplicity = 1.0
            if multiplicity > 1.0:
                magmoms = [0.0 for a in atoms]
                magmoms[heaviest_index] = multiplicity - 1
                atoms.set_initial_magnetic_moments(magmoms)
            geometries.append((compound, atoms))
    elif dataformat == 'gaussian':
        # remove new lines
        table = table.replace('\n', '')
        # fix: MeHg(Cl) written as MeHg(CN)
        table = table.replace(
            'MeHg(CN), qzvp (SDD/def-qzvp for metal)\\\\0,1\\Hg,0.,0.,0.1975732257',
            'MeHg(Cl), qzvp (SDD/def-qzvp for metal)\\\\0,1\\Hg,0.,0.,0.1975732257'
        )
        # split on compound end marks
        table = table.split('\\\@')
        # remove empty elements
        table = [l.strip() for l in table]
        table = [l for l in table if len(l) > 1]
        # extract compounds
        for n, line in enumerate(table):
            # split on gaussian separator '\\'
            entries = line.split('\\\\')
            compound = entries[2].split(',')[0].split(' ')[0]
            # charge and multiplicity from gaussian archive
            charge, multiplicity = entries[3].split('\\')[0].split(',')
            charge = float(charge)
            multiplicity = float(multiplicity)
            if compound in ['Au(Me)PMe3']:  # in gzmat format!
                # check openbabel version (babel >= 2.2 needed)
                cmd = popen3('babel -V')[1]
                output = cmd.read().strip()
                cmd.close()
                v1, v2, v3 = output.split()[2].split('.')
                v1, v2, v3 = int(v1), int(v2), int(v3)
                if not (v1 > 2 or ((v1 == 2) and (v2 >= 2))):
                    print compound + ': skipped - version of babel does not support gzmat format'
                    continue  # this one is given in z-matrix format
                finame = compound.replace('(', '').replace(')', '') + '.orig'
                foname = finame.split('.')[0] + '.xyz'
                fi = open(finame, 'w')
                fo = open(foname, 'w')
                if 1:  # how to extract zmat by hand
                    zmat = ['#']  # must start with gaussian input start
                    zmat.extend('@')  # separated by newline
                    zmat.extend([compound])
                    zmat.extend('@')  # separated by newline
                    zmat.extend(
                        [str(int(charge)) + ' ' + str(int(multiplicity))])
                    zmat.extend(entries[3].replace(',', ' ').split('\\')[1:])
                    zmat.extend(
                        '@'
                    )  # atom and variable definitions separated by newline
                    zmat.extend(entries[4].split('\\'))
                    zmat.extend('@')  # end with newline
                    for l in zmat:
                        fi.write(l.replace('@', '').replace('=', ' ') + '\n')
                    fi.close()
                if 0:
                    # or use the whole gausian archive entry
                    entries = ''.join(entries)
                    fi.write(entries)
                # convert gzmat into xyz using openbabel (babel >= 2.2 needed)
                cmd = popen3('babel -i gzmat ' + finame + ' -o xyz ' +
                             foname)[2]
                error = cmd.read().strip()
                cmd.close()
                fo.close()
                if not (error.find('0 molecules') != -1):
                    atoms = ase.io.read(foname)
                else:
                    print compound + ': babel conversion failed'
                    continue  # conversion failed
            else:
                positions = entries[3].replace(',', ' ').split('\\')[1:]
                geometry = []
                for k, atom in enumerate(positions):
                    geometry.append(
                        Atom(symbol=atom.split()[0],
                             position=[float(p) for p in atom.split()[1:]]))
                atoms = Atoms(geometry)
            #
            # set the charge and magnetic moment on the heaviest atom (better ideas?)
            heaviest = max([a.get_atomic_number() for a in atoms])
            heaviest_index = [a.get_atomic_number()
                              for a in atoms].index(heaviest)
            if abs(charge) > 0.0:
                charges = [0.0 for a in atoms]
                charges[heaviest_index] = charge
                atoms.set_charges(charges)
            if multiplicity > 1.0:
                magmoms = [0.0 for a in atoms]
                magmoms[heaviest_index] = multiplicity - 1
                atoms.set_initial_magnetic_moments(magmoms)
            geometries.append((compound, atoms))
    return geometries
Пример #30
0
    def __init__(self,
                 symbol="X",
                 position=(0, 0, 0),
                 tag=None,
                 momentum=None,
                 mass=None,
                 magmom=None,
                 charge=None,
                 atoms=None,
                 index=None,
                 pse=None,
                 element=None,
                 **qwargs):
        if element is None:
            element = symbol

        SparseArrayElement.__init__(self, **qwargs)
        # super(SparseArrayElement, self).__init__(**qwargs)
        # verify that element is given (as string, ChemicalElement object or nucleus number
        if pse is None:
            pse = PeriodicTable()

        if element is None or element == "X":
            if "Z" in qwargs:
                el_symbol = pse.atomic_number_to_abbreviation(qwargs["Z"])
                self._lists["element"] = pse.element(el_symbol)
        else:
            if isinstance(element, string_types):
                el_symbol = element
                self._lists["element"] = pse.element(el_symbol)
            elif isinstance(element, str):
                el_symbol = element
                self._lists["element"] = pse.element(el_symbol)
            elif isinstance(element, ChemicalElement):
                self._lists["element"] = element
            else:
                raise ValueError("Unknown element type")

        # KeyError handling required for user defined elements
        try:
            ASEAtom.__init__(self,
                             symbol=symbol,
                             position=position,
                             tag=tag,
                             momentum=momentum,
                             mass=mass,
                             magmom=magmom,
                             charge=charge,
                             atoms=atoms,
                             index=index)
        except KeyError:
            symbol = pse.Parent[symbol]
            ASEAtom.__init__(self,
                             symbol=symbol,
                             position=position,
                             tag=tag,
                             momentum=momentum,
                             mass=mass,
                             magmom=magmom,
                             charge=charge,
                             atoms=atoms,
                             index=index)

        # ASE compatibility for tags
        for key, val in qwargs.items():
            self.data[key] = val
Пример #31
0
def make_Td(names, sizes):

    #work out the expansion factor
    factor = sum(sizes)
    #factor = 3.0

    Td = Atoms()
    Td.append(Atom('F', position=(0, 0, 0)))
    Td.append(Atom('N', position=(0, 0, factor)))
    #Atom 3
    Td.append(Atom('N', position=(1.0, 0, 0.0)))
    Td.set_angle([1, 0, 2], 1.91062939)
    Td.set_distance(0, 2, factor, fix=0)
    #Atom 4
    Td.append(Atom('N', position=(1.0, 0, 0.0)))
    Td.set_distance(0, 3, factor, fix=0)
    Td.set_angle([1, 0, 3], 1.91062939, mask=None)
    Td.set_dihedral([2, 1, 0, 3], 2.0943951, mask=None)
    #print Td.get_angle([1,0,2])
    #Atom 5
    Td.append(Atom('N', position=(1.0, 0, 0)))
    Td.set_angle([1, 0, 4], 1.91062939)
    Td.set_dihedral([2, 1, 0, 4], -2.0943951)
    Td.set_distance(0, 4, factor, fix=0)

    #find side centroids
    tmp1 = Td[1:4]
    coside = tmp1.get_center_of_mass()
    Td.append(Atom('C', position=coside))
    #
    tmp1 = Td[2:5]
    coside = tmp1.get_center_of_mass()
    Td.append(Atom('C', position=coside))
    #
    tmp1 = Td[3:5]
    tmp1.append(Td[1])
    coside = tmp1.get_center_of_mass()
    Td.append(Atom('C', position=coside))
    #
    tmp1 = Td[1:3]
    tmp1.append(Td[4])
    coside = tmp1.get_center_of_mass()
    Td.append(Atom('C', position=coside))

    write('td.xyz', Td)

    # Now we make tags etc

    ## C -> triangles (faces), N => triangle caps

    eps = 0.05
    model_molecule = {}
    n_obj = -1  #initialise to -1 such that it can be indexed at start of add
    n_tags = 0

    #First detect global bonding
    cov_rad = []
    for atom in Td:
        #cov_rad.append(covalent_radii[atom.number])
        cov_rad.append(factor / 2)

    nlist = NeighborList(cov_rad,
                         skin=0.1,
                         self_interaction=False,
                         bothways=True)
    nlist.build(Td)

    nbond = 1
    bond_matrix = np.zeros((len(Td), len(Td)))
    pbc_bond_matrix = np.zeros((len(Td), len(Td)))

    bond_dict = {}

    for atom in Td:
        print "---------------------"
        indices, offsets = nlist.get_neighbors(atom.index)
        for index, offset in zip(indices, offsets):
            print atom.index, index, atom.symbol, Td[
                index].symbol, offset, Td.get_distance(atom.index,
                                                       index,
                                                       mic=True)
            if atom.index < index:
                this_bond = [atom.index, index]
                for o in offset:
                    this_bond.append(o)
                bond = tuple(this_bond)
                print bond
                bond_dict[bond] = nbond
                #Now we need to find the same bond the other direction to get the offsets right
                indices2, offsets2 = nlist.get_neighbors(index)
                for i2, o2 in zip(indices2, offsets2):
                    if i2 == atom.index:
                        #print "sum of offsets = ", offset, o2, sum(offset + o2)
                        if sum(offset + o2) == 0:  #same bond
                            this_bond = [index, atom.index]
                            for o in o2:
                                this_bond.append(o)
                            bond = tuple(this_bond)
                            print bond
                            bond_dict[bond] = nbond
                nbond += 1

    print nbond
    for k, v in bond_dict.items():
        print k, v

    #Now we look for all the things with unit*factor bondlengths
    #Start with N (rectangles)
    for atom in Td:
        if atom.symbol == 'N':
            print '======================================='
            print 'N Atom ', atom.index
            n_obj += 1
            model_molecule[n_obj] = Atoms()
            model_molecule[n_obj] += atom
            model_molecule[n_obj][0].original_index = atom.index
            model_molecule[n_obj][0].symbol = 'F'
            indices, offsets = nlist.get_neighbors(atom.index)
            #Just checking the symbols here
            print indices
            print offsets
            symbols = ([Td[index].symbol for index in indices])
            symbol_string = ''.join(
                sorted([Td[index].symbol for index in indices]))
            #print symbol_string
            #for i,o in zip(indices, offsets):
            #    print i,o
            for index, offset in zip(indices, offsets):
                print atom.index, index, offset
                this_bond = [atom.index, index]
                for o in offset:
                    this_bond.append(o)
                bond = tuple(this_bond)
                print bond_dict[bond]
                if Td[index].symbol == 'C':
                    #By definition, we can't be going over a periodic boundary (no pbc)
                    model_molecule[n_obj] += Td[index]
                    model_molecule[n_obj][-1].tag = bond_dict[bond]
                    model_molecule[n_obj].positions[-1] = Td.positions[index]

    n_centers = n_obj

    ##Now we do the  C  (triangles)
    for atom in Td:
        if atom.symbol == 'C':
            #print'======================================='
            #print 'N Atom ',atom.index, " finding squares1"
            n_obj += 1
            model_molecule[n_obj] = Atoms()
            model_molecule[n_obj] += atom
            indices, offsets = nlist.get_neighbors(atom.index)
            for index, offset in zip(indices, offsets):
                print index, offset, Td[index].symbol
                this_bond = [atom.index, index]
                for o in offset:
                    this_bond.append(o)
                bond = tuple(this_bond)
                #if not bond_dict.has_key(bond):
                #Then
                if Td[index].symbol == 'N':
                    #By definition, we can't be going over a periodic boundary (no pbc)
                    model_molecule[n_obj] += Td[index]
                    model_molecule[n_obj][-1].tag = bond_dict[bond]
                    model_molecule[n_obj].positions[-1] = Td.positions[index]

    f = open('Td.model', 'w')
    g = open('control-mofgen.txt', 'w')
    #Just for checking, now lets gather everything in the model_molecule dict into one big thing and print it
    test_mol = Atoms()
    for obj in model_molecule:
        test_mol += model_molecule[obj]

    write('test_model.xyz', test_mol)

    #print n_centers, n_model, n_obj
    #Headers and cell
    f.write('%-20s %-3d\n' % ('Number of objects =', n_obj + 1))
    f.write('%-20s\n' % ('build = systre'))
    f.write('%5s\n' % ('Cell:'))
    f.write('%8.3f %8.3f %8.3f \n' % (0.0, 0.0, 0.0))
    f.write('%8.3f %8.3f %8.3f \n' % (0.0, 0.0, 0.0))
    f.write('%8.3f %8.3f %8.3f \n' % (0.0, 0.0, 0.0))

    g.write('%-20s\n' % ('model = Td'))

    for obj in xrange(n_centers + 1):
        f.write('\n%-8s %-3d\n' % ('Center: ', obj + 1))
        f.write('%-3d\n' % (len(model_molecule[obj])))
        f.write('%-20s\n' % ('type = triangle'))
        #process positions to make it a bit more ideal
        for atom in model_molecule[obj]:
            #if atom.symbol == 'C':
            if atom.index != 0:
                model_molecule[obj].set_distance(atom.index, 0, 1.0, fix=1)
        for atom in model_molecule[obj]:
            (x, y, z) = atom.position
            #print atom.symbol, atom.position, atom.tag
            if atom.tag:
                f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' %
                        ('X', x, y, z, atom.tag))
                #f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' % (atom.symbol, x, y, z, atom.tag))
            else:
                f.write('%-2s %15.8f %15.8f %15.8f\n' % ('Q', x, y, z))
                #f.write('%-2s %15.8f %15.8f %15.8f\n' % (atom.symbol, x, y, z))
        g.write('%-9s %-50s\n' % ('center =', names[0]))

    for obj in xrange(n_centers + 1, n_obj + 1):
        f.write('\n%-8s %-3d\n' % ('Linker: ', obj - n_centers))
        f.write('%-3d\n' % (len(model_molecule[obj])))
        f.write('%-20s\n' % ('type = triangle'))
        #process positions to make it a bit more ideal
        for atom in model_molecule[obj]:
            #if atom.symbol == 'C':
            if atom.index != 0:
                model_molecule[obj].set_distance(atom.index, 0, 1.0, fix=1)
        for atom in model_molecule[obj]:
            (x, y, z) = atom.position
            #print atom.symbol, atom.position, atom.tag
            if atom.tag:
                f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' %
                        ('X', x, y, z, atom.tag))
                #f.write('%-2s %15.8f %15.8f %15.8f %-4s\n' % (atom.symbol, x, y, z, atom.tag))
            else:
                f.write('%-2s %15.8f %15.8f %15.8f\n' % ('Q', x, y, z))
                #f.write('%-2s %15.8f %15.8f %15.8f\n' % (atom.symbol, x, y, z))
        g.write('%-9s %-50s\n' % ('linker =', names[1]))

    test_mol = Atoms()
    for obj in model_molecule:
        test_mol += model_molecule[obj]

    write('test_model2.xyz', test_mol)
Пример #32
0
def add_adsorbate(slab,
                  adsorbate,
                  height,
                  position=(0, 0),
                  offset=None,
                  mol_index=0):
    """Add an adsorbate to a surface.

    This function adds an adsorbate to a slab.  If the slab is
    produced by one of the utility functions in ase.build, it
    is possible to specify the position of the adsorbate by a keyword
    (the supported keywords depend on which function was used to
    create the slab).

    If the adsorbate is a molecule, the atom indexed by the mol_index
    optional argument is positioned on top of the adsorption position
    on the surface, and it is the responsibility of the user to orient
    the adsorbate in a sensible way.

    This function can be called multiple times to add more than one
    adsorbate.

    Parameters:

    slab: The surface onto which the adsorbate should be added.

    adsorbate:  The adsorbate. Must be one of the following three types:
        A string containing the chemical symbol for a single atom.
        An atom object.
        An atoms object (for a molecular adsorbate).

    height: Height above the surface.

    position: The x-y position of the adsorbate, either as a tuple of
        two numbers or as a keyword (if the surface is produced by one
        of the functions in ase.build).

    offset (default: None): Offsets the adsorbate by a number of unit
        cells. Mostly useful when adding more than one adsorbate.

    mol_index (default: 0): If the adsorbate is a molecule, index of
        the atom to be positioned above the location specified by the
        position argument.

    Note *position* is given in absolute xy coordinates (or as
    a keyword), whereas offset is specified in unit cells.  This
    can be used to give the positions in units of the unit cell by
    using *offset* instead.

    """
    info = slab.adsorbate_info
    if 'cell' not in info:
        info['cell'] = slab.get_cell()[:2, :2]

    pos = np.array([0.0, 0.0])  # (x, y) part
    spos = np.array([0.0, 0.0])  # part relative to unit cell
    if offset is not None:
        spos += np.asarray(offset, float)

    if isinstance(position, str):
        # A site-name:
        if 'sites' not in info:
            raise TypeError('If the atoms are not made by an ' +
                            'ase.build function, ' +
                            'position cannot be a name.')
        if position not in info['sites']:
            raise TypeError('Adsorption site %s not supported.' % position)
        spos += info['sites'][position]
    else:
        pos += position

    pos += np.dot(spos, info['cell'])

    # Convert the adsorbate to an Atoms object
    if isinstance(adsorbate, Atoms):
        ads = adsorbate
    elif isinstance(adsorbate, Atom):
        ads = Atoms([adsorbate])
    else:
        # Assume it is a string representing a single Atom
        ads = Atoms([Atom(adsorbate)])

    # Get the z-coordinate:
    try:
        a = info['top layer atom index']
    except KeyError:
        a = slab.positions[:, 2].argmax()
        info['top layer atom index'] = a
    z = slab.positions[a, 2] + height

    # Move adsorbate into position
    ads.translate([pos[0], pos[1], z] - ads.positions[mol_index])

    # Attach the adsorbate
    slab.extend(ads)