def wavefunction(grid, dV):
     # evaluate orbital
     amp = Cube.orbital_amplitude(grid,
                                  bs.bfs,
                                  scat_orbs[:, i],
                                  cache=False)
     return amp
Beispiel #2
0
    def _computeMO(self, i):
        cube = CubeData()
        atomlist = self.tddftb.dftb2.getGeometry()

        (xmin, xmax), (ymin, ymax), (zmin, zmax) = Cube.get_bbox(atomlist,
                                                                 dbuff=5.0)
        dx, dy, dz = xmax - xmin, ymax - ymin, zmax - zmin

        ppb_text = self.ppbGrid.itemText(self.ppbGrid.currentIndex())
        ppb = float(ppb_text.split()[1])  # points per bohr

        nx, ny, nz = int(dx * ppb), int(dy * ppb), int(dz * ppb)
        x, y, z = np.mgrid[xmin:xmax:nx * 1j, ymin:ymax:ny * 1j,
                           zmin:zmax:nz * 1j]
        grid = (x, y, z)
        #
        orbs = self.tddftb.dftb2.getKSCoefficients()
        moGrid = Cube.orbital_amplitude(grid,
                                        self.bs.bfs,
                                        orbs[:, i],
                                        cache=True)

        mo_cube = CubeData()
        mo_cube.data = moGrid.real
        mo_cube.grid = grid
        mo_cube.atomlist = atomlist

        return mo_cube
Beispiel #3
0
    def plotBoundOrbital(self):
        selected = self.orbitalSelection.selectedItems()
        assert len(selected) == 1
        selected_orbital = self.orbital_dict[str(selected[0].text())]

        self.mo_bound = self.bound_orbs[:, selected_orbital]
        # shift geometry so that the expectation value of the dipole operator vanishes
        # dipole matrix
        dipole = np.tensordot(self.mo_bound,
                              np.tensordot(self.tddftb.dftb2.D,
                                           self.mo_bound,
                                           axes=(1, 0)),
                              axes=(0, 0))
        print "expectation value of dipole: %s" % dipole
        # shift molecule R -> R - dipole
        self.atomlist = MolCo.transform_molecule(
            self.tddftb.dftb2.getGeometry(), (0, 0, 0), -dipole)
        # load bound basis functions
        self.bs_bound = AtomicBasisSet(self.atomlist)
        # plot selected orbital
        (xmin, xmax), (ymin, ymax), (zmin, zmax) = Cube.get_bbox(self.atomlist,
                                                                 dbuff=5.0)
        dx, dy, dz = xmax - xmin, ymax - ymin, zmax - zmin
        ppb = 3.0  # Points per bohr
        nx, ny, nz = int(dx * ppb), int(dy * ppb), int(dz * ppb)
        x, y, z = np.mgrid[xmin:xmax:nx * 1j, ymin:ymax:ny * 1j,
                           zmin:zmax:nz * 1j]
        grid = (x, y, z)
        amplitude_bound = Cube.orbital_amplitude(grid,
                                                 self.bs_bound.bfs,
                                                 self.mo_bound,
                                                 cache=False)

        bound_cube = CubeData()
        bound_cube.data = amplitude_bound.real
        bound_cube.grid = grid
        bound_cube.atomlist = self.atomlist

        self.boundOrbitalViewer.setCubes([bound_cube])
