31    this->
index = site_index; 
    38 void CheMPS2::TensorT::AllocateAllArrays(){
    46                for ( 
int NR = NL; NR <= NL+2; NR++ ){
    47                   const int TwoJ = (( NR == NL + 1 ) ? 1 : 0 );
    48                   for ( 
int TwoSR = TwoSL - TwoJ; TwoSR <= TwoSL + TwoJ; TwoSR += 2 ){
    63    sectorNL    = 
new int[ 
nKappa ];
    64    sectorNR    = 
new int[ 
nKappa ];
    65    sectorIL    = 
new int[ 
nKappa ];
    66    sectorIR    = 
new int[ 
nKappa ];
    67    sectorTwoSL = 
new int[ 
nKappa ];
    68    sectorTwoSR = 
new int[ 
nKappa ];
    78                for ( 
int NR = NL; NR <= NL+2; NR++ ){
    79                   const int TwoJ = (( NR == NL + 1 ) ? 1 : 0 );
    80                   for ( 
int TwoSR = TwoSL - TwoJ; TwoSR <= TwoSL + TwoJ; TwoSR += 2 ){
    89                            sectorTwoSL[ 
nKappa ] = TwoSL;
    90                            sectorTwoSR[ 
nKappa ] = TwoSR;
   112 void CheMPS2::TensorT::DeleteAllArrays(){
   118    delete [] sectorTwoSL;
   119    delete [] sectorTwoSR;
   138    for ( 
int cnt = 0; cnt < 
nKappa; cnt++ ){
   139       if (( sectorNL[ cnt ] == N1 ) &&
   140           ( sectorNR[ cnt ] == N2 ) &&
   141           ( sectorIL[ cnt ] == I1 ) &&
   142           ( sectorIR[ cnt ] == I2 ) &&
   143           ( sectorTwoSL[ cnt ] == TwoS1 ) &&
   144           ( sectorTwoSR[ cnt ] == TwoS2 )){ 
return cnt; }
   155    int kappa = 
gKappa( N1, TwoS1, I1, N2, TwoS2, I2 );
   156    if ( kappa == -1 ){ 
return NULL; }
   170       storage[ cnt ] = ((double) rand()) / RAND_MAX;
   177    #pragma omp parallel for schedule(dynamic)   178    for ( 
int ikappa = 0; ikappa < 
nKappa; ikappa++ ){
   180       double * array = 
storage + kappa2index[ ikappa ];
   181       double factor = beta + alpha * ( sectorNR[ ikappa ] - sectorNL[ ikappa ] );
   183       dscal_( &size, &factor, array, &inc1 );
   194    #pragma omp parallel for schedule(dynamic)   203                for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   204                   if ((NR==sectorNR[ikappa])&&(TwoSR==sectorTwoSR[ikappa])&&(IR==sectorIR[ikappa])){
   205                      dimLtotal += denBK->
gCurrentDim(
index,sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa]);
   211                   double * mem = 
new double[dimLtotal*dimR];
   214                   for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   215                      if ((NR==sectorNR[ikappa])&&(TwoSR==sectorTwoSR[ikappa])&&(IR==sectorIR[ikappa])){
   216                         int dimL = denBK->
gCurrentDim(
index,sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa]);
   218                            for (
int l=0; l<dimL; l++){
   219                               for (
int r=0; r<dimR; r++){
   230                   int minofdims = min(dimR,dimLtotal);
   231                   double * tau = 
new double[minofdims];
   232                   double * work = 
new double[dimR];
   233                   dgeqrf_(&dimLtotal,&dimR,mem,&dimLtotal,tau,work,&dimR,&info);
   236                   double * wheretoput = Rstorage->
gStorage(NR,TwoSR,IR,NR,TwoSR,IR); 
   238                   for (
int irow = 0; irow<minofdims; irow++){
   239                      for (
int icol = 0; icol<irow; icol++){
   240                         wheretoput[irow + dimR * icol] = 0.0;
   242                      for (
int icol = irow; icol<dimR; icol++){
   243                         wheretoput[irow + dimR * icol] = mem[irow + dimLtotal * icol];
   246                   for (
int irow = minofdims; irow<dimR; irow++){
   247                      for (
int icol = 0; icol<dimR; icol++){
   248                         wheretoput[irow + dimR * icol] = 0.0;
   253                   dorgqr_(&dimLtotal,&minofdims,&minofdims,mem,&dimLtotal,tau,work,&dimR,&info);
   254                   if (dimLtotal < dimR){ 
   255                      for (
int irow=0; irow<dimLtotal; irow++){
   256                         for (
int icol=dimLtotal; icol<dimR; icol++){
   257                            mem[irow + dimLtotal * icol] = 0.0;
   264                   for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   265                      if ((NR==sectorNR[ikappa])&&(TwoSR==sectorTwoSR[ikappa])&&(IR==sectorIR[ikappa])){
   266                         int dimL = denBK->
gCurrentDim(
index,sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa]);
   268                            for (
int l=0; l<dimL; l++){
   269                               for (
int r=0; r<dimR; r++){
   297    #pragma omp parallel for schedule(dynamic)   306                for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   307                   if ((NL==sectorNL[ikappa])&&(TwoSL==sectorTwoSL[ikappa])&&(IL==sectorIL[ikappa])){
   308                      dimRtotal += denBK->
gCurrentDim(
index+1,sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa]);
   314                   double * mem = 
new double[dimRtotal*dimL];
   317                   for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   318                      if ((NL==sectorNL[ikappa])&&(TwoSL==sectorTwoSL[ikappa])&&(IL==sectorIL[ikappa])){
   319                         int dimR = denBK->
gCurrentDim(
index+1,sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa]);
   321                            double factor = sqrt((sectorTwoSR[ikappa]+1.0)/(TwoSL+1.0));
   322                            for (
int l=0; l<dimL; l++){
   323                               for (
int r=0; r<dimR; r++){
   324                                  mem[l + dimL * (dimRtotal2 + r)] = factor * 
storage[
kappa2index[ikappa] + l + dimL * r];
   334                   int minofdims = min(dimL,dimRtotal);
   335                   double * tau = 
new double[minofdims];
   336                   double * work = 
new double[dimL];
   337                   dgelqf_(&dimL,&dimRtotal,mem,&dimL,tau,work,&dimL,&info);
   340                   double * wheretoput = Lstorage->
gStorage(NL,TwoSL,IL,NL,TwoSL,IL); 
   342                   for (
int irow = 0; irow<dimL; irow++){
   343                      for (
int icol = 0; icol<min(irow+1,dimRtotal); icol++){ 
   344                         wheretoput[irow + dimL * icol] = mem[irow + dimL * icol];
   346                      for (
int icol = min(irow+1,dimRtotal); icol<dimL; icol++){
   347                         wheretoput[irow + dimL * icol] = 0.0;
   352                   dorglq_(&minofdims,&dimRtotal,&minofdims,mem,&dimL,tau,work,&dimL,&info);
   353                   if (dimRtotal < dimL){ 
   354                      for (
int irow=dimRtotal; irow<dimL; irow++){
   355                         for (
int icol=0; icol<dimRtotal; icol++){
   356                            mem[irow + dimL * icol] = 0.0;
   363                   for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   364                      if ((NL==sectorNL[ikappa])&&(TwoSL==sectorTwoSL[ikappa])&&(IL==sectorIL[ikappa])){
   365                         int dimR = denBK->
gCurrentDim(
index+1,sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa]);
   367                            double factor = sqrt((TwoSL+1.0)/(sectorTwoSR[ikappa]+1.0));
   368                            for (
int l=0; l<dimL; l++){
   369                               for (
int r=0; r<dimR; r++){
   370                                  storage[
kappa2index[ikappa] + l + dimL * r] = factor * mem[l + dimL * (r + dimRtotal2)];
   394    #pragma omp parallel for schedule(dynamic)   395    for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   396       int dimL = denBK->
gCurrentDim(
index,sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa]);
   397       int dimR = denBK->
gCurrentDim(
index+1,sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa]);
   398       double * MxBlock = Mx->
gStorage(sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa],sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa]);
   403       double * mem = 
new double[dim];
   404       dgemm_(¬rans,¬rans,&dimL,&dimR,&dimL,&one,MxBlock,&dimL,
storage+
kappa2index[ikappa],&dimL,&zero,mem,&dimL);
   415    #pragma omp parallel for schedule(dynamic)   416    for (
int ikappa=0; ikappa<
nKappa; ikappa++){
   417       int dimL = denBK->
gCurrentDim(
index,sectorNL[ikappa],sectorTwoSL[ikappa],sectorIL[ikappa]);
   418       int dimR = denBK->
gCurrentDim(
index+1,sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa]);
   419       double * MxBlock = Mx->
gStorage(sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa],sectorNR[ikappa],sectorTwoSR[ikappa],sectorIR[ikappa]);
   424       double * mem = 
new double[dim];
   425       dgemm_(¬rans,¬rans,&dimL,&dimR,&dimR,&one,
storage+
kappa2index[ikappa],&dimL,MxBlock,&dimR,&zero,mem,&dimL);
   435    bool isLeftNormal = 
true;
   442                double * result = 
new double[dimR*dimR];
   443                bool firsttime = 
true;
   444                for (
int NL=NR-2; NL<=NR; NL++){
   445                   for (
int TwoSL=TwoSR-((NR==NL+1)?1:0); TwoSL<TwoSR+2; TwoSL+=2){
   453                         double beta = (firsttime)?0.0:1.0;
   454                         dgemm_(&trans,¬rans,&dimR,&dimR,&dimL,&one,Block,&dimL,Block,&dimL,&beta,result,&dimR);
   459                for (
int cnt=0; cnt<dimR; cnt++) result[(dimR+1)*cnt] -= 1.0;
   462                double TwoNorm = dlansy_(&norm,&uplo,&dimR,result,&dimR,result); 
   463                if (TwoNorm>CheMPS2::TENSORT_orthoComparison) isLeftNormal = 
false;
   476    bool isRightNormal = 
true;
   483                double * result = 
new double[dimL*dimL];
   484                bool firsttime = 
true;
   485                for (
int NR=NL; NR<=NL+2; NR++){
   486                   for (
int TwoSR=TwoSL-((NR==NL+1)?1:0); TwoSR<TwoSL+2; TwoSR+=2){
   493                         double alpha = (TwoSR+1.0)/(TwoSL+1.0);
   494                         double beta = (firsttime)?0.0:1.0;
   496                         dgemm_(¬rans,&trans,&dimL,&dimL,&dimR,&alpha,Block,&dimL,Block,&dimL,&beta,result,&dimL);
   501                for (
int cnt=0; cnt<dimL; cnt++) result[(dimL+1)*cnt] -= 1.0;
   504                double TwoNorm = dlansy_(&norm,&uplo,&dimL,result,&dimL,result); 
   505                if (TwoNorm>CheMPS2::TENSORT_orthoComparison) isRightNormal = 
false;
   512    return isRightNormal;
 void random()
Fill storage with random numbers 0 < val < 1. 
int gNmin(const int boundary) const 
Get the min. possible particle number for a certain boundary. 
void RightMultiply(Tensor *Mx)
Multiply at the right with a diagonal TensorOperator. 
int index
Index of the Tensor object. For TensorT: a site index; for other tensors: a boundary index...
virtual ~TensorT()
Destructor. 
void LQ(Tensor *Lstorage)
Right-normalization. 
TensorT(const int site_index, const SyBookkeeper *denBK)
Constructor. 
int gIndex() const 
Get the location index. 
int gCurrentDim(const int boundary, const int N, const int TwoS, const int irrep) const 
Get the current virtual dimensions. 
int gNKappa() const 
Get the number of symmetry blocks. 
virtual double * gStorage()=0
Get the pointer to the storage. 
int gTwoSmin(const int boundary, const int N) const 
Get the minimum possible spin value for a certain boundary and particle number. 
int gTwoSmax(const int boundary, const int N) const 
Get the maximum possible spin value for a certain boundary and particle number. 
void sBK(const SyBookkeeper *newBK)
Set the pointer to the symmetry bookkeeper. 
double * gStorage()
Get the pointer to the storage. 
static int directProd(const int Irrep1, const int Irrep2)
Get the direct product of the irreps with numbers Irrep1 and Irrep2: a bitwise XOR for psi4's convent...
int gKappa(const int N1, const int TwoS1, const int I1, const int N2, const int TwoS2, const int I2) const 
Get the index corresponding to a certain tensor block. 
void QR(Tensor *Rstorage)
Left-normalization. 
void LeftMultiply(Tensor *Mx)
Multiply at the left with a diagonal TensorOperator. 
const SyBookkeeper * gBK() const 
Get the pointer to the symmetry bookkeeper. 
int getNumberOfIrreps() const 
Get the total number of irreps. 
int * kappa2index
kappa2index[kappa] indicates the start of tensor block kappa in storage. kappa2index[nKappa] gives th...
int gNmax(const int boundary) const 
Get the max. possible particle number for a certain boundary. 
void number_operator(const double alpha, const double beta)
Apply alpha * ( number operator ) + beta to the MPS tensor. 
bool CheckLeftNormal() const 
Check whether the TensorT is left-normal. 
int nKappa
Number of Tensor blocks. 
int gIrrep(const int orbital) const 
Get an orbital irrep. 
bool CheckRightNormal() const 
Check whether the TensorT is right-normal. 
void Reset()
Reset the TensorT (if virtual dimensions are changed) 
int gKappa2index(const int kappa) const 
Get the storage jump corresponding to a certain tensor block. 
double * storage
The actual variables. Tensor block kappa begins at storage+kappa2index[kappa] and ends at storage+kap...