def test_gradient_functional_deriv(): fn_fchk = context.get_fn('test/n2_hfs_sto3g.fchk') mol = IOData.from_file(fn_fchk) obasis = mol.obasis dm_full = mol.get_dm_full() rtf = ExpRTransform(1e-3, 1e1, 10) rgrid = RadialGrid(rtf) grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, (rgrid, 6), random_rotate=False, mode='keep') pot = grid.points[:,2].copy() def fun(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) f = obasis.compute_grid_gradient_dm(dm_full, grid.points) tmp = (f*f).sum(axis=1) return 0.5*grid.integrate(tmp, pot) def fun_deriv(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) result = dm_full.new() tmp = obasis.compute_grid_gradient_dm(dm_full, grid.points) tmp *= pot.reshape(-1,1) obasis.compute_grid_gradient_fock(grid.points, grid.weights, tmp, result) return result._array.ravel() eps = 1e-4 x = dm_full._array.copy().ravel() dxs = [] for i in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape)*x tmp = (tmp+tmp.T)/2 dxs.append(tmp) from horton.test.common import check_delta check_delta(fun, fun_deriv, x, dxs)
def test_kinetic_functional_deriv(): fn_fchk = context.get_fn('test/n2_hfs_sto3g.fchk') mol = IOData.from_file(fn_fchk) obasis = mol.obasis dm_full = mol.get_dm_full() grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, random_rotate=False, mode='keep') pot = grid.points[:, 2] def fun(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) f = obasis.compute_grid_kinetic_dm(dm_full, grid.points) return 0.5 * grid.integrate(f, f, pot) def fun_deriv(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) result = dm_full.new() tmp = obasis.compute_grid_kinetic_dm(dm_full, grid.points) * pot obasis.compute_grid_kinetic_fock(grid.points, grid.weights, tmp, result) return result._array.ravel() eps = 1e-4 x = dm_full._array.copy().ravel() dxs = [] for i in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape) * x dxs.append(tmp) from horton.test.common import check_delta check_delta(fun, fun_deriv, x, dxs)
def test_kinetic_functional_deriv(): fn_fchk = context.get_fn('test/n2_hfs_sto3g.fchk') mol = IOData.from_file(fn_fchk) obasis = mol.obasis dm_full = mol.get_dm_full() grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, random_rotate=False, mode='keep') pot = grid.points[:,2] def fun(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) f = obasis.compute_grid_kinetic_dm(dm_full, grid.points) return 0.5*grid.integrate(f, f, pot) def fun_deriv(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) result = dm_full.new() tmp = obasis.compute_grid_kinetic_dm(dm_full, grid.points)*pot obasis.compute_grid_kinetic_fock(grid.points, grid.weights, tmp, result) return result._array.ravel() eps = 1e-4 x = dm_full._array.copy().ravel() dxs = [] for i in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape)*x dxs.append(tmp) from horton.test.common import check_delta check_delta(fun, fun_deriv, x, dxs)
def check_density_hessian(obasis, dm_full, point, eps): """Finite difference checker for density Hessian. Parameters ---------- obasis : GOBasis The basis set to use in the test. dm_full : DenseTwoIndex The spin-summed density matrix. point : np.ndarray, shape=(3, ), dtype=float The reference point for check_delta. eps : float The magnitude of the displacements. """ def fun(p): """Evaluate the density gradient at point p.""" return obasis.compute_grid_gradient_dm(dm_full, np.array([p]))[0] def fun_deriv(p): """Evaluate the density Hessian at point p.""" row = obasis.compute_grid_hessian_dm(dm_full, np.array([p]))[0] result = np.zeros((3, 3), float) result[0, 0] = row[0] result[0, 1] = row[1] result[1, 0] = row[1] result[0, 2] = row[2] result[2, 0] = row[2] result[1, 1] = row[3] result[1, 2] = row[4] result[2, 1] = row[4] result[2, 2] = row[5] return result dpoints = np.random.uniform(-eps, eps, (100, 3)) check_delta(fun, fun_deriv, point, dpoints)
def test_gradient_functional_deriv(): fn_fchk = context.get_fn('test/n2_hfs_sto3g.fchk') sys = System.from_file(fn_fchk) rtf = ExpRTransform(1e-3, 1e1, 10) rgrid = RadialGrid(rtf) grid = BeckeMolGrid(sys, (rgrid, 6), random_rotate=False, mode='keep') pot = grid.points[:,2].copy() def fun(x): sys.wfn.dm_full._array[:] = x.reshape(sys.obasis.nbasis, -1) f = sys.compute_grid_gradient(grid.points) tmp = (f*f).sum(axis=1) return 0.5*grid.integrate(tmp, pot) def fun_deriv(x): sys.wfn.dm_full._array[:] = x.reshape(sys.obasis.nbasis, -1) result = sys.wfn.dm_full.copy() result.clear() tmp = sys.compute_grid_gradient(grid.points) tmp *= pot.reshape(-1,1) sys.compute_grid_gradient_fock(grid.points, grid.weights, tmp, result) return result._array.ravel() eps = 1e-4 x = sys.wfn.update_dm('full')._array.copy().ravel() dxs = [] for i in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape)*x tmp = (tmp+tmp.T)/2 dxs.append(tmp) from horton.test.common import check_delta check_delta(fun, fun_deriv, x, dxs)
def check_functional_deriv(fn, comp, dm_method, fock_method): """Test consistency of properties on a grid and implementation of Fock build. Parameters ---------- fn : str The filename of the molecule to run the test on. It should contain a wavefunction and it is assumed to be located in the data directory. comp : int The component of the potential to be tested. (Potentials may have multiple components, e.g. in the case of GGA the gradient has different components.) dm_method : function Computes from a density matrix the density properties of interest, e.g. density. This function takes three arguments: obasis, dm_full and points. (See e.g. ``GOBasis.compute_grid_density_dm``) fock_method : function Computes from a potential on a grid, the fock operator. This function takes five arguments: obasis, points, weights, potential and fock. (See e.g. ``GOBasis.compute_grid_density_fock``) """ fn_fchk = context.get_fn(fn) mol = IOData.from_file(fn_fchk) obasis = mol.obasis dm_full = mol.get_dm_full() grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, 'coarse', random_rotate=False, mode='keep') def fun(x): """Compute the grid properties from a density matrix.""" dm_full[:] = x.reshape(obasis.nbasis, -1) f = dm_method(obasis, dm_full, grid.points) f = f.reshape((grid.size, -1)) return 0.5 * grid.integrate(f[:, comp], f[:, comp]) def fun_deriv(x): """Compute a Fock matrix from potential data on a grid.""" dm_full[:] = x.reshape(obasis.nbasis, -1) tmp = dm_method(obasis, dm_full, grid.points) if tmp.ndim > 1: tmp[:, :comp] = 0.0 tmp[:, comp + 1:] = 0.0 fock = fock_method(obasis, grid.points, grid.weights, tmp) return fock.ravel() eps = 1e-4 x = dm_full.copy().ravel() dxs = [] for _irep in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape) * x dxs.append(tmp) check_delta(fun, fun_deriv, x, dxs)
def test_esp_cost_cube3d_gradient(): # Some parameters coordinates, numbers, origin, grid_rvecs, shape, pbc, vref, weights = get_random_esp_cost_cube3d_args() grid = UniformGrid(origin, grid_rvecs, shape, pbc) cost = ESPCost.from_grid_data(coordinates, grid, vref, weights) x0 = np.random.uniform(-0.5, 0.5, len(numbers) + 1) dxs = np.random.uniform(-1e-5, 1e-5, (100, len(numbers) + 1)) check_delta(cost.value, cost.gradient, x0, dxs)
def check_functional_deriv(fn, comp, dm_method, fock_method): """Test consistency of properties on a grid and implementation of Fock build. Parameters ---------- fn : str The filename of the molecule to run the test on. It should contain a wavefunction and it is assumed to be located in the data directory. comp : int The component of the potential to be tested. (Potentials may have multiple components, e.g. in the case of GGA the gradient has different components.) dm_method : function Computes from a density matrix the density properties of interest, e.g. density. This function takes three arguments: obasis, dm_full and points. (See e.g. ``GOBasis.compute_grid_density_dm``) fock_method : function Computes from a potential on a grid, the fock operator. This function takes five arguments: obasis, points, weights, potential and fock. (See e.g. ``GOBasis.compute_grid_density_fock``) """ fn_fchk = context.get_fn(fn) mol = IOData.from_file(fn_fchk) obasis = mol.obasis dm_full = mol.get_dm_full() grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, 'coarse', random_rotate=False, mode='keep') def fun(x): """Compute the grid properties from a density matrix.""" dm_full._array[:] = x.reshape(obasis.nbasis, -1) f = dm_method(obasis, dm_full, grid.points) f = f.reshape((grid.size, -1)) return 0.5*grid.integrate(f[:, comp], f[:, comp]) def fun_deriv(x): """Compute a Fock matrix from potential data on a grid.""" dm_full._array[:] = x.reshape(obasis.nbasis, -1) result = dm_full.new() tmp = dm_method(obasis, dm_full, grid.points) orig_shape = tmp.shape tmp = tmp.reshape((grid.size, -1)) tmp[:, :comp] = 0.0 tmp[:, comp+1:] = 0.0 tmp.shape = orig_shape fock_method(obasis, grid.points, grid.weights, tmp, result) return result._array.ravel() eps = 1e-4 x = dm_full._array.copy().ravel() dxs = [] for _irep in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape)*x dxs.append(tmp) check_delta(fun, fun_deriv, x, dxs)
def test_esp_cost_cube3d_gradient(): # Some parameters coordinates, numbers, origin, grid_rvecs, shape, pbc, vref, weights = \ get_random_esp_cost_cube3d_args() grid = UniformGrid(origin, grid_rvecs, shape, pbc) cost = ESPCost.from_grid_data(coordinates, grid, vref, weights) x0 = np.random.uniform(-0.5, 0.5, len(numbers)+1) dxs = np.random.uniform(-1e-5, 1e-5, (100, len(numbers)+1)) check_delta(cost.value, cost.gradient, x0, dxs)
def test_esp_cost_cube3d_gradient(): for irep in xrange(nrep): # Some parameters coordinates, origin, grid_rvecs, shape, pbc, vref, weights = \ get_random_esp_cost_cube3d_args(irep) grid = UniformGrid(origin, grid_rvecs, shape, pbc) cost = ESPCost.from_grid_data(coordinates, grid, vref, weights) with numpy_seed(irep): x0 = np.random.uniform(-0.5, 0.5, len(coordinates)+1) dxs = np.random.uniform(-1e-5, 1e-5, (100, len(coordinates)+1)) check_delta(cost.value, cost.gradient, x0, dxs)
def test_gradient_functional_deriv(): fn_fchk = context.get_fn('test/n2_hfs_sto3g.fchk') mol = IOData.from_file(fn_fchk) obasis = mol.obasis dm_full = mol.get_dm_full() rtf = ExpRTransform(1e-3, 1e1, 10) rgrid = RadialGrid(rtf) grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, (rgrid, 6), random_rotate=False, mode='keep') pot = grid.points[:, 2].copy() def fun(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) f = obasis.compute_grid_gradient_dm(dm_full, grid.points) tmp = (f * f).sum(axis=1) return 0.5 * grid.integrate(tmp, pot) def fun_deriv(x): dm_full._array[:] = x.reshape(obasis.nbasis, -1) result = dm_full.new() tmp = obasis.compute_grid_gradient_dm(dm_full, grid.points) tmp *= pot.reshape(-1, 1) obasis.compute_grid_gradient_fock(grid.points, grid.weights, tmp, result) return result._array.ravel() eps = 1e-4 x = dm_full._array.copy().ravel() dxs = [] for i in xrange(100): tmp = np.random.uniform(-eps, +eps, x.shape) * x tmp = (tmp + tmp.T) / 2 dxs.append(tmp) from horton.test.common import check_delta check_delta(fun, fun_deriv, x, dxs)
def check_density_gradient(obasis, dm_full, point, eps): """Finite difference checker for density gradient. Parameters ---------- obasis : GOBasis The basis set to use in the test. dm_full : DenseTwoIndex The spin-summed density matrix. point : np.ndarray, shape=(3, ), dtype=float The reference point for check_delta. eps : float The magnitude of the displacements. """ def fun(p): """Evaluate the density at point p.""" return obasis.compute_grid_density_dm(dm_full, np.array([p]))[0] def fun_deriv(p): """Evaluate the density gradient at point p.""" return obasis.compute_grid_gradient_dm(dm_full, np.array([p]))[0] dpoints = np.random.uniform(-eps, eps, (100, 3)) check_delta(fun, fun_deriv, point, dpoints)
def test_ap1rog_one_dm(): fn_xyz = context.get_fn('test/li2.xyz') mol = IOData.from_file(fn_xyz) obasis = get_gobasis(mol.coordinates, mol.numbers, 'cc-pvdz') lf = DenseLinalgFactory(obasis.nbasis) occ_model = AufbauOccModel(3) exp_alpha = lf.create_expansion(obasis.nbasis) olp = obasis.compute_overlap(lf) kin = obasis.compute_kinetic(lf) na = obasis.compute_nuclear_attraction(mol.coordinates, mol.pseudo_numbers, lf) guess_core_hamiltonian(olp, kin, na, exp_alpha) er = obasis.compute_electron_repulsion(lf) external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)} terms = [ RTwoIndexTerm(kin, 'kin'), RDirectTerm(er, 'hartree'), RExchangeTerm(er, 'x_hf'), RTwoIndexTerm(na, 'ne'), ] ham = REffHam(terms, external) scf_solver = PlainSCFSolver() scf_solver(ham, lf, olp, occ_model, exp_alpha) one = lf.create_two_index(obasis.nbasis) one.iadd(kin) one.iadd(na) # Do AP1roG optimization: geminal_solver = RAp1rog(lf, occ_model) energy, g, l = geminal_solver( one, er, external['nn'], exp_alpha, olp, True, **{ 'checkpoint': -1, 'maxiter': { 'orbiter': 0 } }) one_mo_ = lf.create_two_index() one_mo_.assign_two_index_transform(one, exp_alpha) two_mo = [] output = geminal_solver.lf.create_four_index() output.assign_four_index_transform(er, exp_alpha, exp_alpha, exp_alpha, exp_alpha, 'tensordot') two_mo.append(output) def fun(x): one_mo = [] one_mo.append(geminal_solver.lf.create_two_index()) one_mo[0].assign(x.reshape(28, 28)) geminal_solver.clear_auxmatrix() geminal_solver.update_auxmatrix('scf', two_mo, one_mo) iiaa = geminal_solver.get_auxmatrix('gppqq') iaia = geminal_solver.get_auxmatrix('lpqpq') fock = geminal_solver.get_auxmatrix('fock') one = geminal_solver.get_auxmatrix('t') coeff = geminal_solver.geminal._array lcoeff = geminal_solver.lagrange._array lagrangian = geminal_solver.compute_total_energy() lagrangian += np.dot( lcoeff.ravel(order='C'), geminal_solver.vector_function_geminal(coeff, iiaa, iaia, one, fock)) return lagrangian def fun_deriv(x): one_mo = [] one_mo.append(geminal_solver.lf.create_two_index()) one_mo[0].assign(x.reshape(28, 28)) geminal_solver.clear_auxmatrix() geminal_solver.update_auxmatrix('scf', two_mo, one_mo) guesst = geminal_solver.generate_guess({ 'type': 'random', 'factor': -0.1 }) # Optimize OAP1roG wavefunction amplitudes: coeff = geminal_solver.solve_geminal(guesst, {'wfn': 'krylov'}, 10e-12, 128) # Optimize OAP1roG Lagrange multipliers (lambda equations): lcoeff = geminal_solver.solve_lagrange(guesst, {'lagrange': 'krylov'}, 10e-12, 128) onebody1 = geminal_solver.lf.create_two_index(3, 25) onebody2 = geminal_solver.lf.create_two_index(3, 25) onebody1.assign(coeff) onebody2.assign(lcoeff) onedm = geminal_solver.lf.create_one_index() geminal_solver.compute_1dm(onedm, onebody1, onebody2, factor=2.0) a = np.zeros((28, 28)) np.fill_diagonal(a, onedm._array.T) return a.ravel() x = one_mo_._array.ravel() dxs = np.random.rand(100, 28 * 28) * 0.00001 check_delta(fun, fun_deriv, x, dxs)
def test_ap1rog_one_dm(): fn_xyz = context.get_fn('test/li2.xyz') mol = IOData.from_file(fn_xyz) obasis = get_gobasis(mol.coordinates, mol.numbers, 'cc-pvdz') lf = DenseLinalgFactory(obasis.nbasis) occ_model = AufbauOccModel(3) exp_alpha = lf.create_expansion(obasis.nbasis) olp = obasis.compute_overlap(lf) kin = obasis.compute_kinetic(lf) na = obasis.compute_nuclear_attraction(mol.coordinates, mol.pseudo_numbers, lf) guess_core_hamiltonian(olp, kin, na, exp_alpha) er = obasis.compute_electron_repulsion(lf) external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)} terms = [ RTwoIndexTerm(kin, 'kin'), RDirectTerm(er, 'hartree'), RExchangeTerm(er, 'x_hf'), RTwoIndexTerm(na, 'ne'), ] ham = REffHam(terms, external) scf_solver = PlainSCFSolver() scf_solver(ham, lf, olp, occ_model, exp_alpha) one = lf.create_two_index(obasis.nbasis) one.iadd(kin) one.iadd(na) # Do AP1roG optimization: geminal_solver = RAp1rog(lf, occ_model) energy, g, l = geminal_solver(one, er, external['nn'], exp_alpha, olp, True, **{'checkpoint': -1, 'maxiter': {'orbiter': 0}}) one_mo_ = lf.create_two_index() one_mo_.assign_two_index_transform(one, exp_alpha) two_mo = [] output = geminal_solver.lf.create_four_index() output.assign_four_index_transform(er, exp_alpha, exp_alpha, exp_alpha, exp_alpha, 'tensordot') two_mo.append(output) def fun(x): one_mo = [] one_mo.append(geminal_solver.lf.create_two_index()) one_mo[0].assign(x.reshape(28,28)) geminal_solver.clear_auxmatrix() geminal_solver.update_auxmatrix('scf', two_mo, one_mo) iiaa = geminal_solver.get_auxmatrix('gppqq') iaia = geminal_solver.get_auxmatrix('lpqpq') fock = geminal_solver.get_auxmatrix('fock') one = geminal_solver.get_auxmatrix('t') coeff = geminal_solver.geminal._array lcoeff = geminal_solver.lagrange._array lagrangian = geminal_solver.compute_total_energy() lagrangian += np.dot(lcoeff.ravel(order='C'), geminal_solver.vector_function_geminal(coeff, iiaa, iaia, one, fock)) return lagrangian def fun_deriv(x): one_mo = [] one_mo.append(geminal_solver.lf.create_two_index()) one_mo[0].assign(x.reshape(28,28)) geminal_solver.clear_auxmatrix() geminal_solver.update_auxmatrix('scf', two_mo, one_mo) guesst = geminal_solver.generate_guess({'type': 'random', 'factor': -0.1}) # Optimize OAP1roG wavefunction amplitudes: coeff = geminal_solver.solve_geminal(guesst, {'wfn': 'krylov'}, 10e-12, 128) # Optimize OAP1roG Lagrange multipliers (lambda equations): lcoeff = geminal_solver.solve_lagrange(guesst, {'lagrange': 'krylov'}, 10e-12, 128) onebody1 = geminal_solver.lf.create_two_index(3,25) onebody2 = geminal_solver.lf.create_two_index(3,25) onebody1.assign(coeff) onebody2.assign(lcoeff) onedm = geminal_solver.lf.create_one_index() geminal_solver.compute_1dm(onedm, onebody1, onebody2, factor=2.0) a = np.zeros((28,28)) np.fill_diagonal(a, onedm._array.T) return a.ravel() x = one_mo_._array.ravel() dxs = np.random.rand(100, 28*28)*0.00001 check_delta(fun, fun_deriv, x, dxs)