TBTK
Need a break? Support the development by playing Polarity Puzzles
TBTK::Solver::BlockDiagonalizer Class Reference

Solves a block diagonal Model using diagonalization. More...

#include <BlockDiagonalizer.h>

Inheritance diagram for TBTK::Solver::BlockDiagonalizer:
TBTK::Solver::Solver TBTK::Communicator

Classes

class  SelfConsistencyCallback
 

Public Member Functions

 BlockDiagonalizer ()
 
void setSelfConsistencyCallback (SelfConsistencyCallback &selfConsistencyCallback)
 
void setMaxIterations (int maxIterations)
 
void run ()
 
const double getEigenValue (int state)
 
const double getEigenValue (const Index &blockIndex, int state)
 
const std::complex< double > getAmplitude (int state, const Index &index)
 
const std::complex< double > getAmplitude (const Index &blockIndex, int state, const Index &intraBlockIndex)
 
unsigned int getFirstStateInBlock (const Index &index) const
 
unsigned int getLastStateInBlock (const Index &index) const
 
void setParallelExecution (bool parallelExecution)
 
- Public Member Functions inherited from TBTK::Solver::Solver
 Solver ()
 
virtual ~Solver ()
 
virtual void setModel (Model &model)
 
ModelgetModel ()
 
const ModelgetModel () const
 
- Public Member Functions inherited from TBTK::Communicator
 Communicator (bool verbose)
 
void setVerbose (bool verbose)
 
bool getVerbose () const
 

Additional Inherited Members

- Static Public Member Functions inherited from TBTK::Communicator
static void setGlobalVerbose (bool globalVerbose)
 
static bool getGlobalVerbose ()
 

Detailed Description

Solves a block diagonal Model using diagonalization.

Solves a Model by Diagonalizing the Hamiltonian. Is similar to Diagonalizer, but is able to take advantage of a Hamiltonian's block diagonal structure. Use PropertyExtractor::BlockDiagonalizer to extract Properties.

The BlockDiagonalizer is able to take advantage of a Model's block diagonal structure if the Subindices that the Model is block diagonal in appear to the left of Subindices that are not block indices. Therefore, if for example kx, ky, and kz are block labels, while sublattice and orbital are not, make sure the Model is specified such that the Index structure is {kx, ky, kz, sublattice, orbital} rather than {sublattice, orbital, kx, ky, kz}.

Scaling behavior:
If the Model has no blocks, the scaling behavior is the same as for the Diagonalizer, but with a larger prefactor. If the Model consists of \(b\) blocks, each of dimension \(h\), the scaling behavior is:
Time: \(O(nh^3)\)
Space: \(O(nh^2)\)

If the Model consists of \(b\) blocks of varying size, the above scaling behavior instead becomes an upper bound, with \(h\) the maximum block dimension.

Example

#include "TBTK/Array.h"
#include "TBTK/Model.h"
#include "TBTK/PropertyExtractor/BlockDiagonalizer.h"
#include "TBTK/Solver/BlockDiagonalizer.h"
#include "TBTK/Streams.h"
#include "TBTK/TBTK.h"
#include <complex>
using namespace std;
using namespace TBTK;
int main(){
Model model;
//Block 0.
model << HoppingAmplitude(1, {0, 0}, {0, 1});
model << HoppingAmplitude(1, {0, 1}, {0, 0});
//Block 1.
model << HoppingAmplitude(2, {1, 0}, {1, 1});
model << HoppingAmplitude(2, {1, 1}, {1, 0});
model.construct();
solver.setVerbose(true);
solver.setModel(model);
solver.run();
PropertyExtractor::BlockDiagonalizer propertyExtractor(solver);
Streams::out << "----------------\n";
//Blockwise access.
Array<double> eigenValues({2, 2});
Array<complex<double>> eigenVectors({4, 2});
for(unsigned int block = 0; block < 2; block++){
for(unsigned int state = 0; state < 2; state++){
eigenValues[{block, state}]
= propertyExtractor.getEigenValue(
{block},
state
);
for(unsigned int n = 0; n < 2; n++){
eigenVectors[{2*block + state, n}]
= propertyExtractor.getAmplitude(
{block},
state,
{n}
);
}
}
}
Streams::out << eigenValues << "\n";
Streams::out << eigenVectors << "\n";
Streams::out << "----------------\n";
//Global access.
eigenValues = Array<double>({4});
eigenVectors = Array<complex<double>>({4, 4});
for(
unsigned int state = 0;
(int)state < solver.getModel().getBasisSize();
state++
){
eigenValues[{state}] = propertyExtractor.getEigenValue(state);
for(unsigned int block = 0; block < 2; block++){
for(unsigned int n = 0; n < 2; n++){
eigenVectors[{state, 2*block + n}]
= propertyExtractor.getAmplitude(
state,
{block, n}
);
}
}
}
Streams::out << eigenValues << "\n";
Streams::out << eigenVectors << "\n";
}

Output

