Example #1
0
def get_geometry(mol):
    """
    extract atomlist from block with title 'molecule'
    """
    atoms = mol.get("geometry")
    atomlist = []
    for atom in atoms:
        atname = atom.get("atom")
        atnumber = AtomicData.atomic_number(str(atname))
        coords = atom.get("xyz")
        if mol.get("units", "Angstrom") == "Angstrom":
            coords = [xyz/AtomicData.bohr_to_angs for xyz in coords]
        atomlist.append( (atnumber, coords) )

    return atomlist
Example #2
0
def load_hotbit_pseudoatom(elmfile):
    """
    load description of pseudo atom from a hotbit element (.elm) file

    Parameters:
    ===========
    elmfile: path to element description

    Returns:
    ========
    atom module with data stored as members
    """
    Data = parseHotbitParameters(elmfile)

    class Atom:
        pass

    atom = Atom()
    atom.Z = AtomicData.atomic_number(Data["atom_name"])
    atom.energies = []
    atom.valence_orbitals = []
    atom.nshell = []
    atom.angular_momenta = []
    atom.orbital_occupation = []
    atom.r = None
    atom.radial_wavefunctions = []
    spectr2l = {"s": 0, "p": 1, "d": 2, "f": 3, "g": 4, "h": 5, "i": 6}
    for k in Data.keys():
        if "orbital_energy" in k:
            atom.energies.append(float(Data[k]))
            dummy, spectr = k.rsplit("_", 1)
            n = int(spectr[0])
            l = int(spectr2l[spectr[1]])
            occnr = AtomicData.valence_occ_numbers[Data["atom_name"]]
            if occnr.has_key(spectr):
                atom.orbital_occupation.append(occnr[spectr])
            else:
                atom.orbital_occupation.append(0)
            atom.valence_orbitals.append(len(atom.valence_orbitals))
            atom.nshell.append(n)
            atom.angular_momenta.append(l)
            if Data.has_key("radial_wavefunction_%s" % spectr):
                atom.r = Data["radial_wavefunction_%s" % spectr][:, 0]
                atom.radial_wavefunctions.append(
                    Data["radial_wavefunction_%s" % spectr][:, 1])
            atom.hubbard_U = Data["hubbard_U"]
    return atom
 def __init__(self,
              symbols,
              coordinates,
              tstep,
              nstates,
              charge,
              sc_threshold=0.001):
     # build list of atoms
     atomlist = []
     for s, xyz in zip(symbols, coordinates):
         Z = AtomicData.atomic_number(s)
         atomlist.append((Z, xyz))
     self.dt_nuc = tstep  # nuclear time step in a.u.
     self.nstates = nstates  # number of electronic states including the ground state
     self.sc_threshold = sc_threshold  # threshold for coefficients that are included in the
     # computation of the scalar coupling
     self.Nat = len(atomlist)
     self.masses = AtomicData.atomlist2masses(atomlist)
     self.pes = PotentialEnergySurfaces(atomlist, nstates, charge=charge)
     # save results from last step
     self.last_step = None
Example #4
0
 def process(self, l):
     # Which kind of information should be read?
     l = l.strip()
     if self.read == None:
         if l == "coordinates":
             self.read = "C"
             return
     elif self.read == "C":
         if l == "velocities":
             self.read = "V"
             return
     # Read coordinates or velocities line by line
     if self.read == "C":
         atom, X, Y, Z = l.split()
         Zi = AtomicData.atomic_number(atom)
         # positions in bohr
         pos = float(X), float(Y), float(Z)
         self.atomlist.append((Zi, pos))
     elif self.read == "V":
         vx, vy, vz = l.split()
         vel = float(vx), float(vy), float(vz)
         self.velocities.append(vel)
