26 #include "DMRGSCFrotations.h" 33 void CheMPS2::DMRGSCFrotations::fetch(
double * eri,
const FourIndex * ORIG_VMAT,
const int irrep1,
const int irrep2,
const int irrep3,
const int irrep4, DMRGSCFindices * idx,
const int start,
const int stop,
const bool pack ){
37 assert( irrep1 == irrep2 );
38 assert( irrep3 == irrep4 );
40 const int NORB12 = idx->getNORB( irrep1 );
41 const int NORB34 = idx->getNORB( irrep3 );
44 for (
int cnt4 = 0; cnt4 < NORB34; cnt4++ ){
45 for (
int cnt3 = 0; cnt3 <= cnt4; cnt3++ ){
46 if (( start <= counter ) && ( counter < stop )){
47 for (
int cnt2 = 0; cnt2 < NORB12; cnt2++ ){
48 for (
int cnt1 = 0; cnt1 < NORB12; cnt1++ ){
49 eri[ cnt1 + NORB12 * ( cnt2 + NORB12 * ( counter - start ) ) ]
50 = ORIG_VMAT->get( irrep1, irrep3, irrep2, irrep4, cnt1, cnt3, cnt2, cnt4 );
63 const int NORB1 = idx->getNORB( irrep1 );
64 const int NORB2 = idx->getNORB( irrep2 );
65 const int NORB3 = idx->getNORB( irrep3 );
66 const int NORB4 = idx->getNORB( irrep4 );
69 for (
int cnt4 = 0; cnt4 < NORB4; cnt4++ ){
70 for (
int cnt3 = 0; cnt3 < NORB3; cnt3++ ){
71 if (( start <= counter ) && ( counter < stop )){
72 for (
int cnt2 = 0; cnt2 < NORB2; cnt2++ ){
73 for (
int cnt1 = 0; cnt1 < NORB1; cnt1++ ){
74 eri[ cnt1 + NORB1 * ( cnt2 + NORB2 * ( counter - start ) ) ]
75 = ORIG_VMAT->get( irrep1, irrep3, irrep2, irrep4, cnt1, cnt3, cnt2, cnt4 );
88 void CheMPS2::DMRGSCFrotations::write(
double * eri, FourIndex * NEW_VMAT, DMRGSCFintegrals * ROT_TEI,
const char space1,
const char space2,
const char space3,
const char space4,
const int irrep1,
const int irrep2,
const int irrep3,
const int irrep4, DMRGSCFindices * idx,
const int start,
const int stop,
const bool pack ){
91 if (( space1 == space2 ) && ( space1 == space3 ) && ( space1 == space4 )){
95 assert( irrep1 == irrep2 );
96 assert( irrep3 == irrep4 );
98 const int NEW12 = dimension( idx, irrep1, space1 );
99 const int NEW34 = dimension( idx, irrep3, space3 );
100 const int SIZE = stop - start;
103 for (
int cnt2 = 0; cnt2 < NEW12; cnt2++ ){
104 for (
int cnt1 = 0; cnt1 <= cnt2; cnt1++ ){
105 if (( start <= counter ) && ( counter < stop )){
106 for (
int cnt4 = 0; cnt4 < NEW34; cnt4++ ){
107 for (
int cnt3 = 0; cnt3 <= cnt4; cnt3++ ){
108 NEW_VMAT->set( irrep1, irrep3, irrep2, irrep4, cnt1, cnt3, cnt2, cnt4,
109 eri[ ( counter - start ) + SIZE * ( cnt3 + NEW34 * cnt4 ) ] );
123 const int NEW1 = dimension( idx, irrep1, space1 );
124 const int NEW2 = dimension( idx, irrep2, space2 );
125 const int NEW3 = dimension( idx, irrep3, space3 );
126 const int NEW4 = dimension( idx, irrep4, space4 );
127 const int SIZE = stop - start;
130 for (
int cnt2 = 0; cnt2 < NEW2; cnt2++ ){
131 for (
int cnt1 = 0; cnt1 < NEW1; cnt1++ ){
132 if (( start <= counter ) && ( counter < stop )){
133 for (
int cnt4 = 0; cnt4 < NEW4; cnt4++ ){
134 for (
int cnt3 = 0; cnt3 < NEW3; cnt3++ ){
135 NEW_VMAT->set( irrep1, irrep3, irrep2, irrep4, cnt1, cnt3, cnt2, cnt4,
136 eri[ ( counter - start ) + SIZE * ( cnt3 + NEW3 * cnt4 ) ] );
149 if (( space1 ==
'C' ) && ( space2 ==
'C' ) && ( space3 ==
'F' ) && ( space4 ==
'F' )){
153 assert( irrep1 == irrep2 );
154 assert( irrep3 == irrep4 );
156 const int NEW12 = dimension( idx, irrep1, space1 );
157 const int NEW34 = dimension( idx, irrep3, space3 );
158 const int SIZE = stop - start;
161 for (
int cnt2 = 0; cnt2 < NEW12; cnt2++ ){
162 for (
int cnt1 = 0; cnt1 <= cnt2; cnt1++ ){
163 if (( start <= counter ) && ( counter < stop )){
164 for (
int cnt4 = 0; cnt4 < NEW34; cnt4++ ){
165 for (
int cnt3 = 0; cnt3 <= cnt4; cnt3++ ){
166 ROT_TEI->set_coulomb( irrep1, irrep2, irrep3, irrep4, cnt1, cnt2, cnt3, cnt4,
167 eri[ ( counter - start ) + SIZE * ( cnt3 + NEW34 * cnt4 ) ] );
181 const int NEW1 = dimension( idx, irrep1, space1 );
182 const int NEW2 = dimension( idx, irrep2, space2 );
183 const int NEW3 = dimension( idx, irrep3, space3 );
184 const int NEW4 = dimension( idx, irrep4, space4 );
185 const int SIZE = stop - start;
188 for (
int cnt2 = 0; cnt2 < NEW2; cnt2++ ){
189 for (
int cnt1 = 0; cnt1 < NEW1; cnt1++ ){
190 if (( start <= counter ) && ( counter < stop )){
191 for (
int cnt4 = 0; cnt4 < NEW4; cnt4++ ){
192 for (
int cnt3 = 0; cnt3 < NEW3; cnt3++ ){
193 ROT_TEI->set_coulomb( irrep1, irrep2, irrep3, irrep4, cnt1, cnt2, cnt3, cnt4,
194 eri[ ( counter - start ) + SIZE * ( cnt3 + NEW3 * cnt4 ) ] );
207 if (( space1 ==
'C' ) && ( space2 ==
'V' ) && ( space3 ==
'C' ) && ( space4 ==
'V' )){
209 assert( pack ==
false );
212 const int NEW1 = dimension( idx, irrep1, space1 );
213 const int NEW2 = dimension( idx, irrep2, space2 );
214 const int NEW3 = dimension( idx, irrep3, space3 );
215 const int NEW4 = dimension( idx, irrep4, space4 );
216 const int JUMP2 = jump( idx, irrep2, space2 );
217 const int JUMP4 = jump( idx, irrep4, space4 );
218 const int SIZE = stop - start;
221 for (
int cnt2 = 0; cnt2 < NEW2; cnt2++ ){
222 for (
int cnt1 = 0; cnt1 < NEW1; cnt1++ ){
223 if (( start <= counter ) && ( counter < stop )){
224 for (
int cnt4 = 0; cnt4 < NEW4; cnt4++ ){
225 for (
int cnt3 = 0; cnt3 < NEW3; cnt3++ ){
226 ROT_TEI->set_exchange( irrep1, irrep3, irrep2, irrep4, cnt1, cnt3, JUMP2 + cnt2, JUMP4 + cnt4,
227 eri[ ( counter - start ) + SIZE * ( cnt3 + NEW3 * cnt4 ) ] );
239 assert( written ==
true );
243 void CheMPS2::DMRGSCFrotations::blockwise_first(
double * origin,
double * target,
int orig1,
int dim2,
const int dim34,
double * umat1,
int new1,
int lda1 ){
248 int right_dim = dim2 * dim34;
249 dgemm_( ¬rans, ¬rans, &new1, &right_dim, &orig1, &one, umat1, &lda1, origin, &orig1, &
set, target, &new1 );
253 void CheMPS2::DMRGSCFrotations::blockwise_second(
double * origin,
double * target,
int dim1,
int orig2,
const int dim34,
double * umat2,
int new2,
int lda2 ){
259 const int jump_old = dim1 * orig2;
260 const int jump_new = dim1 * new2;
261 #pragma omp parallel for schedule(static) 262 for (
int index = 0; index < dim34; index++ ){
263 dgemm_( ¬rans, &trans, &dim1, &new2, &orig2, &one, origin + jump_old * index, &dim1, umat2, &lda2, &
set, target + jump_new * index, &dim1 );
268 void CheMPS2::DMRGSCFrotations::blockwise_third(
double * origin,
double * target,
const int dim12,
int orig3,
const int dim4,
double * umat3,
int new3,
int lda3 ){
274 int left_dim = dim12;
275 const int jump_old = dim12 * orig3;
276 const int jump_new = dim12 * new3;
277 #pragma omp parallel for schedule(static) 278 for (
int index = 0; index < dim4; index++ ){
279 dgemm_( ¬rans, &trans, &left_dim, &new3, &orig3, &one, origin + jump_old * index, &left_dim, umat3, &lda3, &
set, target + jump_new * index, &left_dim );
284 void CheMPS2::DMRGSCFrotations::blockwise_fourth(
double * origin,
double * target,
const int dim12,
int dim3,
int orig4,
double * umat4,
int new4,
int lda4 ){
290 int left_dim = dim12 * dim3;
291 dgemm_( ¬rans, &trans, &left_dim, &new4, &orig4, &one, origin, &left_dim, umat4, &lda4, &
set, target, &left_dim );
295 void CheMPS2::DMRGSCFrotations::open_file( hid_t * file_id, hid_t * dspc_id, hid_t * dset_id,
const int first,
const int second,
const string filename ){
297 file_id[0] = H5Fcreate( filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
298 hsize_t fdim_h5[] = { (hsize_t) second, (hsize_t) first };
299 dspc_id[0] = H5Screate_simple( 2, fdim_h5, NULL );
300 dset_id[0] = H5Dcreate( file_id[0],
"storage", H5T_NATIVE_DOUBLE, dspc_id[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
304 void CheMPS2::DMRGSCFrotations::close_file( hid_t file_id, hid_t dspc_id, hid_t dset_id ){
312 void CheMPS2::DMRGSCFrotations::write_file( hid_t dspc_id, hid_t dset_id,
double * eri,
const int start,
const int size,
const int first_write ){
314 hsize_t stride_h5[] = { 1, 1 };
315 hsize_t count_h5[] = { 1, 1 };
316 hsize_t start_h5[] = { (hsize_t) start, 0 };
317 hsize_t block_h5[] = { (hsize_t) size, (hsize_t) first_write };
318 H5Sselect_hyperslab( dspc_id, H5S_SELECT_SET, start_h5, stride_h5, count_h5, block_h5 );
319 hsize_t mem_h5 = size * first_write;
320 hid_t mem_id = H5Screate_simple( 1, &mem_h5, NULL );
321 H5Dwrite( dset_id, H5T_NATIVE_DOUBLE, mem_id, dspc_id, H5P_DEFAULT, eri );
326 void CheMPS2::DMRGSCFrotations::read_file( hid_t dspc_id, hid_t dset_id,
double * eri,
const int start,
const int size,
const int second_read ){
328 hsize_t stride_h5[] = { 1, 1 };
329 hsize_t count_h5[] = { 1, 1 };
330 hsize_t start_h5[] = { 0, (hsize_t) start };
331 hsize_t block_h5[] = { (hsize_t) second_read, (hsize_t) size };
332 H5Sselect_hyperslab( dspc_id, H5S_SELECT_SET, start_h5, stride_h5, count_h5, block_h5 );
333 hsize_t mem_h5 = second_read * size;
334 hid_t mem_id = H5Screate_simple( 1, &mem_h5, NULL );
335 H5Dread( dset_id, H5T_NATIVE_DOUBLE, mem_id, dspc_id, H5P_DEFAULT, eri );
340 int CheMPS2::DMRGSCFrotations::dimension( DMRGSCFindices * idx,
const int irrep,
const char space ){
342 if ( space ==
'O' ){
return idx->getNOCC( irrep ); }
343 if ( space ==
'A' ){
return idx->getNDMRG( irrep ); }
344 if ( space ==
'V' ){
return idx->getNVIRT( irrep ); }
345 if ( space ==
'C' ){
return ( idx->getNOCC( irrep ) + idx->getNDMRG( irrep ) ); }
346 if ( space ==
'F' ){
return idx->getNORB( irrep ); }
351 int CheMPS2::DMRGSCFrotations::jump( DMRGSCFindices * idx,
const int irrep,
const char space ){
353 if ( space ==
'A' ){
return idx->getNOCC( irrep ); }
354 if ( space ==
'V' ){
return idx->getNOCC( irrep ) + idx->getNDMRG( irrep ); }
359 void CheMPS2::DMRGSCFrotations::unpackage_second(
double * mem1,
double * mem2,
const int SIZE,
const int ORIG ){
361 #pragma omp parallel for schedule(static) 362 for (
int cnt4 = 0; cnt4 < ORIG; cnt4++ ){
363 for (
int cnt3 = 0; cnt3 < ORIG; cnt3++ ){
364 const int combined = (( cnt3 < cnt4 ) ? ( cnt3 + ( cnt4 * ( cnt4 + 1 )) / 2 )
365 : ( cnt4 + ( cnt3 * ( cnt3 + 1 )) / 2 ));
367 for (
int cnt12 = 0; cnt12 < SIZE; cnt12++ ){
368 mem2[ cnt12 + SIZE * ( cnt3 + ORIG * cnt4 ) ] = mem1[ cnt12 + SIZE * combined ];
375 void CheMPS2::DMRGSCFrotations::package_first(
double * mem1,
double * mem2,
const int NEW,
const int PACKED,
const int SIZE ){
377 #pragma omp parallel for schedule(static) 378 for (
int cnt34 = 0; cnt34 < SIZE; cnt34++ ){
379 for (
int cnt2 = 0; cnt2 < NEW; cnt2++ ){
381 for (
int cnt1 = 0; cnt1 <= cnt2; cnt1++ ){
382 mem2[ cnt1 + ( cnt2 * ( cnt2 + 1 ))/2 + PACKED * cnt34 ] = mem1[ cnt1 + NEW * ( cnt2 + NEW * cnt34 ) ];
389 void CheMPS2::DMRGSCFrotations::rotate(
const FourIndex * ORIG_VMAT,
FourIndex * NEW_VMAT,
DMRGSCFintegrals * ROT_TEI,
const char space1,
const char space2,
const char space3,
const char space4,
DMRGSCFindices * idx,
DMRGSCFunitary * umat,
double * mem1,
double * mem2,
const int mem_size,
const string filename ){
393 assert(( space1 ==
'O' ) || ( space1 ==
'A' ) || ( space1 ==
'V' ) || ( space1 ==
'C' ) || ( space1 ==
'F' ));
394 assert(( space2 ==
'O' ) || ( space2 ==
'A' ) || ( space2 ==
'V' ) || ( space2 ==
'C' ) || ( space2 ==
'F' ));
395 assert(( space3 ==
'O' ) || ( space3 ==
'A' ) || ( space3 ==
'V' ) || ( space3 ==
'C' ) || ( space3 ==
'F' ));
396 assert(( space4 ==
'O' ) || ( space4 ==
'A' ) || ( space4 ==
'V' ) || ( space4 ==
'C' ) || ( space4 ==
'F' ));
399 const bool equal12 = ( space1 == space2 );
400 const bool equal34 = ( space3 == space4 );
401 const bool eightfold = (( space1 == space3 ) && ( space2 == space4 ));
403 for (
int irrep1 = 0; irrep1 < num_irreps; irrep1++ ){
404 for (
int irrep2 = (( equal12 ) ? irrep1 : 0 ); irrep2 < num_irreps; irrep2++ ){
406 for (
int irrep3 = (( eightfold ) ? irrep1 : 0 ); irrep3 < num_irreps; irrep3++ ){
408 if ( irrep4 >= (( equal34 ) ? irrep3 : 0 ) ){
410 const int NEW1 = dimension( idx, irrep1, space1 );
411 const int NEW2 = dimension( idx, irrep2, space2 );
412 const int NEW3 = dimension( idx, irrep3, space3 );
413 const int NEW4 = dimension( idx, irrep4, space4 );
415 if (( NEW1 > 0 ) && ( NEW2 > 0 ) && ( NEW3 > 0 ) && ( NEW4 > 0 )){
417 const int ORIG1 = idx->
getNORB( irrep1 );
418 const int ORIG2 = idx->
getNORB( irrep2 );
419 const int ORIG3 = idx->
getNORB( irrep3 );
420 const int ORIG4 = idx->
getNORB( irrep4 );
422 double * umat1 = umat->
getBlock( irrep1 ) + jump( idx, irrep1, space1 );
423 double * umat2 = umat->
getBlock( irrep2 ) + jump( idx, irrep2, space2 );
424 double * umat3 = umat->
getBlock( irrep3 ) + jump( idx, irrep3, space3 );
425 double * umat4 = umat->
getBlock( irrep4 ) + jump( idx, irrep4, space4 );
427 const int block_size1 = mem_size / ( ORIG1 * ORIG2 );
428 const int block_size2 = mem_size / ( ORIG3 * ORIG4 );
429 assert( block_size1 > 0 );
430 assert( block_size2 > 0 );
432 const bool pack_first = (( equal12 ) && ( irrep1 == irrep2 ));
433 const bool pack_second = (( equal34 ) && ( irrep3 == irrep4 ));
434 const int first_size = (( pack_first ) ? ( NEW1 * ( NEW1 + 1 )) / 2 : NEW1 * NEW2 );
435 const int second_size = (( pack_second ) ? ( ORIG3 * ( ORIG3 + 1 )) / 2 : ORIG3 * ORIG4 );
437 const bool io_free = (( block_size1 >= second_size ) && ( block_size2 >= first_size ));
438 hid_t file_id, dspc_id, dset_id;
440 if ( io_free ==
false ){
441 assert( filename.compare(
"edmistonruedenberg" ) != 0 );
442 open_file( &file_id, &dspc_id, &dset_id, first_size, second_size, filename );
447 while ( start < second_size ){
448 const int stop = min( start + block_size1, second_size );
449 const int size = stop - start;
450 fetch( mem1, ORIG_VMAT, irrep1, irrep2, irrep3, irrep4, idx, start, stop, pack_second );
451 blockwise_first( mem1, mem2, ORIG1, ORIG2, size, umat1, NEW1, ORIG1 );
452 blockwise_second( mem2, mem1, NEW1, ORIG2, size, umat2, NEW2, ORIG2 );
454 package_first( mem1, mem2, NEW1, first_size, size );
455 double * temp = mem1;
459 if ( io_free ==
false ){ write_file( dspc_id, dset_id, mem1, start, size, first_size ); }
462 assert( start == second_size );
466 while ( start < first_size ){
467 const int stop = min( start + block_size2, first_size );
468 const int size = stop - start;
469 if ( io_free ==
false ){ read_file( dspc_id, dset_id, mem1, start, size, second_size ); }
471 unpackage_second( mem1, mem2, size, ORIG3 );
472 double * temp = mem1;
476 blockwise_fourth( mem1, mem2, size, ORIG3, ORIG4, umat4, NEW4, ORIG4 );
477 blockwise_third( mem2, mem1, size, ORIG3, NEW4, umat3, NEW3, ORIG3 );
478 write( mem1, NEW_VMAT, ROT_TEI, space1, space2, space3, space4, irrep1, irrep2, irrep3, irrep4, idx, start, stop, pack_first );
481 assert( start == first_size );
482 if ( io_free ==
false ){ close_file( file_id, dspc_id, dset_id ); }
int getNORB(const int irrep) const
Get the number of orbitals for an irrep.
double * getBlock(const int irrep)
Get a matrix block.
static void rotate(const FourIndex *ORIG_VMAT, FourIndex *NEW_VMAT, DMRGSCFintegrals *ROT_TEI, const char space1, const char space2, const char space3, const char space4, DMRGSCFindices *idx, DMRGSCFunitary *umat, double *mem1, double *mem2, const int mem_size, const string filename)
Fill the rotated two-body matrix elements for the space. If the blocks become too large...
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 getNirreps() const
Get the number of irreps.