-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMPSUtility.h
More file actions
229 lines (211 loc) · 5.84 KB
/
MPSUtility.h
File metadata and controls
229 lines (211 loc) · 5.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#ifndef __MPSUTILITY_H_CMC__
#define __MPSUTILITY_H_CMC__
#include <iomanip>
#include "itensor/mps/mpo.h"
#include "GeneralUtility.h"
using namespace std;
using namespace itensor;
namespace iut {
IndexSet siteInds (const MPO& mpo)
{
vector<Index> ss;
for(int i = 1; i <= length(mpo); i++)
{
auto s = siteIndex (mpo, i);
ss.push_back (s);
}
return IndexSet (ss);
}
bool operator== (const IndexSet& s1, const IndexSet& s2)
{
if (length(s1) != length(s2))
return false;
for(int i = 1; i <= length(s1); i++)
if (s1(i) != s2(i))
return false;
return true;
}
inline bool operator!= (const IndexSet& s1, const IndexSet& s2)
{
return !operator==(s1,s2);
}
// Apply <gate> on sites (<i>,<i>+1) on <psi>.
// <dir> = Fromleft: the orthogonality center of the resulting MPS is on <i>+1, or
// Fromright: the orthogonality center of the resulting MPS is on <i>
// The truncation settings in <args>: MaxDim, Cutoff
Spectrum apply_gate (MPS& psi, int i, const ITensor& gate, Direction dir, const Args& args=Args::global())
{
int oc = orthoCenter(psi);
assert (oc == i || oc == i+1);
auto AA = psi(i) * psi(i+1) * gate;
AA.noPrime();
auto spec = psi.svdBond (i, AA, dir, args);
return spec;
}
MPO Make_Nup_MPO (const Electron& sites)
{
AutoMPO ampo (sites);
for(int i = 1; i <= length(sites); i++)
{
ampo += 1.0,"Nup",i;
}
return toMPO (ampo);
}
MPO Make_Ndn_MPO (const Electron& sites)
{
AutoMPO ampo (sites);
for(int i = 1; i <= length(sites); i++)
{
ampo += 1.0,"Ndn",i;
}
return toMPO (ampo);
}
MPO Make_NMPO (const Electron& sites)
{
AutoMPO ampo (sites);
for(int i = 1; i <= length(sites); i++)
{
ampo += 1.0,"Ntot",i;
}
return toMPO (ampo);
}
MPO Make_NMPO (const Fermion& sites)
{
AutoMPO ampo (sites);
for(int i = 1; i <= length(sites); i++)
{
ampo += 1.0,"N",i;
}
return toMPO (ampo);
}
template <typename MPSType>
void check_indices (const MPSType& psi)
{
int N = length(psi);
for(int i = 1; i <= N; i++)
{
if (i != N)
mycheck (commonIndex (psi(i), psi(i+1)), "MPS/MPO link-index check failed");
auto is = findIndex (psi(i), "Site,0");
mycheck (is, "MPS/MPO site-index check failed");
if constexpr (is_same_v <MPSType,MPO>)
mycheck (prime(is), "MPS/MPO site-index check failed");
}
}
void print_MPO_tensors (const MPO& mpo, int i)
{
cout << "site " << i << endl << endl;
auto il = leftLinkIndex (mpo, i);
auto ir = rightLinkIndex (mpo, i);
for(int i1 = 1; i1 <= il.dim(); i1++)
for(int i2 = 1; i2 <= ir.dim(); i2++)
{
auto Wij = mpo(i);
auto is = findIndex (Wij, "Site,0");
if (il) Wij *= setElt(dag(il)=i1);
if (ir) Wij *= setElt(dag(ir)=i2);
if (norm(Wij) != 0.)
{
if (!il)
cout << "iright = " << i2 << endl;
else if (!ir)
cout << "ileft = " << i1 << endl;
else
cout << "ileft, iright = " << i1 << " " << i2 << endl;
Wij.permute ({is, prime(is)});
//PrintData(Wij);
// Print in matrix form
cout << setprecision(4);
cout << endl;
for(int j1 = 1; j1 <= dim(is); j1++)
{
for(int j2 = 1; j2 <= dim(is); j2++)
cout << setw(10) << elt (Wij, j2, j1);
cout << endl;
}
cout << endl;
}
}
}
void print_MPO (const MPO& mpo)
{
for(int i = 1; i <= length(mpo); i++)
{
cout << "------------------------" << endl;
print_MPO_tensors (mpo, i);
cout << "------------------------" << endl;
}
}
template <typename MPSTYPE>
inline Index leftIndex (const MPSTYPE& mps, int i)
{
if (i == 1)
return uniqueIndex (mps(1), mps(2), "Link");
else
return leftLinkIndex (mps, i);
}
template <typename MPSTYPE>
inline Index rightIndex (const MPSTYPE& mps, int i)
{
int N = length (mps);
if (i == N)
return uniqueIndex (mps(N), mps(N-1), "Link");
else
return rightLinkIndex (mps, i);
}
Real inner_imps (const MPS& mps1, const MPS& mps2)
{
int N = length(mps1);
auto L = delta (dag(leftIndex(mps1,1)), prime(leftIndex(mps2,1)));
for(int i = 1; i < N; i++)
{
L *= mps1(i);
L *= prime(dag(mps2(i)),"Link");
}
L *= mps1(N);
auto il = leftIndex (mps1, N);
L *= prime(dag(mps2(N)),{il});
return elt(L);
}
void renewLinkInds (MPS& mps, int ibeg, int iend)
{
auto ir0 = rightLinkIndex (mps, ibeg);
auto ir = sim(ir0);
mps.ref(ibeg).replaceInds ({ir0}, {ir});
for(int i = ibeg+1; i < iend; i++)
{
// Left index
auto il0 = leftLinkIndex (mps, i);
mps.ref(i).replaceInds ({il0}, {dag(ir)});
// Right index
ir0 = rightLinkIndex (mps, i);
ir = sim(ir0);
mps.ref(i).replaceInds ({ir0}, {ir});
}
auto il0 = leftLinkIndex (mps, iend);
mps.ref(iend).replaceInds ({il0}, {dag(ir)});
}
void MPSReplaceTensors (MPS& psi, const MPS& subpsi, int ibeg)
{
for(int i = 1; i <= length(subpsi); i++)
{
int i0 = i+ibeg-1;
auto iis = findIndex (psi(i0), "Site");
auto iis2 = findIndex (subpsi(i), "Site");
Index iil;
if (i == 1)
iil = leftLinkIndex (psi, i0);
else if (i == length(subpsi))
iil = rightLinkIndex (psi, i0);
auto A = subpsi(i);
A.replaceInds ({iis2}, {iis});
psi.ref(i0) = A;
if (iil)
{
mycheck (dim(iil) == 1, "not dummy index");
psi.ref(i0) *= setElt(iil=1);
}
}
}
} // namespace
#endif