def Fdual(j_data_opt, j_data_spplus, j_data_spminus, grid_par=-6): qc_opt = read.convert_json(j_data_opt) qc_spplus = read.convert_json(j_data_spplus) qc_spminus = read.convert_json(j_data_spminus) X, Y, Z = _init_ORB_grid(qc_opt, grid_par=grid_par) dx, dy, dz = (X[10, 0, 0] - X[9, 0, 0]), (Y[0, 10, 0] - Y[0, 9, 0]), (Z[0, 0, 10] - Z[0, 0, 9]) d3r = dx * dy * dz rho_opt = core.rho_compute(qc_opt, numproc=6) rho_spplus = core.rho_compute(qc_spplus, numproc=6) rho_spminus = core.rho_compute(qc_spminus, numproc=6) delta_rho_plus = np.subtract(rho_spplus, rho_opt) delta_rho_minus = np.subtract(rho_opt, rho_spminus) delta_rho_2 = np.subtract(delta_rho_plus, delta_rho_minus) print "Rho : ", np.sum(rho_opt) * d3r, "(", np.min( rho_opt), " ... ", np.max(rho_opt), ")" print "d : ", dx, dy, dz print "P0 : ", X[0, 0, 0], Y[0, 0, 0], Z[0, 0, 0] print "P1 : ", X[-1, 0, 0], Y[0, -1, 0], Z[0, 0, -1] P = np.array([X, Y, Z]) return delta_rho_2, X, Y, Z
def Fukui(j_data_opt, j_data_sp, label=None, grid_par=-6): u"""Calculates the density differences/Fukui functions of the molecule. ** Parameters ** j_data_opt : dict Data on the optimized molecule, as deserialized from the scanlog format. j_data_sp : dict Data on the optimized molecule, as deserialized from the scanlog format. grid_par : int, optional Governs the grid to be used for voxel data. - If positive, it indicates the number of points in all 3 dimensions. - If zero, it indicates the default number of points (80). - If negative, it indicates the resolution, in Á^-1. ** Returns ** rho : numpy.ndarray The voxels containing the scalar values of the density. V : numpy.ndarray The voxels containing the scalar values of the potential. X, Y, Z : numpy.ndarray Meshgrids (as generated by numpy.mgrid), required for placing the voxels contained in rho and V. """ qc_opt = read.convert_json(j_data_opt) qc_sp = read.convert_json(j_data_sp) X, Y, Z = _init_ORB_grid(qc_opt, grid_par=grid_par) dx, dy, dz = (X[10, 0, 0] - X[9, 0, 0]), (Y[0, 10, 0] - Y[0, 9, 0]), (Z[0, 0, 10] - Z[0, 0, 9]) d3r = dx * dy * dz rho_opt = core.rho_compute(qc_opt, numproc=6) rho_sp = core.rho_compute(qc_sp, numproc=6) ## Calculation of the delta rho if label == 'plus': delta_rho = np.subtract(rho_sp, rho_opt) elif label == 'minus': delta_rho = np.subtract(rho_opt, rho_sp) print "Rho : ", np.sum(rho_opt) * d3r, "(", np.min( rho_opt), " ... ", np.max(rho_opt), ")" print "d : ", dx, dy, dz print "P0 : ", X[0, 0, 0], Y[0, 0, 0], Z[0, 0, 0] print "P1 : ", X[-1, 0, 0], Y[0, -1, 0], Z[0, 0, -1] P = np.array([X, Y, Z]) return delta_rho, X, Y, Z
def MO(j_data, MO_list, grid_par=-6): u"""Calculates the voxels representing the requested molecular orbitals of a molecule. ** Parameters ** j_data : dict Data on the molecule, deserialized from the scanlog format. MO_list : list(str) or list(int) A list containing either: - integers designating the molecular orbitals (starting from 1) - strings designating the molecular orbitals either through: - keywords (e.g. "h**o", "lumo") - ranges (e.g. "h**o-1:lumo+2") - symmetries (e.g. "5.A") grid_par : int, optional Governs the grid to be used for the voxels. - If positive, it indicates the number of points in all 3 dimensions. - If zero, it indicates the default number of points (80). - If negative, it indicates the resolution, in (A.U.)^-1. ** Returns ** out : list(numpy.ndarray) List of numpy.ndarrays, each one containing the values of the probability amplitude of a single molecular orbital at each voxel of the grid. X, Y, Z : numpy.ndarray Meshgrids (as generated by numpy.mgrid) required for positioning the voxel values contained in out. """ ## Prepare data for ORBKIT qc = read.convert_json(j_data, all_mo=True) X, Y, Z = _init_ORB_grid(qc, grid_par=grid_par) ## Get list of orbitals qc.mo_spec = read.mo_select(qc.mo_spec, MO_list)["mo_spec"] ## Calculate out = core.rho_compute(qc, calc_mo=True, numproc=6) return out, X, Y, Z
def Potential(j_data, grid_par=-6): u"""Calculates the electric potential difference for the molecule. ** Parameters ** j_data : dict Data on the molecule, as deserialized from the scanlog format. grid_par : int, optional Governs the grid to be used for voxel data. - If positive, it indicates the number of points in all 3 dimensions. - If zero, it indicates the default number of points (80). - If negative, it indicates the resolution, in Á^-1. ** Returns ** rho : numpy.ndarray The voxels containing the scalar values of the density. V : numpy.ndarray The voxels containing the scalar values of the potential. X, Y, Z : numpy.ndarray Meshgrids (as generated by numpy.mgrid), required for placing the voxels contained in rho and V. """ qc = read.convert_json(j_data) X, Y, Z = _init_ORB_grid(qc, grid_par=grid_par) dx, dy, dz = (X[10, 0, 0] - X[9, 0, 0]), (Y[0, 10, 0] - Y[0, 9, 0]), (Z[0, 0, 10] - Z[0, 0, 9]) d3r = dx * dy * dz rho = core.rho_compute(qc, numproc=6) print "Rho : ", np.sum(rho) * d3r, "(", np.min(rho), " ... ", np.max( rho), ")" print "d : ", dx, dy, dz print "P0 : ", X[0, 0, 0], Y[0, 0, 0], Z[0, 0, 0] print "P1 : ", X[-1, 0, 0], Y[0, -1, 0], Z[0, 0, -1] P = np.array([X, Y, Z]) ## The potential can be separated into two terms ## V_n, the contribution from nuclear charges (positive) V_n = np.zeros(rho.shape) for i in range(len(qc.geo_spec)): ## This currently works by: ## 1. reshaping the atom position triplet to the shape of the meshgrids ## 2. calculating the norm accross the three dimensions ## 3. propagating the meshgrid shape to the charge R = np.linalg.norm(P - qc.geo_spec[i].reshape((3, 1, 1, 1)), axis=0) R[R < 0.005] = np.inf N_i = float(qc.geo_info[i, -1]) / R V_n += N_i print "V_n (", qc.geo_info[i, 0], qc.geo_info[i, -1], ") : (", np.min( N_i), ", ", np.max(N_i), ") (", np.argwhere(N_i > 250).size, ")" TIx, TIy, TIz = rho.shape Tx, Ty, Tz = X[-1, 0, 0] - X[0, 0, 0], Y[0, -1, 0] - Y[0, 0, 0], Z[0, 0, -1] - Z[0, 0, 0] ## V_r, the contribution from the electron density (negative) ## To avoid calculating the full volume integral, ## we consider rho as a kernel and apply it to ## the grid of inverse distances as though it ## were an image ## 1. Accumulate local potential V_e = np.ones(rho.shape) * rho ## Reverse rho, so that it is traversed in the ## same direction as the image matrix rho_r = rho[::-1, ::-1, ::-1].copy() ## 2. Extend grid X_, Y_, Z_ = np.mgrid[dx * (1 - TIx):dx * TIx:dx, dy * (1 - TIy):dy * TIy:dy, dz * (1 - TIz):dz * TIz:dz] print P.shape ## 3. Calculate distance grid D = np.linalg.norm(np.array([0, 0, 0]).reshape( (3, 1, 1, 1)) - np.array([X_, Y_, Z_]), axis=0) D[TIx - 1, TIy - 1, TIz - 1] = np.inf R = 1 / D ## 4. Convolute for i in xrange(TIx): ie = i + TIx for j in xrange(TIy): je = j + TIy for k in xrange(TIz): V_e[i, j, k] += (rho_r * R[i:ie, j:je, k:k + TIz]).sum() #from scipy import signal as sg #V_e += sg.fftconvolve(R, rho, "valid") V_e *= d3r return rho, V_n - V_e, X, Y, Z