https://github.com/ITensor/ITensor
Raw File
Tip revision: 6b54fa39438c296f80049dc937ca966746eded68 authored by Miles Stoudenmire on 11 April 2016, 18:02:29 UTC
Updated localop.h diag method to correctly use delta function to tie indices. Fixes #96 - thanks to Xiongjie Yu for reporting it.
Tip revision: 6b54fa3
iqindex.h
//
// Distributed under the ITensor Library License, Version 1.2
//    (See accompanying LICENSE file.)
//
#ifndef __ITENSOR_IQINDEX_H
#define __ITENSOR_IQINDEX_H
#include "itensor/index.h"
#include "itensor/qn.h"
#include "itensor/util/readwrite.h"

namespace itensor {

// Forward declarations
struct IndexQN;
class IQIndexDat;
class IQIndexVal;
template<typename IndexT>
class ITensorT;

using ITensor = ITensorT<Index>;

//
// IQIndex
//

class IQIndex : public Index
    {
    public:
    using storage = std::vector<IndexQN>;
    using storage_ptr = std::shared_ptr<IQIndexDat>;
    using indexval_type = IQIndexVal;
    using const_iterator = storage::const_iterator;
    private:
    storage_ptr pd;
    Arrow dir_;
    public:

    IQIndex();

    //
    //Construct IQIndex from name,
    //collection of any number of 
    //Index-QN pairs.
    //Optional last argument can
    //be Arrow direction of the IQIndex:
    //IQIndex("name",i1,q1,i2,q2,In);
    //
    template<typename... Rest>
    IQIndex(std::string const& name, 
            Index const& i1, QN const& q1, 
            Rest const&... etc);

    //Constructor taking a container
    //of IndexQN's
    IQIndex(std::string const& name, 
            storage && ind_qn, 
            Arrow dir = Out, 
            int plev = 0);

    //
    //Accessor Methods
    //

    long 
    nindex() const;

    //1-indexed
    Index 
    index(long i) const;

    //0-indexed
    Index 
    operator[](long i) const;

    //1-indexed
    QN const& 
    qn(long i) const;

    Arrow 
    dir() const { return dir_; }

    //
    // Operators
    //

    IQIndexVal 
    operator()(long n) const;

    //
    // Other methods
    //

    IQIndex& 
    dag();

    const_iterator
    begin() const;

    const_iterator
    end() const;

    void 
    write(std::ostream& s) const;

    IQIndex& 
    read(std::istream& s);

    }; //class IQIndex

//
// IndexQN
//

struct IndexQN //: public Index
    {
    using IndexValT = IQIndexVal;

    Index index;
    QN qn;

    IndexQN() { }

    IndexQN(Index const& i, QN const& q) : index(i), qn(q) { }

    explicit operator Index() const { return index; }

    void
    dag() { index.dag(); }

    auto
    m() const -> decltype(index.m()) { return index.m(); }

    IndexType
    type() const { return index.type(); }

    void 
    write(std::ostream& s) const { index.write(s); itensor::write(s,qn); }

    void 
    read(std::istream& s) { index.read(s); itensor::read(s,qn); }
    };

bool inline
operator==(IndexQN const& iq, Index const& i) { return iq.index == i; }
bool inline
operator==(Index const& i, IndexQN const& iq) { return iq.index == i; }
bool inline
operator!=(IndexQN const& iq, Index const& i) { return iq.index != i; }
bool inline
operator!=(Index const& i, IndexQN const& iq) { return iq.index != i; }


//
// IQIndexVal
//

class IQIndexVal
    {
    public:
    using index_type = IQIndex;

    IQIndex index;
    long val;

    IQIndexVal();

    IQIndexVal(IQIndex const& iqindex, long val_);

    explicit operator IndexVal() const;

    explicit operator bool() const { return bool(index); }

    QN const&
    qn() const;

    QN const&
    qn(long j) const { return index.qn(j); }

    IndexQN
    indexqn() const;

    IndexVal 
    blockIndexVal() const;

    long 
    m() const { return index.m(); }

    IQIndexVal& 
    prime(int inc = 1);

    IQIndexVal& 
    prime(IndexType type, int inc = 1);

    IQIndexVal& 
    noprime(IndexType type = All);

    IQIndexVal& 
    mapprime(int plevold, int plevnew, IndexType type = All);