Example #5
0
def read_slakoformat_par(parfile, atom_order="AB"):
    """
    read table for S and H in the format used by hotbit (https://trac.cc.jyu.fi/projects/hotbit)

    Paramters:
    ==========
    parfile: path to <atom1>_<atom2>.par

    Returns:
    ========
    sk

    The Slater Koster data is stored in attributes of sk:
    sk.Z1, sk.Z2, sk.d, sk.S, sk.H    
    """

    from os.path import basename
    at1, at2 = basename(parfile).replace(".par", "").split("_")
    if atom_order == "BA":
        tmp = at1
        at1 = at2
        at2 = tmp
    data_blocks = parseHotbitParameters(parfile)
    data_AB = data_blocks["slako_integrals_%s_%s" % (at1, at2)]
    data_BA = data_blocks["slako_integrals_%s_%s" % (at2, at1)]
    m, n = data_AB.shape
    assert data_AB.shape == data_BA.shape

    d = data_AB[:, 0]
    assert np.all(data_AB[:, 0] == data_BA[:, 0])

    sk = SlakoModule()
    sk.Z1 = AtomicData.atomic_number(at1)
    sk.Z2 = AtomicData.atomic_number(at2)
    sk.d = d
    sk.S = {}
    sk.H = {}

    S = sk.S
    H = sk.H
    for pos, (tausym_AB, tausym_BA) in enumerate(
            zip(T.tausymbols_AB[-n:], T.tausymbols_BA[-n:])):
        try:
            tau_AB = T.symbol2tau[tausym_AB]
            tau_BA = T.symbol2tau[tausym_BA]
        except KeyError:
            continue
        # AB
        l1, l2 = tau_AB[0], tau_AB[2]

        H[(l1, l2, T.tau2index[tau_AB])] = data_AB[:, pos + 1]
        S[(l1, l2,
           T.tau2index[tau_AB])] = data_AB[:,
                                           len(T.tausymbols_AB) + pos + 1]
        # BA
        l1, l2 = tau_BA[0], tau_BA[2]

        ##        if sk.Z1 == sk.Z2: # I think this is the right condition
        if sk.Z1 > 1 and sk.Z2 > 1:  # but with this illogical condition I can reproduce Roland's results for HCNO compounds
            orbital_parity = pow(-1, l1 + l2)
        else:
            orbital_parity = 1
        H[(l1, l2, T.tau2index[tau_BA])] = orbital_parity * data_BA[:, pos + 1]
        S[(l1, l2, T.tau2index[tau_BA]
           )] = orbital_parity * data_BA[:, len(T.tausymbols_BA) + pos + 1]

    return sk
Example #6
0
def read_slakoformat_skf(skfile, sk=None, atom_order="AB"):
    """
    read table for S and H in the format used by DFTB+ 
    see http://www.dftb.org/fileadmin/DFTB/public/misc/slakoformat.pdf

    Parameters:
    ===========
    skfile: path to <atom 1>-<atom 2>.skf
    sk: slako_module loaded from a different file, to which the data from current table
      is appended.
    atom_order: Which of the atoms in the SK table is to be treated as the first atom?
      "AB": The first orbital belongs to the first atom
      "BA": The first orbital belongs to the second atom

    
    Returns:
    ========
    sk

    The Slater Koster data is stored in attributes of sk:
    sk.Z1, sk.Z2, sk.d, sk.S, sk.H    
    """
    from os.path import basename
    at1, at2 = basename(skfile).replace(".skf", "").split("-")
    fh = open(skfile, "r")
    # line 1
    parts = process_slako_line(fh.readline())
    gridDist, nGridPoints = float(parts[0]), int(parts[1])
    if at1 == at2:
        # line 2
        # homonuclear case
        Ed, Ep, Es, SPE, Ud, Up, Us, fd, fp, fs = map(
            float, process_slako_line(fh.readline()))
    # line 2 or 3
    mass, c2, c3, c4, c5, c6, c7, c8, c9, rcut, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10 = \
        map(float, process_slako_line(fh.readline()))

    d = linspace(0.0, gridDist * (nGridPoints - 1), nGridPoints)
    if sk == None:
        sk = SlakoModule()
        sk.Z1 = AtomicData.atomic_number(at1)
        sk.Z2 = AtomicData.atomic_number(at2)
        sk.d = d
        sk.S = {}
        sk.H = {}
    S = sk.S
    H = sk.H

    if atom_order == "BA":
        tausymbols = T.tausymbols_BA
    else:
        tausymbols = T.tausymbols_AB

    lines = fh.readlines()
    parts = process_slako_line(lines[0])
    n = len(parts) / 2
    assert n == 10  # for orbitals up to d functions there are 10 Slater Koster integrals
    for tausym in tausymbols[-n:]:
        try:
            tau = T.symbol2tau[tausym]
        except KeyError:
            continue


#        print "found %s integrals" % (T.tau2symbol[tau])
        H[(tau[0], tau[2], T.tau2index[tau])] = array(
            [0.0 for i in range(0, int(nGridPoints))])
        S[(tau[0], tau[2], T.tau2index[tau])] = array(
            [0.0 for i in range(0, int(nGridPoints))])
    # line 4 to (4 + nGridPoints -1)
    for i in range(0, nGridPoints):
        parts = process_slako_line(lines[i])
        #Hdd0 Hdd1 Hdd2 Hpd0 Hpd1 Hpp0 Hpp1 Hsd0 Hsp0 Hss0 Sdd0 Sdd1 Sdd2 Spd0 Spd1 Spp0 Spp1 Ssd0 Ssp0 Sss0
        for pos, tausym in enumerate(tausymbols[-n:]):
            try:
                tau = T.symbol2tau[tausym]
            except KeyError:
                continue
            l1, l2 = tau[0], tau[2]
            if atom_order == "BA":
                orbital_parity = pow(-1, l1 + l2)
            else:
                orbital_parity = 1

            H[(l1, l2,
               T.tau2index[tau])][i] = orbital_parity * float(parts[pos])
            S[(l1, l2, T.tau2index[tau])][i] = orbital_parity * float(
                parts[len(tausymbols) + pos])

    return sk
