-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFinalSuperblock.cpp
147 lines (141 loc) · 5.79 KB
/
FinalSuperblock.cpp
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
#include "FreeFunctions.h"
using namespace Eigen;
FinalSuperblock::FinalSuperblock(const HamSolver& hSuperSolver, int lSupFinal,
int mSFinal, int mEFinal, int skips)
: gsEnergy(hSuperSolver.lowestEval), lSupFinal(lSupFinal),
psiGround(hSuperSolver.lowestEvec), mSFinal(mSFinal), mEFinal(mEFinal),
skips(skips)
{
if(lSupFinal % 2)
{
lSFinal = (lSupFinal - 1)/2;
lEFinal = (lSupFinal - 3)/2;
}
else
lSFinal = lEFinal = lSupFinal / 2 - 1;
};
double FinalSuperblock::expValue(const opsVec& ops,
std::vector<TheBlock>& leftBlocks,
std::vector<TheBlock>& rightBlocks)
{
opsMap sysBlockOps, // observable operators that will act on the system block
envBlockOps; // same for environment block
obsMatrixD_t lFreeSite = obsId_d,
rFreeSite = obsId_d;
bool opAtlFreeSite = false,
opAtrFreeSite = false;
for(const auto& opToEvaluate : ops) // split up operators into their blocks
{
int site = opToEvaluate.second;
if(site < lSFinal)
placeOp(opToEvaluate, sysBlockOps, true);
else if(site == lSFinal) // if necessary, assign left free-site operator
{
lFreeSite *= opToEvaluate.first;
opAtlFreeSite = true;
}
else if(site == lSFinal + 1) // and right free-site operator
{
rFreeSite *= opToEvaluate.first;
opAtrFreeSite = true;
}
else
placeOp(opToEvaluate, envBlockOps, false);
};
// evaluate observable:
if(sysBlockOps.empty() && !opAtlFreeSite)
// observables in right-hand half of superblock case
if(envBlockOps.empty())
{ // right-hand free site single-site observable case
psiGround.resize(mSFinal * d * mEFinal, d);
return obsRe((psiGround
* rFreeSite.transpose()
* psiGround.adjoint()
).trace());
}
else
{
psiGround.resize(mSFinal * d, mEFinal * d);
return obsRe((psiGround.adjoint()
* psiGround
* kp(rhoBasisRep(envBlockOps, rightBlocks, lEFinal),
rFreeSite).transpose()
).trace());
}
else if(envBlockOps.empty() && !opAtrFreeSite)
// observables in left-hand half of superblock case
if(!opAtlFreeSite) // all observables in system block case
{
psiGround.resize(mSFinal, d * mEFinal * d);
return obsRe((psiGround.adjoint()
* rhoBasisRep(sysBlockOps, leftBlocks, lSFinal)
* psiGround
).trace());
}
else
{
psiGround.resize(mSFinal * d, mEFinal * d);
return obsRe((psiGround.adjoint()
* kp(rhoBasisRep(sysBlockOps, leftBlocks, lSFinal),
lFreeSite)
* psiGround
).trace());
}
else // observables in both halves of superblock case
{
psiGround.resize(mSFinal * d, mEFinal * d);
return obsRe((psiGround.adjoint()
* kp(rhoBasisRep(sysBlockOps, leftBlocks, lSFinal), lFreeSite)
* psiGround
* kp(rhoBasisRep(envBlockOps, rightBlocks, lEFinal), rFreeSite)
.transpose()
).trace());
};
};
void FinalSuperblock::placeOp(const std::pair<obsMatrixD_t, int>& op,
opsMap& blockSide, bool systemSide)
{
int lhSite = (systemSide ? op.second : lSupFinal - 1 - op.second);
if(blockSide.count(lhSite)) // already an observable at this site?
blockSide[lhSite] *= op.first;
else
blockSide.insert(std::pair<int, obsMatrixD_t>(lhSite, op.first));
};
obsMatrixX_t FinalSuperblock::rhoBasisRep(const opsMap& blockOps,
std::vector<TheBlock>& blocks,
int blockSize) const
{
if(blockOps.empty())
return obsId(blocks[blockSize - 1].m);
obsMatrixX_t rhoBasisBlockOp;
const auto firstOp = blockOps.begin();
// first nontrivial site operator at which to start tensoring
auto currentOp = firstOp;
const auto firstSite = blocks.begin();
auto currentSite = firstSite;
if(firstOp -> first == 0) // one-site observable at first site?
{
rhoBasisBlockOp = firstOp -> second;
currentOp++;
}
else
{
currentSite += (firstOp -> first - 1);
rhoBasisBlockOp = obsId(currentSite -> m);
};
const auto opsEnd = blockOps.end();
for(const auto end = firstSite + (blockSize - 1); currentSite != end;
currentSite++)
{
obsMatrixX_t primeBasisBlockOp = kp(rhoBasisBlockOp,
(currentOp != opsEnd
&& currentSite - firstSite
== currentOp -> first - 1 ?
currentOp++ -> second :
obsId_d));
rhoBasisBlockOp = (currentSite - firstSite < skips ?
primeBasisBlockOp :
currentSite -> obsChangeBasis(primeBasisBlockOp));
};
return rhoBasisBlockOp;
};