    IQIndexVal& 
    dag();

    };

ITensor
operator*(IQIndexVal const& iqiv, IndexVal const& iv);

bool
operator==(IQIndexVal const& iv1, IQIndexVal const& iv2);

bool inline
operator!=(IQIndexVal const& iv1, IQIndexVal const& iv2) { return !(iv1==iv2); }

bool inline
operator==(IQIndexVal const& iv, IQIndex const& I) { return iv.index == I; }

bool inline
operator!=(IQIndexVal const& iv, IQIndex const& I) { return !(iv==I); }

bool inline
operator==(IQIndex const& I, IQIndexVal const& iv) { return iv == I; }

bool inline
operator!=(IQIndex const& I, IQIndexVal const& iv) { return !(iv==I); }

IQIndex inline
dag(IQIndex res) { res.dag(); return res; }

IndexQN inline
dag(IndexQN res) { res.dag(); return res; }

IQIndexVal inline
dag(IQIndexVal res) { res.dag(); return res; }

bool
hasindex(const IQIndex& I, const Index& i);

long
findindex(const IQIndex& I, const Index& i);

long 
offset(const IQIndex& I, const Index& i);

QN 
qn(const IQIndex& I, const Index& i);

Index
findByQN(const IQIndex& I, const QN& qn);

std::string 
showm(IQIndex const& I);

std::ostream& 
operator<<(std::ostream &o, const IQIndex &I);

std::ostream& 
operator<<(std::ostream &s, const IndexQN& x);

std::ostream& 
operator<<(std::ostream& s, const IQIndexVal& iv);

template<typename... VarArgs>
IQIndex
prime(IQIndex I, VarArgs&&... vargs) { I.prime(std::forward<VarArgs>(vargs)...); return I; }

template<typename... VarArgs>
IQIndex
noprime(IQIndex I, VarArgs&&... vargs) { I.noprime(std::forward<VarArgs>(vargs)...); return I; }

//Return a copy of I with prime level changed to plevnew if
//old prime level was plevold. Otherwise has no effect.
IQIndex inline
mapprime(IQIndex I, int plevold, int plevnew, IndexType type = All)
    { I.mapprime(plevold,plevnew,type); return I; }

template<typename... VarArgs>
IQIndexVal
prime(IQIndexVal I, VarArgs&&... vargs) { I.prime(std::forward<VarArgs>(vargs)...); return I; }

template<typename... VarArgs>
IQIndexVal
noprime(IQIndexVal I, VarArgs&&... vargs) { I.noprime(std::forward<VarArgs>(vargs)...); return I; }

//Return a copy of I with prime level changed to plevnew if
//old prime level was plevold. Otherwise has no effect.
IQIndexVal inline
mapprime(IQIndexVal I, int plevold, int plevnew, IndexType type = All)
    { I.mapprime(plevold,plevnew,type); return I; }


//
//
// Implementations
//
//

class IQIndexDat
    {
    public:
    using storage = std::vector<IndexQN>;
    using iterator = storage::iterator;
    using const_iterator = storage::const_iterator;
    private:
    storage iq_;
    public:

    IQIndexDat() { }

    template<typename... Rest>
    IQIndexDat(Index const& i1, QN const& q1,
               Rest const&... args) 
        { 
        constexpr auto size = sizeof...(args)/2+1;
        iq_.resize(size);
        fill<0>(i1,q1,args...);
        }

    explicit
    IQIndexDat(const storage& ind_qn) 
      : iq_(ind_qn)
        { }

    explicit
    IQIndexDat(storage&& ind_qn) 
      : iq_(std::move(ind_qn))
        { }

    //Disallow copying
    IQIndexDat(const IQIndexDat&) = delete;

    void 
    operator=(IQIndexDat const&) = delete;

    storage const&
    inds() const { return iq_; }

    long
    size() { return iq_.size(); }

    Index const&
    index(long i) { return iq_[i-1].index; }

    Index const&
    operator[](long i) { return iq_[i].index; }

    const QN&
    qn(long i) { return iq_[i-1].qn; }

    iterator
    begin() { return iq_.begin(); }

    iterator
    end() { return iq_.end(); }

    const_iterator
    begin() const { return iq_.begin(); }

    const_iterator
    end()   const { return iq_.end(); }

    void 
    write(std::ostream& s) const { itensor::write(s,iq_); }

    void 
    read(std::istream& s) { itensor::read(s,iq_); }

    //IQIndex::storage_ptr
    //clone() { return std::make_shared<IQIndexDat>(iq_); }

    template<long J>
    void
    fill(Arrow dir = Out) { }

    template<long J, typename... Rest>
    void
    fill(Index const& i, 
         QN const& q, 
         Rest const&... rest)
        {
#ifdef DEBUG
        assert(J < iq_.size());
#endif
        iq_[J] = IndexQN(i,q);
        fill<J+1>(rest...);
        }
    };

long
totalM(IQIndexDat::storage const& storage);

inline IQIndex::
IQIndex() 
    : 
    dir_(Neither)
    { }

namespace detail {

long inline
totalM(Arrow dir = Out)
    {
    return 0;
    }

template<typename... Rest>
long
totalM(Index const& i, 
       QN const& q,
       Rest const&... rest)
    {
    return i.m()+detail::totalM(rest...);
    }

Arrow inline
getDir(Arrow dir = Out)
    {
    return dir;
    }

template<typename... Rest>
Arrow
getDir(Index const& i, 
       QN const& q,
       Rest const&... rest)
    {
    return detail::getDir(rest...);
    }

} //namespace detail


template<typename... Rest>
IQIndex::
IQIndex(std::string const& name, 
        Index const& i1, QN const& q1, 
        Rest const&... rest)
  : Index(name,detail::totalM(i1,q1,rest...),i1.type(),i1.primeLevel()), 
    pd(std::make_shared<IQIndexDat>(i1,q1,rest...)),
    dir_(detail::getDir(rest...))
    { }

inline IQIndex::
IQIndex(std::string const& name, 
        storage && ind_qn, 
        Arrow dir, 
        int plev) 
  : Index(name,totalM(ind_qn),ind_qn.front().index.type(),plev),
    pd(std::make_shared<IQIndexDat>(std::move(ind_qn))),
    dir_(dir)
    { }


} //namespace itensor

#endif
back to top