Skip to content

Commit ba15358

Browse files
committed
added gtests
1 parent 74caf0d commit ba15358

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

tests/BlockFermionicUniTensor_test.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,77 @@ TEST_F(BlockFermionicUniTensorTest, LinAlgElementwise) {
7676
EXPECT_EQ(AreNearlyEqUniTensor(res.apply_(), BFUT3.Pow(2.).apply(), tol), true);
7777
}
7878

79+
/*=====test info=====
80+
describe:test fermion_twists behavior on tagged fermionic tensors
81+
====================*/
82+
TEST_F(BlockFermionicUniTensorTest, FermionTwists) {
83+
UniTensor twisted = BFUT5.fermion_twists();
84+
UniTensor manual = BFUT5.clone();
85+
for (cytnx_int64 idx = manual.rowrank(); idx < manual.rank(); idx++) {
86+
if (manual.bonds()[idx].type() != BD_BRA) manual.twist_(idx);
87+
}
88+
EXPECT_EQ(twisted.signflip(), manual.signflip());
89+
EXPECT_TRUE(AreEqUniTensor(twisted.apply_(), manual.apply_()));
90+
91+
// applying fermion_twists_ twice toggles the same set of signs twice
92+
UniTensor twice = BFUT5.clone();
93+
twice.fermion_twists_().fermion_twists_();
94+
EXPECT_EQ(twice.signflip(), BFUT5.signflip());
95+
EXPECT_TRUE(AreEqUniTensor(twice.apply_(), BFUT5.apply()));
96+
}
97+
98+
/*=====test info=====
99+
describe:test SVD unitarity and reconstruction for fermionic tensors with mixed in/out legs
100+
====================*/
101+
TEST_F(BlockFermionicUniTensorTest, SvdUnitaryAndReconstruction) {
102+
const double tol = 1e-10;
103+
104+
std::vector<UniTensor> svd_out = linalg::Svd_truncate(BFUT5, 10, 0., true, 0);
105+
ASSERT_EQ(svd_out.size(), 3);
106+
UniTensor S = svd_out[0].set_name("S");
107+
UniTensor U = svd_out[1].set_name("U");
108+
UniTensor vT = svd_out[2].set_name("vT");
109+
UniTensor Udag = U.Dagger().set_name("Udag");
110+
Udag.relabel_("_aux_L", "_aux_L_dag");
111+
UniTensor vTdag = vT.Dagger().set_name("vTdag");
112+
vTdag.relabel_("_aux_R", "_aux_R_dag");
113+
114+
// Check U^dagger U = I on the auxiliary left space.
115+
UniTensor UdagU = Contract(Udag.fermion_twists(), U);
116+
UniTensor Iu = 0. * UdagU.clone(); // will be identity matrix
117+
auto shape_u = Iu.shape();
118+
for (cytnx_uint64 k = 0; k < shape_u[0]; k++) {
119+
auto proxy = Iu.at({k, k});
120+
proxy = 1.0;
121+
}
122+
EXPECT_TRUE(AreNearlyEqUniTensor(UdagU.apply(), Iu, tol));
123+
124+
// Check vT vT^dagger = I on the auxiliary right space.
125+
UniTensor vTvTdag = Contract(vT.fermion_twists(), vTdag);
126+
UniTensor Iv = 0. * vTvTdag.clone(); // will be identity matrix
127+
auto shape_v = Iv.shape();
128+
for (cytnx_uint64 k = 0; k < shape_v[0]; k++) {
129+
auto proxy = Iv.at({k, k});
130+
proxy = 1.0;
131+
}
132+
EXPECT_TRUE(AreNearlyEqUniTensor(vTvTdag.apply(), Iv, tol));
133+
134+
// Check U^dagger * BFUT5 * V^dagger = S (where V^dagger is returned as vT).
135+
UniTensor Scontr = Contract(Contract(Udag.fermion_twists(), BFUT5.fermion_twists()), vTdag);
136+
Scontr.relabel_("_aux_L_dag", "_aux_L");
137+
Scontr.relabel_("_aux_R_dag", "_aux_R");
138+
Scontr.permute_(S.labels());
139+
UniTensor Sref = 0. * Scontr.clone(); // Creating Sref, a dense version of S
140+
S.apply_();
141+
auto shape_s = Sref.shape();
142+
for (cytnx_uint64 k = 0; k < shape_s[0]; k++) {
143+
auto pref = Sref.at({k, k});
144+
auto ps = S.at({k, k});
145+
if (pref.exists() && ps.exists()) pref = Scalar(ps);
146+
}
147+
EXPECT_TRUE(AreNearlyEqUniTensor(Scontr.apply(), Sref.apply(), tol));
148+
}
149+
79150
TEST_F(BlockFermionicUniTensorTest, group_basis) {
80151
auto out = BFUT4.group_basis();
81152

tests/BlockFermionicUniTensor_test.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ class BlockFermionicUniTensorTest : public ::testing::Test {
2828
UniTensor BFUT3PERM = UniTensor({B3, B2, B4, B12, B1}, {"d", "b", "e", "c", "a"})
2929
.set_name("BFUT3PERM"); // permutation {3, 1, 4, 2, 0}
3030
UniTensor BFUT4 = UniTensor({B1g, B2g, B3g}, {"a", "b", "c"}).set_name("BFUT4");
31+
// BFUT5 has mixed in/out legs on both row and column spaces, and degeneracies.
32+
Bond B5Li = Bond(BD_IN, {Qs(0), Qs(1)}, {2, 1}, {Symmetry::FermionParity()});
33+
Bond B5Lo = Bond(BD_OUT, {Qs(0), Qs(1)}, {1, 2}, {Symmetry::FermionParity()});
34+
Bond B5Ri = Bond(BD_IN, {Qs(0), Qs(1)}, {1, 2}, {Symmetry::FermionParity()});
35+
Bond B5Ro = Bond(BD_OUT, {Qs(0), Qs(1)}, {2, 1}, {Symmetry::FermionParity()});
36+
UniTensor BFUT5 = UniTensor({B5Li, B5Lo, B5Ri, B5Ro}, {"li", "lo", "ri", "ro"}).set_name("BFUT5");
3137
// UniTensor BFUTfparfnum; // fpar x fnum symmetries
3238

3339
protected:
@@ -89,6 +95,20 @@ class BlockFermionicUniTensorTest : public ::testing::Test {
8995
BFUT4.at({2, 1, 1}) = 7;
9096
BFUT4.at({1, 1, 2}) = 8;
9197
BFUT4.at({2, 1, 2}) = 9;
98+
99+
BFUT5.set_rowrank_(2);
100+
cytnx_double val = 1.0;
101+
auto sh = BFUT5.shape();
102+
for (cytnx_uint64 i = 0; i < sh[0]; i++)
103+
for (cytnx_uint64 j = 0; j < sh[1]; j++)
104+
for (cytnx_uint64 k = 0; k < sh[2]; k++)
105+
for (cytnx_uint64 l = 0; l < sh[3]; l++) {
106+
auto proxy = BFUT5.at({i, j, k, l});
107+
if (proxy.exists()) {
108+
proxy = val;
109+
val += 1.0;
110+
}
111+
}
92112
}
93113
void TearDown() override {}
94114
};

0 commit comments

Comments
 (0)