def transform_turbomole_orbitals(tm_dir, dyson_file, method="atomwise", selected_orbitals=None):
    """
    The molecular orbitals from a Turbomole calculation are transformed
    into the basis used by DFTB. Since in DFTB there are much less atomic orbitals
    this transformation is not bijective and does not conserve the normalization and
    orthogonality among the MOs. 

    Parameters:
    ===========
    tm_dir: directory with coord, basis and mos files
    dyson_file: transformed MO coefficients for DFTB are written to this file
    method: Method used to find the coefficients in the minimal basis
      'atomwise': overlaps are only calculated between orbitals on the same atom (very fast).
      'grid': the DFT orbital mo(r) and the minimal DFT atomic orbitals ao_i(r) are calculated 
         on a grid and the coefficients are obtained by minimizing the deviation
             error(c_i) = integral |mo(r) - sum_i c_i ao_i(r)|^2 dr
         in a least square sense (slower, but more accurate).
    selected_orbitals: list of indeces (starting at 1, e.g. '[1,2,3]') of orbitals that should be transformed.
      If not set all orbitals are transformed.
    """
    print "Reading geometry and basis from Turbomole directory %s" % tm_dir
    Data = Turbomole.parseTurbomole(tm_dir + "/coord")
    atomlist = Data["coord"]
    Data = Turbomole.parseTurbomole(tm_dir + "/basis")
    basis_data = Data["basis"]
    bs_gaussian = GaussianBasisSet(atomlist, basis_data)
    # load Turbomole orbitals
    try:
        Data = Turbomole.parseTurbomole(tm_dir + "/mos")
        orbe,orbs_turbomole = Data["scfmo"]
    except IOError:
        print "'mos' file not found! Maybe this is an open-shell calculation. Trying to read file 'alpha'"
        Data = Turbomole.parseTurbomole(tm_dir + "/alpha")
        orbe,orbs_turbomole = Data["uhfmo_alpha"]
    # Which orbitals should be transformed?
    if selected_orbitals == None:
        selected_mos = np.array(range(0, len(orbe)), dtype=int)
    else:
        selected_mos = np.array(eval(selected_orbitals), dtype=int)-1 
    nmo = len(selected_mos)
    # transform them to DFTB basis
    if method == "atomwise":
        T = bs_gaussian.getTransformation_GTO_to_DFTB()
        orbs = np.dot(T, orbs_turbomole[:,selected_mos])
    elif method == "grid":
        # define grid for integration
        (xmin,xmax),(ymin,ymax),(zmin,zmax) = Cube.get_bbox(atomlist, dbuff=7.0)
        dx,dy,dz = xmax-xmin,ymax-ymin,zmax-zmin
        ppb = 5.0 # Points per bohr
        nx,ny,nz = int(dx*ppb),int(dy*ppb),int(dz*ppb)
        x,y,z = np.mgrid[xmin:xmax:nx*1j, ymin:ymax:ny*1j, zmin:zmax:nz*1j]
        grid = (x,y,z)
        dV = dx/float(nx-1) * dy/float(ny-1) * dz/float(nz-1)
        # numerical atomic DFTB orbitals on the grid
        bs_atomic = AtomicBasisSet(atomlist)
        aos = [bf.amp(x,y,z) for bf in bs_atomic.bfs]
        nao = len(aos)
        # overlaps S2_mn = <m|n>
        S2 = np.zeros((nao,nao))
        for m in range(0, nao):
            S2[m,m] = np.sum(aos[m]*aos[m]*dV)
            for n in range(m+1,nao):
                S2[m,n] = np.sum(aos[m]*aos[n]*dV)
                S2[n,m] = S2[m,n]
        # DFT molecular orbitals on the grid
        mos = [Cube.orbital_amplitude(grid, bs_gaussian.bfs, orbs_turbomole[:,i]).real for i in selected_mos]
        # overlaps S1_mi = <m|i>, m is an atomic DFTB orbital, i a molecular DFT orbital
        S1 = np.zeros((nao,nmo))
        for m in range(0, nao):
            for i in range(0, nmo):
                S1[m,i] = np.sum(aos[m]*mos[i]*dV)
        # Linear regression leads to the matrix equation
        #   sum_n S2_mn c_ni = S1_mi
        # which has to be solved for the coefficients c_ni.
        orbs = la.solve(S2, S1)

    else:
        raise ValueError("Method should be 'atomwise' or 'grid' but not '%s'!" % method)
    # normalize orbitals, due to the incomplete transformation they are not necessarily
    # orthogonal
    dftb2 = DFTB2(atomlist)
    dftb2.setGeometry(atomlist)
    S = dftb2.getOverlapMatrix()
    for i in range(0, nmo):
        norm2 = np.dot(orbs[:,i], np.dot(S, orbs[:,i]))
        orbs[:,i] /= np.sqrt(norm2)
    # save orbitals 
    xyz_file = "geometry.xyz"
    XYZ.write_xyz(xyz_file, [atomlist])
    print "Molecular geometry was written to '%s'." % xyz_file
    ionization_energies = -orbe[selected_mos]
    save_dyson_orbitals(dyson_file, ["%d" % (i+1) for i in selected_mos], ionization_energies, orbs, mode="w")
    print "MO coefficients for DFTB were written to '%s'." % dyson_file
 def wavefunction(grid, dV):
     # evaluate continuum orbital
     amp = Cube.orbital_amplitude(grid, bs.bfs, mo_scatt, cache=False)
     return amp
 def f(x, y, z):
     # evaluate orbital
     grid = (x, y, z)
     amp = Cube.orbital_amplitude(grid, bs.bfs, mo, cache=False)
     return amp
