31 #include "MPIchemps2.h" 45 const long long size = ((
long long) L ) * ((
long long) L ) * ((
long long) L ) * ((
long long) L );
46 assert( INT_MAX >= size );
47 two_rdm_A =
new double[ size ];
48 two_rdm_B =
new double[ size ];
51 for (
int cnt = 0; cnt < size; cnt++){ two_rdm_A[ cnt ] = 0.0; }
52 for (
int cnt = 0; cnt < size; cnt++){ two_rdm_B[ cnt ] = 0.0; }
63 #ifdef CHEMPS2_MPI_COMPILATION 66 const int size = L*L*L*L;
67 double * temp =
new double[ size ];
68 MPIchemps2::allreduce_array_double( two_rdm_A, temp, size );
for (
int cnt = 0; cnt < size; cnt++){ two_rdm_A[ cnt ] = temp[ cnt ]; }
69 MPIchemps2::allreduce_array_double( two_rdm_B, temp, size );
for (
int cnt = 0; cnt < size; cnt++){ two_rdm_B[ cnt ] = temp[ cnt ]; }
75 void CheMPS2::TwoDM::set_2rdm_A_DMRG(
const int cnt1,
const int cnt2,
const int cnt3,
const int cnt4,
const double value){
79 two_rdm_A[ cnt1 + L * ( cnt2 + L * ( cnt3 + L * cnt4 ) ) ] = value;
80 two_rdm_A[ cnt2 + L * ( cnt1 + L * ( cnt4 + L * cnt3 ) ) ] = value;
81 two_rdm_A[ cnt3 + L * ( cnt4 + L * ( cnt1 + L * cnt2 ) ) ] = value;
82 two_rdm_A[ cnt4 + L * ( cnt3 + L * ( cnt2 + L * cnt1 ) ) ] = value;
86 void CheMPS2::TwoDM::set_2rdm_B_DMRG(
const int cnt1,
const int cnt2,
const int cnt3,
const int cnt4,
const double value){
90 two_rdm_B[ cnt1 + L * ( cnt2 + L * ( cnt3 + L * cnt4 ) ) ] = value;
91 two_rdm_B[ cnt2 + L * ( cnt1 + L * ( cnt4 + L * cnt3 ) ) ] = value;
92 two_rdm_B[ cnt3 + L * ( cnt4 + L * ( cnt1 + L * cnt2 ) ) ] = value;
93 two_rdm_B[ cnt4 + L * ( cnt3 + L * ( cnt2 + L * cnt1 ) ) ] = value;
100 const int irrep1 = Prob->
gIrrep(cnt1);
101 const int irrep2 = Prob->
gIrrep(cnt2);
102 const int irrep3 = Prob->
gIrrep(cnt3);
103 const int irrep4 = Prob->
gIrrep(cnt4);
105 return two_rdm_A[ cnt1 + L * ( cnt2 + L * ( cnt3 + L * cnt4 ) ) ];
115 const int irrep1 = Prob->
gIrrep(cnt1);
116 const int irrep2 = Prob->
gIrrep(cnt2);
117 const int irrep3 = Prob->
gIrrep(cnt3);
118 const int irrep4 = Prob->
gIrrep(cnt4);
120 return two_rdm_B[ cnt1 + L * ( cnt2 + L * ( cnt3 + L * cnt4 ) ) ];
130 const int irrep1 = Prob->
gIrrep(cnt1);
131 const int irrep2 = Prob->
gIrrep(cnt2);
132 if ( irrep1 == irrep2 ){
134 for (
int orbsum = 0; orbsum < L; orbsum++ ){ value +=
getTwoDMA_DMRG( cnt1, orbsum, cnt2, orbsum ); }
135 value = value / ( Prob->
gN() - 1.0 );
146 const int irrep1 = Prob->
gIrrep(cnt1);
147 const int irrep2 = Prob->
gIrrep(cnt2);
148 if ( irrep1 == irrep2 ){
149 const int two_s = Prob->
gTwoS();
152 for (
int orb = 0; orb < Prob->
gL(); orb++ ){
155 value = 1.5 * value / ( 0.5 * two_s + 1 );
207 for (
int cnt1=0; cnt1<L; cnt1++){
208 for (
int cnt2=0; cnt2<L; cnt2++){
219 for (
int cnt1=0; cnt1<L; cnt1++){
220 for (
int cnt2=0; cnt2<L; cnt2++){
221 for (
int cnt3=0; cnt3<L; cnt3++){
222 for (
int cnt4=0; cnt4<L; cnt4++){
236 double * OneRDM =
new double[ L * L ];
237 double * work =
new double[ lwork ];
238 double * eigs =
new double[ L ];
245 for (
int orb1 = 0; orb1 < L; orb1++ ){
246 if ( Prob->
gIrrep( orb1 ) == irrep ){
248 for (
int orb2 = orb1; orb2 < L; orb2++ ){
249 if ( Prob->
gIrrep( orb2 ) == irrep ){
251 OneRDM[ jump1 + L * jump2 ] = value;
252 OneRDM[ jump2 + L * jump1 ] = value;
265 dsyev_(&jobz, &uplo, &jump1, OneRDM, &lda, eigs, work, &lwork, &info);
266 cout <<
" NOON of irrep " << my_irreps.getIrrepName( irrep ) <<
" = [ ";
267 for (
int cnt = 0; cnt < jump1 - 1; cnt++ ){ cout << eigs[ jump1 - 1 - cnt ] <<
" , "; }
268 cout << eigs[ 0 ] <<
" ]." << endl;
281 const int total_size = L * L * L * L;
282 double * local_array =
new double[ total_size ];
283 for (
int ham4 = 0; ham4 < L; ham4++ ){
284 for (
int ham3 = 0; ham3 < L; ham3++ ){
285 for (
int ham2 = 0; ham2 < L; ham2++ ){
286 for (
int ham1 = 0; ham1 < L; ham1++ ){
287 local_array[ ham1 + L * ( ham2 + L * ( ham3 + L * ham4 ) ) ] =
getTwoDMA_HAM( ham1, ham2, ham3, ham4 );
294 hid_t file_id = H5Fcreate( filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
295 hsize_t dimarray = total_size;
296 hid_t group_id = H5Gcreate( file_id,
"2-RDM", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
297 hid_t dataspace_id = H5Screate_simple( 1, &dimarray, NULL );
298 hid_t dataset_id = H5Dcreate( group_id,
"elements", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
300 H5Dwrite( dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, local_array );
302 H5Dclose( dataset_id );
303 H5Sclose( dataspace_id );
304 H5Gclose( group_id );
308 delete [] local_array;
310 cout <<
"Saved the 2-RDM to the file " << filename << endl;
316 hid_t file_id = H5Fcreate(CheMPS2::TWO_RDM_storagename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
317 hsize_t dimarray = L*L*L*L;
319 hid_t group_id = H5Gcreate(file_id,
"two_rdm_A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
321 hid_t dataspace_id = H5Screate_simple(1, &dimarray, NULL);
322 hid_t dataset_id = H5Dcreate(group_id,
"elements", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
323 H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, two_rdm_A);
325 H5Dclose(dataset_id);
326 H5Sclose(dataspace_id);
331 hid_t group_id = H5Gcreate(file_id,
"two_rdm_B", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
333 hid_t dataspace_id = H5Screate_simple(1, &dimarray, NULL);
334 hid_t dataset_id = H5Dcreate(group_id,
"elements", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
335 H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, two_rdm_B);
336 H5Dclose(dataset_id);
337 H5Sclose(dataspace_id);
347 hid_t file_id = H5Fopen(CheMPS2::TWO_RDM_storagename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
349 hid_t group_id = H5Gopen(file_id,
"two_rdm_A", H5P_DEFAULT);
351 hid_t dataset_id = H5Dopen(group_id,
"elements", H5P_DEFAULT);
352 H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, two_rdm_A);
353 H5Dclose(dataset_id);
358 hid_t group_id = H5Gopen(file_id,
"two_rdm_B", H5P_DEFAULT);
360 hid_t dataset_id = H5Dopen(group_id,
"elements", H5P_DEFAULT);
361 H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, two_rdm_B);
362 H5Dclose(dataset_id);
368 std::cout <<
"TwoDM::read : Everything loaded!" << std::endl;
379 capturing = fopen( filename.c_str(),
"w" );
380 fprintf( capturing,
" &2-RDM NORB= %d,NELEC= %d,MS2= %d,\n", L, Prob->
gN(), Prob->
gTwoS() );
381 fprintf( capturing,
" ORBSYM=" );
382 for (
int HamOrb=0; HamOrb<L; HamOrb++){
383 const int DMRGOrb = ( Prob->
gReorder() ) ? Prob->
gf1( HamOrb ) : HamOrb;
384 fprintf( capturing,
"%d,", psi2molpro[ Prob->
gIrrep( DMRGOrb ) ] );
386 fprintf( capturing,
"\n ISYM=%d,\n /\n", psi2molpro[ Prob->
gIrrep() ] );
387 delete [] psi2molpro;
389 for (
int ham_p=0; ham_p<L; ham_p++){
390 const int dmrg_p = (Prob->
gReorder())?Prob->
gf1(ham_p):ham_p;
391 for (
int ham_q=0; ham_q<=ham_p; ham_q++){
392 const int dmrg_q = (Prob->
gReorder())?Prob->
gf1(ham_q):ham_q;
394 for (
int ham_r=0; ham_r<=ham_p; ham_r++){
395 const int dmrg_r = (Prob->
gReorder())?Prob->
gf1(ham_r):ham_r;
396 for (
int ham_s=0; ham_s<=ham_p; ham_s++){
397 const int dmrg_s = (Prob->
gReorder())?Prob->
gf1(ham_s):ham_s;
399 if ( irrep_pq == irrep_rs ){
400 const int num_equal = (( ham_q == ham_p ) ? 1 : 0 )
401 + (( ham_r == ham_p ) ? 1 : 0 )
402 + (( ham_s == ham_p ) ? 1 : 0 );
412 if ( ( num_equal != 2 ) || ( ham_p > ham_s ) ){
413 const double value =
getTwoDMA_DMRG(dmrg_p, dmrg_r, dmrg_q, dmrg_s);
414 fprintf( capturing,
" % 23.16E %3d %3d %3d %3d\n", value, ham_p+1, ham_q+1, ham_r+1, ham_s+1 );
423 const double prefactor = 1.0 / ( Prob->
gN() - 1.0 );
424 for (
int ham_p=0; ham_p<L; ham_p++){
425 const int dmrg_p = (Prob->
gReorder())?Prob->
gf1(ham_p):ham_p;
426 for (
int ham_q=0; ham_q<=ham_p; ham_q++){
427 const int dmrg_q = (Prob->
gReorder())?Prob->
gf1(ham_q):ham_q;
430 for (
int orbsum = 0; orbsum < L; orbsum++ ){ value +=
getTwoDMA_DMRG( dmrg_p, orbsum, dmrg_q, orbsum ); }
432 fprintf( capturing,
" % 23.16E %3d %3d %3d %3d\n", value, ham_p+1, ham_q+1, 0, 0 );
438 fprintf( capturing,
" % 23.16E %3d %3d %3d %3d", 1.0, 0, 0, 0, 0 );
440 cout <<
"Created the file " << filename <<
"." << endl;
446 #ifdef CHEMPS2_MPI_COMPILATION 450 const int theindex = denT->
gIndex();
453 #ifdef CHEMPS2_MPI_COMPILATION 454 if ( MPIRANK == MPI_CHEMPS2_MASTER )
458 const double d1 = doD1(denT);
459 set_2rdm_A_DMRG(theindex,theindex,theindex,theindex, 2*d1);
460 set_2rdm_B_DMRG(theindex,theindex,theindex,theindex,-2*d1);
466 double * workmem =
new double[DIM*DIM];
467 double * workmem2 =
new double[DIM*DIM];
469 #pragma omp for schedule(static) nowait 470 for (
int j_index=theindex+1; j_index<L; j_index++){
472 #ifdef CHEMPS2_MPI_COMPILATION 473 if ( MPIRANK == MPIchemps2::owner_q( L, j_index ) )
477 const double d2 = doD2(denT, Ltens[theindex][j_index-theindex-1], workmem);
478 set_2rdm_A_DMRG(theindex,j_index,theindex,theindex, 2*d2);
479 set_2rdm_B_DMRG(theindex,j_index,theindex,theindex,-2*d2);
484 const int dimTriangle = L - theindex - 1;
485 const int upperboundTriangle = ( dimTriangle * ( dimTriangle + 1 ) ) / 2;
487 #pragma omp for schedule(static) nowait 488 for (
int global = 0; global < upperboundTriangle; global++ ){
490 const int j_index = L - 1 - result[ 1 ];
491 const int k_index = j_index + result[ 0 ];
492 if ( denBK->
gIrrep( j_index ) == denBK->
gIrrep( k_index )){
494 #ifdef CHEMPS2_MPI_COMPILATION 495 if ( MPIRANK == MPIchemps2::owner_absigma( j_index, k_index ) )
499 const double d3 = doD3(denT, S0tens[theindex][k_index-j_index][j_index-theindex-1], workmem);
500 set_2rdm_A_DMRG(theindex,theindex,j_index,k_index, 2*d3);
501 set_2rdm_B_DMRG(theindex,theindex,j_index,k_index,-2*d3);
504 #ifdef CHEMPS2_MPI_COMPILATION 505 if ( MPIRANK == MPIchemps2::owner_cdf( L, j_index, k_index ) )
509 const double d4 = doD4(denT, F0tens[theindex][k_index-j_index][j_index-theindex-1], workmem);
510 const double d5 = doD5(denT, F0tens[theindex][k_index-j_index][j_index-theindex-1], workmem);
511 const double d6 = doD6(denT, F1tens[theindex][k_index-j_index][j_index-theindex-1], workmem);
512 set_2rdm_A_DMRG(theindex,j_index,k_index,theindex, -2*d4 - 2*d5 - 3*d6);
513 set_2rdm_B_DMRG(theindex,j_index,k_index,theindex, -2*d4 - 2*d5 + d6);
514 set_2rdm_A_DMRG(theindex,j_index,theindex,k_index, 4*d4 + 4*d5);
515 set_2rdm_B_DMRG(theindex,j_index,theindex,k_index, 2*d6);
520 #pragma omp for schedule(static) nowait 521 for (
int g_index=0; g_index<theindex; g_index++){
523 #ifdef CHEMPS2_MPI_COMPILATION 524 if ( MPIRANK == MPIchemps2::owner_q( L, g_index ) )
528 const double d7 = doD7(denT, Ltens[theindex-1][theindex-g_index-1], workmem);
529 set_2rdm_A_DMRG(g_index,theindex,theindex,theindex, 2*d7);
530 set_2rdm_B_DMRG(g_index,theindex,theindex,theindex,-2*d7);
535 const int globalsize8to12 = theindex * ( L - 1 - theindex );
536 #pragma omp for schedule(static) nowait 537 for (
int gj_index=0; gj_index<globalsize8to12; gj_index++){
538 const int g_index = gj_index % theindex;
539 const int j_index = ( gj_index / theindex ) + theindex + 1;
540 const int I_g = denBK->
gIrrep(g_index);
542 #ifdef CHEMPS2_MPI_COMPILATION 543 if ( MPIRANK == MPIchemps2::owner_absigma( g_index, j_index ) )
547 const double d8 = doD8(denT, Ltens[theindex-1][theindex-g_index-1], Ltens[theindex][j_index-theindex-1], workmem, workmem2, I_g);
549 doD9andD10andD11(denT, Ltens[theindex-1][theindex-g_index-1], Ltens[theindex][j_index-theindex-1], workmem, workmem2, &d9, &d10, &d11, I_g);
550 set_2rdm_A_DMRG(g_index,theindex,j_index,theindex, -4*d8-d9);
551 set_2rdm_A_DMRG(g_index,theindex,theindex,j_index, 2*d8 + d11);
552 set_2rdm_B_DMRG(g_index,theindex,j_index,theindex, d9 - 2*d10);
553 set_2rdm_B_DMRG(g_index,theindex,theindex,j_index, 2*d8 + 2*d10 - d11);
556 const double d12 = doD12(denT, Ltens[theindex-1][theindex-g_index-1], Ltens[theindex][j_index-theindex-1], workmem, workmem2, I_g);
557 set_2rdm_A_DMRG(g_index,j_index,theindex,theindex, 2*d12);
558 set_2rdm_B_DMRG(g_index,j_index,theindex,theindex,-2*d12);
563 const int globalsize = theindex * upperboundTriangle;
564 #pragma omp for schedule(static) nowait 565 for (
int gjk_index = 0; gjk_index < globalsize; gjk_index++ ){
566 const int g_index = gjk_index % theindex;
567 const int global = gjk_index / theindex;
569 const int j_index = L - 1 - result[ 1 ];
570 const int k_index = j_index + result[ 0 ];
571 const int I_g = denBK->
gIrrep( g_index );
572 const int cnt1 = k_index - j_index;
573 const int cnt2 = j_index - theindex - 1;
576 #ifdef CHEMPS2_MPI_COMPILATION 577 if ( MPIRANK == MPIchemps2::owner_absigma( j_index, k_index ) )
581 const double d13 = doD13(denT, Ltens[theindex-1][theindex-g_index-1], S0tens[theindex][cnt1][cnt2], workmem, workmem2, I_g);
582 const double d14 = doD14(denT, Ltens[theindex-1][theindex-g_index-1], S0tens[theindex][cnt1][cnt2], workmem, workmem2, I_g);
585 if (k_index>j_index){
586 d15 = doD15(denT, Ltens[theindex-1][theindex-g_index-1], S1tens[theindex][cnt1][cnt2], workmem, workmem2, I_g);
587 d16 = doD16(denT, Ltens[theindex-1][theindex-g_index-1], S1tens[theindex][cnt1][cnt2], workmem, workmem2, I_g);
589 set_2rdm_A_DMRG(g_index,theindex,j_index,k_index, 2*d13 + 2*d14 + 3*d15 + 3*d16);
590 set_2rdm_A_DMRG(g_index,theindex,k_index,j_index, 2*d13 + 2*d14 - 3*d15 - 3*d16);
591 set_2rdm_B_DMRG(g_index,theindex,j_index,k_index,-2*d13 - 2*d14 + d15 + d16);
592 set_2rdm_B_DMRG(g_index,theindex,k_index,j_index,-2*d13 - 2*d14 - d15 - d16);
595 #ifdef CHEMPS2_MPI_COMPILATION 596 if ( MPIRANK == MPIchemps2::owner_cdf( L, j_index, k_index ) )
600 const double d17 = doD17orD21(denT, Ltens[theindex-1][theindex-g_index-1], F0tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
true);
601 const double d18 = doD18orD22(denT, Ltens[theindex-1][theindex-g_index-1], F0tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
true);
602 const double d19 = doD19orD23(denT, Ltens[theindex-1][theindex-g_index-1], F1tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
true);
603 const double d20 = doD20orD24(denT, Ltens[theindex-1][theindex-g_index-1], F1tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
true);
604 set_2rdm_A_DMRG(g_index,j_index,k_index,theindex, -2*d17 - 2*d18 - 3*d19 - 3*d20);
605 set_2rdm_A_DMRG(g_index,j_index,theindex,k_index, 4*d17 + 4*d18 );
606 set_2rdm_B_DMRG(g_index,j_index,k_index,theindex, -2*d17 - 2*d18 + d19 + d20);
607 set_2rdm_B_DMRG(g_index,j_index,theindex,k_index, 2*d19 + 2*d20);
610 const double d21 = doD17orD21(denT, Ltens[theindex-1][theindex-g_index-1], F0tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
false);
611 const double d22 = doD18orD22(denT, Ltens[theindex-1][theindex-g_index-1], F0tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
false);
612 const double d23 = doD19orD23(denT, Ltens[theindex-1][theindex-g_index-1], F1tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
false);
613 const double d24 = doD20orD24(denT, Ltens[theindex-1][theindex-g_index-1], F1tens[theindex][cnt1][cnt2], workmem, workmem2, I_g,
false);
614 set_2rdm_A_DMRG(g_index,k_index,j_index,theindex, -2*d21 - 2*d22 - 3*d23 - 3*d24);
615 set_2rdm_A_DMRG(g_index,k_index,theindex,j_index, 4*d21 + 4*d22 );
616 set_2rdm_B_DMRG(g_index,k_index,j_index,theindex, -2*d21 - 2*d22 + d23 + d24);
617 set_2rdm_B_DMRG(g_index,k_index,theindex,j_index, 2*d23 + 2*d24);
631 if ( Prob->
gTwoS() != 0 ){
632 double alpha = 1.0 / ( Prob->
gTwoS() + 1.0 );
633 int length = L*L*L*L;
635 dscal_( &length, &alpha, two_rdm_A, &inc );
636 dscal_( &length, &alpha, two_rdm_B, &inc );
641 double CheMPS2::TwoDM::doD1(
TensorT * denT){
643 int theindex = denT->
gIndex();
647 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
648 for (
int TwoSL = denBK->
gTwoSmin(theindex,NL); TwoSL<= denBK->
gTwoSmax(theindex,NL); TwoSL+=2){
650 int dimL = denBK->
gCurrentDim(theindex, NL, TwoSL,IL);
651 int dimR = denBK->
gCurrentDim(theindex+1,NL+2,TwoSL,IL);
652 if ((dimL>0) && (dimR>0)){
654 double * Tblock = denT->
gStorage(NL,TwoSL,IL,NL+2,TwoSL,IL);
656 int length = dimL*dimR;
658 total += (TwoSL+1) * ddot_(&length, Tblock, &inc, Tblock, &inc);
669 double CheMPS2::TwoDM::doD2(
TensorT * denT,
TensorL * Lright,
double * workmem){
671 int theindex = denT->
gIndex();
675 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
676 for (
int TwoSL = denBK->
gTwoSmin(theindex,NL); TwoSL<= denBK->
gTwoSmax(theindex,NL); TwoSL+=2){
678 for (
int TwoSR = TwoSL-1; TwoSR<=TwoSL+1; TwoSR+=2){
682 int dimL = denBK->
gCurrentDim(theindex, NL, TwoSL,IL);
683 int dimRdown = denBK->
gCurrentDim(theindex+1,NL+2,TwoSL,IL);
684 int dimRup = denBK->
gCurrentDim(theindex+1,NL+1,TwoSR,IRup);
686 if ((dimL>0) && (dimRup>0) && (dimRdown>0)){
688 double * Tdown = denT->
gStorage(NL,TwoSL,IL,NL+2,TwoSL,IL );
689 double * Tup = denT->
gStorage(NL,TwoSL,IL,NL+1,TwoSR,IRup);
690 double * Lblock = Lright->
gStorage(NL+1,TwoSR,IRup,NL+2,TwoSL,IL);
696 dgemm_(¬rans,&trans,&dimL,&dimRup,&dimRdown,&alpha,Tdown,&dimL,Lblock,&dimRup,&beta,workmem,&dimL);
698 const double factor =
Special::phase( TwoSL + 1 - TwoSR ) * 0.5 * sqrt((TwoSL+1)*(TwoSR+1.0));
700 int length = dimL * dimRup;
702 total += factor * ddot_(&length, workmem, &inc, Tup, &inc);
714 double CheMPS2::TwoDM::doD3(
TensorT * denT,
TensorS0 * S0right,
double * workmem){
716 int theindex = denT->
gIndex();
720 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
721 for (
int TwoSL = denBK->
gTwoSmin(theindex,NL); TwoSL<= denBK->
gTwoSmax(theindex,NL); TwoSL+=2){
724 int dimL = denBK->
gCurrentDim(theindex, NL, TwoSL,IL);
725 int dimRdown = denBK->
gCurrentDim(theindex+1,NL, TwoSL,IL);
726 int dimRup = denBK->
gCurrentDim(theindex+1,NL+2,TwoSL,IL);
728 if ((dimL>0) && (dimRup>0) && (dimRdown>0)){
730 double * Tdown = denT->
gStorage(NL,TwoSL,IL,NL, TwoSL,IL);
731 double * Tup = denT->
gStorage(NL,TwoSL,IL,NL+2,TwoSL,IL);
732 double * S0block = S0right->
gStorage(NL, TwoSL, IL, NL+2, TwoSL, IL);
737 dgemm_(¬rans,¬rans,&dimL,&dimRup,&dimRdown,&alpha,Tdown,&dimL,S0block,&dimRdown,&beta,workmem,&dimL);
739 double factor = sqrt(0.5) * (TwoSL+1);
741 int length = dimL * dimRup;
743 total += factor * ddot_(&length, workmem, &inc, Tup, &inc);
754 double CheMPS2::TwoDM::doD4(
TensorT * denT,
TensorF0 * F0right,
double * workmem){
756 int theindex = denT->
gIndex();
760 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
761 for (
int TwoSL = denBK->
gTwoSmin(theindex,NL); TwoSL<= denBK->
gTwoSmax(theindex,NL); TwoSL+=2){
764 int dimL = denBK->
gCurrentDim(theindex, NL, TwoSL,IL);
765 int dimR = denBK->
gCurrentDim(theindex+1,NL+2,TwoSL,IL);
767 if ((dimL>0) && (dimR>0)){
769 double * Tblock = denT->
gStorage(NL, TwoSL, IL, NL+2, TwoSL, IL);
770 double * F0block = F0right->
gStorage(NL+2, TwoSL, IL, NL+2, TwoSL, IL);
775 dgemm_(¬rans,¬rans,&dimL,&dimR,&dimR,&alpha,Tblock,&dimL,F0block,&dimR,&beta,workmem,&dimL);
777 double factor = sqrt(0.5) * (TwoSL+1);
779 int length = dimL * dimR;
781 total += factor * ddot_(&length, workmem, &inc, Tblock, &inc);
792 double CheMPS2::TwoDM::doD5(
TensorT * denT,
TensorF0 * F0right,
double * workmem){
794 int theindex = denT->
gIndex();
798 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
799 for (
int TwoSL = denBK->
gTwoSmin(theindex,NL); TwoSL<= denBK->
gTwoSmax(theindex,NL); TwoSL+=2){
801 for (
int TwoSR=TwoSL-1; TwoSR<=TwoSL+1; TwoSR+=2){
804 int dimL = denBK->
gCurrentDim(theindex, NL, TwoSL,IL);
805 int dimR = denBK->
gCurrentDim(theindex+1,NL+1,TwoSR,IR);
807 if ((dimL>0) && (dimR>0)){
809 double * Tblock = denT->
gStorage(NL, TwoSL, IL, NL+1, TwoSR, IR);
810 double * F0block = F0right->
gStorage(NL+1, TwoSR, IR, NL+1, TwoSR, IR);
815 dgemm_(¬rans,¬rans,&dimL,&dimR,&dimR,&alpha,Tblock,&dimL,F0block,&dimR,&beta,workmem,&dimL);
817 double factor = 0.5 * sqrt(0.5) * (TwoSR+1);
819 int length = dimL * dimR;
821 total += factor * ddot_(&length, workmem, &inc, Tblock, &inc);
833 double CheMPS2::TwoDM::doD6(
TensorT * denT,
TensorF1 * F1right,
double * workmem){
835 int theindex = denT->
gIndex();
839 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
840 for (
int TwoSL = denBK->
gTwoSmin(theindex,NL); TwoSL<= denBK->
gTwoSmax(theindex,NL); TwoSL+=2){
842 for (
int TwoSRup=TwoSL-1; TwoSRup<=TwoSL+1; TwoSRup+=2){
843 for (
int TwoSRdown=TwoSL-1; TwoSRdown<=TwoSL+1; TwoSRdown+=2){
846 int dimL = denBK->
gCurrentDim(theindex, NL, TwoSL, IL);
847 int dimRup = denBK->
gCurrentDim(theindex+1,NL+1,TwoSRup, IR);
848 int dimRdown = denBK->
gCurrentDim(theindex+1,NL+1,TwoSRdown,IR);
850 if ((dimL>0) && (dimRup>0) && (dimRdown>0)){
852 double * Tup = denT->
gStorage(NL, TwoSL, IL, NL+1, TwoSRup, IR);
853 double * Tdown = denT->
gStorage(NL, TwoSL, IL, NL+1, TwoSRdown, IR);
854 double * F1block = F1right->
gStorage(NL+1, TwoSRdown, IR, NL+1, TwoSRup, IR);
859 dgemm_(¬rans,¬rans,&dimL,&dimRup,&dimRdown,&alpha,Tdown,&dimL,F1block,&dimRdown,&beta,workmem,&dimL);
861 const double factor = sqrt((TwoSRup+1)/3.0) * ( TwoSRdown + 1 )
865 int length = dimL * dimRup;
867 total += factor * ddot_(&length, workmem, &inc, Tup, &inc);
880 double CheMPS2::TwoDM::doD7(
TensorT * denT,
TensorL * Lleft,
double * workmem){
882 int theindex = denT->
gIndex();
886 for (
int NLup = denBK->
gNmin(theindex); NLup<=denBK->
gNmax(theindex); NLup++){
887 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NLup); TwoSLup<= denBK->
gTwoSmax(theindex,NLup); TwoSLup+=2){
890 int dimLup = denBK->
gCurrentDim(theindex, NLup, TwoSLup, ILup);
892 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
895 int dimLdown = denBK->
gCurrentDim(theindex, NLup-1, TwoSLdown, IR);
896 int dimR = denBK->
gCurrentDim(theindex+1, NLup+1, TwoSLdown, IR);
898 if ((dimLup>0) && (dimLdown>0) && (dimR>0)){
900 double * Tup = denT->
gStorage(NLup, TwoSLup, ILup, NLup+1, TwoSLdown, IR);
901 double * Tdown = denT->
gStorage(NLup-1, TwoSLdown, IR, NLup+1, TwoSLdown, IR);
902 double * Lblock = Lleft->
gStorage(NLup-1, TwoSLdown, IR, NLup, TwoSLup, ILup);
908 dgemm_(&trans,¬rans,&dimLup,&dimR,&dimLdown,&alpha,Lblock,&dimLdown,Tdown,&dimLdown,&beta,workmem,&dimLup);
910 const double factor = 0.5 * sqrt((TwoSLdown+1)*(TwoSLup+1.0)) *
Special::phase( TwoSLup - TwoSLdown + 3 );
912 int length = dimLup * dimR;
914 total += factor * ddot_(&length, workmem, &inc, Tup, &inc);
926 double CheMPS2::TwoDM::doD8(
TensorT * denT,
TensorL * Lleft,
TensorL * Lright,
double * workmem,
double * workmem2,
int Irrep_g){
928 int theindex = denT->
gIndex();
932 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
933 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
936 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
937 int dimRup = denBK->
gCurrentDim(theindex+1, NL+2, TwoSLup, ILup);
939 if ((dimLup>0) && (dimRup>0)){
941 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
945 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, Idown);
946 int dimRdown = denBK->
gCurrentDim(theindex+1, NL+1, TwoSLdown, Idown);
948 if ((dimLdown>0) && (dimRdown>0)){
950 double * Tup = denT->
gStorage(NL, TwoSLup, ILup, NL+2, TwoSLup, ILup);
951 double * Tdown = denT->
gStorage(NL-1, TwoSLdown, Idown, NL+1, TwoSLdown, Idown);
952 double * LleftBlk = Lleft->
gStorage(NL-1, TwoSLdown, Idown, NL, TwoSLup, ILup);
953 double * LrightBlk = Lright->
gStorage(NL+1, TwoSLdown, Idown, NL+2, TwoSLup, ILup);
959 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,LleftBlk,&dimLdown,Tdown,&dimLdown,&beta,workmem,&dimLup);
961 dgemm_(¬rans,¬rans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,LrightBlk,&dimRdown,&beta,workmem2,&dimLup);
963 double factor = -0.5 * (TwoSLup+1);
965 int length = dimLup * dimRup;
967 total += factor * ddot_(&length, workmem2, &inc, Tup, &inc);
980 void CheMPS2::TwoDM::doD9andD10andD11(
TensorT * denT,
TensorL * Lleft,
TensorL * Lright,
double * workmem,
double * workmem2,
double * d9,
double * d10,
double * d11,
int Irrep_g){
986 int theindex = denT->
gIndex();
988 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
989 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
992 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
999 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1000 for (
int TwoSRup=TwoSLup-1; TwoSRup<=TwoSLup+1; TwoSRup+=2){
1001 for (
int TwoSRdown=TwoSRup-1; TwoSRdown<=TwoSRup+1; TwoSRdown+=2){
1002 if ((TwoSLdown>=0) && (TwoSRup>=0) && (TwoSRdown>=0) && (abs(TwoSLdown - TwoSRdown)<=1)){
1004 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, ILdown);
1005 int dimRup = denBK->
gCurrentDim(theindex+1, NL+1, TwoSRup, IRup);
1006 int dimRdown = denBK->
gCurrentDim(theindex+1, NL, TwoSRdown, IRdown);
1008 if ((dimLdown>0) && (dimRup>0) && (dimRdown>0)){
1010 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+1, TwoSRup, IRup);
1011 double * T_down = denT->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSRdown, IRdown);
1012 double * LleftBlk = Lleft->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, ILup);
1013 double * LrightBlk = Lright->
gStorage(NL, TwoSRdown, IRdown, NL+1, TwoSRup, IRup);
1020 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,LleftBlk,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1022 dgemm_(¬rans,¬rans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,LrightBlk,&dimRdown,&beta,workmem2,&dimLup);
1024 int length = dimLup * dimRup;
1026 double value = ddot_(&length, workmem2, &inc, T_up, &inc);
1029 * ( TwoSRup + 1 ) * sqrt( ( TwoSRdown + 1 ) * ( TwoSLup + 1.0 ) )
1031 const double fact2 = 2 * ( TwoSRup + 1 ) * sqrt( ( TwoSRdown + 1 ) * ( TwoSLup + 1.0 ) )
1034 const int fact3 = (( TwoSRdown == TwoSLup ) ? ( TwoSRup + 1 ) : 0 );
1036 d9[0] += fact1 * value;
1037 d10[0] += fact2 * value;
1038 d11[0] += fact3 * value;
1052 double CheMPS2::TwoDM::doD12(
TensorT * denT,
TensorL * Lleft,
TensorL * Lright,
double * workmem,
double * workmem2,
int Irrep_g){
1056 int theindex = denT->
gIndex();
1058 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1059 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1062 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1063 int dimRup = denBK->
gCurrentDim(theindex+1, NL, TwoSLup, ILup);
1064 if ((dimLup>0) && (dimRup>0)){
1068 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1070 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, Idown);
1071 int dimRdown = denBK->
gCurrentDim(theindex+1, NL+1, TwoSLdown, Idown);
1073 if ((dimLdown>0) && (dimRdown>0)){
1075 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL, TwoSLup, ILup);
1076 double * T_down = denT->
gStorage(NL-1, TwoSLdown, Idown, NL+1, TwoSLdown, Idown);
1077 double * LleftBlk = Lleft->
gStorage(NL-1, TwoSLdown, Idown, NL, TwoSLup, ILup);
1078 double * LrightBlk = Lright->
gStorage(NL, TwoSLup, ILup, NL+1, TwoSLdown, Idown);
1085 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,LleftBlk,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1087 dgemm_(¬rans,&trans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,LrightBlk,&dimRup,&beta,workmem2,&dimLup);
1090 * 0.5 * sqrt( ( TwoSLup + 1 ) * ( TwoSLdown + 1.0 ) );
1092 int length = dimLup * dimRup;
1094 d12 += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
1107 double CheMPS2::TwoDM::doD13(
TensorT * denT,
TensorL * Lleft,
TensorS0 * S0right,
double * workmem,
double * workmem2,
int Irrep_g){
1111 int theindex = denT->
gIndex();
1113 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1114 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1117 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1118 int dimRup = denBK->
gCurrentDim(theindex+1, NL+2, TwoSLup, ILup);
1120 if ((dimLup>0) && (dimRup>0)){
1125 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1127 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, ILdown);
1128 int dimRdown = denBK->
gCurrentDim(theindex+1, NL, TwoSLup, IRdown);
1130 if ((dimLdown>0) && (dimRdown>0)){
1132 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+2, TwoSLup, ILup);
1133 double * T_down = denT->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, IRdown);
1134 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, ILup);
1135 double * S0block = S0right->
gStorage(NL, TwoSLup, IRdown, NL+2, TwoSLup, ILup);
1142 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1144 dgemm_(¬rans,¬rans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,S0block,&dimRdown,&beta,workmem2,&dimLup);
1146 double factor = -0.5 * sqrt(0.5) * (TwoSLup+1);
1148 int length = dimLup * dimRup;
1150 d13 += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
1163 double CheMPS2::TwoDM::doD14(
TensorT * denT,
TensorL * Lleft,
TensorS0 * S0right,
double * workmem,
double * workmem2,
int Irrep_g){
1167 int theindex = denT->
gIndex();
1169 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1170 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1173 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1180 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1182 int dimRup = denBK->
gCurrentDim(theindex+1, NL+1, TwoSLdown, IRup);
1183 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, Idown);
1184 int dimRdown = denBK->
gCurrentDim(theindex+1, NL-1, TwoSLdown, Idown);
1186 if ((dimLdown>0) && (dimRdown>0) && (dimRup>0)){
1188 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+1, TwoSLdown, IRup);
1189 double * T_down = denT->
gStorage(NL-1, TwoSLdown, Idown, NL-1, TwoSLdown, Idown);
1190 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, Idown, NL, TwoSLup, ILup);
1191 double * S0block = S0right->
gStorage(NL-1, TwoSLdown, Idown, NL+1, TwoSLdown, IRup);
1198 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1200 dgemm_(¬rans,¬rans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,S0block,&dimRdown,&beta,workmem2,&dimLup);
1202 const double factor =
Special::phase( TwoSLdown + 1 - TwoSLup ) * 0.5 * sqrt(0.5 * (TwoSLup+1) * (TwoSLdown+1));
1204 int length = dimLup * dimRup;
1206 d14 += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
1219 double CheMPS2::TwoDM::doD15(
TensorT * denT,
TensorL * Lleft,
TensorS1 * S1right,
double * workmem,
double * workmem2,
int Irrep_g){
1223 int theindex = denT->
gIndex();
1225 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1226 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1229 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1230 int dimRup = denBK->
gCurrentDim(theindex+1, NL+2, TwoSLup, ILup);
1232 if ((dimLup>0) && (dimRup>0)){
1237 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1238 for (
int TwoSRdown=TwoSLdown-1; TwoSRdown<=TwoSLdown+1; TwoSRdown+=2){
1240 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, ILdown);
1241 int dimRdown = denBK->
gCurrentDim(theindex+1, NL, TwoSRdown, IRdown);
1243 if ((dimLdown>0) && (dimRdown>0)){
1245 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+2, TwoSLup, ILup);
1246 double * T_down = denT->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSRdown, IRdown);
1247 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, ILup);
1248 double * S1block = S1right->
gStorage(NL, TwoSRdown, IRdown, NL+2, TwoSLup, ILup);
1255 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1257 dgemm_(¬rans,¬rans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,S1block,&dimRdown,&beta,workmem2,&dimLup);
1260 * ( TwoSLup + 1 ) * sqrt((TwoSRdown+1)/3.0) *
Wigner::wigner6j( 1, 1, 2, TwoSLup, TwoSRdown, TwoSLdown );
1262 int length = dimLup * dimRup;
1264 d15 += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
1278 double CheMPS2::TwoDM::doD16(
TensorT * denT,
TensorL * Lleft,
TensorS1 * S1right,
double * workmem,
double * workmem2,
int Irrep_g){
1282 int theindex = denT->
gIndex();
1284 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1285 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1288 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1295 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1296 for (
int TwoSRup=TwoSLup-1; TwoSRup<=TwoSLup+1; TwoSRup+=2){
1298 int dimRup = denBK->
gCurrentDim(theindex+1, NL+1, TwoSRup, IRup);
1299 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, Idown);
1300 int dimRdown = denBK->
gCurrentDim(theindex+1, NL-1, TwoSLdown, Idown);
1302 if ((dimLdown>0) && (dimRdown>0) && (dimRup>0)){
1304 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+1, TwoSRup, IRup);
1305 double * T_down = denT->
gStorage(NL-1, TwoSLdown, Idown, NL-1, TwoSLdown, Idown);
1306 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, Idown, NL, TwoSLup, ILup);
1307 double * S1block = S1right->
gStorage(NL-1, TwoSLdown, Idown, NL+1, TwoSRup, IRup);
1314 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1316 dgemm_(¬rans,¬rans,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,S1block,&dimRdown,&beta,workmem2,&dimLup);
1318 const double factor =
Special::phase( TwoSRup + TwoSLdown + 2 ) * (TwoSRup+1) * sqrt((TwoSLup+1)/3.0)
1321 int length = dimLup * dimRup;
1323 d16 += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
1337 double CheMPS2::TwoDM::doD17orD21(
TensorT * denT,
TensorL * Lleft,
TensorF0 * F0right,
double * workmem,
double * workmem2,
int Irrep_g,
bool shouldIdoD17){
1341 int theindex = denT->
gIndex();
1343 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1344 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1347 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1354 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1356 int dimRup = denBK->
gCurrentDim(theindex+1, NL, TwoSLup, ILup);
1357 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, ILdown);
1358 int dimRdown = denBK->
gCurrentDim(theindex+1, NL, TwoSLup, IRdown);
1360 if ((dimLdown>0) && (dimRdown>0) && (dimRup>0)){
1362 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL, TwoSLup, ILup);
1363 double * T_down = denT->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, IRdown);
1364 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, ILup);
1365 double * F0block = (shouldIdoD17) ? F0right->
gStorage(NL, TwoSLup, IRdown, NL, TwoSLup, ILup)
1366 : F0right->
gStorage(NL, TwoSLup, ILup, NL, TwoSLup, IRdown) ;
1370 char var = (shouldIdoD17) ? notrans : trans;
1373 int dimvar = (shouldIdoD17) ? dimRdown : dimRup ;
1375 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1377 dgemm_(¬rans,&var,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,F0block,&dimvar,&beta,workmem2,&dimLup);
1379 int length = dimLup * dimRup;
1381 total += sqrt(0.5) * 0.5 * (TwoSLup+1) * ddot_(&length, workmem2, &inc, T_up, &inc);
1394 double CheMPS2::TwoDM::doD18orD22(
TensorT * denT,
TensorL * Lleft,
TensorF0 * F0right,
double * workmem,
double * workmem2,
int Irrep_g,
bool shouldIdoD18){
1398 int theindex = denT->
gIndex();
1400 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1401 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1404 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1411 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1413 int dimRup = denBK->
gCurrentDim(theindex+1, NL+1, TwoSLdown, IRup);
1414 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, Idown);
1415 int dimRdown = denBK->
gCurrentDim(theindex+1, NL+1, TwoSLdown, Idown);
1417 if ((dimLdown>0) && (dimRdown>0) && (dimRup>0)){
1419 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+1, TwoSLdown, IRup);
1420 double * T_down = denT->
gStorage(NL-1, TwoSLdown, Idown, NL+1, TwoSLdown, Idown);
1421 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, Idown, NL, TwoSLup, ILup);
1422 double * F0block = (shouldIdoD18) ? F0right->
gStorage(NL+1, TwoSLdown, Idown, NL+1, TwoSLdown, IRup)
1423 : F0right->
gStorage(NL+1, TwoSLdown, IRup, NL+1, TwoSLdown, Idown) ;
1427 char var = (shouldIdoD18) ? notrans : trans;
1430 int dimvar = (shouldIdoD18) ? dimRdown : dimRup ;
1432 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1434 dgemm_(¬rans,&var,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,F0block,&dimvar,&beta,workmem2,&dimLup);
1436 const double factor =
Special::phase( TwoSLdown + 1 - TwoSLup ) * 0.5 * sqrt(0.5*(TwoSLup+1)*(TwoSLdown+1));
1438 int length = dimLup * dimRup;
1440 total += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
1453 double CheMPS2::TwoDM::doD19orD23(
TensorT * denT,
TensorL * Lleft,
TensorF1 * F1right,
double * workmem,
double * workmem2,
int Irrep_g,
bool shouldIdoD19){
1457 int theindex = denT->
gIndex();
1459 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1460 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1463 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1470 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1471 for (
int TwoSRdown=TwoSLdown-1; TwoSRdown<=TwoSLdown+1; TwoSRdown+=2){
1473 int dimRup = denBK->
gCurrentDim(theindex+1, NL, TwoSLup, ILup);
1474 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, ILdown);
1475 int dimRdown = denBK->
gCurrentDim(theindex+1, NL, TwoSRdown, IRdown);
1477 if ((dimLdown>0) && (dimRdown>0) && (dimRup>0)){
1479 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL, TwoSLup, ILup);
1480 double * T_down = denT->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSRdown, IRdown);
1481 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, ILdown, NL, TwoSLup, ILup);
1482 double * F1block = (shouldIdoD19) ? F1right->
gStorage(NL, TwoSRdown, IRdown, NL, TwoSLup, ILup)
1483 : F1right->
gStorage(NL, TwoSLup, ILup, NL, TwoSRdown, IRdown) ;
1487 char var = (shouldIdoD19) ? notrans : trans;
1490 int dimvar = (shouldIdoD19) ? dimRdown : dimRup ;
1492 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1494 dgemm_(¬rans,&var,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,F1block,&dimvar,&beta,workmem2,&dimLup);
1496 double factor = 0.0;
1499 * ( TwoSRdown + 1 ) * sqrt((TwoSLup+1)/3.0) *
Wigner::wigner6j( 1, 1, 2, TwoSLup, TwoSRdown, TwoSLdown );
1502 * ( TwoSLup + 1 ) * sqrt((TwoSRdown+1)/3.0) *
Wigner::wigner6j( 1, 1, 2, TwoSLup, TwoSRdown, TwoSLdown );
1505 int length = dimLup * dimRup;
1507 total += factor * ddot_(&length,workmem2,&inc,T_up,&inc);
1521 double CheMPS2::TwoDM::doD20orD24(
TensorT * denT,
TensorL * Lleft,
TensorF1 * F1right,
double * workmem,
double * workmem2,
int Irrep_g,
bool shouldIdoD20){
1525 int theindex = denT->
gIndex();
1527 for (
int NL = denBK->
gNmin(theindex); NL<=denBK->
gNmax(theindex); NL++){
1528 for (
int TwoSLup = denBK->
gTwoSmin(theindex,NL); TwoSLup<= denBK->
gTwoSmax(theindex,NL); TwoSLup+=2){
1531 int dimLup = denBK->
gCurrentDim(theindex, NL, TwoSLup, ILup);
1538 for (
int TwoSLdown=TwoSLup-1; TwoSLdown<=TwoSLup+1; TwoSLdown+=2){
1539 for (
int TwoSRup=TwoSLup-1; TwoSRup<=TwoSLup+1; TwoSRup+=2){
1541 int dimRup = denBK->
gCurrentDim(theindex+1, NL+1, TwoSRup, IRup);
1542 int dimLdown = denBK->
gCurrentDim(theindex, NL-1, TwoSLdown, Idown);
1543 int dimRdown = denBK->
gCurrentDim(theindex+1, NL+1, TwoSLdown, Idown);
1545 if ((dimLdown>0) && (dimRdown>0) && (dimRup>0)){
1547 double * T_up = denT->
gStorage(NL, TwoSLup, ILup, NL+1, TwoSRup, IRup);
1548 double * T_down = denT->
gStorage(NL-1, TwoSLdown, Idown, NL+1, TwoSLdown, Idown);
1549 double * Lblock = Lleft->
gStorage(NL-1, TwoSLdown, Idown, NL, TwoSLup, ILup);
1550 double * F1block = (shouldIdoD20) ? F1right->
gStorage(NL+1, TwoSLdown, Idown, NL+1, TwoSRup, IRup)
1551 : F1right->
gStorage(NL+1, TwoSRup, IRup, NL+1, TwoSLdown, Idown) ;
1555 char var = (shouldIdoD20) ? notrans : trans;
1558 int dimvar = (shouldIdoD20) ? dimRdown : dimRup ;
1560 dgemm_(&trans,¬rans,&dimLup,&dimRdown,&dimLdown,&alpha,Lblock,&dimLdown,T_down,&dimLdown,&beta,workmem,&dimLup);
1562 dgemm_(¬rans,&var,&dimLup,&dimRup,&dimRdown,&alpha,workmem,&dimLup,F1block,&dimvar,&beta,workmem2,&dimLup);
1564 double factor = 0.0;
1567 * sqrt((TwoSLup+1)*(TwoSRup+1)*(TwoSLdown+1)/3.0) *
Wigner::wigner6j( 1, 1, 2, TwoSRup, TwoSLdown, TwoSLup );
1570 * (TwoSRup+1) * sqrt((TwoSLup+1)/3.0) *
Wigner::wigner6j( 1, 1, 2, TwoSRup, TwoSLdown, TwoSLup );
1573 int length = dimLup * dimRup;
1575 total += factor * ddot_(&length, workmem2, &inc, T_up, &inc);
void FillSite(TensorT *denT, TensorL ***Ltens, TensorF0 ****F0tens, TensorF1 ****F1tens, TensorS0 ****S0tens, TensorS1 ****S1tens)
Fill the 2DM terms with as second site index denT->gIndex()
static double wigner6j(const int two_ja, const int two_jb, const int two_jc, const int two_jd, const int two_je, const int two_jf)
Wigner-6j symbol (gsl api)
int gNmin(const int boundary) const
Get the min. possible particle number for a certain boundary.
virtual ~TwoDM()
Destructor.
double get1RDM_HAM(const int cnt1, const int cnt2) const
Get a 1-RDM term, using the HAM indices.
bool gReorder() const
Get whether the Hamiltonian orbitals are reordered for the DMRG calculation.
int gIndex() const
Get the location index.
void save() const
Save the TwoDMs to disk.
int gCurrentDim(const int boundary, const int N, const int TwoS, const int irrep) const
Get the current virtual dimensions.
static int mpi_rank()
Get the rank of this MPI process.
double getTwoDMB_DMRG(const int cnt1, const int cnt2, const int cnt3, const int cnt4) const
Get a 2DM_B term, using the DMRG indices.
void symm_psi2molpro(int *psi2molpro) const
Fill the array psi2molpro with the irrep conventions of molpro for the currently activated group...
static int phase(const int power_times_two)
Phase function.
double energy() const
Calculate the energy based on the 2DM-A.
int gTwoSmin(const int boundary, const int N) const
Get the minimum possible spin value for a certain boundary and particle number.
double spin_density_dmrg(const int cnt1, const int cnt2) const
Get a spin-density term, using the DMRG indices.
int gTwoSmax(const int boundary, const int N) const
Get the maximum possible spin value for a certain boundary and particle number.
void correct_higher_multiplicities()
After the whole 2-RDM is filled, a prefactor for higher multiplicities should be applied.
int gN() const
Get the targeted particle number.
int gTwoS() const
Get twice the targeted spin.
double * gStorage()
Get the pointer to the storage.
double getTwoDMA_HAM(const int cnt1, const int cnt2, const int cnt3, const int cnt4) const
Get a 2DM_A term, using the HAM indices.
double gMxElement(const int alpha, const int beta, const int gamma, const int delta) const
Get a specific interaction matrix element.
double get1RDM_DMRG(const int cnt1, const int cnt2) const
Get a 1-RDM term, using the DMRG indices.
int gIrrep(const int nOrb) const
Get an orbital irrep.
double getTwoDMA_DMRG(const int cnt1, const int cnt2, const int cnt3, const int cnt4) const
Get a 2DM_A term, using the DMRG indices.
double trace() const
Return the double trace of 2DM-A (should be N(N-1))
double * gStorage()
Get the pointer to the storage.
int gf1(const int HamOrb) const
Get the DMRG index corresponding to a Ham index.
static void invert_triangle_two(const int global, int *result)
Triangle function for two variables.
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 gL() const
Get the number of orbitals.
double spin_density_ham(const int cnt1, const int cnt2) const
Get a spin-density term, using the HAM indices.
void mpi_allreduce()
Add the 2-RDM elements of all MPI processes.
int getNumberOfIrreps() const
Get the total number of irreps.
double getTwoDMB_HAM(const int cnt1, const int cnt2, const int cnt3, const int cnt4) const
Get a 2DM_B term, using the HAM indices.
void print_noon() const
Print the natural orbital occupation numbers.
int gL() const
Get the number of orbitals.
int gMaxDimAtBound(const int boundary) const
Get the maximum virtual dimension at a certain boundary.
void read()
Load the TwoDMs from disk.
void save_HAM(const string filename) const
Save the 2-RDM-A to disk in Hamiltonian indices.
int gNmax(const int boundary) const
Get the max. possible particle number for a certain boundary.
TwoDM(const SyBookkeeper *denBKIn, const Problem *ProbIn)
Constructor.
void write2DMAfile(const string filename) const
Write the 2-RDM-A to a file.
int gIrrep(const int orbital) const
Get an orbital irrep.
double gEconst() const
Get the constant part of the Hamiltonian.
int gSy() const
Get the point group symmetry.