def wavefunction(grid, dV): # evaluate orbital amp = Cube.orbital_amplitude(grid, bs.bfs, scat_orbs[:, i], cache=False) return amp
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
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
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()
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]