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...