https://github.com/ITensor/ITensor
Tip revision: 127526447e9a22be1b847ff5703fd80b055e0941 authored by Miles Stoudenmire on 07 July 2016, 15:45:24 UTC
Made SiteSet operator string parsing recursive, now supports "A*B*C*D*..."
Made SiteSet operator string parsing recursive, now supports "A*B*C*D*..."
Tip revision: 1275264
spectrum.cc
//
// Distributed under the ITensor Library License, Version 1.1.
// (See accompanying LICENSE file.)
//
#include <algorithm>
#include <utility>
#include "itensor/spectrum.h"
using std::pair;
using std::make_pair;
namespace itensor {
struct OrderSecond
{
using value_type = pair<QN,Real>;
bool
operator()(const value_type& i, const value_type& j) const
{
return i.second > j.second;
}
};
Spectrum::
Spectrum(const Args& args)
:
truncerr_(0)
{
computeTruncerr(args);
}
Spectrum::
Spectrum(const ITensor& D, const Args& args)
:
truncerr_(0)
{
if(D.type() != ITensor::Diag) Error("Spectrum may only be constructed from Diag type ITensor.");
eigs_ = D.diag();
for(int n = 1; n <= eigs_.Length(); ++n)
eigs_(n) = sqr(eigs_(n));
computeTruncerr(args);
}
Spectrum::
Spectrum(const IQTensor& D, const Args& args)
:
truncerr_(0)
{
std::vector<OrderSecond::value_type> eigs;
eigs.reserve(D.indices().front().m());
for(const ITensor& t : D.blocks())
{
if(t.type() != ITensor::Diag)
Error("Spectrum may only be constructed from IQTensor containing only Diag type ITensor.");
const Vector svals = t.diag();
const QN q = itensor::qn(D,t.indices().front());
for(int n = 1; n <= svals.Length(); ++n)
{
eigs.push_back(std::make_pair(q,sqr(svals(n))));
}
}
std::sort(eigs.begin(),eigs.end(),OrderSecond());
qns_.resize(eigs.size());
eigs_.ReDimension(eigs.size());
for(size_t j = 0; j < eigs.size(); ++j)
{
qns_.at(j) = eigs.at(j).first;
eigs_[j] = eigs.at(j).second;
}
computeTruncerr(args);
}
Spectrum::
Spectrum(const Vector& eigs, const Args& args)
:
eigs_(eigs)
{
computeTruncerr(args);
}
Spectrum::
Spectrum(const Vector& eigs,
const QNStorage& qns,
const Args& args)
:
eigs_(eigs),
qns_(qns)
{
computeTruncerr(args);
}
QN Spectrum::
qn(int n) const
{
if(qns_.empty()) return QN();
return qns_.at(n-1);
}
void Spectrum::
read(std::istream& s)
{
s.read((char*)&truncerr_,sizeof(truncerr_));
eigs_.read(s);
size_t sz = 0;
s.read((char*)&sz,sizeof(sz));
qns_.resize(sz);
for(size_t j = 0; j < sz; ++j)
{
s.read((char*)&qns_[j],sizeof(qns_[j]));
}
}
void Spectrum::
write(std::ostream& s) const
{
s.write((char*)&truncerr_,sizeof(truncerr_));
eigs_.write(s);
size_t sz = qns_.size();
s.write((char*)&sz,sizeof(sz));
for(size_t j = 0; j < sz; ++j)
{
s.write((char*)&qns_[j],sizeof(qns_[j]));
}
}
void Spectrum::
computeTruncerr(const Args& args)
{
if(args.defined("Truncerr"))
{
truncerr_ = args.getReal("Truncerr");
}
else
{
if(eigs_.Length() > 0)
{
// Note: This only makes sense if the spectrum was normalized before truncation.
// Otherwise this will mostly return zero.
truncerr_ = 1.-eigs_.sumels();
if(truncerr_ < 0) truncerr_ = 0;
}
}
}
std::ostream&
operator<<(std::ostream & s, const Spectrum& spec)
{
const Vector& eigs = spec.eigsKept();
const int N = eigs.Length();
if(N > 0)
{
const int max_show = 20;
int stop = min(N,max_show);
s << " Eigs kept: ";
for(int j = 1; j <= stop; ++j)
{
s << format(eigs(j) > 1E-3 ? ("%.3f") : ("%.3E"), eigs(j));
s << ((j != stop) ? ", " : "\n");
}
s << format(" Trunc. error = %.3E\n", spec.truncerr());
}
return s;
}
} //namespace itensor