def read_repulsive_potential(filename):
    """
    read repulsive potential in the format used by Hotbit, DFTBaby or DFTB+
    """
    from os.path import exists, basename, dirname, join
    if ".par" in filename:
        # Hotbit's format
        at1, at2 = basename(filename).replace(".par", "").split("_")
        if not exists(filename):
            # file file A_B.par does not exist, look for file B_A.par
            filename_BA = join(dirname(filename), "%s_%s.par" % (at2, at1))
            print "parameter file %s does not exist -> try to load %s" % (
                filename, filename_BA)
            filename = filename_BA
        data_blocks = hotbit_format.parseHotbitParameters(filename)
        mod = ReppotModule()
        mod.d = data_blocks["repulsive_potential"][:, 0]
        mod.Vrep = data_blocks["repulsive_potential"][:, 1]
        mod.Z1 = AtomicData.atomic_number(at1)
        mod.Z2 = AtomicData.atomic_number(at2)
        return mod
    elif ".py" in filename:
        # DFTBaby format
        # access dictionary by .-notation
        mod = utils.dotdic()
        execfile(filename, mod)
        return mod
    elif ".skf" in filename:
        # DFTB+ format, only the Splines part is read
        at1, at2 = basename(filename).replace(".skf", "").split("-")
        if not exists(filename):
            # file file A-B.skf does not exist, look for file B-A.skf
            filename_BA = join(dirname(filename), "%s-%s.skf" % (at2, at1))
            print "parameter file %s does not exist -> try to load %s" % (
                filename, filename_BA)
            filename = filename_BA
        fh = open(filename)
        lines = fh.readlines()
        fh.close()
        # find section with repulsive potential
        for i, l in enumerate(lines):
            if l.strip() == "Spline":
                break
        else:
            raise Exception("No 'Spline' section found in parameter file %s" %
                            filename)
        # Line 2:
        nInt, cutoff = lines[i + 1].strip().split()
        nInt, cutoff = int(nInt), float(cutoff)
        # Line 3: V(r < r0) = exp(-a1*r+a2) + a3   is r too small to be covered by the spline
        a1, a2, a3 = map(float, lines[i + 2].strip().split())
        # Line 4 to 4+nInt-2
        rs = np.zeros(nInt)
        cs = np.zeros((4, nInt))
        for j in range(0, nInt):
            # spline for the range [rj=start,r_(j+1)=end]
            # V(r_j <= r < r_(j+1)) = c0 + c1*(r-r0) + c2*(r-r0)^2 + c3*(r-r0)^3
            start, end, c0, c1, c2, c3 = map(
                float, lines[i + 3 + j].strip().split()[:6])
            rs[j] = start
            cs[:, j] = np.array([c0, c1, c2, c3])
        # V(r_nInt < r) = 0.0
        assert end == cutoff
        # Now we evaluate the spline on a equidistant grid
        Npts = 100
        d = np.linspace(0.0, cutoff, Npts)
        Vrep = np.zeros(Npts)
        j = 0
        for i, di in enumerate(d):
            if (di < rs[0]):
                Vrep[i] = np.exp(-a1 * di + a2) + a3
            else:
                # find interval such that r[j] <= di < r[j+1]
                while (di >= rs[j + 1]) and j < nInt - 2:
                    j += 1
                if j < nInt - 2:
                    assert rs[j] <= di < rs[j + 1]
                    c0, c1, c2, c3 = cs[:, j]
                    Vrep[i] = c0 + c1 * (di - rs[j]) + c2 * (
                        di - rs[j])**2 + c3 * (di - rs[j])**3
                else:
                    Vrep[i] = 0.0
        # create python module
        mod = ReppotModule()
        mod.d = d
        mod.Vrep = Vrep
        mod.Z1 = AtomicData.atomic_number(at1)
        mod.Z2 = AtomicData.atomic_number(at2)
        return mod
    else:
        raise Exception("Format of %s not understood" % filename)
