\documentclass{book}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{graphicx}
\usepackage{fancyvrb} %keep
\usepackage{fancyhdr}
\usepackage{booktabs} %keep
\usepackage{mathtools} %keep
\usepackage{hyperref}

\fancyhead{}
\fancyhead[LE]{\leftmark}
\fancyhead[RO]{\rightmark}
\cfoot{}
\rfoot{\thepage} %exit

\hypersetup{colorlinks=true}


\newcommand{\cppFile}[1]{\texttt{#1}}
\newcommand{\inputItem}[1]{\noindent\texttt{\bf #1} ---}
\newcommand{\inputSubItem}[1]{\indent\texttt{\it #1} --}
%% Remove the below command before submission
\newcommand{\todo}[1]{\textcolor{red}{#1}}
%Format to denote a C++ class name:
\newcommand{\cppClass}[1]{{\sffamily #1}}
%Format to denote a C++ variable:
\newcommand{\cppFunction}[1]{{\tt #1}}
% for the cover page:
\newcommand{\HRule}{\noindent\rule{\linewidth}{1.5pt}}
\newcommand{\ptexPaste}[1]{\fbox{\textcolor{red}{PLEASE RUN ptex.pl on this .ptex source
to obtain the correct test for tag #1}}}
\newcommand{\ptexLabel}[1]{\ptexPaste{#1}}
\newcommand{\ptexInterface}[1]{\ptexPaste{#1}}
\newcommand{\ptexReadFile}[1]{\ptexPaste{#1}}
\newcommand{\ptexReadFileVerbatim}[1]{\ptexPaste{#1}}

\hyphenation{Wave-Function-Transformation}
\lstset{language=c++,basicstyle=\footnotesize\ttfamily,
keywordstyle=\color{blue}\bfseries,frame=shadowbox}
\pagestyle{fancy}
\begin{document}

\begin{titlepage}
\vspace*{\stretch{1}}
\HRule
\begin{flushright}
\LARGE  DMRG++ v5 Manual\\
\end{flushright}
\HRule
\vspace*{\stretch{2}}

%
\begin{center}
\Large Manual Version: \today\\
\end{center}

\begin{center}
\textsc{Oak Ridge, 2018}
\end{center}

\end{titlepage}
%
\begin{titlepage}
\noindent
\begin{minipage}{0.4\textwidth}
\begin{flushleft}
Gonzalo \textsc{Alvarez}\\
Nanomaterials Theory Institute\\
Oak Ridge National Laboratory\\[0.2cm]
Oak Ridge, TN 37831\\
\today
\end{flushleft}
\end{minipage}

\vspace*{\stretch{2}}
\noindent
%\begin{minipage}{0.6\textwidth}
\begin{tiny}
\fontshape{sc}\selectfont
%\begin{verbatim}
\noindent
DISCLAIMER\\[0.2cm]
THE SOFTWARE IS SUPPLIED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER, CONTRIBUTORS, UNITED STATES GOVERNMENT,
OR THE UNITED STATES DEPARTMENT OF ENERGY BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT OF ENERGY,
NOR THE COPYRIGHT OWNER, NOR
ANY OF THEIR EMPLOYEES, REPRESENTS THAT THE USE OF ANY
INFORMATION, DATA, APPARATUS, PRODUCT, OR PROCESS
DISCLOSED WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.\\[1cm]

\fontshape{\shapedefault}\selectfont
%\end{verbatim}
\end{tiny}
%\end{minipage}
\noindent
\begin{minipage}{0.4\textwidth}
Copyright \copyright 2009,\\
 UT-Battelle, LLC\\
All rights reserved
\end{minipage}
\hfill
\begin{minipage}{0.4\textwidth}
\begin{flushright}
\includegraphics[width=3cm]{dmrgV2LogoBW.png}
\end{flushright}
\end{minipage}
\end{titlepage}
\tableofcontents

\begin{center}
\includegraphics[width=2cm]{Under_construction_icon-blue}\\
{\tiny http://commons.wikimedia.org/wiki/File:Under\_construction\_icon-blue.svg}
\end{center}
\pagebreak

\ptexReadFile{../README.md}

\chapter{Input}\label{sec:inputfile}

\section{Running DMRG++}

\ptexPaste{DmrgDriver}

Examples of input files can be found under \verb!TestSuite/inputs/!
There are three kinds of parameters in the input file:
(i) model connections (``geometry'') parameters, (ii) model on-site parameters,
and (iii) DMRG Solver parameters.
Each type of input parameters is discussed below.

\section{SolverOptions}
\ptexPaste{dmrgSolverOptions}

\section{Geometry Input}
This needs to be in PsimagLite.

\section{Model Input}

The Model parameters vary from model to model.

\section{DMRG Solver parameters}

\ptexPaste{ParametersDmrgSolver}

\subsection{Finite Loops}

\ptexPaste{FiniteLoop}

\chapter{Output}

\section{Standard Output and Error}
If you run
\begin{verbatim}
./dmrg -f input.inp
\end{verbatim}
you will see messages printed to the log file.
These are processed by the \verb!PsimagLite! class \verb!ProgressIndicator! and
are designed to show the DMRG++ progress.
All these messages are of the form:
\begin{verbatim}
Class [T]: Message
\end{verbatim}
where \verb!Class! is the class that is currently executing and the message hints at
what is being executed. The number \verb!T! between brackets is the wall
time ellapsed since
program start.

After the program finishes, all files are put in a tar file. You can obtain the energies
with
\begin{verbatim}
grep -i energy runForinput.cout
\end{verbatim}

\section{The Disk Stacks}

\section{The Wft Data Files}

\chapter{Measurements}
Both the main dmrg driver and the observe driver (CROSS REFERENCE) may
have a whatToMeasure argument as follows.
\begin{verbatim}
./dmrg -f input.inp whatToMeasure
./observe -f input.inp whatToMeasure
\end{verbatim}
\texttt{whatToMeasure} is a comma separated list of braket specifications:
\texttt{whatToMeasure = braket spec, braket spec, ...}
Braket specifications come in two forms: bare and dressed.

\section{Bare braket specification}
A bare braket specification is a semicolon-separated list of at least one 
operator expressions (opExpr)
\verb!braket spec=opExpr; opExpr; opExpr; ...!
If just one opExpr is given (no semicolon), then the bare braket is referred to as 
``local'' or one-point;
if two opExpr are given (one semicolon), then the bare braket is refererred to as a
two-point correlation; and so on.
Bare brakets cannot be computed directly by DMRG++, but must first be
dressed with a bra and a ket. What bra and ket is chosen is Targeting and context dependent.
Because of this it is recommended to use dressed braket specifications instead.

For GroundStateTargeting, bra and ket are both equal to the current target, usually the ground state,
sometimes only in \emph{WFT} form. But if restarting a run, the current target
can be the state left off by the previous run.

For MettsTargeting and TargetingAncilla,
\verb!<bra|bare braket spec|ket>! is computed multiple times
at each DMRG step for different bra=ket vectors.
These are all the temperature evolved states, and the collapsed state for
MettsTargeting.

For all other targetings, \verb!<bra|bare braket spec|ket>! is computed multiple times
at each DMRG step for different bra=ket vectors, including the 
one corresponding to GroundStateTargeting.
The other vectors bra=ket are either (i) time vectors for TimeStepTargeting,
(ii) dynamic vectors for AdaptiveDynamicTargeting and DynamicTargeting, and
(iii) correction vectors for CorrectionVectorTargeting.

To be able to compute Green functions, TimeStepTargeting computes \emph{in addition}
\verb!<bra|bare braket spec|ket>! with bra not equal to ket:
where bra is the GroundStateTargeting vector, and
ket the first time vector. The same is true for
CorrectionVectorTargeting, where ket is the correction vector.

\section{Dressed braket specification}

Operators in braket specifications may be dressed, as follows.
\begin{verbatim}
./dmrg -f input.inp '<bra|bare braket|ket>,<bra|bare braket|ket>,...'
\end{verbatim}
The opsec was described previously.\footnote{What is new here 
is that bras and kets dress the operators, whereas before,
an automatic dressing procedure was used, choosing what bras and kets to use.}
The bras and kets must be in the set $\{gs, P0, P1, \cdots\}$.
The meaning of $gs$ is context dependent, but often 
refers to the ground state vector, whether freshly computed or WFTed.
``P0'' is (always?) the first targeted vector other than ``gs'', ``P1'' the
next targeted vector, and so on.
FIXME: EXPLORE USE OF DRESSED BRAKETS IN ALL NGSTs.
Bare and dressed braket specifications may \emph{not} be combined.

\section{Operator Expressions}

{\textsc An operator expression} is an algebraic expression involving
floating point numbers and operator specifications or \texttt{opSpec}s.
For example, 
\begin{verbatim}
3*nup + ndown*(1.5*:sz.txt - 3.5*(c?1'*c?1 + I)).
\end{verbatim}
A \emph{canonical operator expression} is an operator expression composed of one or
more canonical operator terms separated by the plus $+$ sign.
A \emph{canonical operator term} is a string that starts with an 
optional canonical scalar,
followed by a star $*$, followed by one or more \texttt{opSpec}s concatenated
by starts $*$.

A canonical scalar is of one the following 
forms.
\begin{enumerate}
\item One or more digits, followed by an optional dot $.$, followed by zero or
more digits. For example, $3.5$, $3.$, $3$.
\item A dot $.$ followed by one or more digits. For example, $.5$.
\item A parenthesis followed by an optional minus sign $-$, 
followed by a scalar prefix of form (1) or (2) above, and ending in a
parenthesis.
For example, $(-3.5)$ $(3)$ $(.5)$ $-(.5)$ $(3.)$ $(-3.)$.
\end{enumerate}
Note that these scalars are \emph{not} canonical: $+3.5$, $(+3.5)$, $-3.5$.
The sample expression above in canonical form is
\begin{verbatim}
3*nup + 1.5*ndown*:sz.txt + (-3.5)*ndown*c?1'*c?1 + 3.5*ndown*I.
\end{verbatim}

\textsc{A} \texttt{opExpr} can be used in the following cases.
(1) In a bare braket spec:
 \texttt{braketSpec = opExpr;opExpr;...}
(2) In a dressed braket spec:
 \texttt{braketSpec =} \texttt{<bra|opExpr;opExpr;...|ket>}.
(3) After the input label \texttt{OperatorExpression=} when
 \texttt{TSPOperator=expression} is specified.
And (4) after the option \verb!-e! in the operator driver.

\emph{Only canonical operator expression have been implemented so far.}

\section{Operator specifications}

There are two kinds of operator specifications: by label and by file.

By label, it is given by \verb!name?dof'[site]!
Name is mandatory; it is a non-empty string \verb![a-zA-Z_]+!, and if the
label ends in underscore \_ then the operator is considered
unnatural.\footnote{Unnatural operators aren't yet implemented.}
Optionally, a site may be specified by enclosing it in brakets.
Optionally, the character ? may be present, and if so, it must
be followed by a non-negative integer \verb![0-9]+! that becomes 
\texttt{dof.}
Optionally, a single quote ' may be present at the end, to mean
that the whole operator must be transposed.
The operator is obtained by calling the model member function
\verb!naturalOperator! with arguments
\verb!(name,site,dof)! and optionally transposing it. Defaults
values of \verb!site! and \verb!dof! are 0.
Note that the fermion sign and the $SU(2)$ properties of the
resulting operator are determined by the member function in
the corresponding model class.

By file, it is given by \verb!:filename!,
where filename must be a non-empty string. Every occurrence (if any)
 of the character \$ in filename is replaced by the current site.
The resulting string names a file that must exist and be
readable by the DMRG++ process owner. The file must contain an
operator in file form; the format of this file is given by the
following items, in order.

\begin{itemize}
\ptexPaste{Operator}
\end{itemize}

\section{The operator Driver}\label{sec:operator}
The operator driver may be used to produce an operator by file.
\ptexPaste{OperatorDriver}

\chapter{Post Processing}

\section{The Observer Driver}\label{sec:observe}
\ptexPaste{ObserveDriver}

\section{The DMRG ToolBox Driver}\label{sec:toolbox}
\ptexPaste{ToolboxDriver}
\ptexPaste{ToolBoxActions}

\chapter{Miscellanea}

\section{Restarting a run}

\section{The TestSuite}

\section{Signals}

\ptexPaste{RegisterSignals}

\chapter{Developer's Guide}

\section{Main Driver}
The high level program is this
\begin{lstlisting}
//! Setup the Model
ModelType model(mp,dmrgGeometry);

//! Setup the dmrg solver:
SolverType dmrgSolver(dmrgSolverParams,model,concurrency);

//! Perform DMRG Loops:
dmrgSolver.main();
\end{lstlisting}

\todo{Graphic showing the template dependencies of the classes}

\section{DMRG Engine}
\subsection{DMRG Algorithm}
Let us define {\it block} to mean a finite set of sites.
Let $C$ denote the states of a single site. This set is model dependent. For the
Hubbard model it is given by:
$C=\{e,\uparrow,\downarrow,(\uparrow,\downarrow)\}$, where $e$ is a formal element that
denotes an empty state.
For the t-J model it is given by  $C=\{e,\uparrow,\downarrow\}$, and for the Heisenberg
model by  $C=\{\uparrow,\downarrow\}$.
A {\it real-space-based Hilbert space} $\mathcal{V}$ on a block $B$ and  set $C$ is a
 Hilbert space with basis $B^{C}$.  I will simply denote this as $\mathcal{V}(B)$ and
 assume that $C$
 is implicit and fixed.
A {\it real-space-based Hilbert space} can also be thought of as the external product
space of $\#B$ Hilbert spaces on a site, one for each
 site in block $B$.
We will consider general Hamiltonians   that
 act on Hilbert spaces $\mathcal{V}$, as previously defined.

\ptexPaste{DmrgSolverInfiniteDmrgLoop}
\ptexPaste{DmrgSolverFiniteDmrgLoops}

The advantage of the DMRG algorithm is that the truncation procedure described
above keeps the error bounded and small.
Assume $m_S=m_E=m$.
At each DMRG step\cite{re:dechiara08} the truncation error
$\epsilon_{tr}=\sum_{i>m} \lambda_i$, where $\lambda_i$ are the eigenvalues of the
truncated density matrix $\rho_S$ in decreasing order. The parameter $m$ should
be chosen such that $\epsilon_{tr}$ remains small, say \cite{re:dechiara08}
$\epsilon_{tr}<10^{-6}$. For critical 1D systems $\epsilon_{tr}$ decays as a function
of $m$ with a  power law, while for 1D system
away from criticality it decays exponentially. For a more detailed description of
the error introduced by the DMRG truncation in other
systems see \cite{re:dechiara08,re:schollwock05,re:hallberg06,re:rodriguez02}.

\subsection{Driver Program}
Let us motivate the discussion by introducing a typical problem to be solved by
DMRG: ``Using the DMRG method,
one would like to calculate the local density of states on all sites for a Hubbard
model with
inhomogeneous Hubbard U values on a one-dimensional (1D) chain''.
We want to modularize as many tasks mentioned in the last sentence as possible.
We certainly want to separate the DMRG solver from the model in question,
since we could later want to do the same calculation for the t-J model; and
the model from the lattice, since we might want to do the same calculation on, say,
a n-leg ladder, instead of a 1D chain.
C++ is a computer language that is very fit for this purpose, since it allows to
template classes.
Then we can write a C++ class to implement the DMRG method (\cppClass{DmrgSolver}
class),  and template this class
on a strongly-correlated-electron (SCE) model template, so that we can delegate all
SCE model related code to the SCE model class.

However, for DmrgSolver to be able to use a given SCE model, we need a convention
that such SCE model class
will have to follow.
This is known as a C++ public interface, and for a SCE model it is given in
\cppClass{DmrgModelBase}.
To do the calculation for a new SCE model, we simply need to
 implement all functions found in \cppClass{DmrgModelBase}  \emph{without}
 changing the \cppClass{DmrgSolver} class.
The model will, in turn, be templated on the geometry. For example,
the Hubbard model  with
inhomogeneous Hubbard U values and inhomogeneous hoppings
(class \cppClass{DmrgModelHubbard})
delegates all geometry related operations to a templated geometry class.
Then \cppClass{DmrgModelHubbard} can be used for, say, one-dimensional
chains and n-leg ladders \emph{without} modification.
This is done by just instantiating
 \cppClass{DmrgModelHubbard} with the appropriate
geometry class, either \cppClass{DmrgGeometryOneD} or
\cppClass{DmrgGeometryLadder}, or some other class that the reader may wish
to write, which implements the interface given in
\cppClass{DmrgGeometryBase}.
\todo{Add figure showing interfaces}

In the following sections I will describe these different modules. Since the reader
may wish to first understand how the DMRG method is implemented, I will
start with the core C++ classes that implement the method.
The user of the program
will not need to change these core classes to add functionality. Instead,
new models and geometries can be added by creating implementations
for \cppClass{DmrgModelBase} and \cppClass{DmrgGeometryBase}, and
those public interfaces will be explained next.

But for now I end this section by briefly describing the ``driver'' program
for a Hubbard model on a 1D chain (see file \verb!dmrg.cpp!).
There, \cppClass{DmrgSolver} is instantiated with \cppClass{DmrgModelHubbard},
since in this case one wishes to perform the calculation for the Hubbard model.
In turn, \cppClass{DmrgModelHubbard}  is instantiated with
\cppClass{DmrgGeometryOneD} since now one wishes to perform the calculation on a 1D chain.

\todo{Expand the driver explanation}

\subsection{DmrgSolver and The ``Infinite'' DMRG Algorithm}
The purpose of the \cppClass{DmrgSolver} class is to perform  the loop
for the DMRG ``infinite algorithm'' discussed before.
This class  also performs
the ``finite algorithm''  \cite{re:schollwock05} to allow for the
calculation of static (and in the future dynamic)
observables, such as static correlations.

The program is structured as a series of header files containing the
implementation\footnote{Traditionally, implementation is written in cpp files
that are compiled separately. However, here templates
are used heavily, and to avoid complications related to templates that some
C++ compilers cannot handle,
 we choose to have only one translation unit.} with each class written
 in the header file of the same name,
 and a ``driver'' program that uses the
capabilities provided by the header files to solve a specific problem.
To simplify the discussion, we start where the ``driver program'' starts,
in its \cppFunction{int main()} function,
which calls \cppFunction{dmrgSolver.main()}, whose main work is to perform
the loop for the
``infinite'' DMRG algorithm. Let us now discuss this loop which is found in
the \cppFunction{infiniteDmrgLoop} function,
and is sketched in Fig.~\ref{fig:infiniteloop}.

\begin{figure}
\begin{lstlisting}
for (step=0;step<X.size();step++) {
  // grow system (a)
  lrs_.growLeftBlock(model_,pS,X[step]);
  // grow environment (b)
  lrs_.growRightBlock(model_,pE,Y[step]);
  // product of system and environment (c)
  lrs_.setToProduct(quantumSector_);

  diagonalization_(psi,INFINITE,X[step],Y[step]); (d)
  truncate_(pS,psi,parameters_.keptStatesInfinite,EXPAND_SYSTEM); (e)
  truncate_(pE,psi,parameters_.keptStatesInfinite,EXPAND_ENVIRON); (f)

  checkpoint_.push(pS,pE); //(g)
}
\end{lstlisting}
\caption{\label{fig:infiniteloop}Implementation of the ``infinite'' DMRG loop
for a general SCE model
 on a general geometry.}
\end{figure}
%Again have in mind that the geometry is shown schematically in Figure~\ref{fig:sxye}.
In Fig.~\ref{fig:infiniteloop}(a) the system pS is grown by adding the sites
contained in block X[step]. Note that X is a vector of blocks to
be added one at a time\footnote{So X is a vector of vector of integers, and
X[step] is a vector of integers.}.  The block X[step] (usually just a single site)
is  added \emph{to the right of} pS.  The result is stored in \verb!lrs_.left()!.
Similarly is done in Fig.~\ref{fig:infiniteloop}(b) for the environment:
the block Y[step]  (usually just a single site) is added to the environment
 given in pE and stored in \verb!lrs_.right()!.
This time the addition is
done \emph{to the left of} pE, since pE is the environment.
In Fig.~\ref{fig:infiniteloop}(c) the outer product of \verb!lrs_.left()!
(the new system) and \verb!lrs_.right()! (the new environment) is made and stored in pSE.
The actual task is delegated to the \cppClass{Basis} class
(see Section~\ref{sec:dmrgbasis}).
In Fig.~\ref{fig:infiniteloop}(d) the diagonalization of the Hamiltonian for block pSE
is performed,
and the ground state vector is computed and stored in psi, following Eq.~(\ref{eq:psi}).
The object called concurrency is used to handle parallelization over matrix blocks
related to symmetries present in the model (see section).
Next, in Fig.~\ref{fig:infiniteloop}(e) the bases are changed
following Eqs.~(\ref{eq:rhoSystem},\ref{eq:rhoEnviron}),
truncated if necessary, and the result is stored in
pS for the system, and in pE, Fig.~\ref{fig:infiniteloop}(f),
for the environment. Note that this overwrites the old pS and pE, preparing these
variable for the next DMRG step.

A copy of the current state of the system is pushed into a last-in-first-out stack
in Fig.~\ref{fig:infiniteloop}(g),
so that it can later be used in the finite DMRG algorithm (not discussed here, see code).
The loop continues until all blocks in vector of blocks X have been added to the initial
system S, and all blocks in vector of blocks Y have been added to
the initial environment E. We repeat again that  vector of sites are used instead of
simply sites to generalize the growth process,
in case one might want to add more than one site at a time.

The implementation of
the steps mentioned in the previous paragraph (i.e., growth process,  outer products,
diagonalization, change of basis and truncation)
are described in \todo{FIXME}.

\subsection{Finite Algorithm}

\section{Hilbert Space Basis I: DmrgBasis and Symmetries}\label{sec:dmrgbasis}

\subsection{Local Symmetries}
DMRG++ has two C++ classes that handle the concept of a basis (of a Hilbert space).
The first one (\cppClass{DmrgBasis}) handles reordering
and symmetries in a general way, without the need to consider operators.
The second one (\cppClass{DmrgBasisWithOperators})  does consider operators, and
will be explained in
the next sub-section. The advantage of dividing  functionality in this way will
become apparent later.

In any actual computer simulation the ``infinite'' DMRG loop will actually stop at
a certain point.
Let us say that it stops after 50 sites have been added to the
system\footnote{For simplicity, this explanatory text considers the case of
blocks having a single site, so one site is added at a time, but a more general
case can be handled by the code.}.
There will also be at this point another 50 sites that constitute the environment.
Now, from the beginning each of these 100 sites is given a fixed number from 0 to 99.
Therefore, sites are always labeled in a fixed way and
their labels are always known (see Fig.~\ref{fig:sxye}).
\ptexPaste{BasisBlock}

%\ptexPaste{Basis}

\ptexPaste{BasisQuantumNumbers}

\ptexPaste{BasisPermutationVector}

\ptexPaste{BasisPartition}

\ptexPaste{BasisSetToProduct}

\subsection{Product of Spaces}
If $\mathcal{V}_1$ is a Hilbert space of dimension $n_1$, and $\mathcal{V}_2$ is a
Hilbert space of dimension $n_2$, then a
state $\psi\in\mathcal{V}_1\otimes\mathcal{V}_2$ is given by:
$\psi_{\alpha,\beta}$ with $\alpha\in\mathcal{V}_1$ and $\beta\in\mathcal{V}_2$. In
DMRG++ a single index is used to ``pack''
$\alpha$ and $\beta$ together, like this $\alpha + n_1 \beta$ (you can prove that this
is a bijection from
$(\alpha,\beta)\longleftrightarrow \alpha + n_1 \beta$. This isn't the complete packing,
however, because we need to reorder
the states for symmetry reasons. We use then a permutation (actually it's the inverse
permutation in the code) $P^{-1}$.
Putting all together you get
$\psi_i$,  with  $i=P^{-1}(\alpha + n_1 \beta)$. I like to write it more formally
with a Kronecker delta, like this:
$\sum_{i}\psi_i \delta_{P(i),\alpha+n_1\beta}$. Note how, for fixed $\alpha$ and
$\beta$, the $\delta$ picks up the correct
(packed and permuted) index $i$.


\subsection{Left, Right, and Super}
In standard DMRG, states are decomposed into left, right and super[block] spaces.
The left and right spaces are further decomposed
into a block plus a site, on the left side; and site plus a block, on the right side.
There are then 3 products of spaces, giving
rise to 3 packings  and 3 permutations. I use the notations $P_S$, $P_E$, and $P_{SE}$,
respectively (or its inverses).
The words left and system, right and environment, and super[block] and
system-environment are used interchangably in the code.

Consider the system or left block $\mathcal{S}$ as $\mathcal{S'}$ plus a site, like this:
$\mathcal{S}=\mathcal{S'}\otimes\mathcal{V}_1$. Consider an operator $A_{x_1,x_1'}$
acting on the space of one site,
$\mathcal{V}_1$ such that both $x_1,x_1'\in\mathcal{V}_1$. Consider the superblock
$\mathcal{S'}\otimes\mathcal{V}_1\otimes\mathcal{E}\equiv\mathcal{S}\otimes\mathcal{E}$.
Consider a state on the superblock $\psi$. Then the $j-$th component of $A\psi$ is
\begin{eqnarray}
(A\psi)_j &=& \sum \delta_{P_{SE}(i),x+y n_s} \delta_{P_S(x),x0+x1 n_0)} A_{x_1,x_1'} \\
& & \delta_{x',P_S^{-1}(x0+x1' n_0)}  \delta_{j,P_{SE}^{-1}(x'+y'n_s)}  \psi_i  f_S(x)
\end{eqnarray}
A sum over all indices except $j$ is assumed.
Let's analyze this. Because $i$ is in the superblock, it's packed and permuted,
so we have to unpack it and un-permute it, that is,
find $x\in\mathcal{S}$ and $y\in\mathcal{E}$
that correspond to it. Formally, in the equation in this paper, the delta picks up
the right
one: $\delta_{P_{SE}(i),x+y n_s}$. In the code we simply apply the permutation
$P_{SE}$ to $i$ and then divide
by $n_s$. The quotient is $y$ and the remainder is $x$.  Now, $A$ does not act on
$\mathcal{E}$, so $y$ will remain the same.
But $x\in\mathcal{S'}\otimes\mathcal{V}_1$, so again, we need to unpack it and
un- permute it. That's what the next delta,
$\delta_{P_S(x),x0+x1 n_0}$ does. Note that now the permutation is
$P_S$ as opposed to $P_{SE}$. We are ready now to apply $A$, with
$A_{x_1,x_1'}$.

Next, the reverse procedure must be applied. We need to pack $x_0 ,x_1',y$
into a single index and perform all permutations. We do this in two stages
(two $\delta$s).
The first one does $x_0,x_1'$ into $x'$, the second one $x',y$ into $j$,
which is the free index.

In the above, I left out a few complications, which I will now attend to.

\subsubsection{Fermionic Sign}
To apply $A_{x_1,x_1'}$ to $(x_0,x_1)$ we need to step over $x_0$, that is,
the space  $\mathcal{S'}$. If $A$ is fermionic we might pick up a sign.
This sign will be equal to 1 if the number of electrons of state $x_0$ is even,
and -1 otherwise. This is represented by $ f_S(x)$ in the equation above.

\subsubsection{Vectors in chunks}
Because of symmetry, the vector $\psi$ has only one (or a few) non-zero chunks.
Then we ought not to loop or sum over the whole superblock like in $\sum_i$.
Instead, we need to only loop or sweep or sum over the non-zero chunk(s).
This is easily taken care of by storing the partition of the superblock, and is mostly
straightforward, except that there is one complication we must attend to.
For simplicity, assume that $\psi$ has only one chunk. Then if the resulting $j$ is
outside $\psi$'s chunk, $A\psi$ and $\psi$ will have
different symmetries, and $A\psi$ will need to be stored in a different chunk.
The DMRG++ class \verb!VectorWithOffsets! does this transparently.
For performance reasons, there
is also a \verb!VectorWithOffset! class to use when we know $A$ does not transport
$\psi$ into a different symmetry chunk.

\subsubsection{Sparse matrices}
The matrix $A$ is usually stored in a sparse format. DMRG++ uses compressed
row storage (CRS, REFERENCE HERE FIXME). Therefore the looping is done according
to the CRS scheme.
See the loop in \verb!ApplyOperatorLocal.h!, line 155 or whereabouts.
\subsection{SU(2) Symmetry}

\section{Hilbert Space Basis II: DmrgBasisWithOperators}
\subsection{Outer Product of Operators}\label{subsec:dmrgBasisWithOperators}
\ptexPaste{BasisWithOperators}

Let us now go back to the ``infinite'' DMRG loop and discuss in more detail
Fig.~\ref{fig:infiniteloop}(a) ((b) is similar)), i.e.,
the function grow().

\ptexPaste{LeftRightSuperGrow}

\ptexPaste{OperatorsExternalProduct}

\ptexPaste{Operators}

Let us now examine in more detail Fig.~\ref{fig:infiniteloop}(c), where
we form the outer product of the current system and current environment,
and calculate its Hamiltonian.
We could use the same procedure as outlined in the previous paragraph, i.e.,
to use the DmrgBasisWithOperators class
to resize the matrices for all local operators.
Storing matrices in this case (even in a sparse way and even considering that
there is truncation) would be too much of
a penalty for performance. Therefore, in this latter case we do the outer product
on-the-fly only, without storing any matrices.
In Fig.~\ref{fig:infiniteloop}(c)  pSE contains the outer product
of system and environment, but pSE is only a \cppClass{Basis} object, not a
\cppClass{BasisWithOperators} object, i.e., it does not
contain operators. In the code see \cppFunction{setToProductSolver}, and
\cppFunction{setToProductLrs}.

We now consider Fig.~\ref{fig:infiniteloop}(d), where the diagonalization of the
system's plus environment's Hamiltonian is performed.
Since \verb!lrs_.super()!, being only a \cppClass{Basis} object, does not contain
all the information related to the outer product of system and environment
(as we saw, this would be prohibitively expensive), we need to pass
the system's basis (pSprime) and the environment's basis (pEprime) to
the diagonalization functor \cppFunction{diagonalization\_()}, see
\cppFunction{Diagonalization}, in order to be able to form the outer product on-the-fly.
There,  since \verb!lrs_.super()! does provide information about effective symmetry
blocking, we block the Hamiltonian matrix using effective symmetry,
and call  \cppFunction{diagonaliseOneBlock()}, see  \cppFunction{diagonaliseOneBlock},
for each symmetry block. Only those matrix blocks
that contain the desired or targeted number of electrons (or other local symmetry)
will be considered.

\subsection{Truncation}
\ptexPaste{Truncation}
\ptexPaste{DiagOfDensityMatrix}

\subsection{Lanczos Solver}\label{sec:lanczos}
To diagonalize Hamiltonian $H$ we use the Lanczos
method\cite{re:lanczos50,re:pettifor85}, although this is also templated.

For the Lanczos diagonalization method we also want to provide as much code
isolation and modularity as possible.
The Lanczos method needs only to know how
to perform the operation $x+=Hy$, given vectors $x$ and $y$. Using this fact,
we can separate the matrix type from the Lanczos method.
To keep the discussion short this is not addressed here, but can be seen in
the \cppFunction{diagonaliseOneBlock()} function, and in
classes \cppClass{SolverLanczos}, \cppClass{HamiltonianInternalProduct},
and \cppClass{DmrgModelHelper}.
The first of these classes contains an implementation of the Lanczos method
that is templated on
a class that simply has to provide the operation $x+=Hy$ and, therefore, it
is generic and valid for any SCE model.
It is important to remark that the operation  $x+=Hy$ is finally delegated to the
model in question.
As an example,  the operation $x+=Hy$ for the Hubbard model is performed in
function \cppFunction{matrixVectorProduct()} in class \cppClass{DmrgModelHubbard}.
This function performs only three tasks: (i)  $x+=H_{system}y$, (ii)
$x+=H_{environment}y$ and (iii) $x+=H_{connection}y$.
The fist two are straightforward, so we focus on the last one, in
\cppFunction{hamiltonianConnectionProduct()},
that considers the part of the Hamiltonian
that connects system and environment. This function runs the following loop:
for every site $i$ in the system and every site $j$ in the environment
it calculates $x+=H_{ij}y$ in function \cppFunction{linkProduct}, after finding
the appropriate tight binding hopping value.

The function \cppFunction{linkProduct} is useful not only for the Hubbard model, but it is
 generic enough to use in other SCE models that include a tight binding connection
 of the type $c^\dagger_{i\sigma}c_{j\sigma}$,
  and, therefore, is part of a separate class,
 \cppClass{ConnectorHopping}. Likewise, the function \cppFunction{linkProduct}
 in \cppClass{ConnectorExchange} deals
 with Hamiltonian connections of the type $\vec{S}_i\cdot\vec{S}_j$, and
 can be used by models that include that type of term, such as the
 sample Heisenberg model provided with DMRG++.
We remind readers that wish to understand this code that the function
\cppFunction{linkProduct} and, in particular, the
related function \cppFunction{fastOpProdInter} are more complicated than usual,
since (i) the outer product is constructed on the fly, and (ii)
the resulting states of this outer product need to be reordered so that effective
symmetry blocking can be used.

\section{Model Interface}\label{subsec:models}
\subsection{Abstract Interface}
\ptexPaste{ModelInterface}

\subsection{Heisenberg Model}
\subsection{One-Orbital Hubbard Model}
\subsection{Many-Orbital Hubbard Model}
\subsection{t-J model}

\section{Geometry Interface} \label{subsec:geometries}
\subsection{Abstract Interface}
I present two sample geometries, one for 1D chains and one for n-leg ladders in
classes \cppClass{DmrgGeometryOneD}
 and \cppClass{DmrgGeometryLadder}.
Both derive from the abstract class \cppClass{DmrgGeometryBase}.
To implement new geometries a new class needs to be derived from this base class,
and the functions in the base class (the interface) needs to be implemented.
As in the case of \cppClass{DmrgModelBase}, the interface is documented in the code,
but here I briefly describe the most important functions.

The function \cppFunction{setBlocksOfSites}
 needs to set the initial block for system and environment, and for the vector of
 blocks $X$ and $Y$ to be added
to system and environment, respectively, according to the convention given in
Fig.~\ref{fig:sxye}.
There are two \cppFunction{calcConnectorType} functions. Both calculate the type of
connection between two sites $i$ and $j$,
which can be SystemSystem, SystemEnviron,
EnvironSystem or EnvironEnviron, where the names are self-explanatory. The
function \cppFunction{calcConnectorValue}
 determines the value of the connector (e.g., tight-binding hopping for the
 Hubbard model or $J_{ij}$ for the
 case of the Heisenberg model) between two sites, delegating
the work to the model class if necessary.  The function
\cppFunction{findExtremes} determines the
extremes sites of a given block of sites and
the function \cppFunction{findReflection} finds the ``reflection'' in the
environment block of a given site in the system block or vice-versa.

\subsection{One Dimensional Chains}
\subsection{Ladders}

\section{Concurrency Interface: Code Parallelization} \label{subsec:concurrency}
\subsection{Abstract Interface}
The \cppClass{Concurrency} class encapsulates parallelization. Two concrete classes
that implement this interface
are included in the present code. One is for serial code (\cppClass{ConcurrencySerial}
class) that does no parallelization at all, and the other one
(\cppClass{ConcurrencyMpi} class)  is for
parallelization based on the MPI\footnote{See, for example,
http://www-unix.mcs.anl.gov/mpi/}.
Other parallelization implementations, e.g. using pthreads, can be similarly
written by implementing this interface.
The interface is described in place in class \cppClass{Concurrency}.
Here, I briefly mention its most important functions. Function \cppFunction{rank()}
returns the rank of the current processor or thread.
\cppFunction{nprocs()} returns the total number of processors.
Functions \cppFunction{loopCreate()} and \cppFunction{loop()} handle a parallelization
of a standard loop.
Function \cppFunction{gather()} gathers data from each processor into the root processor.

\subsection{MPI}
\subsection{Pthreads}
\subsection{CUDA}

\section{Input and Output}

\subsection{Input System}

\subsection{DiskStack}

\subsection{Program Output}

\subsection{Test Suite}

\section{Optimizations}
\subsection{Wave Function Transformation}
I will describe the WFT when shrinking the system. The implementation of this is
in class \cppClass{WaveFunctionTransformation}. Here I focus on the system
without SU(2) symmetry support first.
We need to consider that site $j$ has just been swallowed by the growing environment.
See figure~\ref{fig:wft} for the setup.
\begin{figure}[b]
\centering{
\includegraphics[width=4cm]{wft}}
\caption{TBW.\label{fig:wft}}
\end{figure}
Latin letters label points, Greek letters label states.
The sub-index $p$ indicates the newest DMRG step.
The approximate guess for the new wave-function $\psi^p_{\eta_p}$ is given in
terms of the previous
wave-function $\psi_{\eta}$ by:
\begin{equation}
\psi^p_{\eta_p} =
W^S_{\alpha,\epsilon}\psi_{\eta}W^E_{\beta,\beta_p}
\delta_{P^{SE}(\eta);\epsilon+\beta n_0}
\delta_{P^S(\alpha);\alpha_{p}+\kappa_{p}n_1}
\delta_{P^S_p(\eta_p);\alpha_p+\gamma_p n_2}
\delta_{P^E_p(\gamma_p);\kappa_p+\beta_p n_3},
\end{equation}
where the system transformation is $W^S$, the environment transformation is $W^E$,
the new system-environment permutation $P^{SE}_p$, the new environment
permutation $P^E_p$,
the old system-environment permutation $P^{SE}$, and the new system permutation $P^S$.
A sum should be assumed for all indices except $\eta_p$.
\pagebreak

Here are formulas for WFT when expanding system.
\begin{equation}
\psi^{\text{new}}(i, k; j) = \sum_{i', j'} W_S^{T}(i, i') \psi^{\text{old}}(i', j')W_E^{T}(j'; k, j)
\,\,\,\text{one-site DMRG}
\end{equation}
%
\begin{equation}
\psi^{\text{new}}(i, k, j) = \sum_{i', j'} W_S^{T}(i, i') \psi^{\text{old}}(i', k, j')W_E^{T}(j', j)
\,\,\,\text{two-site DMRG}
\end{equation}

\todo{Write equivalent formulas when expanding environ.}

\subsection{SU(2) Reduced Operators}

\subsection{Checkpointing}
Let's say you want to first run 3 moves on a 16-site lattice:
\verb=7 100 0 -5 100 0 -2 100 0=, and then continue it with 2 more
\verb=-7 200 0 7 200 0=. Then one needs to set up input files as in
\verb=TestSuite/inputs/input23.inp=
and
\verb=TestSuite/inputs/input24.inp=.
Compile and do the first run:
\begin{verbatim}
cd src/
perl configure.pl < ../TestSuite/inputs/model23.spec
(or say ModelHeisenberg and DiskStack)
make
./dmrg ../TestSuite/inputs/input23.inp
\end{verbatim}
You are ready for the continuation of this run now with:
\begin{verbatim}
./dmrg ../TestSuite/inputs/input24.inp
\end{verbatim}
Note that the continued run's input (\verb=input24.inp=) has the option checkpoint,
and the CheckpointFilename tag.
Continued (raw) results will be in file \verb=data24= as usual.

Note the following caveat or ``todo'':
\begin{itemize}
\item There's no check (yet) of finite loops for consistency while checkpoint is in use.
Therefore, make sure the second run is starting at a point on the lattice where the
previous to-be-continued run left off.
\end{itemize}

\subsection{Distributed Parallelization}
\subsection{Shared-memory Parallelization}

\section{Static Observables}
A quick run with the calculation of static observables can be done like so:
\begin{verbatim}
cd src/
perl configure.pl
(all default answers here)
make
make observe
./dmrg ../TestSuite/input2.inp
./observe ../TestSuite/input2.inp data2.txt
\end{verbatim}
You will see something like this:
\begin{verbatim}
OperatorC:
8 16
0.5 0.426244 -2.84172e-08 ...
0 0.5 -0.252775 1.67222e-07 0.0586682 ...
...
\end{verbatim}
Here we are computing $C_{ij} = \langle c_{i\uparrow}c_{j\uparrow}\rangle$,
where $8 16$ are the dimensions of the matrix
that follow ($C_{ij}$ is not computed for $i>j$).
For example $C_{00}=0.5$, $C_{01}=0.426244$, $C_{12}=-0.252775$.

The same is done for $N_{ij} = \langle n_{i}n_{j}\rangle$, where
$n_i = n_{i\uparrow}+n_{i\downarrow}$, and also for $\langle S_{i}^zS_{j}^z\rangle$

The observer driver (\verb=observe.cpp=) controls what is calculated.
Please have a look at it and modify as necessary.

\todo{THIS SECTION NEEDS MORE WORK. IN PARTICULAR HOW TO SETUP THE INPUT FILE
TO BE ABLE TO PRODUCE DATA FOR THE OBSERVER.}


\subsection{Ground State Energy and Error}
\subsection{Static Correlations}
\subsection{Observables Driver}

\section{Time Evolution}
\subsection{Time Evolution Input}
\begin{itemize}
\ptexPaste{TargetParamsTimeVectors}
\ptexPaste{TargetParamsCommon}
\end{itemize}

\section*{LICENSE}
\begin{verbatim}
\ptexReadFile{../src/LICENSE}
\end{verbatim}
\bibliographystyle{plain}
\bibliography{thesis}
\end{document}
