35 #include "ConjugateGradient.h" 37 CheMPS2::FCI::FCI(
Hamiltonian * Ham,
const unsigned int theNel_up,
const unsigned int theNel_down,
const int TargetIrrep_in,
const double maxMemWorkMB_in,
const int FCIverbose_in){
40 FCIverbose = FCIverbose_in;
41 maxMemWorkMB = maxMemWorkMB_in;
43 assert( theNel_up <= L );
44 assert( theNel_down <= L );
45 assert( maxMemWorkMB > 0.0 );
47 Nel_down = theNel_down;
51 TargetIrrep = TargetIrrep_in;
52 orb2irrep =
new int[ L ];
53 for (
unsigned int orb = 0; orb < L; orb++){ orb2irrep[ orb ] = Ham->
getOrbitalIrrep( orb ); }
59 Gmat =
new double[ L * L ];
60 ERI =
new double[ L * L * L * L ];
61 for (
unsigned int orb1 = 0; orb1 < L; orb1++){
62 for (
unsigned int orb2 = 0; orb2 < L; orb2++){
64 for (
unsigned int orb3 = 0; orb3 < L; orb3++){
65 tempvar += Ham->
getVmat( orb1, orb3, orb3, orb2 );
66 for (
unsigned int orb4 = 0; orb4 < L; orb4++){
68 ERI[ orb1 + L * ( orb2 + L * ( orb3 + L * orb4 ) ) ] = Ham->
getVmat( orb1 , orb3 , orb2 , orb4 );
71 Gmat[ orb1 + L * orb2 ] = Ham->
getTmat( orb1 , orb2 ) - 0.5 * tempvar;
76 StartupCountersVsBitstrings();
77 StartupLookupTables();
90 for (
unsigned int irrep=0; irrep<num_irreps; irrep++ ){
91 delete [] str2cnt_up[irrep];
92 delete [] str2cnt_down[irrep];
93 delete [] cnt2str_up[irrep];
94 delete [] cnt2str_down[irrep];
97 delete [] str2cnt_down;
99 delete [] cnt2str_down;
100 delete [] numPerIrrep_up;
101 delete [] numPerIrrep_down;
104 for (
unsigned int irrep = 0; irrep < num_irreps; irrep++ ){
105 for (
unsigned int ij = 0; ij < L * L; ij++ ){
106 delete [] lookup_cnt_alpha[irrep][ij];
107 delete [] lookup_cnt_beta[irrep][ij];
108 delete [] lookup_sign_alpha[irrep][ij];
109 delete [] lookup_sign_beta[irrep][ij];
111 delete [] lookup_cnt_alpha[irrep];
112 delete [] lookup_cnt_beta[irrep];
113 delete [] lookup_sign_alpha[irrep];
114 delete [] lookup_sign_beta[irrep];
116 delete [] lookup_cnt_alpha;
117 delete [] lookup_cnt_beta;
118 delete [] lookup_sign_alpha;
119 delete [] lookup_sign_beta;
122 for (
unsigned int irrep=0; irrep<num_irreps; irrep++ ){
123 delete [] irrep_center_crea_orb[irrep];
124 delete [] irrep_center_anni_orb[irrep];
125 delete [] irrep_center_jumps[irrep];
127 delete [] irrep_center_crea_orb;
128 delete [] irrep_center_anni_orb;
129 delete [] irrep_center_jumps;
130 delete [] irrep_center_num;
131 delete [] HXVworksmall;
132 delete [] HXVworkbig1;
133 delete [] HXVworkbig2;
137 void CheMPS2::FCI::StartupCountersVsBitstrings(){
140 assert( L <= CHAR_BIT *
sizeof(
unsigned int) );
143 unsigned int TwoPowL = 1;
144 for (
unsigned int orb = 0; orb < L; orb++){ TwoPowL *= 2; }
147 numPerIrrep_up =
new unsigned int[ num_irreps ];
148 numPerIrrep_down =
new unsigned int[ num_irreps ];
149 str2cnt_up =
new int*[ num_irreps ];
150 str2cnt_down =
new int*[ num_irreps ];
151 cnt2str_up =
new unsigned int*[ num_irreps ];
152 cnt2str_down =
new unsigned int*[ num_irreps ];
154 for (
unsigned int irrep = 0; irrep < num_irreps; irrep++){
155 numPerIrrep_up [ irrep ] = 0;
156 numPerIrrep_down[ irrep ] = 0;
157 str2cnt_up [ irrep ] =
new int[ TwoPowL ];
158 str2cnt_down[ irrep ] =
new int[ TwoPowL ];
161 int * bits =
new int[ L ];
164 for (
unsigned int bitstring = 0; bitstring < TwoPowL; bitstring++){
168 unsigned int Nparticles = 0;
170 for (
unsigned int orb=0; orb<L; orb++){
178 for (
unsigned int irr = 0; irr < num_irreps; irr++ ){
179 str2cnt_up [ irr ][ bitstring ] = -1;
180 str2cnt_down[ irr ][ bitstring ] = -1;
182 if ( Nparticles == Nel_up ){
183 str2cnt_up[ irrep ][ bitstring ] = numPerIrrep_up[ irrep ];
184 numPerIrrep_up[ irrep ]++;
186 if ( Nparticles == Nel_down ){
187 str2cnt_down[ irrep ][ bitstring ] = numPerIrrep_down[ irrep ];
188 numPerIrrep_down[ irrep ]++;
194 for (
unsigned int irrep = 0; irrep < num_irreps; irrep++ ){
197 cout <<
"FCI::Startup : For irrep " << irrep <<
" there are " << numPerIrrep_up [ irrep ] <<
" alpha Slater determinants and " 198 << numPerIrrep_down[ irrep ] <<
" beta Slater determinants." << endl;
201 cnt2str_up [ irrep ] =
new unsigned int[ numPerIrrep_up [ irrep ] ];
202 cnt2str_down[ irrep ] =
new unsigned int[ numPerIrrep_down[ irrep ] ];
203 for (
unsigned int bitstring = 0; bitstring < TwoPowL; bitstring++){
204 if ( str2cnt_up [ irrep ][ bitstring ] != -1 ){ cnt2str_up [ irrep ][ str2cnt_up [ irrep ][ bitstring ] ] = bitstring; }
205 if ( str2cnt_down[ irrep ][ bitstring ] != -1 ){ cnt2str_down[ irrep ][ str2cnt_down[ irrep ][ bitstring ] ] = bitstring; }
214 void CheMPS2::FCI::StartupLookupTables(){
217 lookup_cnt_alpha =
new int**[ num_irreps ];
218 lookup_cnt_beta =
new int**[ num_irreps ];
219 lookup_sign_alpha =
new int**[ num_irreps ];
220 lookup_sign_beta =
new int**[ num_irreps ];
222 int * bits =
new int[ L ];
225 for (
unsigned int irrep = 0; irrep < num_irreps; irrep++ ){
227 const unsigned int num_up = numPerIrrep_up [ irrep ];
228 const unsigned int num_down = numPerIrrep_down[ irrep ];
230 lookup_cnt_alpha [ irrep ] =
new int*[ L * L ];
231 lookup_cnt_beta [ irrep ] =
new int*[ L * L ];
232 lookup_sign_alpha[ irrep ] =
new int*[ L * L ];
233 lookup_sign_beta [ irrep ] =
new int*[ L * L ];
235 for (
unsigned int ij = 0; ij < L * L; ij++ ){
237 lookup_cnt_alpha [ irrep ][ ij ] =
new int[ num_up ];
238 lookup_cnt_beta [ irrep ][ ij ] =
new int[ num_down ];
239 lookup_sign_alpha[ irrep ][ ij ] =
new int[ num_up ];
240 lookup_sign_beta [ irrep ][ ij ] =
new int[ num_down ];
242 for (
unsigned int cnt_new_alpha = 0; cnt_new_alpha < num_up; cnt_new_alpha++ ){
244 lookup_cnt_alpha [ irrep ][ ij ][ cnt_new_alpha ] = 0;
245 lookup_sign_alpha[ irrep ][ ij ][ cnt_new_alpha ] = 0;
247 for (
unsigned int cnt_new_beta = 0; cnt_new_beta < num_down; cnt_new_beta++ ){
249 lookup_cnt_beta [ irrep ][ ij ][ cnt_new_beta ] = 0;
250 lookup_sign_beta[ irrep ][ ij ][ cnt_new_beta ] = 0;
254 for (
unsigned int cnt_new_alpha = 0; cnt_new_alpha < num_up; cnt_new_alpha++ ){
256 str2bits( L , cnt2str_up[ irrep ][ cnt_new_alpha ] , bits );
259 for (
unsigned int crea = 0; crea < L; crea++ ){
264 for (
unsigned int anni = 0; anni < L; anni++ ){
265 if ( !(bits[ anni ]) ){
269 const int cnt_old = str2cnt_up[ irrep_old ][
bits2str( L , bits ) ];
270 const int phase = phase_crea * phase_anni;
272 lookup_cnt_alpha [ irrep ][ crea + L * anni ][ cnt_new_alpha ] = cnt_old;
273 lookup_sign_alpha[ irrep ][ crea + L * anni ][ cnt_new_alpha ] = phase;
287 for (
unsigned int cnt_new_beta = 0; cnt_new_beta < num_down; cnt_new_beta++ ){
289 str2bits( L , cnt2str_down[ irrep ][ cnt_new_beta ] , bits );
292 for (
unsigned int crea = 0; crea < L; crea++ ){
297 for (
unsigned int anni = 0; anni < L; anni++ ){
298 if ( !(bits[ anni ]) ){
302 const int cnt_old = str2cnt_down[ irrep_old ][
bits2str( L , bits ) ];
303 const int phase = phase_crea * phase_anni;
305 lookup_cnt_beta [ irrep ][ crea + L * anni ][ cnt_new_beta ] = cnt_old;
306 lookup_sign_beta [ irrep ][ crea + L * anni ][ cnt_new_beta ] = phase;
326 void CheMPS2::FCI::StartupIrrepCenter(){
329 irrep_center_num =
new unsigned int [ num_irreps ];
330 irrep_center_crea_orb =
new unsigned int*[ num_irreps ];
331 irrep_center_anni_orb =
new unsigned int*[ num_irreps ];
333 for (
unsigned int irrep_center = 0; irrep_center < num_irreps; irrep_center++ ){
334 const int irrep_center_const_signed = irrep_center;
336 irrep_center_num[ irrep_center ] = 0;
337 for (
unsigned int crea = 0; crea < L; crea++ ){
338 for (
unsigned int anni = crea; anni < L; anni++ ){
340 irrep_center_num[ irrep_center ] += 1;
344 irrep_center_crea_orb[ irrep_center ] =
new unsigned int[ irrep_center_num[ irrep_center ] ];
345 irrep_center_anni_orb[ irrep_center ] =
new unsigned int[ irrep_center_num[ irrep_center ] ];
346 irrep_center_num[ irrep_center ] = 0;
347 for (
unsigned int creator = 0; creator < L; creator++ ){
348 for (
unsigned int annihilator = creator; annihilator < L; annihilator++){
350 irrep_center_crea_orb[ irrep_center ][ irrep_center_num[ irrep_center ] ] = creator;
351 irrep_center_anni_orb[ irrep_center ][ irrep_center_num[ irrep_center ] ] = annihilator;
352 irrep_center_num[ irrep_center ] += 1;
359 irrep_center_jumps =
new unsigned int*[ num_irreps ];
360 HXVsizeWorkspace = 0;
361 for (
unsigned int irrep_center = 0; irrep_center < num_irreps; irrep_center++ ){
362 unsigned long long check = 0;
363 irrep_center_jumps[ irrep_center ] =
new unsigned int[ num_irreps + 1 ];
365 irrep_center_jumps[ irrep_center ][ 0 ] = 0;
366 for (
unsigned int irrep_up = 0; irrep_up < num_irreps; irrep_up++ ){
368 check += ((
unsigned long long) numPerIrrep_up[ irrep_up ] ) * ((
unsigned long long) numPerIrrep_down[ irrep_down ] );
369 unsigned int temp = numPerIrrep_up[ irrep_up ] * numPerIrrep_down[ irrep_down ];
370 irrep_center_jumps[ irrep_center ][ irrep_up + 1 ] = irrep_center_jumps[ irrep_center ][ irrep_up ] + temp;
371 HXVsizeWorkspace = std::max( HXVsizeWorkspace, ((
unsigned long long) irrep_center_num[ irrep_center ] ) * ((
unsigned long long) temp ) );
373 assert( check <= ((
unsigned int) INT_MAX ) );
375 if ( FCIverbose > 0 ){
376 cout <<
"FCI::Startup : Number of variables in the FCI vector = " <<
getVecLength( 0 ) << endl;
377 double num_megabytes = ( 2.0 *
sizeof(double) * HXVsizeWorkspace ) / 1048576;
378 cout <<
"FCI::Startup : Without additional loops the FCI matrix-vector product requires a workspace of " << num_megabytes <<
" MB memory." << endl;
379 if ( maxMemWorkMB < num_megabytes ){
380 HXVsizeWorkspace = (
unsigned int) ceil( ( maxMemWorkMB * 1048576 ) / ( 2 *
sizeof(double) ) );
381 num_megabytes = ( 2.0 *
sizeof(double) * HXVsizeWorkspace ) / 1048576;
382 cout <<
" For practical purposes, the workspace is constrained to " << num_megabytes <<
" MB memory." << endl;
385 HXVworksmall =
new double[ L * L * L * L ];
386 HXVworkbig1 =
new double[ HXVsizeWorkspace ];
387 HXVworkbig2 =
new double[ HXVsizeWorkspace ];
393 for (
unsigned int bit = 0; bit < Lval; bit++){ bits[ bit ] = ( bitstring & ( 1 << bit ) ) >> bit; }
399 unsigned int factor = 1;
400 unsigned int result = 0;
401 for (
unsigned int bit = 0; bit < Lval; bit++){
402 result += bits[ bit ] * factor;
411 int irrep_up = num_irreps;
412 while ( counter < irrep_center_jumps[ irrep_center ][ irrep_up-1 ] ){ irrep_up--; }
424 const unsigned int count_up = ( counter - irrep_center_jumps[ irrep_center ][ irrep_up ] ) % numPerIrrep_up[ irrep_up ];
425 const unsigned int count_down = ( counter - irrep_center_jumps[ irrep_center ][ irrep_up ] ) / numPerIrrep_up[ irrep_up ];
427 const unsigned int string_up = cnt2str_up [ irrep_up ][ count_up ];
428 const unsigned int string_down = cnt2str_down[ irrep_down ][ count_down ];
430 str2bits( L , string_up , bits_up );
431 str2bits( L , string_down , bits_down );
437 const unsigned string_up =
bits2str(L, bits_up );
438 const unsigned string_down =
bits2str(L, bits_down);
442 for (
unsigned int orb = 0; orb < L; orb++ ){
447 const int counter_up = str2cnt_up [ irrep_up ][ string_up ];
448 const int counter_down = str2cnt_down[ irrep_down ][ string_down ];
450 if (( counter_up == -1 ) || ( counter_down == -1 )){
return 0.0; }
452 return vector[ irrep_center_jumps[ 0 ][ irrep_up ] + counter_up + numPerIrrep_up[ irrep_up ] * counter_down ];
530 void CheMPS2::FCI::excite_alpha_omp(
const unsigned int dim_new_up,
const unsigned int dim_old_up,
const unsigned int dim_down,
double * origin,
double * result,
int * signmap,
int * countmap ){
532 #pragma omp parallel for schedule(static) 533 for (
unsigned int cnt_new_up = 0; cnt_new_up < dim_new_up; cnt_new_up++ ){
534 const int sign_up = signmap[ cnt_new_up ];
536 const int cnt_old_up = countmap[ cnt_new_up ];
537 for (
unsigned int cnt_down = 0; cnt_down < dim_down; cnt_down++ ){
538 result[ cnt_new_up + dim_new_up * cnt_down ] += sign_up * origin[ cnt_old_up + dim_old_up * cnt_down ];
545 void CheMPS2::FCI::excite_beta_omp(
const unsigned int dim_up,
const unsigned int dim_new_down,
double * origin,
double * result,
int * signmap,
int * countmap ){
547 #pragma omp parallel for schedule(static) 548 for (
unsigned int cnt_new_down = 0; cnt_new_down < dim_new_down; cnt_new_down++ ){
549 const int sign_down = signmap[ cnt_new_down ];
550 if ( sign_down != 0 ){
551 const int cnt_old_down = countmap[ cnt_new_down ];
552 for (
unsigned int cnt_up = 0; cnt_up < dim_up; cnt_up++ ){
553 result[ cnt_up + dim_up * cnt_new_down ] += sign_down * origin[ cnt_up + dim_up * cnt_old_down ];
560 void CheMPS2::FCI::excite_alpha_first(
const unsigned int dim_new_up,
const unsigned int dim_old_up,
const unsigned int start_down,
const unsigned int stop_down,
double * origin,
double * result,
int * signmap,
int * countmap ){
562 for (
unsigned int cnt_new_up = 0; cnt_new_up < dim_new_up; cnt_new_up++ ){
563 const int sign_up = signmap[ cnt_new_up ];
565 const int cnt_old_up = countmap[ cnt_new_up ];
566 for (
unsigned int cnt_down = start_down; cnt_down < stop_down; cnt_down++ ){
567 result[ cnt_new_up + dim_new_up * ( cnt_down - start_down ) ] += sign_up * origin[ cnt_old_up + dim_old_up * cnt_down ];
574 void CheMPS2::FCI::excite_beta_first(
const unsigned int dim_up,
const unsigned int start_down,
const unsigned int stop_down,
double * origin,
double * result,
int * signmap,
int * countmap ){
576 for (
unsigned int cnt_new_down = start_down; cnt_new_down < stop_down; cnt_new_down++ ){
577 const int sign_down = signmap[ cnt_new_down ];
578 if ( sign_down != 0 ){
579 const int cnt_old_down = countmap[ cnt_new_down ];
580 for (
unsigned int cnt_up = 0; cnt_up < dim_up; cnt_up++ ){
581 result[ cnt_up + dim_up * ( cnt_new_down - start_down ) ] += sign_down * origin[ cnt_up + dim_up * cnt_old_down ];
588 void CheMPS2::FCI::excite_alpha_second_omp(
const unsigned int dim_new_up,
const unsigned int dim_old_up,
const unsigned int start_down,
const unsigned int stop_down,
double * origin,
double * result,
int * signmap,
int * countmap ){
590 #pragma omp parallel for schedule(static) 591 for (
unsigned int cnt_old_up = 0; cnt_old_up < dim_old_up; cnt_old_up++ ){
592 const int sign_up = signmap[ cnt_old_up ];
594 const int cnt_new_up = countmap[ cnt_old_up ];
595 for (
unsigned int cnt_down = start_down; cnt_down < stop_down; cnt_down++ ){
596 result[ cnt_new_up + dim_new_up * cnt_down ] += sign_up * origin[ cnt_old_up + dim_old_up * ( cnt_down - start_down ) ];
603 void CheMPS2::FCI::excite_beta_second_omp(
const unsigned int dim_up,
const unsigned int start_down,
const unsigned int stop_down,
double * origin,
double * result,
int * signmap,
int * countmap ){
605 #pragma omp parallel for schedule(static) 606 for (
unsigned int cnt_old_down = start_down; cnt_old_down < stop_down; cnt_old_down++ ){
607 const int sign_down = signmap[ cnt_old_down ];
608 if ( sign_down != 0 ){
609 const int cnt_new_down = countmap[ cnt_old_down ];
610 for (
unsigned int cnt_up = 0; cnt_up < dim_up; cnt_up++ ){
611 result[ cnt_up + dim_up * cnt_new_down ] += sign_down * origin[ cnt_up + dim_up * ( cnt_old_down - start_down ) ];
620 struct timeval start, end;
621 gettimeofday( &start, NULL );
628 for (
unsigned int irrep_center = 0; irrep_center < num_irreps; irrep_center++ ){
631 const unsigned int num_pairs = irrep_center_num[ irrep_center ];
632 const unsigned int * center_crea_orb = irrep_center_crea_orb[ irrep_center ];
633 const unsigned int * center_anni_orb = irrep_center_anni_orb[ irrep_center ];
634 const unsigned int * zero_jumps = irrep_center_jumps[ 0 ];
636 for (
unsigned int irrep_center_up = 0; irrep_center_up < num_irreps; irrep_center_up++ ){
637 const int irrep_center_down =
Irreps::directProd( irrep_target_center, irrep_center_up );
638 const unsigned int dim_center_up = numPerIrrep_up [ irrep_center_up ];
639 const unsigned int dim_center_down = numPerIrrep_down[ irrep_center_down ];
640 if ( dim_center_up * dim_center_down > 0 ){
641 const unsigned int blocksize_beta = HXVsizeWorkspace / std::max( (
unsigned int) 1, dim_center_up * num_pairs );
642 assert( blocksize_beta > 0 );
643 unsigned int num_block_beta = dim_center_down / blocksize_beta;
644 while ( blocksize_beta * num_block_beta < dim_center_down ){ num_block_beta++; }
645 for (
unsigned int block = 0; block < num_block_beta; block++ ){
646 const unsigned int start_center_down = block * blocksize_beta;
647 const unsigned int stop_center_down = std::min( ( block + 1 ) * blocksize_beta, dim_center_down );
648 const unsigned int size_center = dim_center_up * ( stop_center_down - start_center_down );
649 if ( size_center > 0 ){
652 #pragma omp parallel for schedule(static) 653 for (
unsigned int pair = 0; pair < num_pairs; pair++ ){
654 double * target_space = HXVworkbig1 + size_center * pair;
655 const unsigned int crea = center_crea_orb[ pair ];
656 const unsigned int anni = center_anni_orb[ pair ];
659 const unsigned int dim_zero_up = numPerIrrep_up[ irrep_zero_up ];
660 for (
unsigned int count = 0; count < size_center; count++ ){ target_space[ count ] = 0.0; }
662 excite_alpha_first( dim_center_up, dim_zero_up, start_center_down, stop_center_down,
663 input + zero_jumps[ irrep_zero_up ],
665 lookup_sign_alpha[ irrep_center_up ][ crea + L * anni ],
666 lookup_cnt_alpha [ irrep_center_up ][ crea + L * anni ] );
668 excite_beta_first( dim_center_up, start_center_down, stop_center_down,
669 input + zero_jumps[ irrep_center_up ],
671 lookup_sign_beta[ irrep_center_down ][ crea + L * anni ],
672 lookup_cnt_beta [ irrep_center_down ][ crea + L * anni ] );
676 excite_alpha_first( dim_center_up, dim_zero_up, start_center_down, stop_center_down,
677 input + zero_jumps[ irrep_zero_up ],
679 lookup_sign_alpha[ irrep_center_up ][ anni + L * crea ],
680 lookup_cnt_alpha [ irrep_center_up ][ anni + L * crea ] );
682 excite_beta_first( dim_center_up, start_center_down, stop_center_down,
683 input + zero_jumps[ irrep_center_up ],
685 lookup_sign_beta[ irrep_center_down ][ anni + L * crea ],
686 lookup_cnt_beta [ irrep_center_down ][ anni + L * crea ] );
692 if ( irrep_center == 0 ){
693 for (
unsigned int pair = 0; pair < num_pairs; pair++ ){
694 HXVworksmall[ pair ] =
getGmat( center_crea_orb[ pair ], center_anni_orb[ pair ] );
698 int mdim = size_center;
699 int kdim = num_pairs;
701 double * target = output + zero_jumps[ irrep_center_up ] + dim_center_up * start_center_down;
702 dgemm_( ¬rans, ¬rans, &mdim, &ndim, &kdim, &one, HXVworkbig1, &mdim, HXVworksmall, &kdim, &one, target, &mdim );
707 for (
unsigned int pair1 = 0; pair1 < num_pairs; pair1++ ){
708 for (
unsigned int pair2 = 0; pair2 < num_pairs; pair2++ ){
709 HXVworksmall[ pair1 + num_pairs * pair2 ]
710 = 0.5 *
getERI( center_crea_orb[ pair1 ], center_anni_orb[ pair1 ] ,
711 center_crea_orb[ pair2 ], center_anni_orb[ pair2 ] );
717 int mdim = size_center;
718 int kdim = num_pairs;
719 int ndim = num_pairs;
720 dgemm_( ¬rans, ¬rans, &mdim, &ndim, &kdim, &one, HXVworkbig1, &mdim, HXVworksmall, &kdim, &
set, HXVworkbig2, &mdim );
724 for (
unsigned int pair = 0; pair < num_pairs; pair++ ){
725 double * origin_space = HXVworkbig2 + size_center * pair;
726 const unsigned int crea = center_crea_orb[ pair ];
727 const unsigned int anni = center_anni_orb[ pair ];
730 const unsigned int dim_zero_up = numPerIrrep_up[ irrep_zero_up ];
732 excite_alpha_second_omp( dim_zero_up, dim_center_up, start_center_down, stop_center_down,
734 output + zero_jumps[ irrep_zero_up ],
735 lookup_sign_alpha[ irrep_center_up ][ anni + L * crea ],
736 lookup_cnt_alpha [ irrep_center_up ][ anni + L * crea ] );
738 excite_beta_second_omp( dim_center_up, start_center_down, stop_center_down,
740 output + zero_jumps[ irrep_center_up ],
741 lookup_sign_beta[ irrep_center_down ][ anni + L * crea ],
742 lookup_cnt_beta [ irrep_center_down ][ anni + L * crea ] );
746 excite_alpha_second_omp( dim_zero_up, dim_center_up, start_center_down, stop_center_down,
748 output + zero_jumps[ irrep_zero_up ],
749 lookup_sign_alpha[ irrep_center_up ][ crea + L * anni ],
750 lookup_cnt_alpha [ irrep_center_up ][ crea + L * anni ] );
752 excite_beta_second_omp( dim_center_up, start_center_down, stop_center_down,
754 output + zero_jumps[ irrep_center_up ],
755 lookup_sign_beta[ irrep_center_down ][ crea + L * anni ],
756 lookup_cnt_beta [ irrep_center_down ][ crea + L * anni ] );
766 gettimeofday( &end, NULL );
767 const double elapsed = ( end.tv_sec - start.tv_sec ) + 1e-6 * ( end.tv_usec - start.tv_usec );
768 if ( FCIverbose >= 1 ){ cout <<
"FCI::matvec : Wall time = " << elapsed <<
" seconds" << endl; }
775 const int result_target_irrep =
Irreps::directProd( excitation_irrep, orig_target_irrep );
777 const int result_irrep_center =
Irreps::directProd( TargetIrrep, result_target_irrep );
781 for (
unsigned int result_irrep_up = 0; result_irrep_up < num_irreps; result_irrep_up++ ){
783 const int result_irrep_down =
Irreps::directProd( result_irrep_up, result_target_irrep );
786 excite_alpha_omp( numPerIrrep_up [ result_irrep_up ],
787 numPerIrrep_up [ orig_irrep_up ],
788 numPerIrrep_down[ result_irrep_down ],
789 orig_vector + irrep_center_jumps[ orig_irrep_center ][ orig_irrep_up ],
790 result_vector + irrep_center_jumps[ result_irrep_center ][ result_irrep_up ],
791 lookup_sign_alpha[ result_irrep_up ][ crea + L * anni ],
792 lookup_cnt_alpha [ result_irrep_up ][ crea + L * anni ] );
794 excite_beta_omp( numPerIrrep_up [ result_irrep_up ],
795 numPerIrrep_down[ result_irrep_down ],
796 orig_vector + irrep_center_jumps[ orig_irrep_center ][ result_irrep_up ],
797 result_vector + irrep_center_jumps[ result_irrep_center ][ result_irrep_up ],
798 lookup_sign_beta[ result_irrep_down ][ crea + L * anni ],
799 lookup_cnt_beta [ result_irrep_down ][ crea + L * anni ] );
807 assert( Nel_up + Nel_down >= 2 );
809 struct timeval start, end;
810 gettimeofday(&start, NULL);
814 unsigned int max_length = 0;
815 for (
unsigned int irrep = 0; irrep < num_irreps; irrep++ ){
818 double * workspace1 =
new double[ max_length ];
819 double * workspace2 =
new double[ orig_length ];
822 for (
unsigned int anni1 = 0; anni1 < L; anni1++ ){
823 for (
unsigned int crea1 = anni1; crea1 < L; crea1++ ){
829 if ( irrep_center1 == 0 ){
830 const double value =
FCIddot( orig_length, workspace1, vector );
831 for (
unsigned int jk = anni1; jk < L; jk++ ){
832 two_rdm[ crea1 + L * ( jk + L * ( jk + L * anni1 ) ) ] -= value;
836 for (
unsigned int crea2 = anni1; crea2 < L; crea2++ ){
837 for (
unsigned int anni2 = anni1; anni2 < L; anni2++ ){
840 if ( irrep_center2 == irrep_center1 ){
843 const double value =
FCIddot( orig_length, workspace2, vector );
844 two_rdm[ crea2 + L * ( crea1 + L * ( anni2 + L * anni1 ) ) ] += value;
851 delete [] workspace1;
852 delete [] workspace2;
854 for (
unsigned int anni1 = 0; anni1 < L; anni1++ ){
855 for (
unsigned int crea1 = anni1; crea1 < L; crea1++ ){
857 for (
unsigned int crea2 = anni1; crea2 < L; crea2++ ){
858 for (
unsigned int anni2 = anni1; anni2 < L; anni2++ ){
860 if ( irrep_center2 == irrep_center1 ){
861 const double value = two_rdm[ crea2 + L * ( crea1 + L * ( anni2 + L * anni1 ) ) ];
862 two_rdm[ crea1 + L * ( crea2 + L * ( anni1 + L * anni2 ) ) ] = value;
863 two_rdm[ anni2 + L * ( anni1 + L * ( crea2 + L * crea1 ) ) ] = value;
864 two_rdm[ anni1 + L * ( anni2 + L * ( crea1 + L * crea2 ) ) ] = value;
873 for (
unsigned int orb1 = 0; orb1 < L; orb1++ ){
874 for (
unsigned int orb2 = 0; orb2 < L; orb2++ ){
875 double tempvar = 0.0;
876 double tempvar2 = 0.0;
877 for (
unsigned int orb3 = 0; orb3 < L; orb3++ ){
878 tempvar +=
getERI( orb1 , orb3 , orb3 , orb2 );
879 tempvar2 += two_rdm[ orb1 + L * ( orb3 + L * ( orb2 + L * orb3 ) ) ];
880 for (
unsigned int orb4 = 0; orb4 < L; orb4++ ){
881 FCIenergy += 0.5 * two_rdm[ orb1 + L * ( orb2 + L * ( orb3 + L * orb4 ) ) ] *
getERI( orb1 , orb3 , orb2 , orb4 );
884 FCIenergy += (
getGmat( orb1 , orb2 ) + 0.5 * tempvar ) * tempvar2 / ( Nel_up + Nel_down - 1.0);
888 gettimeofday(&end, NULL);
889 const double elapsed = (end.tv_sec - start.tv_sec) + 1e-6 * (end.tv_usec - start.tv_usec);
890 if ( FCIverbose > 0 ){ cout <<
"FCI::Fill2RDM : Wall time = " << elapsed <<
" seconds" << endl; }
891 if ( FCIverbose > 0 ){ cout <<
"FCI::Fill2RDM : Energy (Ham * 2-RDM) = " << FCIenergy << endl; }
898 assert( Nel_up + Nel_down >= 4 );
900 struct timeval start, end;
901 gettimeofday(&start, NULL);
933 for (
unsigned int irrep = 1; irrep < num_irreps; irrep++ ){
936 double * workspace1 =
new double[ max_length ];
937 double * workspace2 =
new double[ max_length ];
938 double * workspace3 =
new double[ max_length ];
939 double * workspace4 =
new double[ orig_length ];
941 for (
unsigned int anni1 = 0; anni1 < L; anni1++ ){
942 for (
unsigned int crea1 = anni1; crea1 < L; crea1++ ){
948 if ( irrep_center1 == 0 ){
951 const double value =
FCIddot( orig_length, workspace1, vector );
952 for (
unsigned int p = anni1; p < L; p++ ){
953 for (
unsigned int q = anni1; q < L; q++ ){
954 for (
unsigned int r = anni1; r < L; r++ ){
956 four_rdm[ crea1 + L*( p + L*( q + L*( r + L*( p + L*( q + L*( r + L * anni1 ))))))] -= value;
957 four_rdm[ crea1 + L*( r + L*( p + L*( q + L*( p + L*( q + L*( r + L * anni1 ))))))] -= value;
958 four_rdm[ q + L*( crea1 + L*( p + L*( r + L*( p + L*( q + L*( r + L * anni1 ))))))] -= value;
959 four_rdm[ r + L*( crea1 + L*( q + L*( p + L*( p + L*( q + L*( r + L * anni1 ))))))] -= value;
960 four_rdm[ r + L*( p + L*( crea1 + L*( q + L*( p + L*( q + L*( r + L * anni1 ))))))] -= value;
961 four_rdm[ q + L*( r + L*( crea1 + L*( p + L*( p + L*( q + L*( r + L * anni1 ))))))] -= value;
968 for (
unsigned int crea2 = anni1; crea2 < L; crea2++ ){
969 for (
unsigned int anni2 = anni1; anni2 < L; anni2++ ){
975 if ( irrep_center1 == irrep_center2 ){
978 const double value =
FCIddot( orig_length, workspace2, vector );
979 for (
unsigned int orb = anni1; orb < L; orb++ ){
980 for (
unsigned int xyz = anni1; xyz < L; xyz++ ){
982 four_rdm[ crea2 + L*( crea1 + L*( xyz + L*( orb + L*( anni2 + L*( xyz + L*( orb + L * anni1 ))))))] += value;
983 four_rdm[ crea1 + L*( crea2 + L*( xyz + L*( orb + L*( xyz + L*( anni2 + L*( orb + L * anni1 ))))))] += value;
984 four_rdm[ crea2 + L*( xyz + L*( crea1 + L*( orb + L*( xyz + L*( anni2 + L*( orb + L * anni1 ))))))] += value;
985 four_rdm[ crea2 + L*( xyz + L*( crea1 + L*( orb + L*( anni2 + L*( orb + L*( xyz + L * anni1 ))))))] += value;
986 four_rdm[ crea2 + L*( crea1 + L*( xyz + L*( orb + L*( xyz + L*( orb + L*( anni2 + L * anni1 ))))))] += value;
987 four_rdm[ crea1 + L*( xyz + L*( crea2 + L*( orb + L*( xyz + L*( orb + L*( anni2 + L * anni1 ))))))] += value;
988 four_rdm[ crea1 + L*( crea2 + L*( xyz + L*( orb + L*( orb + L*( xyz + L*( anni2 + L * anni1 ))))))] += value;
989 four_rdm[ xyz + L*( crea1 + L*( crea2 + L*( orb + L*( orb + L*( xyz + L*( anni2 + L * anni1 ))))))] += value;
990 four_rdm[ xyz + L*( crea2 + L*( crea1 + L*( orb + L*( orb + L*( anni2 + L*( xyz + L * anni1 ))))))] += value;
991 four_rdm[ crea2 + L*( xyz + L*( orb + L*( crea1 + L*( xyz + L*( orb + L*( anni2 + L * anni1 ))))))] += value;
992 four_rdm[ crea2 + L*( xyz + L*( orb + L*( crea1 + L*( orb + L*( anni2 + L*( xyz + L * anni1 ))))))] += value;
998 for (
unsigned int crea3 = anni1; crea3 < L; crea3++ ){
999 for (
unsigned int anni3 = (( anni1 == anni2 ) ? anni1 + 1 : anni1 ); anni3 < L; anni3++ ){
1006 if ( irrep_center4 == 0 ){
1009 const double value =
FCIddot( orig_length, workspace3, vector );
1010 for (
unsigned int orb = anni1; orb < L; orb++ ){
1012 four_rdm[ crea3 + L*( crea2 + L*( crea1 + L*( orb + L*( anni3 + L*( anni2 + L*( orb + L * anni1 ))))))] -= value;
1013 four_rdm[ crea3 + L*( crea1 + L*( crea2 + L*( orb + L*( anni3 + L*( orb + L*( anni2 + L * anni1 ))))))] -= value;
1014 four_rdm[ crea1 + L*( crea3 + L*( crea2 + L*( orb + L*( orb + L*( anni3 + L*( anni2 + L * anni1 ))))))] -= value;
1015 four_rdm[ crea3 + L*( crea2 + L*( orb + L*( crea1 + L*( anni3 + L*( orb + L*( anni2 + L * anni1 ))))))] -= value;
1016 four_rdm[ crea3 + L*( crea2 + L*( orb + L*( crea1 + L*( orb + L*( anni2 + L*( anni3 + L * anni1 ))))))] -= value;
1017 four_rdm[ crea3 + L*( orb + L*( crea2 + L*( crea1 + L*( orb + L*( anni3 + L*( anni2 + L * anni1 ))))))] -= value;
1022 if ( crea3 >= (( crea1 == crea2 ) ? crea2 + 1 : crea2 ) ){
1024 for (
unsigned int crea4 = (( crea2 == crea3 ) ? crea3 + 1 : crea3 ); crea4 < L; crea4++ ){
1025 for (
unsigned int anni4 = (( anni1 == anni2 ) ? anni1 + 1 : anni1 ); anni4 < L; anni4++ ){
1027 if ( (( anni2 == anni3 ) && ( anni3 == anni4 )) == false ){
1030 if ( irrep_product4 == irrep_center4 ){
1034 const double value =
FCIddot( orig_length, workspace4, vector );
1035 four_rdm[ crea4 + L*( crea3 + L*( crea2 + L*( crea1 + L*( anni4 + L*( anni3 + L*( anni2 + L * anni1 ))))))] += value;
1048 delete [] workspace1;
1049 delete [] workspace2;
1050 delete [] workspace3;
1051 delete [] workspace4;
1054 for (
unsigned int anni1 = 0; anni1 < L; anni1++ ){
1055 for (
unsigned int crea1 = anni1; crea1 < L; crea1++ ){
1057 for (
unsigned int crea2 = anni1; crea2 < L; crea2++ ){
1058 for (
unsigned int anni2 = anni1; anni2 < L; anni2++ ){
1061 for (
unsigned int crea3 = crea2; crea3 < L; crea3++ ){
1062 for (
unsigned int anni3 = anni1; anni3 < L; anni3++ ){
1065 for (
unsigned int crea4 = crea3; crea4 < L; crea4++ ){
1066 for (
unsigned int anni4 = anni1; anni4 < L; anni4++ ){
1068 if ( irrep_123 == irrep_center4 ){
1073 const double value = four_rdm[ crea4 + L*( crea3 + L*( crea2 + L*( crea1 + L*( anni4 + L*( anni3 + L*( anni2 + L * anni1 )))))) ];
1074 four_rdm[ crea4 + L*( crea2 + L*( crea1 + L*( crea3 + L*( anni4 + L*( anni2 + L*( anni1 + L * anni3 )))))) ] = value;
1075 four_rdm[ crea4 + L*( crea1 + L*( crea3 + L*( crea2 + L*( anni4 + L*( anni1 + L*( anni3 + L * anni2 )))))) ] = value;
1076 four_rdm[ crea4 + L*( crea1 + L*( crea2 + L*( crea3 + L*( anni4 + L*( anni1 + L*( anni2 + L * anni3 )))))) ] = value;
1077 four_rdm[ crea4 + L*( crea2 + L*( crea3 + L*( crea1 + L*( anni4 + L*( anni2 + L*( anni3 + L * anni1 )))))) ] = value;
1078 four_rdm[ crea4 + L*( crea3 + L*( crea1 + L*( crea2 + L*( anni4 + L*( anni3 + L*( anni1 + L * anni2 )))))) ] = value;
1080 four_rdm[ crea3 + L*( crea4 + L*( crea2 + L*( crea1 + L*( anni3 + L*( anni4 + L*( anni2 + L * anni1 )))))) ] = value;
1081 four_rdm[ crea3 + L*( crea2 + L*( crea1 + L*( crea4 + L*( anni3 + L*( anni2 + L*( anni1 + L * anni4 )))))) ] = value;
1082 four_rdm[ crea3 + L*( crea1 + L*( crea4 + L*( crea2 + L*( anni3 + L*( anni1 + L*( anni4 + L * anni2 )))))) ] = value;
1083 four_rdm[ crea3 + L*( crea1 + L*( crea2 + L*( crea4 + L*( anni3 + L*( anni1 + L*( anni2 + L * anni4 )))))) ] = value;
1084 four_rdm[ crea3 + L*( crea2 + L*( crea4 + L*( crea1 + L*( anni3 + L*( anni2 + L*( anni4 + L * anni1 )))))) ] = value;
1085 four_rdm[ crea3 + L*( crea4 + L*( crea1 + L*( crea2 + L*( anni3 + L*( anni4 + L*( anni1 + L * anni2 )))))) ] = value;
1087 four_rdm[ crea2 + L*( crea3 + L*( crea4 + L*( crea1 + L*( anni2 + L*( anni3 + L*( anni4 + L * anni1 )))))) ] = value;
1088 four_rdm[ crea2 + L*( crea4 + L*( crea1 + L*( crea3 + L*( anni2 + L*( anni4 + L*( anni1 + L * anni3 )))))) ] = value;
1089 four_rdm[ crea2 + L*( crea1 + L*( crea3 + L*( crea4 + L*( anni2 + L*( anni1 + L*( anni3 + L * anni4 )))))) ] = value;
1090 four_rdm[ crea2 + L*( crea1 + L*( crea4 + L*( crea3 + L*( anni2 + L*( anni1 + L*( anni4 + L * anni3 )))))) ] = value;
1091 four_rdm[ crea2 + L*( crea4 + L*( crea3 + L*( crea1 + L*( anni2 + L*( anni4 + L*( anni3 + L * anni1 )))))) ] = value;
1092 four_rdm[ crea2 + L*( crea3 + L*( crea1 + L*( crea4 + L*( anni2 + L*( anni3 + L*( anni1 + L * anni4 )))))) ] = value;
1094 four_rdm[ crea1 + L*( crea3 + L*( crea2 + L*( crea4 + L*( anni1 + L*( anni3 + L*( anni2 + L * anni4 )))))) ] = value;
1095 four_rdm[ crea1 + L*( crea2 + L*( crea4 + L*( crea3 + L*( anni1 + L*( anni2 + L*( anni4 + L * anni3 )))))) ] = value;
1096 four_rdm[ crea1 + L*( crea4 + L*( crea3 + L*( crea2 + L*( anni1 + L*( anni4 + L*( anni3 + L * anni2 )))))) ] = value;
1097 four_rdm[ crea1 + L*( crea4 + L*( crea2 + L*( crea3 + L*( anni1 + L*( anni4 + L*( anni2 + L * anni3 )))))) ] = value;
1098 four_rdm[ crea1 + L*( crea2 + L*( crea3 + L*( crea4 + L*( anni1 + L*( anni2 + L*( anni3 + L * anni4 )))))) ] = value;
1099 four_rdm[ crea1 + L*( crea3 + L*( crea4 + L*( crea2 + L*( anni1 + L*( anni3 + L*( anni4 + L * anni2 )))))) ] = value;
1101 four_rdm[ anni4 + L*( anni3 + L*( anni2 + L*( anni1 + L*( crea4 + L*( crea3 + L*( crea2 + L * crea1 )))))) ] = value;
1102 four_rdm[ anni4 + L*( anni2 + L*( anni1 + L*( anni3 + L*( crea4 + L*( crea2 + L*( crea1 + L * crea3 )))))) ] = value;
1103 four_rdm[ anni4 + L*( anni1 + L*( anni3 + L*( anni2 + L*( crea4 + L*( crea1 + L*( crea3 + L * crea2 )))))) ] = value;
1104 four_rdm[ anni4 + L*( anni1 + L*( anni2 + L*( anni3 + L*( crea4 + L*( crea1 + L*( crea2 + L * crea3 )))))) ] = value;
1105 four_rdm[ anni4 + L*( anni2 + L*( anni3 + L*( anni1 + L*( crea4 + L*( crea2 + L*( crea3 + L * crea1 )))))) ] = value;
1106 four_rdm[ anni4 + L*( anni3 + L*( anni1 + L*( anni2 + L*( crea4 + L*( crea3 + L*( crea1 + L * crea2 )))))) ] = value;
1108 four_rdm[ anni3 + L*( anni4 + L*( anni2 + L*( anni1 + L*( crea3 + L*( crea4 + L*( crea2 + L * crea1 )))))) ] = value;
1109 four_rdm[ anni3 + L*( anni2 + L*( anni1 + L*( anni4 + L*( crea3 + L*( crea2 + L*( crea1 + L * crea4 )))))) ] = value;
1110 four_rdm[ anni3 + L*( anni1 + L*( anni4 + L*( anni2 + L*( crea3 + L*( crea1 + L*( crea4 + L * crea2 )))))) ] = value;
1111 four_rdm[ anni3 + L*( anni1 + L*( anni2 + L*( anni4 + L*( crea3 + L*( crea1 + L*( crea2 + L * crea4 )))))) ] = value;
1112 four_rdm[ anni3 + L*( anni2 + L*( anni4 + L*( anni1 + L*( crea3 + L*( crea2 + L*( crea4 + L * crea1 )))))) ] = value;
1113 four_rdm[ anni3 + L*( anni4 + L*( anni1 + L*( anni2 + L*( crea3 + L*( crea4 + L*( crea1 + L * crea2 )))))) ] = value;
1115 four_rdm[ anni2 + L*( anni3 + L*( anni4 + L*( anni1 + L*( crea2 + L*( crea3 + L*( crea4 + L * crea1 )))))) ] = value;
1116 four_rdm[ anni2 + L*( anni4 + L*( anni1 + L*( anni3 + L*( crea2 + L*( crea4 + L*( crea1 + L * crea3 )))))) ] = value;
1117 four_rdm[ anni2 + L*( anni1 + L*( anni3 + L*( anni4 + L*( crea2 + L*( crea1 + L*( crea3 + L * crea4 )))))) ] = value;
1118 four_rdm[ anni2 + L*( anni1 + L*( anni4 + L*( anni3 + L*( crea2 + L*( crea1 + L*( crea4 + L * crea3 )))))) ] = value;
1119 four_rdm[ anni2 + L*( anni4 + L*( anni3 + L*( anni1 + L*( crea2 + L*( crea4 + L*( crea3 + L * crea1 )))))) ] = value;
1120 four_rdm[ anni2 + L*( anni3 + L*( anni1 + L*( anni4 + L*( crea2 + L*( crea3 + L*( crea1 + L * crea4 )))))) ] = value;
1122 four_rdm[ anni1 + L*( anni3 + L*( anni2 + L*( anni4 + L*( crea1 + L*( crea3 + L*( crea2 + L * crea4 )))))) ] = value;
1123 four_rdm[ anni1 + L*( anni2 + L*( anni4 + L*( anni3 + L*( crea1 + L*( crea2 + L*( crea4 + L * crea3 )))))) ] = value;
1124 four_rdm[ anni1 + L*( anni4 + L*( anni3 + L*( anni2 + L*( crea1 + L*( crea4 + L*( crea3 + L * crea2 )))))) ] = value;
1125 four_rdm[ anni1 + L*( anni4 + L*( anni2 + L*( anni3 + L*( crea1 + L*( crea4 + L*( crea2 + L * crea3 )))))) ] = value;
1126 four_rdm[ anni1 + L*( anni2 + L*( anni3 + L*( anni4 + L*( crea1 + L*( crea2 + L*( crea3 + L * crea4 )))))) ] = value;
1127 four_rdm[ anni1 + L*( anni3 + L*( anni4 + L*( anni2 + L*( crea1 + L*( crea3 + L*( crea4 + L * crea2 )))))) ] = value;
1139 for (
unsigned int ann = 0; ann < L; ann++ ){
1140 for (
unsigned int orb = 0; orb < L; orb++ ){
1141 for (
unsigned int combo = 0; combo < L*L*L*L; combo++ ){
1142 four_rdm[ combo + L*L*L*L*( ann + L * ( ann + L * ( ann + L * orb ))) ] = 0.0;
1143 four_rdm[ combo + L*L*L*L*( ann + L * ( ann + L * ( orb + L * ann ))) ] = 0.0;
1144 four_rdm[ combo + L*L*L*L*( ann + L * ( orb + L * ( ann + L * ann ))) ] = 0.0;
1145 four_rdm[ combo + L*L*L*L*( orb + L * ( ann + L * ( ann + L * ann ))) ] = 0.0;
1146 four_rdm[ L*L*L*L * combo + ann + L * ( ann + L * ( ann + L * orb )) ] = 0.0;
1147 four_rdm[ L*L*L*L * combo + ann + L * ( ann + L * ( orb + L * ann )) ] = 0.0;
1148 four_rdm[ L*L*L*L * combo + ann + L * ( orb + L * ( ann + L * ann )) ] = 0.0;
1149 four_rdm[ L*L*L*L * combo + orb + L * ( ann + L * ( ann + L * ann )) ] = 0.0;
1154 gettimeofday(&end, NULL);
1155 const double elapsed = (end.tv_sec - start.tv_sec) + 1e-6 * (end.tv_usec - start.tv_usec);
1156 if ( FCIverbose > 0 ){ cout <<
"FCI::Fill4RDM : Wall time = " << elapsed <<
" seconds" << endl; }
1162 assert( Nel_up + Nel_down >= 4 );
1163 const double elapsed = Driver3RDM( vector, output, three_rdm, fock, L + 1 );
1164 if ( FCIverbose > 0 ){ cout <<
"FCI::Fock4RDM : Wall time = " << elapsed <<
" seconds" << endl; }
1170 assert( Nel_up + Nel_down >= 3 );
1171 const double elapsed = Driver3RDM( vector, output, NULL, NULL, L + 1 );
1172 if ( FCIverbose > 0 ){ cout <<
"FCI::Fill3RDM : Wall time = " << elapsed <<
" seconds" << endl; }
1178 assert( Nel_up + Nel_down >= 4 );
1179 const double elapsed = Driver3RDM( vector, output, three_rdm, NULL, orbz );
1180 if ( FCIverbose > 0 ){ cout <<
"FCI::Diag4RDM : Wall time = " << elapsed <<
" seconds" << endl; }
1184 double CheMPS2::FCI::Driver3RDM(
double * vector,
double * output,
double * three_rdm,
double * fock,
const unsigned int orbz )
const{
1186 struct timeval start, end;
1187 gettimeofday(&start, NULL);
1192 for (
unsigned int irrep = 1; irrep < num_irreps; irrep++ ){
1195 double * workspace1 =
new double[ max_length ];
1196 double * workspace2 =
new double[ max_length ];
1197 double * workspace3 =
new double[ orig_length ];
1199 double * chi = NULL;
1200 const bool task_fock = ( fock != NULL );
1201 const bool task_E_zz = (( fock == NULL ) && ( three_rdm != NULL ));
1202 const bool task_3rdm = (( fock == NULL ) && ( three_rdm == NULL ));
1206 assert( orbz == L + 1 );
1222 chi =
new double[ orig_length ];
1238 assert( orbz == L + 1 );
1239 chi =
new double[ orig_length ];
1241 for (
unsigned int anni = 0; anni < L; anni++ ){
1242 for (
unsigned int crea = 0; crea < L; crea++ ){
1245 FCIdaxpy( orig_length, fock[ crea + L * anni ], workspace1, chi );
1263 for (
unsigned int anni1 = 0; anni1 < L; anni1++ ){
1264 for (
unsigned int crea1 = 0; crea1 < L; crea1++ ){
1270 if ( irrep_center1 == 0 ){
1273 const double value =
FCIddot( orig_length, workspace1, chi );
1274 for (
unsigned int j = anni1; j < L; j++ ){
1275 for (
unsigned int k = anni1; k < L; k++ ){
1277 output[ anni1 + L*( j + L*( k + L*( j + L*( k + L * crea1 )))) ] += value;
1278 output[ anni1 + L*( j + L*( k + L*( k + L*( crea1 + L * j )))) ] += value;
1284 for (
unsigned int crea2 = 0; crea2 < L; crea2++ ){
1285 for (
unsigned int anni2 = anni1; anni2 < L; anni2++ ){
1292 if ( irrep_center1 == irrep_center2 ){
1295 const double value =
FCIddot( orig_length, workspace2, chi );
1296 for (
unsigned int orb = anni1; orb < L; orb++ ){
1298 output[ anni1 + L*( anni2 + L*( orb + L*( crea1 + L*( orb + L * crea2 )))) ] -= value;
1299 output[ anni1 + L*( anni2 + L*( orb + L*( orb + L*( crea2 + L * crea1 )))) ] -= value;
1300 output[ anni1 + L*( orb + L*( anni2 + L*( orb + L*( crea1 + L * crea2 )))) ] -= value;
1305 if (( crea1 >= anni1 ) && ( crea2 >= anni1 )){
1307 for (
unsigned int crea3 = (( crea1 == crea2 ) ? crea2 + 1 : crea2 ); crea3 < L; crea3++ ){
1308 for (
unsigned int anni3 = (( anni1 == anni2 ) ? anni1 + 1 : anni1 ); anni3 < L; anni3++ ){
1312 if ( irrep_center3 == irrep_product3 ){
1317 double value =
FCIddot( orig_length, workspace3, chi );
1320 for (
unsigned int t = 0; t < L; t++ ){
1322 value -= ( fock[ crea3 + L * t ] * three_rdm[ anni1 + L*( anni2 + L*( anni3 + L*( crea1 + L*( crea2 + L * t )))) ]
1323 + fock[ crea2 + L * t ] * three_rdm[ anni1 + L*( anni2 + L*( anni3 + L*( crea1 + L*( t + L * crea3 )))) ]
1324 + fock[ crea1 + L * t ] * three_rdm[ anni1 + L*( anni2 + L*( anni3 + L*( t + L*( crea2 + L * crea3 )))) ] );
1329 const int number = (( orbz == crea1 ) ? 1 : 0 ) + (( orbz == crea2 ) ? 1 : 0 ) + (( orbz == crea3 ) ? 1 : 0 );
1331 value -= number * three_rdm[ anni1 + L*( anni2 + L*( anni3 + L*( crea1 + L*( crea2 + L * crea3 )))) ];
1335 output[ anni1 + L*( anni2 + L*( anni3 + L*( crea1 + L*( crea2 + L * crea3 )))) ] += value;
1345 delete [] workspace1;
1346 delete [] workspace2;
1347 delete [] workspace3;
1348 if (( task_fock ) || ( task_E_zz )){
delete [] chi; }
1351 for (
unsigned int anni1 = 0; anni1 < L; anni1++ ){
1352 for (
unsigned int crea1 = anni1; crea1 < L; crea1++ ){
1354 for (
unsigned int crea2 = anni1; crea2 < L; crea2++ ){
1356 for (
unsigned int anni2 = anni1; anni2 < L; anni2++ ){
1358 for (
unsigned int crea3 = crea2; crea3 < L; crea3++ ){
1360 for (
unsigned int anni3 = anni1; anni3 < L; anni3++ ){
1366 const double value = output[ anni1 + L * ( anni2 + L * ( anni3 + L * ( crea1 + L * ( crea2 + L * crea3 ) ) ) ) ];
1367 output[ anni1 + L * ( anni3 + L * ( anni2 + L * ( crea1 + L * ( crea3 + L * crea2 ) ) ) ) ] = value;
1369 output[ anni3 + L * ( anni2 + L * ( anni1 + L * ( crea3 + L * ( crea2 + L * crea1 ) ) ) ) ] = value;
1370 output[ anni2 + L * ( anni3 + L * ( anni1 + L * ( crea2 + L * ( crea3 + L * crea1 ) ) ) ) ] = value;
1372 output[ anni2 + L * ( anni1 + L * ( anni3 + L * ( crea2 + L * ( crea1 + L * crea3 ) ) ) ) ] = value;
1373 output[ anni3 + L * ( anni1 + L * ( anni2 + L * ( crea3 + L * ( crea1 + L * crea2 ) ) ) ) ] = value;
1375 output[ crea3 + L * ( crea2 + L * ( crea1 + L * ( anni3 + L * ( anni2 + L * anni1 ) ) ) ) ] = value;
1376 output[ crea2 + L * ( crea3 + L * ( crea1 + L * ( anni2 + L * ( anni3 + L * anni1 ) ) ) ) ] = value;
1378 output[ crea2 + L * ( crea1 + L * ( crea3 + L * ( anni2 + L * ( anni1 + L * anni3 ) ) ) ) ] = value;
1379 output[ crea3 + L * ( crea1 + L * ( crea2 + L * ( anni3 + L * ( anni1 + L * anni2 ) ) ) ) ] = value;
1381 output[ crea1 + L * ( crea3 + L * ( crea2 + L * ( anni1 + L * ( anni3 + L * anni2 ) ) ) ) ] = value;
1382 output[ crea1 + L * ( crea2 + L * ( crea3 + L * ( anni1 + L * ( anni2 + L * anni3 ) ) ) ) ] = value;
1392 for (
unsigned int anni = 0; anni < L; anni++ ){
1393 for (
unsigned int combo = 0; combo < L*L*L; combo++ ){
1394 output[ combo + L * L * L * anni * ( 1 + L + L * L ) ] = 0.0;
1395 output[ anni * ( 1 + L + L * L ) + L * L * L * combo ] = 0.0;
1399 gettimeofday(&end, NULL);
1400 const double elapsed = (end.tv_sec - start.tv_sec) + 1e-6 * (end.tv_usec - start.tv_usec);
1408 double result = 0.0;
1410 #pragma omp parallel for schedule(static) reduction(+:result) 1411 for (
unsigned int counter = 0; counter < vecLength; counter++ ){
1412 for (
unsigned int orbi = 0; orbi < L; orbi++ ){
1416 const int count_up = ( counter - irrep_center_jumps[ 0 ][ irrep_up ] ) % numPerIrrep_up[ irrep_up ];
1417 const int count_down = ( counter - irrep_center_jumps[ 0 ][ irrep_up ] ) / numPerIrrep_up[ irrep_up ];
1420 const int diff_ii = lookup_sign_alpha[ irrep_up ][ orbi + L * orbi ][ count_up ]
1421 - lookup_sign_beta [ irrep_down ][ orbi + L * orbi ][ count_down ];
1422 const double vector_at_counter_squared = vector[ counter ] * vector[ counter ];
1423 result += 0.75 * diff_ii * diff_ii * vector_at_counter_squared;
1425 for (
unsigned int orbj = orbi+1; orbj < L; orbj++ ){
1428 const int diff_jj = lookup_sign_alpha[ irrep_up ][ orbj + L * orbj ][ count_up ]
1429 - lookup_sign_beta [ irrep_down ][ orbj + L * orbj ][ count_down ];
1430 result += 0.5 * diff_ii * diff_jj * vector_at_counter_squared;
1435 const int sign_down_ji = lookup_sign_beta [ irrep_down ][ orbj + L * orbi ][ count_down ];
1436 const int sign_up_ij = lookup_sign_alpha[ irrep_up ][ orbi + L * orbj ][ count_up ];
1437 const int sign_product1 = sign_up_ij * sign_down_ji;
1438 if ( sign_product1 != 0 ){
1439 const int cnt_down_ji = lookup_cnt_beta [ irrep_down ][ orbj + L * orbi ][ count_down ];
1440 const int cnt_up_ij = lookup_cnt_alpha[ irrep_up ][ orbi + L * orbj ][ count_up ];
1441 result -= sign_product1 * vector[ irrep_center_jumps[ 0 ][ irrep_up_bis ] + cnt_up_ij + numPerIrrep_up[ irrep_up_bis ] * cnt_down_ji ] * vector[ counter ];
1445 const int sign_down_ij = lookup_sign_beta [ irrep_down ][ orbi + L * orbj ][ count_down ];
1446 const int sign_up_ji = lookup_sign_alpha[ irrep_up ][ orbj + L * orbi ][ count_up ];
1447 const int sign_product2 = sign_up_ji * sign_down_ij;
1448 if ( sign_product2 != 0 ){
1449 const int cnt_down_ij = lookup_cnt_beta [ irrep_down ][ orbi + L * orbj ][ count_down ];
1450 const int cnt_up_ji = lookup_cnt_alpha[ irrep_up ][ orbj + L * orbi ][ count_up ];
1451 result -= sign_product2 * vector[ irrep_center_jumps[ 0 ][ irrep_up_bis ] + cnt_up_ji + numPerIrrep_up[ irrep_up_bis ] * cnt_down_ij ] * vector[ counter ];
1458 if ( FCIverbose > 0 ){
1459 const double intendedS = fabs( 0.5 * Nel_up - 0.5 * Nel_down );
1460 cout <<
"FCI::CalcSpinSquared : For intended spin " << intendedS
1461 <<
" the measured S(S+1) = " << result <<
" and intended S(S+1) = " << intendedS * (intendedS + 1.0) << endl;
1471 #pragma omp parallel 1474 int * bits_up =
new int[ L ];
1475 int * bits_down =
new int[ L ];
1477 #pragma omp for schedule(static) 1478 for (
unsigned int counter = 0; counter < vecLength; counter++ ){
1480 double myResult = 0.0;
1483 for (
unsigned int orb1 = 0; orb1 < L; orb1++ ){
1484 const int n_tot_orb1 = bits_up[ orb1 ] + bits_down[ orb1 ];
1485 myResult += n_tot_orb1 *
getGmat( orb1 , orb1 );
1486 for (
unsigned int orb2 = 0; orb2 < L; orb2++ ){
1487 myResult += 0.5 * n_tot_orb1 * ( bits_up[ orb2 ] + bits_down[ orb2 ] ) *
getERI( orb1 , orb1 , orb2 , orb2 );
1488 myResult += 0.5 * ( n_tot_orb1 - bits_up[ orb1 ] * bits_up[ orb2 ] - bits_down[ orb1 ] * bits_down[ orb2 ] ) *
getERI( orb1 , orb2 , orb2 , orb1 );
1492 diag[ counter ] = myResult;
1497 delete [] bits_down;
1506 struct timeval start, end;
1507 gettimeofday(&start, NULL);
1537 #pragma omp parallel 1540 int * bits_up =
new int[ L ];
1541 int * bits_down =
new int[ L ];
1543 double * Jmat =
new double[ L * L ];
1544 double * K_reg_up =
new double[ L * L ];
1545 double * K_reg_down =
new double[ L * L ];
1546 double * K_bar_up =
new double[ L * L ];
1547 double * K_bar_down =
new double[ L * L ];
1549 int * specific_orbs_irrep =
new int[ num_irreps * ( L + 1 ) ];
1550 for (
unsigned int irrep = 0; irrep < num_irreps; irrep++ ){
1552 for (
unsigned int orb = 0; orb < L; orb++){
1553 specific_orbs_irrep[ orb + ( L + 1 ) * irrep ] = 0;
1555 specific_orbs_irrep[ count + ( L + 1 ) * irrep ] = orb;
1559 specific_orbs_irrep[ L + ( L + 1 ) * irrep ] = count;
1562 #pragma omp for schedule(static) 1563 for (
unsigned int counter = 0; counter < vecLength; counter++){
1568 for (
unsigned int i = 0; i < L; i++ ){
1569 for (
unsigned int j = i; j < L; j++ ){
1572 double val_KregUP = 0.0;
1573 double val_KregDOWN = 0.0;
1574 double val_KbarUP = 0.0;
1575 double val_KbarDOWN = 0.0;
1578 for (
unsigned int k = 0; k < L; k++ ){
1579 const double temp =
getERI(i,k,k,j);
1580 val_J +=
getERI(i,j,k,k) * ( bits_up[k] + bits_down[k] );
1581 val_KregUP += temp * bits_up[k];
1582 val_KregDOWN += temp * bits_down[k];
1583 val_KbarUP += temp * ( 1 - bits_up[k] );
1584 val_KbarDOWN += temp * ( 1 - bits_down[k] );
1588 Jmat[ i + L * j ] = val_J;
1589 Jmat[ j + L * i ] = val_J;
1590 K_reg_up[ i + L * j ] = val_KregUP;
1591 K_reg_up[ j + L * i ] = val_KregUP;
1592 K_reg_down[ i + L * j ] = val_KregDOWN;
1593 K_reg_down[ j + L * i ] = val_KregDOWN;
1594 K_bar_up[ i + L * j ] = val_KbarUP;
1595 K_bar_up[ j + L * i ] = val_KbarUP;
1596 K_bar_down[ i + L * j ] = val_KbarDOWN;
1597 K_bar_down[ j + L * i ] = val_KbarDOWN;
1604 for (
unsigned int i = 0; i < L; i++ ){
1605 const int num_i = bits_up[i] + bits_down[i];
1606 temp +=
getGmat(i, i) * num_i + 0.5 * ( Jmat[ i + L * i ] * num_i + K_bar_up[ i + L * i ] * bits_up[i]
1607 + K_bar_down[ i + L * i ] * bits_down[i] );
1609 double myResult = temp*temp;
1611 for (
unsigned int p = 0; p < L; p++ ){
1612 for (
unsigned int q = 0; q < L; q++ ){
1615 const int special_pq = bits_up[p] * ( 1 - bits_up[q] ) + bits_down[p] * ( 1 - bits_down[q] );
1616 const double GplusJ_pq =
getGmat(p, q) + Jmat[ p + L * q ];
1617 const double K_cross_pq_up = ( K_bar_up[ p + L * q ] - K_reg_up[ p + L * q ] ) * bits_up[p] * ( 1 - bits_up[q] );
1618 const double K_cross_pq_down = ( K_bar_down[ p + L * q ] - K_reg_down[ p + L * q ] ) * bits_down[p] * ( 1 - bits_down[q] );
1620 myResult += ( GplusJ_pq * ( special_pq * GplusJ_pq + K_cross_pq_up + K_cross_pq_down )
1621 + 0.25 * ( K_cross_pq_up * K_cross_pq_up + K_cross_pq_down * K_cross_pq_down ) );
1638 for (
unsigned int k = 0; k < L; k++ ){
1639 if ( bits_up[k] + bits_down[k] < 2 ){
1640 for (
unsigned int a = 0; a < L; a++ ){
1642 const int special_ak = ( bits_up[a] * ( 1 - bits_up[k] )
1643 + bits_down[a] * ( 1 - bits_down[k] ) );
1644 const int local_ak_up = bits_up[a] * ( 1 - bits_up[k] );
1645 const int local_ak_down = bits_down[a] * ( 1 - bits_down[k] );
1647 if ( ( special_ak > 0 ) || ( local_ak_up > 0 ) || ( local_ak_down > 0 ) ){
1651 for (
unsigned int i = 0; i < L; i++ ){
1652 if ( bits_up[i] + bits_down[i] < 2 ){
1655 const int bar_i_up = 1 - bits_up[i];
1656 const int bar_i_down = 1 - bits_down[i];
1657 const int max_c_cnt = specific_orbs_irrep[ L + offset ];
1659 for (
int c_cnt = 0; c_cnt < max_c_cnt; c_cnt++ ){
1660 const int c = specific_orbs_irrep[ c_cnt + offset ];
1661 const int fact_ic_up = bits_up[c] * bar_i_up;
1662 const int fact_ic_down = bits_down[c] * bar_i_down;
1663 const int prefactor1 = ( fact_ic_up + fact_ic_down ) * special_ak;
1664 const int prefactor2 = local_ak_up * fact_ic_up + local_ak_down * fact_ic_down;
1665 const double eri_akci =
getERI(a, k, c, i);
1666 const double eri_aick =
getERI(a, i, c, k);
1667 myResult += 0.5 * eri_akci * ( prefactor1 * eri_akci - prefactor2 * eri_aick );
1676 output[ counter ] = myResult;
1681 delete [] bits_down;
1685 delete [] K_reg_down;
1687 delete [] K_bar_down;
1689 delete [] specific_orbs_irrep;
1693 gettimeofday(&end, NULL);
1694 const double elapsed = (end.tv_sec - start.tv_sec) + 1e-6 * (end.tv_usec - start.tv_usec);
1695 if ( FCIverbose > 0 ){ cout <<
"FCI::DiagHamSquared : Wall time = " << elapsed <<
" seconds" << endl; }
1703 double * energies =
new double[ vecLength ];
1709 unsigned int minEindex = 0;
1710 for (
unsigned int count = 1; count < vecLength; count++ ){
1711 if ( energies[ count ] < energies[ minEindex ] ){
1724 int count_annih_up = 0;
1725 int count_creat_up = 0;
1726 int count_annih_down = 0;
1727 int count_creat_down = 0;
1729 int * annih_up = work;
1730 int * creat_up = work+2;
1731 int * annih_down = work+4;
1732 int * creat_down = work+6;
1735 for (
unsigned int orb = 0; orb < L; orb++){
1736 if ( bits_bra_up[ orb ] != bits_ket_up[ orb ] ){
1737 if ( bits_ket_up[ orb ] ){
1738 if ( count_annih_up == 2 ){
return 0.0; }
1739 annih_up[ count_annih_up ] = orb;
1742 if ( count_creat_up == 2 ){
return 0.0; }
1743 creat_up[ count_creat_up ] = orb;
1747 if ( bits_bra_down[ orb ] != bits_ket_down[ orb ] ){
1748 if ( bits_ket_down[ orb ] ){
1749 if ( count_annih_down == 2 ){
return 0.0; }
1750 annih_down[ count_annih_down ] = orb;
1753 if ( count_creat_down == 2 ){
return 0.0; }
1754 creat_down[ count_creat_down ] = orb;
1761 if ( count_annih_up != count_creat_up ){
return 0.0; }
1762 if ( count_annih_down != count_creat_down ){
return 0.0; }
1765 if ( count_annih_up + count_annih_down > 2 ){
return 0.0; }
1766 if ( count_creat_up + count_creat_down > 2 ){
return 0.0; }
1768 if (( count_annih_up == 0 ) && ( count_annih_down == 0 )){
1770 double result = 0.0;
1771 for (
unsigned int orb1 = 0; orb1 < L; orb1++ ){
1772 const int n_tot_orb1 = bits_ket_up[ orb1 ] + bits_ket_down[ orb1 ];
1773 result += n_tot_orb1 *
getGmat( orb1 , orb1 );
1774 for (
unsigned int orb2 = 0; orb2 < L; orb2++ ){
1775 result += 0.5 * n_tot_orb1 * ( bits_ket_up[ orb2 ] + bits_ket_down[ orb2 ] ) *
getERI( orb1 , orb1 , orb2 , orb2 )
1776 + 0.5 * ( n_tot_orb1 - bits_ket_up[ orb1 ] * bits_ket_up[ orb2 ] - bits_ket_down[ orb1 ] * bits_ket_down[ orb2 ] ) *
getERI( orb1 , orb2 , orb2 , orb1 );
1783 if (( count_annih_up == 1 ) && ( count_annih_down == 0 )){
1785 const int orbj = creat_up[ 0 ];
1786 const int orbl = annih_up[ 0 ];
1788 double result =
getGmat( orbj , orbl );
1789 for (
unsigned int orb1 = 0; orb1 < L; orb1++){
1790 result +=
getERI(orbj, orb1, orb1, orbl) * ( 0.5 - bits_ket_up[ orb1 ] ) +
getERI(orb1, orb1, orbj, orbl) * ( bits_ket_up[ orb1 ] + bits_ket_down[ orb1 ] );
1793 if ( orbj < orbl ){
for (
int orbital = orbj+1; orbital < orbl; orbital++){
if ( bits_ket_up[ orbital ] ){ phase *= -1; } } }
1794 if ( orbl < orbj ){
for (
int orbital = orbl+1; orbital < orbj; orbital++){
if ( bits_ket_up[ orbital ] ){ phase *= -1; } } }
1795 return ( result * phase );
1799 if (( count_annih_up == 0 ) && ( count_annih_down == 1 )){
1801 const int orbj = creat_down[ 0 ];
1802 const int orbl = annih_down[ 0 ];
1804 double result =
getGmat( orbj , orbl );
1805 for (
unsigned int orb1 = 0; orb1 < L; orb1++){
1806 result +=
getERI(orbj, orb1, orb1, orbl) * ( 0.5 - bits_ket_down[ orb1 ] ) +
getERI(orb1, orb1, orbj, orbl) * ( bits_ket_up[ orb1 ] + bits_ket_down[ orb1 ] );
1809 if ( orbj < orbl ){
for (
int orbital = orbj+1; orbital < orbl; orbital++){
if ( bits_ket_down[ orbital ] ){ phase *= -1; } } }
1810 if ( orbl < orbj ){
for (
int orbital = orbl+1; orbital < orbj; orbital++){
if ( bits_ket_down[ orbital ] ){ phase *= -1; } } }
1811 return ( result * phase );
1815 if (( count_annih_up == 2 ) && ( count_annih_down == 0 )){
1818 const int orbi = creat_up[ 0 ];
1819 const int orbj = creat_up[ 1 ];
1820 const int orbk = annih_up[ 0 ];
1821 const int orbl = annih_up[ 1 ];
1823 double result =
getERI(orbi, orbk, orbj, orbl) -
getERI(orbi, orbl, orbj, orbk);
1825 for (
int orbital = orbk+1; orbital < orbl; orbital++){
if ( bits_ket_up[ orbital ] ){ phase *= -1; } }
1826 for (
int orbital = orbi+1; orbital < orbj; orbital++){
if ( bits_bra_up[ orbital ] ){ phase *= -1; } }
1827 return ( result * phase );
1831 if (( count_annih_up == 0 ) && ( count_annih_down == 2 )){
1834 const int orbi = creat_down[ 0 ];
1835 const int orbj = creat_down[ 1 ];
1836 const int orbk = annih_down[ 0 ];
1837 const int orbl = annih_down[ 1 ];
1839 double result =
getERI(orbi, orbk, orbj, orbl) -
getERI(orbi, orbl, orbj, orbk);
1841 for (
int orbital = orbk+1; orbital < orbl; orbital++){
if ( bits_ket_down[ orbital ] ){ phase *= -1; } }
1842 for (
int orbital = orbi+1; orbital < orbj; orbital++){
if ( bits_bra_down[ orbital ] ){ phase *= -1; } }
1843 return ( result * phase );
1847 if (( count_annih_up == 1 ) && ( count_annih_down == 1 )){
1849 const int orbi = creat_up [ 0 ];
1850 const int orbj = creat_down[ 0 ];
1851 const int orbk = annih_up [ 0 ];
1852 const int orbl = annih_down[ 0 ];
1854 double result =
getERI(orbi, orbk, orbj, orbl);
1856 if ( orbi < orbk ){
for (
int orbital = orbi+1; orbital < orbk; orbital++){
if ( bits_ket_up [ orbital ] ){ phase *= -1; } } }
1857 if ( orbk < orbi ){
for (
int orbital = orbk+1; orbital < orbi; orbital++){
if ( bits_ket_up [ orbital ] ){ phase *= -1; } } }
1858 if ( orbj < orbl ){
for (
int orbital = orbj+1; orbital < orbl; orbital++){
if ( bits_ket_down[ orbital ] ){ phase *= -1; } } }
1859 if ( orbl < orbj ){
for (
int orbital = orbl+1; orbital < orbj; orbital++){
if ( bits_ket_down[ orbital ] ){ phase *= -1; } } }
1860 return ( result * phase );
1870 int length = vecLength;
1872 dcopy_( &length , origin , &inc , target , &inc );
1878 int length = vecLength;
1880 return ddot_( &length , vec1 , &inc , vec2 , &inc );
1886 return sqrt(
FCIddot( vecLength , vec , vec ) );
1892 double factor = alpha;
1893 int length = vecLength;
1895 daxpy_( &length , &factor , vec_x , &inc , vec_y , &inc );
1901 double factor = alpha;
1902 int length = vecLength;
1904 dscal_( &length , &factor , vec , &inc );
1910 for (
unsigned int cnt = 0; cnt < vecLength; cnt++ ){ vec[cnt] = 0.0; }
1916 for (
unsigned int cnt = 0; cnt < vecLength; cnt++ ){ vec[cnt] = ( ( 2.0 * rand() ) / RAND_MAX ) - 1.0; }
1923 Davidson deBoskabouter( veclength, DVDSN_NUM_VEC,
1924 CheMPS2::DAVIDSON_NUM_VEC_KEEP,
1925 CheMPS2::DAVIDSON_FCI_RTOL,
1926 CheMPS2::DAVIDSON_PRECOND_CUTOFF,
false );
1927 double ** whichpointers =
new double*[2];
1930 assert( instruction ==
'A' );
1931 if ( inoutput != NULL ){
FCIdcopy( veclength, inoutput, whichpointers[0] ); }
1932 else {
FillRandom( veclength, whichpointers[0] ); }
1936 while ( instruction ==
'B' ){
1937 matvec( whichpointers[0], whichpointers[1] );
1941 assert( instruction ==
'C' );
1942 if ( inoutput != NULL ){
FCIdcopy( veclength, whichpointers[0], inoutput ); }
1943 const double FCIenergy = whichpointers[1][0] +
getEconst();
1944 if ( FCIverbose > 1 ){ cout <<
"FCI::GSDavidson : Required number of matrix-vector multiplications = " << deBoskabouter.
GetNumMultiplications() << endl; }
1945 if ( FCIverbose > 0 ){ cout <<
"FCI::GSDavidson : Converged ground state energy = " << FCIenergy << endl; }
1946 delete [] whichpointers;
1959 assert( orbIndex<L );
1961 int * bits_up =
new int[ L ];
1962 int * bits_down =
new int[ L ];
1965 for (
unsigned int counter = 0; counter < vecLength; counter++){
1967 resultVector[ counter ] = ( bits_up[ orbIndex ] + bits_down[ orbIndex ] ) * sourceVector[ counter ];
1971 delete [] bits_down;
1977 assert( ( whichOperator==
'C' ) || ( whichOperator==
'A' ) );
1978 assert( orbIndex<L );
1979 assert( L==otherFCI->
getL() );
1988 int * bits_up =
new int[ L ];
1989 int * bits_down =
new int[ L ];
1991 if (( whichOperator==
'C') && ( isUp )){
1992 for (
unsigned int counter = 0; counter < vecLength; counter++){
1996 if ( bits_up[ orbIndex ] == 1 ){
1997 bits_up[ orbIndex ] = 0;
1999 for (
unsigned int cnt = 0; cnt < orbIndex; cnt++){
if ( bits_up[ cnt ] ){ phase *= -1; } }
2000 thisVector[ counter ] = phase * otherFCI->
getFCIcoeff( bits_up , bits_down , otherVector );
2002 thisVector[ counter ] = 0.0;
2008 if (( whichOperator==
'C') && ( !(isUp) )){
2009 const int startphase = (( Nel_up % 2 ) == 0) ? 1 : -1;
2010 for (
unsigned int counter = 0; counter < vecLength; counter++){
2014 if ( bits_down[ orbIndex ] == 1 ){
2015 bits_down[ orbIndex ] = 0;
2016 int phase = startphase;
2017 for (
unsigned int cnt = 0; cnt < orbIndex; cnt++){
if ( bits_down[ cnt ] ){ phase *= -1; } }
2018 thisVector[ counter ] = phase * otherFCI->
getFCIcoeff( bits_up , bits_down , otherVector );
2020 thisVector[ counter ] = 0.0;
2026 if (( whichOperator==
'A') && ( isUp )){
2027 for (
unsigned int counter = 0; counter < vecLength; counter++){
2031 if ( bits_up[ orbIndex ] == 0 ){
2032 bits_up[ orbIndex ] = 1;
2034 for (
unsigned int cnt = 0; cnt < orbIndex; cnt++){
if ( bits_up[ cnt ] ){ phase *= -1; } }
2035 thisVector[ counter ] = phase * otherFCI->
getFCIcoeff( bits_up , bits_down , otherVector );
2037 thisVector[ counter ] = 0.0;
2043 if (( whichOperator==
'A') && ( !(isUp) )){
2044 const int startphase = (( Nel_up % 2 ) == 0) ? 1 : -1;
2045 for (
unsigned int counter = 0; counter < vecLength; counter++){
2049 if ( bits_down[ orbIndex ] == 0 ){
2050 bits_down[ orbIndex ] = 1;
2051 int phase = startphase;
2052 for (
unsigned int cnt = 0; cnt < orbIndex; cnt++){
if ( bits_down[ cnt ] ){ phase *= -1; } }
2053 thisVector[ counter ] = phase * otherFCI->
getFCIcoeff( bits_up , bits_down , otherVector );
2055 thisVector[ counter ] = 0.0;
2062 delete [] bits_down;
2066 void CheMPS2::FCI::CGSolveSystem(
const double alpha,
const double beta,
const double eta,
double * RHS,
double * RealSol,
double * ImagSol,
const bool checkError)
const{
2071 double * temp =
new double[ vecLength ];
2072 double * diag =
new double[ vecLength ];
2075 assert( RealSol != NULL );
2076 assert( ImagSol != NULL );
2077 assert( fabs( eta ) > 0.0 );
2093 double ** pointers =
new double*[ 3 ];
2094 double RMSerror = 0.0;
2096 ConjugateGradient CG( vecLength, CheMPS2::CONJ_GRADIENT_RTOL, CheMPS2::CONJ_GRADIENT_PRECOND_CUTOFF,
false );
2097 char instruction = CG.
step( pointers );
2098 assert( instruction ==
'A' );
2099 for (
unsigned int cnt = 0; cnt < vecLength; cnt++){ pointers[ 0 ][ cnt ] = - eta * RHS[ cnt ] / diag[ cnt ]; }
2100 for (
unsigned int cnt = 0; cnt < vecLength; cnt++){ pointers[ 1 ][ cnt ] = diag[ cnt ]; }
2101 for (
unsigned int cnt = 0; cnt < vecLength; cnt++){ pointers[ 2 ][ cnt ] = - eta * RHS[ cnt ]; }
2102 instruction = CG.
step( pointers );
2103 assert( instruction ==
'B' );
2104 while ( instruction ==
'B' ){
2105 CGoperator( alpha, beta, eta, pointers[ 0 ], temp, pointers[ 1 ] );
2106 instruction = CG.
step( pointers );
2108 assert( instruction ==
'C' );
2109 FCIdcopy( vecLength, pointers[ 0 ], ImagSol );
2110 RMSerror += pointers[ 1 ][ 0 ] * pointers[ 1 ][ 0 ];
2115 ConjugateGradient CG( vecLength, CheMPS2::CONJ_GRADIENT_RTOL, CheMPS2::CONJ_GRADIENT_PRECOND_CUTOFF,
false );
2116 char instruction = CG.
step( pointers );
2117 assert( instruction ==
'A' );
2119 for (
unsigned int cnt = 0; cnt < vecLength; cnt++){ pointers[ 1 ][ cnt ] = diag[ cnt ]; }
2121 instruction = CG.
step( pointers );
2122 assert( instruction ==
'B' );
2123 while ( instruction ==
'B' ){
2124 CGoperator( alpha, beta, eta, pointers[ 0 ], temp, pointers[ 1 ] );
2125 instruction = CG.
step( pointers );
2127 assert( instruction ==
'C' );
2128 FCIdcopy( vecLength, pointers[ 0 ], RealSol );
2129 RMSerror += pointers[ 1 ][ 0 ] * pointers[ 1 ][ 0 ];
2131 RMSerror = sqrt( RMSerror );
2136 if (( checkError ) && ( FCIverbose > 0 )){
2137 cout <<
"FCI::CGSolveSystem : RMS error when checking the solution = " << RMSerror << endl;
2146 const double prefactor = alpha + beta *
getEconst();
2147 for (
unsigned int cnt = 0; cnt < vecLength; cnt++){
2148 out[ cnt ] = prefactor * in[ cnt ] + beta * out[ cnt ];
2153 void CheMPS2::FCI::CGoperator(
const double alpha,
const double beta,
const double eta,
double * in,
double * temp,
double * out)
const{
2158 FCIdaxpy( vecLength, eta*eta, in, out );
2170 const double alpha_bis = alpha + beta *
getEconst();
2171 const double factor1 = alpha_bis * alpha_bis + eta * eta;
2172 const double factor2 = 2 * alpha_bis * beta;
2173 const double factor3 = beta * beta;
2174 for (
unsigned int row = 0; row < vecLength; row++){
2175 diagonal[ row ] = factor1 + factor2 * diagonal[ row ] + factor3 * workspace[ row ];
2178 if ( FCIverbose>1 ){
2179 double minval = diagonal[0];
2180 double maxval = diagonal[0];
2181 for (
unsigned int cnt = 1; cnt < vecLength; cnt++){
2182 if ( diagonal[ cnt ] > maxval ){ maxval = diagonal[ cnt ]; }
2183 if ( diagonal[ cnt ] < minval ){ minval = diagonal[ cnt ]; }
2185 cout <<
"FCI::CGdiagonal : Minimum value of diag[ ( alpha + beta * Ham )^2 + eta^2 ] = " << minval << endl;
2186 cout <<
"FCI::CGdiagonal : Maximum value of diag[ ( alpha + beta * Ham )^2 + eta^2 ] = " << maxval << endl;
2191 void CheMPS2::FCI::RetardedGF(
const double omega,
const double eta,
const unsigned int orb_alpha,
const unsigned int orb_beta,
const bool isUp,
const double GSenergy,
double * GSvector,
CheMPS2::Hamiltonian * Ham,
double * RePartGF,
double * ImPartGF)
const{
2193 assert( RePartGF != NULL );
2194 assert( ImPartGF != NULL );
2199 double Realpart, Imagpart;
2200 RetardedGF_addition(omega, eta, orb_alpha, orb_beta, isUp, GSenergy, GSvector, Ham, &Realpart, &Imagpart);
2201 RePartGF[0] = Realpart;
2202 ImPartGF[0] = Imagpart;
2204 RetardedGF_removal( omega, eta, orb_alpha, orb_beta, isUp, GSenergy, GSvector, Ham, &Realpart, &Imagpart);
2205 RePartGF[0] += Realpart;
2206 ImPartGF[0] += Imagpart;
2208 if ( FCIverbose>0 ){
2209 cout <<
"FCI::RetardedGF : G( omega = " << omega <<
" ; eta = " << eta <<
" ; i = " << orb_alpha <<
" ; j = " << orb_beta <<
" ) = " << RePartGF[0] <<
" + I * " << ImPartGF[0] << endl;
2210 cout <<
" Local density of states (LDOS) = " << - ImPartGF[0] / M_PI << endl;
2215 void CheMPS2::FCI::GFmatrix_addition(
const double alpha,
const double beta,
const double eta,
int * orbsLeft,
const unsigned int numLeft,
int * orbsRight,
const unsigned int numRight,
const bool isUp,
double * GSvector,
CheMPS2::Hamiltonian * Ham,
double * RePartsGF,
double * ImPartsGF,
double ** TwoRDMreal,
double ** TwoRDMimag,
double ** TwoRDMadd)
const{
2224 assert( numLeft > 0 );
2225 assert( numRight > 0 );
2226 for (
unsigned int cnt = 0; cnt < numLeft; cnt++){
int orbl = orbsLeft[ cnt ]; assert((orbl < L) && (orbl >= 0)); }
2227 for (
unsigned int cnt = 0; cnt < numRight; cnt++){
int orbr = orbsRight[ cnt ]; assert((orbr < L) && (orbr >= 0)); }
2228 assert( RePartsGF != NULL );
2229 assert( ImPartsGF != NULL );
2230 for (
unsigned int counter = 0; counter < numLeft * numRight; counter++ ){
2231 RePartsGF[ counter ] = 0.0;
2232 ImPartsGF[ counter ] = 0.0;
2234 const unsigned int Lpow4 = L*L*L*L;
2235 for (
unsigned int cnt = 0; cnt < numRight; cnt++ ){
2236 if ( TwoRDMreal != NULL ){
for (
unsigned int elem = 0; elem < Lpow4; elem++ ){ TwoRDMreal[ cnt ][ elem ] = 0.0; } }
2237 if ( TwoRDMimag != NULL ){
for (
unsigned int elem = 0; elem < Lpow4; elem++ ){ TwoRDMimag[ cnt ][ elem ] = 0.0; } }
2238 if ( TwoRDMadd != NULL ){
for (
unsigned int elem = 0; elem < Lpow4; elem++ ){ TwoRDMadd[ cnt ][ elem ] = 0.0; } }
2242 for (
unsigned int cnt_right = 0; cnt_right < numRight; cnt_right++ ){
2244 const int orbitalRight = orbsRight[ cnt_right ];
2245 bool matchingIrrep =
false;
2246 for (
unsigned int cnt_left = 0; cnt_left < numLeft; cnt_left++ ){
2250 if ( isOK && matchingIrrep ){
2252 const unsigned int addNelUP =
getNel_up() + ((isUp) ? 1 : 0);
2253 const unsigned int addNelDOWN =
getNel_down() + ((isUp) ? 0 : 1);
2256 CheMPS2::FCI additionFCI( Ham, addNelUP, addNelDOWN, addIrrep, maxMemWorkMB, FCIverbose );
2257 const unsigned int addVecLength = additionFCI.
getVecLength( 0 );
2258 double * addVector =
new double[ addVecLength ];
2261 double * RealPartSolution =
new double[ addVecLength ];
2262 double * ImagPartSolution =
new double[ addVecLength ];
2263 additionFCI.
CGSolveSystem( alpha, beta, eta, addVector, RealPartSolution, ImagPartSolution );
2265 if ( TwoRDMreal != NULL ){ additionFCI.
Fill2RDM( RealPartSolution, TwoRDMreal[ cnt_right ] ); }
2266 if ( TwoRDMimag != NULL ){ additionFCI.
Fill2RDM( ImagPartSolution, TwoRDMimag[ cnt_right ] ); }
2267 if ( TwoRDMadd != NULL ){ additionFCI.
Fill2RDM( addVector, TwoRDMadd[ cnt_right ] ); }
2269 for (
unsigned int cnt_left = 0; cnt_left < numLeft; cnt_left++ ){
2270 const int orbitalLeft = orbsLeft[ cnt_left ];
2273 RePartsGF[ cnt_left + numLeft * cnt_right ] =
FCIddot( addVecLength, addVector, RealPartSolution );
2274 ImPartsGF[ cnt_left + numLeft * cnt_right ] =
FCIddot( addVecLength, addVector, ImagPartSolution );
2278 delete [] RealPartSolution;
2279 delete [] ImagPartSolution;
2280 delete [] addVector;
2287 void CheMPS2::FCI::RetardedGF_addition(
const double omega,
const double eta,
const unsigned int orb_alpha,
const unsigned int orb_beta,
const bool isUp,
const double GSenergy,
double * GSvector,
CheMPS2::Hamiltonian * Ham,
double * RePartGF,
double * ImPartGF,
double * TwoRDMreal,
double * TwoRDMimag,
double * TwoRDMadd)
const{
2291 double ** TwoRDMreal_wrap = NULL;
if ( TwoRDMreal != NULL ){ TwoRDMreal_wrap =
new double*[1]; TwoRDMreal_wrap[0] = TwoRDMreal; }
2292 double ** TwoRDMimag_wrap = NULL;
if ( TwoRDMimag != NULL ){ TwoRDMimag_wrap =
new double*[1]; TwoRDMimag_wrap[0] = TwoRDMimag; }
2293 double ** TwoRDMadd_wrap = NULL;
if ( TwoRDMadd != NULL ){ TwoRDMadd_wrap =
new double*[1]; TwoRDMadd_wrap[0] = TwoRDMadd; }
2295 int orb_left = orb_alpha;
2296 int orb_right = orb_beta;
2298 GFmatrix_addition( omega + GSenergy, -1.0, eta, &orb_left, 1, &orb_right, 1, isUp, GSvector, Ham, RePartGF, ImPartGF, TwoRDMreal_wrap, TwoRDMimag_wrap, TwoRDMadd_wrap );
2300 if ( TwoRDMreal != NULL ){
delete [] TwoRDMreal_wrap; }
2301 if ( TwoRDMimag != NULL ){
delete [] TwoRDMimag_wrap; }
2302 if ( TwoRDMadd != NULL ){
delete [] TwoRDMadd_wrap; }
2306 void CheMPS2::FCI::GFmatrix_removal(
const double alpha,
const double beta,
const double eta,
int * orbsLeft,
const unsigned int numLeft,
int * orbsRight,
const unsigned int numRight,
const bool isUp,
double * GSvector,
CheMPS2::Hamiltonian * Ham,
double * RePartsGF,
double * ImPartsGF,
double ** TwoRDMreal,
double ** TwoRDMimag,
double ** TwoRDMrem)
const{
2315 assert( numLeft > 0 );
2316 assert( numRight > 0 );
2317 for (
unsigned int cnt = 0; cnt < numLeft; cnt++){
int orbl = orbsLeft [ cnt ]; assert((orbl < L) && (orbl >= 0)); }
2318 for (
unsigned int cnt = 0; cnt < numRight; cnt++){
int orbr = orbsRight[ cnt ]; assert((orbr < L) && (orbr >= 0)); }
2319 assert( RePartsGF != NULL );
2320 assert( ImPartsGF != NULL );
2321 for (
unsigned int counter = 0; counter < numLeft * numRight; counter++ ){
2322 RePartsGF[ counter ] = 0.0;
2323 ImPartsGF[ counter ] = 0.0;
2325 const unsigned int Lpow4 = L*L*L*L;
2326 for (
unsigned int cnt = 0; cnt < numRight; cnt++ ){
2327 if ( TwoRDMreal != NULL ){
for (
unsigned int elem = 0; elem < Lpow4; elem++ ){ TwoRDMreal[ cnt ][ elem ] = 0.0; } }
2328 if ( TwoRDMimag != NULL ){
for (
unsigned int elem = 0; elem < Lpow4; elem++ ){ TwoRDMimag[ cnt ][ elem ] = 0.0; } }
2329 if ( TwoRDMrem != NULL ){
for (
unsigned int elem = 0; elem < Lpow4; elem++ ){ TwoRDMrem[ cnt ][ elem ] = 0.0; } }
2333 for (
unsigned int cnt_right = 0; cnt_right < numRight; cnt_right++ ){
2335 const int orbitalRight = orbsRight[ cnt_right ];
2336 bool matchingIrrep =
false;
2337 for (
unsigned int cnt_left = 0; cnt_left < numLeft; cnt_left++ ){
2341 if ( isOK && matchingIrrep ){
2343 const unsigned int removeNelUP =
getNel_up() - ((isUp) ? 1 : 0);
2344 const unsigned int removeNelDOWN =
getNel_down() - ((isUp) ? 0 : 1);
2347 CheMPS2::FCI removalFCI( Ham, removeNelUP, removeNelDOWN, removeIrrep, maxMemWorkMB, FCIverbose );
2348 const unsigned int removeVecLength = removalFCI.
getVecLength( 0 );
2349 double * removeVector =
new double[ removeVecLength ];
2352 double * RealPartSolution =
new double[ removeVecLength ];
2353 double * ImagPartSolution =
new double[ removeVecLength ];
2354 removalFCI.
CGSolveSystem( alpha, beta, eta, removeVector, RealPartSolution, ImagPartSolution );
2356 if ( TwoRDMreal != NULL ){ removalFCI.
Fill2RDM( RealPartSolution, TwoRDMreal[ cnt_right ] ); }
2357 if ( TwoRDMimag != NULL ){ removalFCI.
Fill2RDM( ImagPartSolution, TwoRDMimag[ cnt_right ] ); }
2358 if ( TwoRDMrem != NULL ){ removalFCI.
Fill2RDM( removeVector, TwoRDMrem[ cnt_right ] ); }
2360 for (
unsigned int cnt_left = 0; cnt_left < numLeft; cnt_left++ ){
2361 const int orbitalLeft = orbsLeft[ cnt_left ];
2364 RePartsGF[ cnt_left + numLeft * cnt_right ] =
FCIddot( removeVecLength, removeVector, RealPartSolution );
2365 ImPartsGF[ cnt_left + numLeft * cnt_right ] =
FCIddot( removeVecLength, removeVector, ImagPartSolution );
2369 delete [] RealPartSolution;
2370 delete [] ImagPartSolution;
2371 delete [] removeVector;
2378 void CheMPS2::FCI::RetardedGF_removal(
const double omega,
const double eta,
const unsigned int orb_alpha,
const unsigned int orb_beta,
const bool isUp,
const double GSenergy,
double * GSvector,
CheMPS2::Hamiltonian * Ham,
double * RePartGF,
double * ImPartGF,
double * TwoRDMreal,
double * TwoRDMimag,
double * TwoRDMrem)
const{
2382 double ** TwoRDMreal_wrap = NULL;
if ( TwoRDMreal != NULL ){ TwoRDMreal_wrap =
new double*[1]; TwoRDMreal_wrap[0] = TwoRDMreal; }
2383 double ** TwoRDMimag_wrap = NULL;
if ( TwoRDMimag != NULL ){ TwoRDMimag_wrap =
new double*[1]; TwoRDMimag_wrap[0] = TwoRDMimag; }
2384 double ** TwoRDMrem_wrap = NULL;
if ( TwoRDMrem != NULL ){ TwoRDMrem_wrap =
new double*[1]; TwoRDMrem_wrap[0] = TwoRDMrem; }
2386 int orb_left = orb_beta;
2387 int orb_right = orb_alpha;
2390 GFmatrix_removal( omega - GSenergy, 1.0, eta, &orb_left, 1, &orb_right, 1, isUp, GSvector, Ham, RePartGF, ImPartGF, TwoRDMreal_wrap, TwoRDMimag_wrap, TwoRDMrem_wrap );
2392 if ( TwoRDMreal != NULL ){
delete [] TwoRDMreal_wrap; }
2393 if ( TwoRDMimag != NULL ){
delete [] TwoRDMimag_wrap; }
2394 if ( TwoRDMrem != NULL ){
delete [] TwoRDMrem_wrap; }
2398 void CheMPS2::FCI::DensityResponseGF(
const double omega,
const double eta,
const unsigned int orb_alpha,
const unsigned int orb_beta,
const double GSenergy,
double * GSvector,
double * RePartGF,
double * ImPartGF)
const{
2400 assert( RePartGF != NULL );
2401 assert( ImPartGF != NULL );
2406 double Realpart, Imagpart;
2408 RePartGF[0] = Realpart;
2409 ImPartGF[0] = Imagpart;
2412 RePartGF[0] -= Realpart;
2413 ImPartGF[0] -= Imagpart;
2415 if ( FCIverbose>0 ){
2416 cout <<
"FCI::DensityResponseGF : X( omega = " << omega <<
" ; eta = " << eta <<
" ; i = " << orb_alpha <<
" ; j = " << orb_beta <<
" ) = " << RePartGF[0] <<
" + I * " << ImPartGF[0] << endl;
2417 cout <<
" Local density-density response (LDDR) = " << - ImPartGF[0] / M_PI << endl;
2422 void CheMPS2::FCI::DensityResponseGF_forward(
const double omega,
const double eta,
const unsigned int orb_alpha,
const unsigned int orb_beta,
const double GSenergy,
double * GSvector,
double * RePartGF,
double * ImPartGF,
double * TwoRDMreal,
double * TwoRDMimag,
double * TwoRDMdens)
const{
2426 assert( ( orb_alpha<L ) && ( orb_beta<L ) );
2427 assert( RePartGF != NULL );
2428 assert( ImPartGF != NULL );
2431 double * densityAlphaVector =
new double[ vecLength ];
2432 double * densityBetaVector = ( orb_alpha == orb_beta ) ? densityAlphaVector :
new double[ vecLength ];
2434 const double n_alpha_0 =
FCIddot( vecLength , densityAlphaVector , GSvector );
2435 FCIdaxpy( vecLength , -n_alpha_0 , GSvector , densityAlphaVector );
2436 if ( orb_alpha != orb_beta ){
2438 const double n_beta_0 =
FCIddot( vecLength , densityBetaVector , GSvector );
2439 FCIdaxpy( vecLength , -n_beta_0 , GSvector , densityBetaVector );
2442 double * RealPartSolution =
new double[ vecLength ];
2443 double * ImagPartSolution =
new double[ vecLength ];
2444 CGSolveSystem( omega + GSenergy , -1.0 , eta , densityBetaVector , RealPartSolution , ImagPartSolution );
2445 if ( TwoRDMreal != NULL ){
Fill2RDM( RealPartSolution , TwoRDMreal ); }
2446 RePartGF[0] =
FCIddot( vecLength , densityAlphaVector , RealPartSolution );
2447 delete [] RealPartSolution;
2448 if ( TwoRDMimag != NULL ){
Fill2RDM( ImagPartSolution , TwoRDMimag ); }
2449 ImPartGF[0] =
FCIddot( vecLength , densityAlphaVector , ImagPartSolution );
2450 delete [] ImagPartSolution;
2452 if ( TwoRDMdens != NULL ){
Fill2RDM( densityBetaVector , TwoRDMdens ); }
2453 if ( orb_alpha != orb_beta ){
delete [] densityBetaVector; }
2454 delete [] densityAlphaVector;
2458 void CheMPS2::FCI::DensityResponseGF_backward(
const double omega,
const double eta,
const unsigned int orb_alpha,
const unsigned int orb_beta,
const double GSenergy,
double * GSvector,
double * RePartGF,
double * ImPartGF,
double * TwoRDMreal,
double * TwoRDMimag,
double * TwoRDMdens)
const{
2462 assert( ( orb_alpha<L ) && ( orb_beta<L ) );
2463 assert( RePartGF != NULL );
2464 assert( ImPartGF != NULL );
2467 double * densityAlphaVector =
new double[ vecLength ];
2468 double * densityBetaVector = ( orb_alpha == orb_beta ) ? densityAlphaVector :
new double[ vecLength ];
2470 const double n_alpha_0 =
FCIddot( vecLength , densityAlphaVector , GSvector );
2471 FCIdaxpy( vecLength , -n_alpha_0 , GSvector , densityAlphaVector );
2472 if ( orb_alpha != orb_beta ){
2474 const double n_beta_0 =
FCIddot( vecLength , densityBetaVector , GSvector );
2475 FCIdaxpy( vecLength , -n_beta_0 , GSvector , densityBetaVector );
2478 double * RealPartSolution =
new double[ vecLength ];
2479 double * ImagPartSolution =
new double[ vecLength ];
2480 CGSolveSystem( omega - GSenergy , 1.0 , eta , densityAlphaVector , RealPartSolution , ImagPartSolution );
2481 if ( TwoRDMreal != NULL ){
Fill2RDM( RealPartSolution , TwoRDMreal ); }
2482 RePartGF[0] =
FCIddot( vecLength , densityBetaVector , RealPartSolution );
2483 delete [] RealPartSolution;
2484 if ( TwoRDMimag != NULL ){
Fill2RDM( ImagPartSolution , TwoRDMimag ); }
2485 ImPartGF[0] =
FCIddot( vecLength , densityBetaVector , ImagPartSolution );
2486 delete [] ImagPartSolution;
2488 if ( TwoRDMdens != NULL ){
Fill2RDM( densityAlphaVector , TwoRDMdens ); }
2489 if ( orb_alpha != orb_beta ){
delete [] densityBetaVector; }
2490 delete [] densityAlphaVector;
static double FCIddot(const unsigned int vecLength, double *vec1, double *vec2)
Take the inproduct of two vectors.
void Diag4RDM(double *vector, double *three_rdm, const unsigned int orbz, double *output) const
Construct part of the 4-RDM: output(i,j,k,p,q,r) = Gamma^4(i,j,k,z,p,q,r,z)
void apply_excitation(double *orig_vector, double *result_vector, const int crea, const int anni, const int orig_target_irrep) const
Apply E_{crea,anni} to |orig_vector> and store the result in |result_vector>
double getEconst() const
Function which returns the nuclear repulsion energy.
void DensityResponseGF(const double omega, const double eta, const unsigned int orb_alpha, const unsigned int orb_beta, const double GSenergy, double *GSvector, double *RePartGF, double *ImPartGF) const
Calculate the density response Green's function (= forward - backward propagating part) ...
void DensityResponseGF_backward(const double omega, const double eta, const unsigned int orb_alpha, const unsigned int orb_beta, const double GSenergy, double *GSvector, double *RePartGF, double *ImPartGF, double *TwoRDMreal=NULL, double *TwoRDMimag=NULL, double *TwoRDMdens=NULL) const
Calculate the backward propagating part of the density response Green's function: <GSvector| ( n_beta...
double getERI(const int orb1, const int orb2, const int orb3, const int orb4) const
Function which returns the electron repulsion integral (in chemists notation: integral dr1 dr2 orb1(r...
void DiagHam(double *diag) const
Function which returns the diagonal elements of the FCI Hamiltonian (without Econstant!!) = Slater de...
static void FCIdcopy(const unsigned int vecLength, double *origin, double *target)
Copy a vector.
void CGdiagonal(const double alpha, const double beta, const double eta, double *diagonal, double *workspace) const
Calculate (without approximation) diagonal = diag[ (alpha + beta * Hamiltonian)^2 + eta^2 ] (Econstan...
int GetNumMultiplications() const
Get the number of matrix vector multiplications which have been performed.
double GSDavidson(double *inoutput=NULL, const int DVDSN_NUM_VEC=CheMPS2::DAVIDSON_NUM_VEC) const
Calculates the FCI ground state with Davidson's algorithm.
int getNumberOfIrreps() const
Get the number of irreps for the currently activated group.
char step(double **pointers)
The iterator to converge the ground state vector.
void ActWithSecondQuantizedOperator(const char whichOperator, const bool isUp, const unsigned int orbIndex, double *thisVector, const FCI *otherFCI, double *otherVector) const
Set thisVector to a creator/annihilator acting on otherVector.
void Fill4RDM(double *vector, double *FourRDM) const
Construct the (spin-summed) 4-RDM of a FCI vector: Gamma^4(i,j,k,l,p,q,r,t) = sum_sigma,tau,s,z < a^+_{i,sigma} a^+_{j,tau} a^+_{k,s} a^+_{l,z} a_{t,z} a_{r,s} a_{q,tau} a_{p,sigma} > = FourRDM[ i + L * ( j + L * ( k + L * ( l + L * ( p + L * ( q + L * ( r + L * t ) ) ) ) ) ) ].
int getOrbitalIrrep(const int nOrb) const
Get an orbital irrep number.
static void FCIdaxpy(const unsigned int vecLength, const double alpha, double *vec_x, double *vec_y)
Do lapack's daxpy vec_y += alpha * vec_x.
void DensityResponseGF_forward(const double omega, const double eta, const unsigned int orb_alpha, const unsigned int orb_beta, const double GSenergy, double *GSvector, double *RePartGF, double *ImPartGF, double *TwoRDMreal=NULL, double *TwoRDMimag=NULL, double *TwoRDMdens=NULL) const
Calculate the forward propagating part of the density response Green's function: <GSvector| ( n_alpha...
double getVmat(const int index1, const int index2, const int index3, const int index4) const
Get a Vmat element.
void GFmatrix_removal(const double alpha, const double beta, const double eta, int *orbsLeft, const unsigned int numLeft, int *orbsRight, const unsigned int numRight, const bool isUp, double *GSvector, CheMPS2::Hamiltonian *Ham, double *RePartsGF, double *ImPartsGF, double **TwoRDMreal=NULL, double **TwoRDMimag=NULL, double **TwoRDMrem=NULL) const
Calculate the removal Green's function: GF[i+numLeft*j] = <GSvector| a^+_{orbsLeft[i], spin} [ alpha + beta * Ham + I*eta ]^{-1} a_{orbsRight[j], spin} |GSvector>
void DiagHamSquared(double *output) const
Function which returns the diagonal elements of the FCI Hamiltonian squared (without Econstant!!) ...
static void FillRandom(const unsigned int vecLength, double *vec)
Fill a vector with random numbers in the interval [-1,1[; used when output for GSDavidson is desired ...
void RetardedGF_removal(const double omega, const double eta, const unsigned int orb_alpha, const unsigned int orb_beta, const bool isUp, const double GSenergy, double *GSvector, CheMPS2::Hamiltonian *Ham, double *RePartGF, double *ImPartGF, double *TwoRDMreal=NULL, double *TwoRDMimag=NULL, double *TwoRDMrem=NULL) const
Calculate the removal part of the retarded Green's function: <GSvector| a^+_{beta, spin(isUp)} [ omega + Ham - GSenergy + I*eta ]^{-1} a_{alpha, spin(isUp)} |GSvector>
static void FCIdscal(const unsigned int vecLength, const double alpha, double *vec)
Do lapack's dscal vec *= alpha.
unsigned int LowestEnergyDeterminant() const
Return the global counter of the Slater determinant with the lowest energy.
void CGoperator(const double alpha, const double beta, const double eta, double *in, double *temp, double *out) const
Calculate out = [(alpha + beta * Hamiltonian)^2 + eta^2] * in (Econstant is taken into account!!) ...
unsigned int getNel_down() const
Getter for the number of down or beta electrons.
double getTmat(const int index1, const int index2) const
Get a Tmat element.
double getGmat(const int orb1, const int orb2) const
Function which returns the AUGMENTED one-body matrix elements ( G_{ij} = T_{ij} - 0...
void CGSolveSystem(const double alpha, const double beta, const double eta, double *RHS, double *RealSol, double *ImagSol, const bool checkError=true) const
Calculate the solution of the equation ( alpha + beta * Hamiltonian + I * eta ) Solution = RHS with c...
void RetardedGF(const double omega, const double eta, const unsigned int orb_alpha, const unsigned int orb_beta, const bool isUp, const double GSenergy, double *GSvector, CheMPS2::Hamiltonian *Ham, double *RePartGF, double *ImPartGF) const
Calculate the retarded Green's function (= addition + removal amplitude)
double getFCIcoeff(int *bits_up, int *bits_down, double *vector) const
Function which returns a FCI coefficient.
void GFmatrix_addition(const double alpha, const double beta, const double eta, int *orbsLeft, const unsigned int numLeft, int *orbsRight, const unsigned int numRight, const bool isUp, double *GSvector, CheMPS2::Hamiltonian *Ham, double *RePartsGF, double *ImPartsGF, double **TwoRDMreal=NULL, double **TwoRDMimag=NULL, double **TwoRDMadd=NULL) const
Calculate the addition Green's function: GF[i+numLeft*j] = <GSvector| a_{orbsLeft[i], spin} [ alpha + beta * Ham + I*eta ]^{-1} a^+_{orbsRight[j], spin} |GSvector>
virtual ~FCI()
Destructor.
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...
unsigned int getVecLength(const int irrep_center) const
Getter for the number of variables in the vector " E_ij | FCI vector > " ; where irrep_center = I_i x...
void Fill3RDM(double *vector, double *ThreeRDM) const
Construct the (spin-summed) 3-RDM of a FCI vector: Gamma^3(i,j,k,l,m,n) = sum_sigma,tau,s < a^+_{i,sigma} a^+_{j,tau} a^+_{k,s} a_{n,s} a_{m,tau} a_{l,sigma} > = ThreeRDM[ i + L * ( j + L * ( k + L * ( l + L * ( m + L * n ) ) ) ) ].
void CGAlphaPlusBetaHAM(const double alpha, const double beta, double *in, double *out) const
Calculate out = (alpha + beta * Hamiltonian) * in (Econstant is taken into account!!) ...
double GetMatrixElement(int *bits_bra_up, int *bits_bra_down, int *bits_ket_up, int *bits_ket_down, int *work) const
Sandwich the Hamiltonian between two Slater determinants (return a specific element) (without Econsta...
static void ClearVector(const unsigned int vecLength, double *vec)
Set the entries of a vector to zero.
void ActWithNumberOperator(const unsigned int orbIndex, double *resultVector, double *sourceVector) const
Set resultVector to the number operator of a specific site acting on sourceVector.
void RetardedGF_addition(const double omega, const double eta, const unsigned int orb_alpha, const unsigned int orb_beta, const bool isUp, const double GSenergy, double *GSvector, CheMPS2::Hamiltonian *Ham, double *RePartGF, double *ImPartGF, double *TwoRDMreal=NULL, double *TwoRDMimag=NULL, double *TwoRDMadd=NULL) const
Calculate the addition part of the retarded Green's function: <GSvector| a_{alpha, spin(isUp)} [ omega - Ham + GSenergy + I*eta ]^{-1} a^+_{beta, spin(isUp)} |GSvector>
static void str2bits(const unsigned int Lvalue, const unsigned int bitstring, int *bits)
Convertor between two representations of a same spin-projection Slater determinant.
static unsigned int bits2str(const unsigned int Lvalue, int *bits)
Convertor between two representations of a same spin-projection Slater determinant.
int getNGroup() const
Get the group number.
unsigned int getNel_up() const
Getter for the number of up or alpha electrons.
char FetchInstruction(double **pointers)
The iterator to converge the ground state vector.
void matvec(double *input, double *output) const
Function which performs the Hamiltonian times Vector product (without Econstant!!) making use of the ...
double getEconst() const
Get the constant energy.
void getBitsOfCounter(const int irrep_center, const unsigned int counter, int *bits_up, int *bits_down) const
Find the bit representation of a global counter corresponding to " E_ij | FCI vector > " ; where irre...
double CalcSpinSquared(double *vector) const
Measure S(S+1) (spin squared)
int getUpIrrepOfCounter(const int irrep_center, const unsigned int counter) const
Find the irrep of the up Slater determinant of a global counter corresponding to " E_ij | FCI vector ...
unsigned int getL() const
Getter for the number of orbitals.
int getTargetIrrep() const
Get the target irrep.
static double FCIfrobeniusnorm(const unsigned int vecLength, double *vec)
Calculate the 2-norm of a vector.
double Fill2RDM(double *vector, double *TwoRDM) const
Construct the (spin-summed) 2-RDM of a FCI vector: Gamma^2(i,j,k,l) = sum_sigma,tau < a^+_i...
void Fock4RDM(double *vector, double *ThreeRDM, double *Fock, double *output) const
Construct the (spin-summed) contraction of the 4-RDM with the Fock operator: output(i,j,k,p,q,r) = sum_{l,t} Fock(l,t) * Gamma^4(i,j,k,l,p,q,r,t)
int getOrb2Irrep(const int orb) const
Get an orbital irrep.
int getL() const
Get the number of orbitals.
FCI(CheMPS2::Hamiltonian *Ham, const unsigned int Nel_up, const unsigned int Nel_down, const int TargetIrrep, const double maxMemWorkMB=100.0, const int FCIverbose=2)
Constructor.