Example #8
0
    def _create_visualization(self, atomlist):
        mlab = self.scene.mlab
        # draw atoms as balls
        vec = XYZ.atomlist2vector(atomlist)
        x, y, z = vec[::3], vec[1::3], vec[2::3]
        Zs = np.array([Z for (Z,pos) in atomlist])
        atom_names = [AtomicData.atom_names[Z-1] for (Z,pos) in atomlist]
        rads = np.array([AtomicData.covalent_radii.get(atname) for atname in atom_names])
        atom_radii = np.sqrt(rads)*1.8

        s = atom_radii
        if self.show_flags["atoms"] == False:
            # make atoms so small that one does not see them
            scale_factor = 0.01
            self.shown_atoms = False
        else:
            scale_factor = 0.45
            self.shown_atoms = True
        atoms = mlab.quiver3d(x,y,z, s,s,s, scalars=Zs.astype(float),
                              mode="sphere", scale_factor=scale_factor, resolution=20,
                              figure=self.scene.mayavi_scene)

        # atoms are coloured by their atomic number
        atoms.glyph.color_mode = "color_by_scalar"
        atoms.glyph.glyph_source.glyph_source.center = [0,0,0]
        self.lut = atoms.module_manager.scalar_lut_manager.lut.table.to_array()
        for atname in set(atom_names):
            Z = AtomicData.atomic_number(atname)
            self.lut[Z,0:3] = ( np.array( atom_colours_rgb.get(atname, (0.0, 0.75, 0.75)) )*255.0 ).astype('uint8')
        atoms.module_manager.scalar_lut_manager.lut.table = self.lut
        atoms.module_manager.scalar_lut_manager.data_range = (0.0, 255.0)
        
        # draw bonds
        C = XYZ.connectivity_matrix(atomlist)
        Nat = len(atomlist)
        connections = []
        bonds = mlab.points3d(x,y,z, scale_factor=0.15, resolution=20,
                              figure=self.scene.mayavi_scene)
        for i in range(0, Nat):
            Zi, posi = atomlist[i]
            for j in range(i+1,Nat):
                if C[i,j] == 1:
                    Zj, posj = atomlist[j]
                    connections.append( (i,j) )
        bonds.mlab_source.dataset.lines = np.array(connections)
        bonds.mlab_source.dataset.modified()
        
        tube = mlab.pipeline.tube(bonds, tube_radius=0.15, #tube_radius=0.05,
                                  figure=self.scene.mayavi_scene)
        tube.filter.radius_factor = 1.0
        surface = mlab.pipeline.surface(tube, color=(0.8,0.8,0.0),
                                        opacity=0.7,
                                        figure=self.scene.mayavi_scene)

        self.atoms = atoms
        self.bonds = bonds
#        self.tube = tube
#        self.surface = surface
        self.atom_radii = s
        self.Zs = Zs.astype(float)
        self.primitives.append(atoms)
        self.primitives.append(bonds)
        self.primitives.append(tube)
        self.primitives.append(surface)
        # Lewis structure
        if self.show_flags["Lewis structure"] == True:
            bondsTuples, bond_orders, lone_pairs, formal_charges = BondOrders.assign_bond_orders(atomlist, C, charge=0)
            # plot DOUBLE bonds
            double_bonds = mlab.points3d(x,y,z, scale_factor=0.15, resolution=20, figure=self.scene.mayavi_scene)
            connections_double = []
            for i,bond in enumerate(bondsTuples):
                if bond_orders[i] == 2:
                    # double bond between atoms I and J
                    connections_double.append( bond )
            double_bonds.mlab_source.dataset.lines = np.array(connections_double)
            double_bonds.mlab_source.dataset.modified()
            
            tube = mlab.pipeline.tube(double_bonds, tube_radius=0.35, figure=self.scene.mayavi_scene)
            tube.filter.radius_factor = 1.0
            surface = mlab.pipeline.surface(tube, color=(0.8,0.8,0.0), figure=self.scene.mayavi_scene)
            #
            self.double_bonds = double_bonds
            self.primitives.append(double_bonds)
            self.primitives.append(tube)
            self.primitives.append(surface)
            #
            # plot TRIPLE bonds
            triple_bonds = mlab.points3d(x,y,z, scale_factor=0.15, resolution=20, figure=self.scene.mayavi_scene)
            connections_triple = []
            for i,bond in enumerate(bondsTuples):
                if bond_orders[i] == 3:
                    # triple bond between atoms I and J
                    connections_triple.append( bond )
            triple_bonds.mlab_source.dataset.lines = np.array(connections_triple)
            triple_bonds.mlab_source.dataset.modified()
            
            tube = mlab.pipeline.tube(triple_bonds, tube_radius=0.35, figure=self.scene.mayavi_scene)
            tube.filter.radius_factor = 1.0
            surface = mlab.pipeline.surface(tube, color=(0.8,0.8,0.0), figure=self.scene.mayavi_scene)
            #
            self.triple_bonds = triple_bonds
            self.primitives.append(triple_bonds)
            self.primitives.append(tube)
            self.primitives.append(surface)

            self.shown_lewis_structure = True