Beispiel #7
0
    def plotMFPAD(self):
        Rmax = 80.0
        npts = 30

        E = self.photo_kinetic_energy
        k = np.sqrt(2 * E)
        wavelength = 2.0 * np.pi / k

        # spherical grid
        rs, thetas, phis = np.mgrid[Rmax:(Rmax + wavelength):30j,
                                    0.0:np.pi:npts * 1j,
                                    0.0:2 * np.pi:npts * 1j]
        # transformed into cartesian coordinates
        xs = rs * np.sin(thetas) * np.cos(phis)
        ys = rs * np.sin(thetas) * np.sin(phis)
        zs = rs * np.cos(thetas)

        grid = (xs, ys, zs)
        amplitude_continuum = Cube.orbital_amplitude(grid,
                                                     self.bs_free.bfs,
                                                     self.mo_free,
                                                     cache=False)
        # integrate continuum orbital along radial-direction for 1 wavelength
        wfn2 = abs(amplitude_continuum)**2
        #
        dr = wavelength / 30.0
        wfn2_angular = np.sum(wfn2 * dr, axis=0)

        # SPHERICAL PLOT
        self.MFPADfig3D.clf()

        xs = wfn2_angular * np.sin(thetas[0, :, :]) * np.cos(phis[0, :, :])
        ys = wfn2_angular * np.sin(thetas[0, :, :]) * np.sin(phis[0, :, :])
        zs = wfn2_angular * np.cos(thetas[0, :, :])

        ax = self.MFPADfig3D.add_subplot(111, projection='3d')

        rmax = wfn2_angular.max() * 1.5
        ax.set_xlim((-rmax, rmax))
        ax.set_ylim((-rmax, rmax))
        ax.set_zlim((-rmax, rmax))

        ax.set_xlabel("x")
        ax.set_ylabel("y")
        ax.set_zlabel("z")
        # draw efield
        arrow_vec = wfn2_angular.max() * 1.2 * self.epol / la.norm(self.epol)
        arrow = Arrow3D([0.0, arrow_vec[0]], [0.0, arrow_vec[1]],
                        [0.0, arrow_vec[2]],
                        color=(0.0, 1.0, 0.0),
                        mutation_scale=20,
                        lw=2,
                        arrowstyle="-|>")
        ax.add_artist(arrow)
        ax.text(arrow_vec[0],
                arrow_vec[1],
                arrow_vec[2],
                "E-field",
                color=(0.0, 1.0, 0.0))

        ax.plot_surface(xs, ys, zs, rstride=1, cstride=1)
        ax.scatter(xs, ys, zs, color="k", s=20)
        ax.get_xaxis().set_ticks([])
        ax.get_yaxis().set_ticks([])
        ax.w_zaxis.set_ticks([])

        self.MFPADCanvas3D.draw()

        # 2D PLOT
        self.MFPADfig2D.clf()

        ax = self.MFPADfig2D.add_subplot(111)

        image = ax.imshow(np.fliplr(wfn2_angular.transpose()),
                          extent=[0.0, np.pi, 0.0, 2 * np.pi],
                          aspect=0.5,
                          origin='lower')
        ax.set_xlim((0.0, np.pi))
        ax.set_ylim((0.0, 2 * np.pi))
        ax.set_xlabel("$\\theta$")
        ax.set_ylabel("$\phi$")
        self.MFPADfig2D.colorbar(image)

        # show piercing points of E-field vector
        # ... coming out of the plane
        r = la.norm(self.epol)
        th_efield = np.arccos(self.epol[2] / r)
        phi_efield = np.arctan2(self.epol[1], self.epol[0]) + np.pi
        print "th, phi = %s %s" % (th_efield, phi_efield)
        ax.plot([th_efield], [phi_efield],
                "o",
                markersize=10,
                color=(0.0, 1.0, 0.0))
        ax.text(th_efield,
                phi_efield,
                "E-field",
                color=(0.0, 1.0, 0.0),
                ha="center",
                va="top")
        # ... going into the plane
        th_efield = np.arccos(-self.epol[2] / r)
        phi_efield = np.arctan2(-self.epol[1], -self.epol[0]) + np.pi
        print "- th, phi = %s %s" % (th_efield, phi_efield)
        ax.plot([th_efield], [phi_efield],
                "x",
                markersize=10,
                color=(0.0, 1.0, 0.0))

        self.MFPADCanvas2D.draw()