Initializing BlockDiagonalizer
Basis size: 4
Hamiltonian size: 1536B
Eigenvectors size: 128B
Number of blocks: 2
Running Diagonalizer
.
----------------
[[-1, 1]
[-2, 2]]
[[(-0.707107,0), (0.707107,0)]
[(0.707107,0), (0.707107,0)]
[(-0.707107,0), (0.707107,0)]
[(0.707107,0), (0.707107,0)]]
----------------
[-1, 1, -2, 2]
[[(-0.707107,0), (0.707107,0), (0,0), (0,0)]
[(0.707107,0), (0.707107,0), (0,0), (0,0)]
[(0,0), (0,0), (-0.707107,0), (0.707107,0)]
[(0,0), (0,0), (0.707107,0), (0.707107,0)]]

Constructor & Destructor Documentation

◆ BlockDiagonalizer()

TBTK::Solver::BlockDiagonalizer::BlockDiagonalizer ( )

Constructs a Solver::Diagonalizer.

Member Function Documentation

◆ getAmplitude() [1/2]

const std::complex< double > TBTK::Solver::BlockDiagonalizer::getAmplitude ( int  state,
const Index index 
)
inline

Get amplitude for given eigenvector \(n\) and physical index \(x\): \(\Psi_{n}(x)\).

Parameters
stateEigenstate number \(n\).
indexPhysical index \(x\).
Returns
The amplitude \(\Psi_{n}(\mathbf{x})\).

◆ getAmplitude() [2/2]

const std::complex< double > TBTK::Solver::BlockDiagonalizer::getAmplitude ( const Index blockIndex,
int  state,
const Index intraBlockIndex 
)
inline

Get amplitude for given eigenvector \(n\), block index \(b\), and physical index \(x\): \(\Psi_{nb}(x)\).

Parameters
blockIndexBlock index \(b\)
stateEigenstate number \(n\) relative to the given block.
indexPhysical index \(x\).
Returns
The amplitude \(\Psi_{nb}(\mathbf{x})\).

◆ getEigenValue() [1/2]

const double TBTK::Solver::BlockDiagonalizer::getEigenValue ( int  state)
inline

Get eigenvalue. The eigenvalues are ordered first by block, and then in accending order. This means that eigenvalues for blocks with smaller Indices comes before eigenvalues for blocks with larger Indices , while inside each block the eigenvalues are in accending order.

Parameters
stateThe state number.
Returns
The eigenvalue for the given state.

◆ getEigenValue() [2/2]

const double TBTK::Solver::BlockDiagonalizer::getEigenValue ( const Index blockIndex,
int  state 
)
inline

Get eigenvalue for specific block. Note that in contrast to getEigenValue(int state), 'state' here is relative to the first state of the block.

Parameters
blockIndexBlock index to get the eigenvalue for.
stateState index relative to the block in accending order.
Returns
The eigenvalue for the given state in the given block.

◆ getFirstStateInBlock()

unsigned int TBTK::Solver::BlockDiagonalizer::getFirstStateInBlock ( const Index index) const
inline

Get first state in the block corresponding to the given Index.

Parameters
indexA physical Index.
Returns
The global state index for the first state that belongs to the block for which the given Index is part of the basis.

◆ getLastStateInBlock()

unsigned int TBTK::Solver::BlockDiagonalizer::getLastStateInBlock ( const Index index) const
inline

Get last state in the block corresponding to the given Index.

Parameters
indexA physical Index.
Returns
The global state index for the last state that belongs to the block for which the given Index is part of the basis.

◆ run()

void TBTK::Solver::BlockDiagonalizer::run ( )

Run calculations. Diagonalizes ones if no self-consistency callback have been set, or otherwise multiple times until slef-consistencey or maximum number of iterations has been reached.

◆ setMaxIterations()

void TBTK::Solver::BlockDiagonalizer::setMaxIterations ( int  maxIterations)
inline

Set maximum number of iterations for the self-consistency loop. Only used if BlockDiagonalizer::setSelfConsistencyCallback() has been called with a non-nullptr argument. If the self-consistency callback does not return true, maxIterations determine the maximum number of times it is called.

Parameters
maxIterationsMaximum number of iterations to use in a self-consistent calculation.

◆ setParallelExecution()

void TBTK::Solver::BlockDiagonalizer::setParallelExecution ( bool  parallelExecution)
inline

Set whether parallel execution is enabled or not. Parallel execution is only possible if OpenMP is available.

parallelExecution True to enable parallel execution.

◆ setSelfConsistencyCallback()

void TBTK::Solver::BlockDiagonalizer::setSelfConsistencyCallback ( SelfConsistencyCallback selfConsistencyCallback)
inline

Set SelfCOnsistencyCallback. If never called, the self-consistency loop will not be run.

Parameters
selfConsistencyCallbackA SelfConsistencyCallback that will be called after the Model has been diagonalized. The callback should calculate relevant quantities, modify the Model if necessary, and return false if further iteration is necessary. If true is returned, self-consistency is considered to be reached and the iteration stops.

The documentation for this class was generated from the following file: