Source code for pytc.legacy.test.test_df

"""Test for density-fitting and tensor decomposition implementations."""

import unittest
import numpy as np
from pyscf import gto, scf

from pytc.legacy.xtc import XTC
from pytc.legacy.jastrow import REXP
from pytc.legacy.df import isdf_decompose_cholesky, reconstruct_rho, test_accuracy, test_multi_accuracy

[docs] def get_be_ccpvdz(): """Return a Be atom with cc-pVDZ basis for testing.""" mol = gto.M(atom='Be 0 0 0', basis='ccpvdz', unit='Bohr') mf = scf.RHF(mol) mf.kernel() return mol, mf
[docs] class TestDF(unittest.TestCase): """Test density-fitting and tensor decomposition methods."""
[docs] @classmethod def setUpClass(cls): """Set up test case using Be atom.""" # Get mean-field data _, cls.mf = get_be_ccpvdz() # Create REXP instance cls.jastrow = REXP([1.4]) # Initialize XTC cls.xtc = XTC(cls.mf, cls.jastrow, grid_lvl=1) # Get orbital values on grid mo_values, _ = cls.xtc._eval_basis_on_grid() rho = mo_values # Get paired density cls.rho_paired = np.einsum('in,jn->ijn', rho, rho).reshape(-1, len(cls.xtc.weights)) # Get mo_grad for tensor tests _, cls.mo_grad = cls.xtc._eval_basis_on_grid() cls.rho_grad = cls.mo_grad # Shape (Nb, N_grid, 3)
[docs] def test_tensor_decomposition(self): """Test ISDF decomposition with tensor input.""" n_rank = 40 # Input has shape (Nb, N_grid, 3) C, xi = isdf_decompose_cholesky(self.rho_grad, n_rank=n_rank) # Check shapes including trailing dimensions self.assertEqual(C.shape, (self.rho_grad.shape[0], n_rank, 3)) self.assertEqual(xi.shape, (n_rank, self.rho_grad.shape[1], 3)) # Test reconstruction rho_reconstructed = reconstruct_rho(C, xi) self.assertEqual(rho_reconstructed.shape, self.rho_grad.shape) # Check error using norm along spatial dimensions error = np.linalg.norm(rho_reconstructed - self.rho_grad) / np.linalg.norm(self.rho_grad) self.assertLess(error, 1e-4)
[docs] def test_multi_decomposition(self): """Test decomposition of scalar and tensor densities.""" # Use both scalar and tensor valued densities rank = 50 # Create tensor test density rho_tensor = self.rho_grad # Shape (Nb, N_grid, 3) # Test decomposition with mixed types rel_error1, abs_error1, rel_error2, abs_error2, n_fused = test_multi_accuracy( self.rho_paired, # Matrix input rho_tensor, # Tensor input rank, rank ) # Check errors are reasonable self.assertLess(rel_error1, 1e-4) self.assertLess(rel_error2, 1e-4) # Check number of fused pivots self.assertLessEqual(n_fused, 2 * rank) self.assertGreaterEqual(n_fused, rank)
[docs] def test_rank_convergence(self): """Test ISDF decomposition with different ranks.""" # Test both matrix and tensor inputs for input_data in [self.rho_paired, self.rho_grad]: ranks = [10, 20, 40] errors = [] for rank in ranks: C, xi = isdf_decompose_cholesky(input_data, n_rank=rank) # Reconstruct and check error reconstructed = reconstruct_rho(C, xi) error = np.linalg.norm(reconstructed - input_data) / np.linalg.norm(input_data) errors.append(error) # Check that error decreases with increasing rank # Check that error generally decreases (highest rank should have lowest error) self.assertLess(errors[-1], errors[0])
[docs] def test_reconstruction_shapes(self): """Test shape preservation in reconstruction.""" rank = 150 # Test matrix input C_mat, xi_mat = isdf_decompose_cholesky(self.rho_paired, n_rank=rank) recon_mat = reconstruct_rho(C_mat, xi_mat) self.assertEqual(recon_mat.shape, self.rho_paired.shape) # Check reconstruction accuracy rel_error, _ = test_accuracy(self.rho_paired, C_mat, xi_mat) self.assertLess(rel_error, 1e-4) # Test tensor input C_tens, xi_tens = isdf_decompose_cholesky(self.rho_grad, n_rank=rank) recon_tens = reconstruct_rho(C_tens, xi_tens) self.assertEqual(recon_tens.shape, self.rho_grad.shape) # Check reconstruction accuracy rel_error, _ = test_accuracy(self.rho_grad, C_tens, xi_tens) self.assertLess(rel_error, 1e-4)
if __name__ == '__main__': unittest.main()