CheMPS2
TensorKM.cpp
1 /*
2  CheMPS2: a spin-adapted implementation of DMRG for ab initio quantum chemistry
3  Copyright (C) 2013-2016 Sebastian Wouters
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <math.h>
21 
22 #include "TensorKM.h"
23 #include "Lapack.h"
24 
25 CheMPS2::TensorKM::TensorKM( const int boundary_index, const char identity, const int Idiff, const SyBookkeeper * denBK ) :
26 TensorOperator( boundary_index,
27  1, // two_j
28  1, // n_elec
29  Idiff,
30  true, // TensorKM only exists moving left to right
31  true, // prime_last
32  false, // No jw_phase when updating (two-orbital mutual information!)
33  denBK,
34  denBK ){
35 
36  this->identity = identity;
37 
38 }
39 
41 
43 
44  clear();
45 
46  if ( identity == 'K' ){
47 
48  for (int ikappa=0; ikappa<nKappa; ikappa++){
49 
50  const int IDR = Irreps::directProd( n_irrep, sector_irrep_up[ikappa] );
51  int dimUR = bk_up->gCurrentDim(index, sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa]);
52  int dimDR = bk_up->gCurrentDim(index, sector_nelec_up[ikappa]+1, sector_spin_down[ikappa], IDR );
53  int dimL = bk_up->gCurrentDim(index-1, sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa]);
54 
55  if (dimL>0){
56 
57  double * BlockTup = denT->gStorage(sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa], sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa]);
58  double * BlockTdown = denT->gStorage(sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa], sector_nelec_up[ikappa]+1, sector_spin_down[ikappa], IDR);
59 
60  char trans = 'T';
61  char notrans = 'N';
62  double alpha = 1.0;
63  double beta = 1.0; //add
64  dgemm_(&trans,&notrans,&dimUR,&dimDR,&dimL,&alpha,BlockTup,&dimL,BlockTdown,&dimL,&beta,storage+kappa2index[ikappa],&dimUR);
65 
66  }
67  }
68  }
69 
70  if ( identity == 'M' ){
71 
72  for (int ikappa=0; ikappa<nKappa; ikappa++){
73 
74  const int IDR = Irreps::directProd( n_irrep, sector_irrep_up[ikappa] );
75  int dimUR = bk_up->gCurrentDim(index, sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa]);
76  int dimDR = bk_up->gCurrentDim(index, sector_nelec_up[ikappa]+1, sector_spin_down[ikappa], IDR );
77  int dimL = bk_up->gCurrentDim(index-1, sector_nelec_up[ikappa]-1, sector_spin_down[ikappa], IDR);
78 
79  if (dimL>0){
80 
81  double * BlockTup = denT->gStorage(sector_nelec_up[ikappa]-1, sector_spin_down[ikappa], IDR, sector_nelec_up[ikappa], sector_spin_up[ikappa], sector_irrep_up[ikappa]);
82  double * BlockTdown = denT->gStorage(sector_nelec_up[ikappa]-1, sector_spin_down[ikappa], IDR, sector_nelec_up[ikappa]+1, sector_spin_down[ikappa], IDR);
83 
84  char trans = 'T';
85  char notrans = 'N';
86  int fase = ((((sector_spin_down[ikappa] - sector_spin_up[ikappa] + 1)/2)%2)!=0)?-1:1;
87  double alpha = fase * sqrt((sector_spin_up[ikappa]+1.0)/(sector_spin_down[ikappa]+1));
88  double beta = 1.0; //add
89  dgemm_(&trans,&notrans,&dimUR,&dimDR,&dimL,&alpha,BlockTup,&dimL,BlockTdown,&dimL,&beta,storage+kappa2index[ikappa],&dimUR);
90 
91  }
92  }
93  }
94 
95 }
96 
97 
int index
Index of the Tensor object. For TensorT: a site index; for other tensors: a boundary index...
Definition: Tensor.h:75
int * sector_nelec_up
The up particle number sector.
int * sector_spin_down
The down spin symmetry sector (pointer points to sectorTwoS1 if two_j == 0)
int gCurrentDim(const int boundary, const int N, const int TwoS, const int irrep) const
Get the current virtual dimensions.
virtual ~TensorKM()
Destructor.
Definition: TensorKM.cpp:40
int * sector_spin_up
The up spin symmetry sector.
double * gStorage()
Get the pointer to the storage.
Definition: TensorT.cpp:134
int n_irrep
The (real-valued abelian) point group irrep difference between the symmetry sectors of the lower and ...
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&#39;s convent...
Definition: Irreps.h:123
int * sector_irrep_up
The up spin symmetry sector.
const SyBookkeeper * bk_up
The bookkeeper of the upper MPS.
int * kappa2index
kappa2index[kappa] indicates the start of tensor block kappa in storage. kappa2index[nKappa] gives th...
Definition: Tensor.h:84
TensorKM(const int boundary_index, const char identity, const int Idiff, const SyBookkeeper *denBK)
Constructor.
Definition: TensorKM.cpp:25
void clear()
Set all storage variables to 0.0.
void construct(TensorT *denT)
Definition: TensorKM.cpp:42
int nKappa
Number of Tensor blocks.
Definition: Tensor.h:81
double * storage
The actual variables. Tensor block kappa begins at storage+kappa2index[kappa] and ends at storage+kap...
Definition: Tensor.h:78