def test_evaluate_basis_spherical(): """Test gbasis.evals.eval.evaluate_basis_spherical.""" basis_dict = parse_nwchem(find_datafile("data_sto6g.nwchem")) # cartesian and spherical are the same for s orbital basis = make_contractions(basis_dict, ["H"], np.array([[0, 0, 0]])) evaluate_obj = Eval(basis) assert np.allclose( evaluate_obj.construct_array_cartesian(points=np.array([[0, 0, 0]])), evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type="spherical"), ) # p orbitals are zero at center basis = make_contractions(basis_dict, ["Li"], np.array([[0, 0, 0]])) evaluate_obj = Eval(basis) assert np.allclose( evaluate_obj.construct_array_cartesian(points=np.array([[0, 0, 0]])), evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type="spherical"), ) basis = make_contractions(basis_dict, ["Kr"], np.array([[0, 0, 0]])) evaluate_obj = Eval(basis) assert np.allclose( evaluate_obj.construct_array_spherical(points=np.array([[1, 1, 1]])), evaluate_basis(basis, np.array([[1, 1, 1]]), coord_type="spherical"), )
def test_evaluate_basis_mix(): """Test gbasis.evals.eval.evaluate_basis_mix.""" basis_dict = parse_nwchem(find_datafile("data_sto6g.nwchem")) # cartesian and spherical are the same for s orbital basis = make_contractions(basis_dict, ["H"], np.array([[0, 0, 0]])) assert np.allclose( evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type="spherical"), evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type=["spherical"]), ) assert np.allclose( evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type="cartesian"), evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type=["cartesian"]), ) basis = make_contractions(basis_dict, ["Kr"], np.array([[0, 0, 0]])) assert np.allclose( evaluate_basis(basis, np.array([[1, 1, 1]]), coord_type="spherical"), evaluate_basis(basis, np.array([[1, 1, 1]]), coord_type=["spherical"] * 8), ) assert np.allclose( evaluate_basis(basis, np.array([[1, 1, 1]]), coord_type="cartesian"), evaluate_basis(basis, np.array([[1, 1, 1]]), coord_type=["cartesian"] * 8), )
def test_evaluate_basis_cartesian(): """Test gbasis.evals.eval.evaluate_basis_cartesian.""" basis_dict = parse_nwchem(find_datafile("data_sto6g.nwchem")) basis = make_contractions(basis_dict, ["H"], np.array([[0, 0, 0]])) evaluate_obj = Eval(basis) assert np.allclose( evaluate_obj.construct_array_cartesian(points=np.array([[0, 0, 0]])), evaluate_basis(basis, np.array([[0, 0, 0]]), coord_type="cartesian"), )
def test_evaluate_basis_horton(): """Test gbasis.evals.eval.evaluate_basis against horton results.""" basis_dict = parse_nwchem(find_datafile("data_anorcc.nwchem")) points = np.array([[0, 0, 0], [0.8, 0, 0]]) basis = make_contractions(basis_dict, ["H", "He"], points) basis = [ HortonContractions(i.angmom, i.coord, i.coeffs, i.exps) for i in basis ] horton_eval_cart = np.load(find_datafile("data_horton_hhe_cart_eval.npy")) horton_eval_sph = np.load(find_datafile("data_horton_hhe_sph_eval.npy")) grid_1d = np.linspace(-2, 2, num=5) grid_x, grid_y, grid_z = np.meshgrid(grid_1d, grid_1d, grid_1d) grid_3d = np.vstack([grid_x.ravel(), grid_y.ravel(), grid_z.ravel()]).T assert np.allclose(evaluate_basis(basis, grid_3d, coord_type="cartesian"), horton_eval_cart.T) assert np.allclose(evaluate_basis(basis, grid_3d, coord_type="spherical"), horton_eval_sph.T)
def test_evaluate_density(): """Test gbasis.evals.density.evaluate_density.""" basis_dict = parse_nwchem(find_datafile("data_sto6g.nwchem")) basis = make_contractions(basis_dict, ["Kr"], np.array([[0, 0, 0]])) transform = np.random.rand(14, 18) density = np.random.rand(14, 14) density += density.T points = np.random.rand(10, 3) evaluate_orbs = evaluate_basis(basis, points, transform) assert np.allclose( evaluate_density(density, basis, points, transform), np.einsum("ij,ik,jk->k", density, evaluate_orbs, evaluate_orbs), )
def test_evaluate_basis_pyscf_cart_norm(): """Test gbasis.evals.eval.evaluate_basis against pyscf results. These cases fail because pyscf seems to have a different normalization constant for the d and f orbitals. """ pytest.importorskip("pyscf") from pyscf import gto from gbasis.wrappers import from_pyscf mol = gto.Mole() mol.build(atom="H 0 0 0; He 0.8 0 0", basis="ano-rcc", spin=1) basis = from_pyscf(mol) grid_1d = np.linspace(-2, 2, num=5) grid_x, grid_y, grid_z = np.meshgrid(grid_1d, grid_1d, grid_1d) grid_3d = np.vstack([grid_x.ravel(), grid_y.ravel(), grid_z.ravel()]).T pyscf_eval_cart = gto.eval_gto(mol, "GTOval_cart", grid_3d) # d orbitals are all off by some scalar factor assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[18:36], pyscf_eval_cart.T[18:36]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[65:83], pyscf_eval_cart.T[65:83]) # f orbitals are all off by some scalar factor assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[36:46], pyscf_eval_cart.T[36:46]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[83:103], pyscf_eval_cart.T[83:103])
def test_evaluate_basis_lincomb(): """Test gbasis.evals.eval.evaluate_basis_lincomb.""" basis_dict = parse_nwchem(find_datafile("data_sto6g.nwchem")) basis = make_contractions(basis_dict, ["Kr"], np.array([[0, 0, 0]])) evaluate_obj = Eval(basis) transform = np.random.rand(14, 18) assert np.allclose( evaluate_obj.construct_array_lincomb(transform, "spherical", points=np.array([[1, 1, 1]])), evaluate_basis(basis, np.array([[1, 1, 1]]), transform=transform, coord_type="spherical"), )
def test_evaluate_density_gradient(): """Test gbasis.evals.density.evaluate_density_gradient.""" basis_dict = parse_nwchem(find_datafile("data_sto6g.nwchem")) basis = make_contractions(basis_dict, ["Kr"], np.array([[0, 0, 0]])) transform = np.random.rand(14, 18) density = np.random.rand(14, 14) density += density.T points = np.random.rand(10, 3) np.allclose( evaluate_density_gradient(density, basis, points, transform).T, np.array([ np.einsum( "ij,ik,jk->k", density, evaluate_deriv_basis(basis, points, np.array([1, 0, 0]), transform), evaluate_basis(basis, points, transform), ) + np.einsum( "ij,ik,jk->k", density, evaluate_basis(basis, points, transform), evaluate_deriv_basis(basis, points, np.array([1, 0, 0]), transform), ), np.einsum( "ij,ik,jk->k", density, evaluate_deriv_basis(basis, points, np.array([0, 1, 0]), transform), evaluate_basis(basis, points, transform), ) + np.einsum( "ij,ik,jk->k", density, evaluate_basis(basis, points, transform), evaluate_deriv_basis(basis, points, np.array([0, 1, 0]), transform), ), np.einsum( "ij,ik,jk->k", density, evaluate_deriv_basis(basis, points, np.array([0, 0, 1]), transform), evaluate_basis(basis, points, transform), ) + np.einsum( "ij,ik,jk->k", density, evaluate_basis(basis, points, transform), evaluate_deriv_basis(basis, points, np.array([0, 0, 1]), transform), ), ]), )
def evaluate_density(one_density_matrix, basis, points, transform=None, coord_type="spherical"): r"""Return the density of the given basis set at the given points. Parameters ---------- one_density_matrix : np.ndarray(K_orbs, K_orbs) One-electron density matrix in terms of the given basis set. If the basis is transformed using `transform` keyword, then the density matrix is assumed to be expressed with respect to the transformed basis set. basis : list/tuple of GeneralizedContractionShell Shells of generalized contractions. points : np.ndarray(N, 3) Cartesian coordinates of the points in space (in atomic units) where the basis functions are evaluated. Rows correspond to the points and columns correspond to the :math:`x, y, \text{and} z` components. transform : np.ndarray(K_orbs, K_cont) Transformation matrix from the basis set in the given coordinate system (e.g. AO) to linear combinations of contractions (e.g. MO). Transformation is applied to the left, i.e. the sum is over the index 1 of `transform` and index 0 of the array for contractions. Default is no transformation. coord_type : {"cartesian", list/tuple of "cartesian" or "spherical", "spherical"} Types of the coordinate system for the contractions. If "cartesian", then all of the contractions are treated as Cartesian contractions. If "spherical", then all of the contractions are treated as spherical contractions. If list/tuple, then each entry must be a "cartesian" or "spherical" to specify the coordinate type of each `GeneralizedContractionShell` instance. Default value is "spherical". Returns ------- density : np.ndarray(N,) Density evaluated at `N` grid points. """ orb_eval = evaluate_basis(basis, points, transform=transform, coord_type=coord_type) return evaluate_density_using_evaluated_orbs(one_density_matrix, orb_eval)
b_density_values = evaluate_density(b_dm, basis, molgrid.points, coord_type="cartesian") inp = {"rho": np.array([a_density_values, b_density_values])} inp["rho"] = inp["rho"].transpose().reshape(len(inp["rho"][0]) * 2) f_xc_values = (xc_function.compute(inp, None, False, False, True, False))["v2rho2"] f_xc_values = np.array([ f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 0], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 1], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 2], ]) del (a_dm, b_dm, a_density_values, b_density_values, xc_function, inp) MO_values = evaluate_basis(basis, molgrid.points, transform=molecule.mo.coeffs.T, coord_type="cartesian") MO_values_conjugated = np.conjugate(MO_values) occupied_ind = [[], []] virtual_ind = [[], []] for i in range(len(molecule.mo.occsa)): if molecule.mo.occsa[i] - 1 == 0: occupied_ind[0] = occupied_ind[0] + [i] if molecule.mo.occsa[i] == 0: virtual_ind[0] = virtual_ind[0] + [i] for i in range(len(molecule.mo.occsb)): if molecule.mo.occsb[i] - 1 == 0: occupied_ind[1] = occupied_ind[1] + [i + molecule.mo.nbasis] if molecule.mo.occsb[i] == 0: virtual_ind[1] = virtual_ind[1] + [i + molecule.mo.nbasis] indices = (occupied_ind, virtual_ind)
def evaluate_linear_response(self, r1, r2, spin): """Return linear response matrices Parameters ---------- spin: tuple of two str, elements can only be 'alpha' or 'beta' r1: ndarray N1 coordinates r2: ndarray N2 coordiantes Return ------ linear_response: np.ndarray of shape [N1, N2]""" if not isinstance(spin, tuple): raise TypeError( """'spin' must be a tuple of two str, being either 'alpha' or 'beta'""" ) if len(spin) != 2: raise ValueError( """'spin' must be a tuple of two str, being either 'alpha' or 'beta'""" ) if not spin[0] in ["alpha", "beta"]: raise ValueError( """'spin' must be a tuple of two str, being either 'alpha' or 'beta'""" ) if not spin[1] in ["alpha", "beta"]: raise ValueError( """'spin' must be a tuple of two str, being either 'alpha' or 'beta'""" ) if not isinstance(r1, np.ndarray): raise TypeError("""'r1' must be a np.ndarray""") if len(r1.shape) != 2: raise ValueError("""'r1' must be a np.ndarray with shape (N, 3)""") if r1.shape[1] != 3: raise ValueError("""'r1' must be a np.ndarray with shape (N, 3)""") if not isinstance(r2, np.ndarray): raise TypeError("""'r2' must be a np.ndarray""") if len(r2.shape) != 2: raise ValueError("""'r2' must be a np.ndarray with shape (N, 3)""") if r2.shape[1] != 3: raise ValueError("""'r2' must be a np.ndarray with shape (N, 3)""") indices = self.K_indices() MO_r1 = evaluate_basis( self._basis, r1, transform=self._molecule.mo.coeffs.T, coord_type=self._coord_type, ) MO_r2 = evaluate_basis( self._basis, r2, transform=self._molecule.mo.coeffs.T, coord_type=self._coord_type, ) a_occ_r1 = MO_r1[indices[0][0]] a_occ_r2 = MO_r2[indices[0][0]] b_occ_r1 = MO_r1[indices[0][1]] b_occ_r2 = MO_r2[indices[0][1]] a_virt_r1 = MO_r1[indices[1][0]] a_virt_r2 = MO_r2[indices[1][0]] b_virt_r1 = MO_r1[indices[1][1]] b_virt_r2 = MO_r2[indices[1][1]] del (MO_r1, MO_r2) phi_a_r1 = a_occ_r1[:, None, :] * a_virt_r1[None, :, :] phi_a_r1 = phi_a_r1.reshape( phi_a_r1.shape[0] * phi_a_r1.shape[1], phi_a_r1.shape[2] ) phi_a_r2 = a_occ_r2[:, None, :] * a_virt_r2[None, :, :] phi_a_r2 = phi_a_r2.reshape( phi_a_r2.shape[0] * phi_a_r2.shape[1], phi_a_r2.shape[2] ) del (a_occ_r1, a_occ_r2, a_virt_r1, a_virt_r2) phi_b_r1 = b_occ_r1[:, None, :] * b_virt_r1[None, :, :] phi_b_r1 = phi_b_r1.reshape( phi_b_r1.shape[0] * phi_b_r1.shape[1], phi_b_r1.shape[2] ) phi_b_r2 = b_occ_r2[:, None, :] * b_virt_r2[None, :, :] phi_b_r2 = phi_b_r2.reshape( phi_b_r2.shape[0] * phi_b_r2.shape[1], phi_b_r2.shape[2] ) del (b_occ_r1, b_occ_r2, b_virt_r1, b_virt_r2) M_inv = self.M_inverse if self._complex == True: if spin[0] == "alpha": if spin[1] == "alpha": linear_response = ( np.dot(phi_a_r1.conj().T, M_inv[0, 0]).dot(phi_a_r2) + np.dot(phi_a_r1.conj().T, M_inv[0, 1]).dot(phi_a_r2.conj()) + np.dot(phi_a_r1.T, M_inv[1, 0]).dot(phi_a_r2) + np.dot(phi_a_r1.T, M_inv[1, 1]).dot(phi_a_r2.conj()) ) else: linear_response = ( np.dot(phi_a_r1.conj().T, M_inv[0, 2]).dot(phi_b_r2) + np.dot(phi_a_r1.conj().T, M_inv[0, 3]).dot(phi_b_r2.conj()) + np.dot(phi_a_r1.T, M_inv[1, 2]).dot(phi_b_r2) + np.dot(phi_a_r1.T, M_inv[1, 3]).dot(phi_b_r2.conj()) ) else: if spin[1] == "alpha": linear_response = ( np.dot(phi_b_r1.conj().T, M_inv[2, 0]).dot(phi_a_r2) + np.dot(phi_b_r1.conj().T, M_inv[2, 1]).dot(phi_a_r2.conj()) + np.dot(phi_b_r1.T, M_inv[3, 0]).dot(phi_a_r2) + np.dot(phi_b_r1.T, M_inv[3, 1]).dot(phi_a_r2.conj()) ) else: linear_response = ( np.dot(phi_b_r1.conj().T, M_inv[2, 2]).dot(phi_b_r2) + np.dot(phi_b_r1.conj().T, M_inv[2, 3]).dot(phi_b_r2.conj()) + np.dot(phi_b_r1.T, M_inv[3, 2]).dot(phi_b_r2) + np.dot(phi_b_r1.T, M_inv[3, 3]).dot(phi_b_r2.conj()) ) else: if spin[0] == "alpha": if spin[1] == "alpha": linear_response = -2 * ( np.dot(phi_a_r1.T, M_inv[0, 0]).dot(phi_a_r2) ) else: linear_response = -2 * ( np.dot(phi_a_r1.T, M_inv[0, 1]).dot(phi_b_r2) ) else: if spin[1] == "alpha": linear_response = -2 * ( np.dot(phi_b_r1.T, M_inv[1, 0]).dot(phi_a_r2) ) else: linear_response = -2 * ( np.dot(phi_b_r1.T, M_inv[1, 1]).dot(phi_b_r2) ) return linear_response
def test_evaluate_basis_pyscf(): """Test gbasis.evals.eval.evaluate_basis against pyscf results.""" pytest.importorskip("pyscf") from pyscf import gto from gbasis.wrappers import from_pyscf mol = gto.Mole() mol.build(atom="H 0 0 0; He 0.8 0 0", basis="ano-rcc", spin=1) basis = from_pyscf(mol) grid_1d = np.linspace(-2, 2, num=5) grid_x, grid_y, grid_z = np.meshgrid(grid_1d, grid_1d, grid_1d) grid_3d = np.vstack([grid_x.ravel(), grid_y.ravel(), grid_z.ravel()]).T pyscf_eval_sph = gto.eval_gto(mol, "GTOval_sph", grid_3d) pyscf_eval_cart = gto.eval_gto(mol, "GTOval_cart", grid_3d) # s orbitals assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[:6], pyscf_eval_cart.T[:6]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[46:53], pyscf_eval_cart.T[46:53]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[:6], pyscf_eval_sph.T[:6]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[40:47], pyscf_eval_sph.T[40:47]) # p orbitals assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[6:18], pyscf_eval_cart.T[6:18]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="cartesian")[53:65], pyscf_eval_cart.T[53:65]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[6:18], pyscf_eval_sph.T[6:18]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[47:59], pyscf_eval_sph.T[47:59]) # d orbitals are off by some constant for the cartesian case assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[18:33], pyscf_eval_sph.T[18:33]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[59:74], pyscf_eval_sph.T[59:74]) # f orbitals are off by some constant for the cartesian case assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[33:40], pyscf_eval_sph.T[33:40]) assert np.allclose( evaluate_basis(basis, grid_3d, coord_type="spherical")[74:88], pyscf_eval_sph.T[74:88])
def K_fxc_DFT(self, molgrid, Type=1, XC_functional="lda_x", shape="square", index=None): """Calculate the exchange-correlation part of the coupling matrix K Parameters ---------- molgrid : MolGrid class object (from grid package) suitable for numerical integration of any real space function related to the molecule (such as the density) Type : int, 1 or 2, in cassee of real molecular orbitals, type1 = type2 XC_functionl : str Code name of the exchange correlation functional as given on the page: https://tddft.org/programs/libxc/functionals/ shape: str; 'square', 'rectangle', 'line' or 'point', default is 'square' If shape == 'square', generate (K_fxc_DFT)ias,jbt Useful to generate the M matrices If shape == 'line' , generate (K_fxc_DFT)ffs,jbt Useful to generate the fukui matrices and hardness If shape == 'point' generate (K_fxc_DFT)ffs,ffs Useful to generate the hardness index: None or list of two list of int, default is None Necessary if shape == 'line' or shape == 'point' If index is a list of two list of integers, it must be like [ l1, l2] with l1 in |[0; molecule.mo.nbasis|[ and l2 in |[molecule.mo.nbasis, 2 * molecule.mo.nbasis|[, (l1 : alpha indices, l2 : beta indices) len(l1) + len(l2) must be equal to 1 if shape is 'line' len(l1) + len(l2) must be equal to 2 if shape is 'point' Return ------ K_fxc_DFT: ndarray [aa_block, ab_block, ba_block, bb_block] if shape == 'square' or 'line' Raises ------ TypeError If 'molgrid' is not a 'MolGrid' instance' If 'Type' is not an int XC_functional is not a str ValueError If 'Type' is not in [1,2] If XC_functional is bot supported by pylibxc (see pylibxc.util.xc_available_functional_names() or https://tddft.org/programs/libxc/functionals/ for the function code spelling) IF XC_functional is not a LDA or a GGA""" if not isinstance(molgrid, MolGrid): raise TypeError("""'molgrid' must be a 'MolGrid' instance""") if not isinstance(Type, int): raise TypeError("""'Type' must be 1 or 2""") if not Type in [1, 2]: raise ValueError("""'Type' must be 1 or 2""") if not isinstance(XC_functional, str): raise TypeError("""'XC_functional' must be a str""") if not XC_functional in pylibxc.util.xc_available_functional_names(): raise ValueError( """"Not suported functionnal, see pylibxc.util.xc_available_functional_names() or the webpage: https://tddft.org/programs/libxc/functionals/""" ) xc_function = pylibxc.LibXCFunctional(XC_functional, "polarized") if not xc_function.get_family() in [1, 2]: raise ValueError( """"Not suported functionnal, only the LDA ans GGAs are supported""" ) # Defining the array of values of fxc(r) suitable for the numerical integration a_dm = np.dot( self._molecule.mo.coeffsa * self._molecule.mo.occsa, self._molecule.mo.coeffsa.T.conj(), ) b_dm = np.dot( self._molecule.mo.coeffsb * self._molecule.mo.occsb, self._molecule.mo.coeffsb.T.conj(), ) a_density_values = evaluate_density(a_dm, self._basis, molgrid.points, coord_type=self._coord_type) b_density_values = evaluate_density(b_dm, self._basis, molgrid.points, coord_type=self._coord_type) inp = {"rho": np.array([a_density_values, b_density_values])} inp["rho"] = inp["rho"].transpose().reshape(len(inp["rho"][0]) * 2) if xc_function.get_family() == 2: a_gradient_density = evaluate_density_gradient( a_dm, self._basis, molgrid.points, coord_type=self._coord_type) b_gradient_density = evaluate_density_gradient( b_dm, self._basis, molgrid.points, coord_type=self._coord_type) inp["sigma"] = np.array([ np.sum(a_gradient_density * a_gradient_density, axis=1), np.sum(a_gradient_density * b_gradient_density, axis=1), np.sum(b_gradient_density * b_gradient_density, axis=1), ]) inp["sigma"] = inp["sigma"].transpose().reshape( len(inp["sigma"][0]) * 3) f_xc_values = (xc_function.compute(inp, None, False, False, True, False))["v2rho2"] f_xc_values = np.array([ f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 0], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 1], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 2], ]) if xc_function.get_family() == 2: del (a_gradient_density, b_gradient_density) del (a_dm, b_dm, a_density_values, b_density_values, xc_function, inp) MO_basis_func_val = evaluate_basis( self._basis, molgrid.points, transform=self._molecule.mo.coeffs.T, coord_type=self._coord_type, ) indices = self.K_indices(shape=shape, index=index) # Defining the arrays of values of all the 4 MO products suitable for the numerical integration if shape == "square" or shape == "line": a_occup_val = MO_basis_func_val[indices[0][0]] a_virt_val = MO_basis_func_val[indices[1][0]] kl_a = (a_occup_val[:, None].conj() * a_virt_val).reshape([ a_occup_val.shape[0] * a_virt_val.shape[0], a_virt_val.shape[1] ]) del (a_occup_val, a_virt_val) b_occup_val = MO_basis_func_val[indices[0][1]] b_virt_val = MO_basis_func_val[indices[1][1]] kl_b = (b_occup_val[:, None].conj() * b_virt_val).reshape([ b_occup_val.shape[0] * b_virt_val.shape[0], b_virt_val.shape[1] ]) del (b_occup_val, b_virt_val) klt = np.block([kl_a.T, kl_b.T]).T del kl_b if shape == "line": a_i_values = MO_basis_func_val[indices[2][0]] b_j_values = MO_basis_func_val[indices[2][1]] ij_a = a_i_values.conj() * a_i_values ij_b = b_j_values.conj() * b_j_values ijs = np.block([ij_a.T, ij_b.T]).T del (a_i_values, b_j_values, ij_b) else: ijs = klt ij_a = kl_a del MO_basis_func_val if type == 2: K_fxc_DFT = ijs[:, None] * klt else: K_fxc_DFT = ijs[:, None] * klt.conj() # generate the alpha-alpha block K_fxc_DFT[:ij_a.shape[0], :kl_a.shape[0]] = ( K_fxc_DFT[:ij_a.shape[0], :kl_a.shape[0]] * f_xc_values[0] * molgrid.weights) # generate the beta-alpha block K_fxc_DFT[ij_a.shape[0]:, :kl_a.shape[0]] = ( K_fxc_DFT[ij_a.shape[0]:, :kl_a.shape[0]] * f_xc_values[1] * molgrid.weights) # generate the alpha-beta block K_fxc_DFT[:ij_a.shape[0], kl_a.shape[0]:] = ( K_fxc_DFT[:ij_a.shape[0], kl_a.shape[0]:] * f_xc_values[1] * molgrid.weights) # generate th beta-beta block K_fxc_DFT[ij_a.shape[0]:, kl_a.shape[0]:] = ( K_fxc_DFT[ij_a.shape[0]:, kl_a.shape[0]:] * f_xc_values[2] * molgrid.weights) # integrate K_fxc_DFT = np.sum(K_fxc_DFT / 3, axis=2) K_fxc_DFt = np.array([ K_fxc_DFT[:ij_a.shape[0], :kl_a.shape[0]], K_fxc_DFT[:ij_a.shape[0], kl_a.shape[0]:], K_fxc_DFT[ij_a.shape[0]:, :kl_a.shape[0]], K_fxc_DFT[ij_a.shape[0]:, kl_a.shape[0]:], ]) return K_fxc_DFt else: l = indices[2][0] + indices[2][1] i_values = MO_basis_func_val[l[0]] k_values = MO_basis_func_val[l[1]] K_fxc_DFT = i_values * i_values.conj() * k_values * k_values.conj() if len(indices[2][0]) == 0: return np.sum(K_fxc_DFT * f_xc_values[2] * molgrid.weights / 3) if len(indices[2][0]) == 1: return np.sum(K_fxc_DFT * f_xc_values[1] * molgrid.weights / 3) else: return np.sum(K_fxc_DFT * f_xc_values[0] * molgrid.weights / 3)
def test_M_matrix_calculate_M(): xc_function = pylibxc.LibXCFunctional("lda_x", "polarized") a_dm = np.dot(molecule.mo.coeffsa * molecule.mo.occsa, molecule.mo.coeffsa.T.conj()) b_dm = np.dot(molecule.mo.coeffsb * molecule.mo.occsb, molecule.mo.coeffsb.T.conj()) a_density_values = evaluate_density(a_dm, basis, molgrid.points, coord_type="cartesian") b_density_values = evaluate_density(b_dm, basis, molgrid.points, coord_type="cartesian") inp = {"rho": np.array([a_density_values, b_density_values])} inp["rho"] = inp["rho"].transpose().reshape(len(inp["rho"][0]) * 2) f_xc_values = (xc_function.compute(inp, None, False, False, True, False))["v2rho2"] f_xc_values = np.array([ f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 0], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 1], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 2], ]) del (a_dm, b_dm, a_density_values, b_density_values, xc_function, inp) MO_values = evaluate_basis(basis, molgrid.points, transform=molecule.mo.coeffs.T, coord_type="cartesian") MO_values_conjugated = np.conjugate(MO_values) occupied_ind = [[], []] virtual_ind = [[], []] for i in range(len(molecule.mo.occsa)): if molecule.mo.occsa[i] - 1 == 0: occupied_ind[0] = occupied_ind[0] + [i] if molecule.mo.occsa[i] == 0: virtual_ind[0] = virtual_ind[0] + [i] for i in range(len(molecule.mo.occsb)): if molecule.mo.occsb[i] - 1 == 0: occupied_ind[1] = occupied_ind[1] + [i + molecule.mo.nbasis] if molecule.mo.occsb[i] == 0: virtual_ind[1] = virtual_ind[1] + [i + molecule.mo.nbasis] indices = (occupied_ind, virtual_ind) M_HF = np.zeros([140, 140], float) M_LDA = np.zeros([140, 140], float) for s in range(2): for i_c, i in enumerate(indices[0][s]): for a_c, a in enumerate(indices[1][s]): ias = (s * len(indices[0][0]) * len(indices[1][0]) + i_c * len(indices[1][s]) + a_c) for t in range(2): for j_c, j in enumerate(indices[0][t]): for b_c, b in enumerate(indices[1][t]): jbt = ( t * len(indices[0][0]) * len(indices[1][0]) + j_c * len(indices[1][t]) + b_c) M_HF[ias][jbt] = (M_HF[ias][jbt] + 2 * two_electron_int[i, a, j, b]) M_LDA[ias][jbt] = ( M_LDA[ias][jbt] + 2 * two_electron_int[i, a, j, b]) values = (f_xc_values[s + t] * MO_values_conjugated[i] * MO_values[a] * MO_values_conjugated[j] * MO_values[b]) M_LDA[ias][jbt] = M_LDA[ias][ jbt] + 2 * molgrid.integrate(values) if s == t: M_HF[ias][jbt] = ( M_HF[ias][jbt] - 2 * two_electron_int[i, a, j, b]) if s == t and i == j and a == b: M_HF[ias][jbt] = (M_HF[ias][jbt] + molecule.mo.energies[a] - molecule.mo.energies[i]) M_LDA[ias][jbt] = (M_LDA[ias][jbt] + molecule.mo.energies[a] - molecule.mo.energies[i]) assert np.allclose(M_mat.calculate_M(k="HF", complex=False), M_HF) assert np.allclose( M_mat.calculate_M(k="lda_x", complex=False, molgrid=molgrid), M_LDA)
def test_K_matrices_K_fxc_DFT(): xc_function = pylibxc.LibXCFunctional("lda_x", "polarized") a_dm = np.dot(molecule.mo.coeffsa * molecule.mo.occsa, molecule.mo.coeffsa.T.conj()) b_dm = np.dot(molecule.mo.coeffsb * molecule.mo.occsb, molecule.mo.coeffsb.T.conj()) a_density_values = evaluate_density(a_dm, basis, molgrid.points, coord_type="cartesian") b_density_values = evaluate_density(b_dm, basis, molgrid.points, coord_type="cartesian") inp = {"rho": np.array([a_density_values, b_density_values])} inp["rho"] = inp["rho"].transpose().reshape(len(inp["rho"][0]) * 2) f_xc_values = (xc_function.compute(inp, None, False, False, True, False))["v2rho2"] f_xc_values = np.array([ f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 0], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 1], f_xc_values.reshape(len(f_xc_values[0]), 3)[:, 2], ]) del (a_dm, b_dm, a_density_values, b_density_values, xc_function, inp) MO_values = evaluate_basis(basis, molgrid.points, transform=molecule.mo.coeffs.T, coord_type="cartesian") MO_values_conjugated = np.conjugate(MO_values) indices = (occupied_ind, virtual_ind) K_size = len(occupied_ind[0]) * len(virtual_ind[0]) + len( occupied_ind[1]) * len(virtual_ind[1]) K_shape = [K_size, K_size] K_fxc_DFT = np.zeros(K_shape, float) for t in range(2): for j_c, j in enumerate(indices[0][t]): for b_c, b in enumerate(indices[1][t]): jbt = (t * len(indices[0][0]) * len(indices[1][0]) + j_c * len(indices[1][t]) + b_c) for s in range(2): for i_c, i in enumerate(indices[0][s]): for a_c, a in enumerate(indices[1][s]): ias = ( s * len(indices[0][0]) * len(indices[1][0]) + i_c * len(indices[1][s]) + a_c) values = (f_xc_values[s + t] * MO_values_conjugated[i] * MO_values[a] * MO_values_conjugated[j] * MO_values[b]) K_fxc_DFT[ias][jbt] = K_fxc_DFT[ias][ jbt] + molgrid.integrate(values) K_fxc_DFT = np.array([ K_fxc_DFT[:70, :70], K_fxc_DFT[:70, 70:], K_fxc_DFT[70:, :70], K_fxc_DFT[70:, 70:], ]) assert np.allclose( K_mats.K_fxc_DFT(XC_functional="lda_x", molgrid=molgrid), K_fxc_DFT) K_shape = [1, K_size] K_fxc_DFT = np.zeros(K_shape, float) index = [[4], []] indices = (occupied_ind, virtual_ind, index) for t in range(2): for j_c, j in enumerate(indices[0][t]): for b_c, b in enumerate(indices[1][t]): jbt = (t * len(indices[0][0]) * len(indices[1][0]) + j_c * len(indices[1][t]) + b_c) for s in range(2): for f_c, f in enumerate(indices[2][s]): ffs = s * len(indices[2][0]) + f_c values = (f_xc_values[s + t] * MO_values_conjugated[f] * MO_values[f] * MO_values_conjugated[j] * MO_values[b]) K_fxc_DFT[ffs][jbt] = K_fxc_DFT[ffs][ jbt] + molgrid.integrate(values) K_fxc_DFT_0 = K_mats.K_fxc_DFT(shape="line", index=index, XC_functional="lda_x", molgrid=molgrid) assert np.allclose(K_fxc_DFT_0[0], K_fxc_DFT[0, :70]) assert np.allclose(K_fxc_DFT_0[1], K_fxc_DFT[0, 70:]) assert np.allclose(K_fxc_DFT_0[2], np.zeros([0, 70])) assert np.allclose(K_fxc_DFT_0[3], np.zeros([0, 70])) values = (f_xc_values[0] * MO_values_conjugated[4] * MO_values[4] * MO_values_conjugated[4] * MO_values[4]) K_fxc_DFT = molgrid.integrate(values) assert np.allclose( K_mats.K_fxc_DFT(shape="point", index=[[4, 4], []], XC_functional="lda_x", molgrid=molgrid), K_fxc_DFT, )