-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrk4_ancilla_hub.cc
271 lines (229 loc) · 7.43 KB
/
rk4_ancilla_hub.cc
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include "itensor/all.h"
#include <iostream>
#include "TStateObserver.h"
//#include "S2.h"
using namespace std;
using namespace itensor;
using TensorT = ITensor;
using MPOT = MPOt<TensorT>;
using MPST = MPSt<TensorT>;
double** get_rdm1up(MPST psi, int N);
double** get_rdm1dn(MPST psi, int N);
double *get_rdm2diag(MPST psi, int N);
double*** get_rdm1s(MPST psi, int N);
MPST rk4_fit_1timestep(MPST psi, double tau, MPOT H, Args args);
MPST rk4_exact_1timestep(MPST psi, double tau, MPOT H, Args args);
int
main(int argc, char* argv[])
{
printfln("TensorT == %s",(std::is_same<TensorT,ITensor>::value ? "ITensor" : "IQTensor"));
//Get parameter file
if(argc != 2)
{
printfln("Usage: %s inputfile.",argv[0]);
return 0;
}
auto input = InputGroup(argv[1],"input");
auto N = input.getInt("N",1);
auto U = input.getReal("U", 1.0);
auto outdir = input.getString("outdir");
auto mu = input.getReal("mu", 1.0);
auto t1 = input.getReal("t", 1.0);
auto periodic = input.getYesNo("periodic",false);
auto beta = input.getReal("beta",1);
auto tau = input.getReal("tau",0.005);
auto maxm = input.getInt("maxm",1000);
auto cutoff = input.getReal("cutoff",1E-11);
auto realstep = input.getYesNo("realstep",false);
auto verbose = input.getYesNo("verbose",false);
auto fitmpo = input.getYesNo("fitmpo", false);
//auto args = Args("N=",N, "Cutoff=",cutoff,"Maxm=",maxm,"Normalize=",false);
Args args;
args.add("N",N);
args.add("Maxm",maxm);
args.add("Cutoff",cutoff);
args.add("Verbose",verbose);
args.add("Normalize",false);
auto sites = Hubbard(2*N, {"ConserveNf",false,"ConserveSz", true});
////////////////////////////////////////////////////////
// Construct Hamitltonian //
////////////////////////////////////////////////////////
auto ampo = AutoMPO(sites);
//////////////////
// Coulomb term //
//////////////////
for(int i=1; i<=N;++i )
{
int s1 = 2*i-1;
ampo += U, "Nupdn", s1;
}
///////////////////////////
// nearest neighbor term //
///////////////////////////
int endpnt; //PBC or OBC
if(periodic) endpnt = N;
else endpnt = N-1;
for(int i=1; i<=endpnt;++i )
{
int s1 = 2*i-1;
int s2 = 2*(i+1)-1;
if(i==N) s2 = 1;
ampo += -1*t1,"Cdagup",s1,"Cup",s2;
ampo += -1*t1,"Cdagup",s2,"Cup",s1;
ampo += -1*t1,"Cdagdn",s1,"Cdn",s2;
ampo += -1*t1,"Cdagdn",s2,"Cdn",s1;
}
auto HE = MPO(ampo);
/////////////////////////////
// chemical potential term //
/////////////////////////////
for(int i=1; i<=N; ++i)
{
int s1 = 2*i-1;
ampo += -1*mu, "Nup", s1;
ampo += -1*mu, "Ndn", s1;
}
auto H = MPOT(ampo);
///////////////////////////////////////////////////
// total number operator //
///////////////////////////////////////////////////
auto nmpo = AutoMPO(sites);
for(int i=1; i<=N; ++i)
{
int s1 = 2*i-1;
nmpo += 1.0, "Nup", s1;
nmpo += 1.0, "Ndn", s1;
}
auto Ntot = MPOT(nmpo);
/////////////////////////////////////////////////////
// double occupancy on first site //
/////////////////////////////////////////////////////
auto dompo = AutoMPO(sites);
dompo += 1.0, "Nupdn", 1;
auto Docc = MPOT(dompo);
//
// Make initial 'wavefunction' which is a product
// of perfect singlets between neighboring sites
//
auto psi = MPST(sites);
auto psin = MPST(sites);
for(int n = 1; n <= 2*N; n += 2)
{
auto s1 = sites(n);
auto s2 = sites(n+1);
auto wf = TensorT(s1,s2);
// define the initial state of the real-facticious pair for fermions
wf.set(s1(1),s2(4), 0.5);
wf.set(s1(2),s2(3), 0.5);
wf.set(s1(3),s2(2), 0.5);
wf.set(s1(4),s2(1), 0.5);
//Wf.set(s1(1),s2(1), 0.5);
//Wf.set(s1(2),s2(2), 0.5);
//Wf.set(s1(3),s2(3), 0.5);
//Wf.set(s1(4),s2(4), 0.5);
TensorT D;
psi.Aref(n) = TensorT(s1);
psi.Aref(n+1) = TensorT(s2);
svd(wf,psi.Aref(n),D,psi.Aref(n+1));
psi.Aref(n) *= D;
psin.Aref(n) = TensorT(s1);
psin.Aref(n+1) = TensorT(s2);
svd(wf,psin.Aref(n),D,psin.Aref(n+1));
psin.Aref(n) *= D;
}
auto obs = TStateObserver<TensorT>(psi);
auto ttotal = beta/2.;
const int nt = int(ttotal/tau+(1e-9*(ttotal/tau)));
if(fabs(nt*tau-ttotal) > 1E-9)
{
Error("Timestep not commensurate with total time");
}
printfln("Doing %d steps of tau=%f",nt,tau);
auto targs = args;
//
// containers to save data
//
auto En = Vector(nt);
auto Don = Vector(nt);
auto Nn = Vector(nt);
auto Betas = Vector(nt);
////////////////////////////////////////////////////////////
// imaginary time evolution
////////////////////////////////////////////////////////////
Real tsofar = 0;
for(int tt = 1; tt <= nt; ++tt)
{
// 4th-order Runge-Kutta
if(fitmpo)
{
cout << "USING RK4 evolution \n";
if(tt<2) psi = rk4_exact_1timestep(psi, tau, H, args);
else psi = rk4_fit_1timestep(psi, tau, H, args);
}
else
{
cout << "USING MPO evolution \n";
psi = rk4_exact_1timestep(psi, tau, H, args);
}
psi.Aref(1) /= norm(psi.A(1));
tsofar += tau;
targs.add("TimeStepNum",tt);
targs.add("Time",tsofar);
targs.add("TotalTime",ttotal);
obs.measure(targs);
//Record beta value
auto bb = (2*tsofar);
Betas(tt-1) = bb;
//
//
// Measure Energy and
//
auto en = overlap(psi,HE,psi);
printfln("###### Energy/N %.4f %.12f",bb,en/N);
En(tt-1) = en/N;
//
// Measure total particle number
//
auto npart = overlap(psi, Ntot, psi);
printfln("###### Ntot %.4f %.6f", bb, npart);
Nn(tt-1) = npart;
//
// Measure double occupancy
//
auto dos = overlap(psi, Docc, psi);
printfln("###### Double occupancy %.4f %.12f",bb, dos);
Don(tt-1) = dos;
}
// end time evolution
return 0;
}
MPST rk4_fit_1timestep(MPST psi, double tau, MPOT H, Args args)
{
auto k1 = -tau*fitApplyMPO(psi, H, args);
auto k2 = -tau*fitApplyMPO(sum(psi, 0.5*k1, args), H, args);
auto k3 = -tau*fitApplyMPO(sum(psi, 0.5*k2, args), H, args);
auto k4 = -tau*fitApplyMPO(sum(psi, k3, args), H, args);
auto terms = vector<MPST>(5);
terms.at(0) = psi;
terms.at(1) = 1./6.* k1;
terms.at(2) = 1./3.* k2;
terms.at(3) = 1./3.* k3;
terms.at(4) = 1./6.* k4;
psi = sum(terms, args);
return psi;
}
MPST rk4_exact_1timestep(MPST psi, double tau, MPOT H, Args args)
{
auto k1 = -tau*exactApplyMPO(H, psi, args);
auto k2 = -tau*exactApplyMPO(H, sum(psi, 0.5*k1, args), args);
auto k3 = -tau*exactApplyMPO(H, sum(psi, 0.5*k2, args), args);
auto k4 = -tau*exactApplyMPO(H, sum(psi, k3, args), args);
auto terms = vector<MPST>(5);
terms.at(0) = psi;
terms.at(1) = 1./6.* k1;
terms.at(2) = 1./3.* k2;
terms.at(3) = 1./3.* k3;
terms.at(4) = 1./6.* k4;
psi = sum(terms, args);
return psi;
}