Beispiel #8
0
    def plotContinuumOrbital(self):
        dbuff = self.settings["Cube"]["extra space / bohr"]
        ppb = self.settings["Cube"]["points per bohr"]
        (xmin, xmax), (ymin, ymax), (zmin, zmax) = Cube.get_bbox(self.atomlist,
                                                                 dbuff=dbuff)
        dx, dy, dz = xmax - xmin, ymax - ymin, zmax - zmin
        nx, ny, nz = int(dx * ppb), int(dy * ppb), int(dz * ppb)
        x, y, z = np.mgrid[xmin:xmax:nx * 1j, ymin:ymax:ny * 1j,
                           zmin:zmax:nz * 1j]
        grid = (x, y, z)

        # plot continuum orbital
        # projection of dipoles onto polarization direction
        Dipole_projected = np.zeros(
            (self.Dipole.shape[0], self.Dipole.shape[1]))
        # normalize polarization
        epol_unit = self.epol / np.sqrt(np.dot(self.epol, self.epol))
        print "Polarization direction of E-field:"
        print "E (normalized) = %s" % epol_unit
        for xyz in [0, 1, 2]:
            Dipole_projected += self.Dipole[:, :, xyz] * epol_unit[xyz]
        #print "Dipole projected"
        #print Dipole_projected
        # unnormalized coefficients of dipole-prepared continuum orbitals
        self.mo_free = np.dot(self.mo_bound, Dipole_projected)
        nrm2 = np.dot(self.mo_free.conjugate(), self.mo_free)
        #print "nrm2 = %s" % nrm2
        # normalized coefficients
        self.mo_free /= np.sqrt(nrm2)

        amplitude_continuum = Cube.orbital_amplitude(grid,
                                                     self.bs_free.bfs,
                                                     self.mo_free,
                                                     cache=False)

        continuum_cube = CubeData()
        continuum_cube.data = amplitude_continuum.real
        continuum_cube.grid = grid
        continuum_cube.atomlist = self.atomlist

        self.continuumOrbitalViewer.setCubes([continuum_cube])

        # plot E-field
        for o in self.efield_objects:
            o.remove()
        mlab = self.continuumOrbitalViewer.visualization.scene.mlab
        #        self.efield_arrow = mlab.quiver3d(0,0,0, self.epol[0], self.epol[1], self.epol[2],
        self.efield_arrow = mlab.quiver3d(0,
                                          0,
                                          0,
                                          float(self.epol[0]),
                                          float(self.epol[1]),
                                          float(self.epol[2]),
                                          color=(0.0, 1.0, 0.0),
                                          scale_factor=1.0,
                                          mode='arrow',
                                          resolution=20,
                                          figure=self.continuumOrbitalViewer.
                                          visualization.scene.mayavi_scene)
        self.efield_text = mlab.text(self.epol[0],
                                     self.epol[1],
                                     "E-field",
                                     z=self.epol[2],
                                     figure=self.continuumOrbitalViewer.
                                     visualization.scene.mayavi_scene)
        self.efield_text.actor.set(text_scale_mode='none',
                                   width=0.05,
                                   height=0.1)
        self.efield_text.property.set(justification='centered',
                                      vertical_justification='centered')

        self.efield_head = mlab.points3d([self.epol[0]], [self.epol[1]],
                                         [self.epol[2]],
                                         scale_factor=0.5,
                                         mode='cube',
                                         resolution=20,
                                         color=(0.0, 1.0, 0.0),
                                         figure=self.continuumOrbitalViewer.
                                         visualization.scene.mayavi_scene)
        self.efield_head.glyph.glyph_source.glyph_source.center = [0, 0, 0]
        self.efield_outline = mlab.outline(line_width=3,
                                           figure=self.continuumOrbitalViewer.
                                           visualization.scene.mayavi_scene)
        self.efield_outline.outline_mode = 'cornered'
        w = 0.1
        self.efield_outline.bounds = (self.epol[0] - w, self.epol[0] + w,
                                      self.epol[1] - w, self.epol[1] + w,
                                      self.epol[2] - w, self.epol[2] + w)

        self.efield_objects = [
            self.efield_arrow, self.efield_text, self.efield_head,
            self.efield_outline
        ]
        self.efield_actors = [self.efield_head.actor.actors]