31 #include "DMRGSCFrotations.h" 35 #include "MPIchemps2.h" 36 #include "EdmistonRuedenberg.h" 46 #ifdef CHEMPS2_MPI_COMPILATION 49 const bool am_i_master =
true;
54 hid_t file_id = H5Fcreate( f4rdm_file.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
55 hid_t group_id = H5Gcreate( file_id,
"/F4RDM", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
57 hsize_t dimarray1 = 1;
58 hid_t dataspace1_id = H5Screate_simple( 1, &dimarray1, NULL );
59 hid_t dataset1_id = H5Dcreate( group_id,
"hamorb1", H5T_NATIVE_INT, dataspace1_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
60 H5Dwrite( dataset1_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, hamorb1 );
61 H5Dclose( dataset1_id );
62 H5Sclose( dataspace1_id );
64 hsize_t dimarray2 = 1;
65 hid_t dataspace2_id = H5Screate_simple( 1, &dimarray2, NULL );
66 hid_t dataset2_id = H5Dcreate( group_id,
"hamorb2", H5T_NATIVE_INT, dataspace2_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
67 H5Dwrite( dataset2_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, hamorb2 );
68 H5Dclose( dataset2_id );
69 H5Sclose( dataspace2_id );
71 hsize_t dimarray3 = tot_dmrg_power6;
72 hid_t dataspace3_id = H5Screate_simple( 1, &dimarray3, NULL );
73 hid_t dataset3_id = H5Dcreate( group_id,
"contract", H5T_NATIVE_DOUBLE, dataspace3_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
74 H5Dwrite( dataset3_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, contract );
75 H5Dclose( dataset3_id );
76 H5Sclose( dataspace3_id );
81 cout <<
"Created F.4-RDM checkpoint file " << f4rdm_file <<
" at next orbitals ( " << hamorb1[ 0 ] <<
" , " << hamorb2[ 0 ] <<
" )." << endl;
89 #ifdef CHEMPS2_MPI_COMPILATION 92 const bool am_i_master =
true;
98 struct stat file_info;
99 const int file_stat = stat( f4rdm_file.c_str(), &file_info );
100 if ( file_stat == 0 ){ exists = 1; }
102 #ifdef CHEMPS2_MPI_COMPILATION 103 MPIchemps2::broadcast_array_int( &exists, 1, MPI_CHEMPS2_MASTER );
111 hid_t file_id = H5Fopen( f4rdm_file.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT );
112 hid_t group_id = H5Gopen( file_id,
"/F4RDM", H5P_DEFAULT );
114 hid_t dataset1_id = H5Dopen( group_id,
"hamorb1", H5P_DEFAULT );
115 H5Dread( dataset1_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, hamorb1 );
116 H5Dclose( dataset1_id );
118 hid_t dataset2_id = H5Dopen( group_id,
"hamorb2", H5P_DEFAULT );
119 H5Dread( dataset2_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, hamorb2 );
120 H5Dclose( dataset2_id );
122 hid_t dataset3_id = H5Dopen( group_id,
"contract", H5P_DEFAULT );
123 H5Dread( dataset3_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, contract );
124 H5Dclose( dataset3_id );
126 H5Gclose( group_id );
130 #ifdef CHEMPS2_MPI_COMPILATION 131 MPIchemps2::broadcast_array_int( hamorb1, 1, MPI_CHEMPS2_MASTER );
132 MPIchemps2::broadcast_array_int( hamorb2, 1, MPI_CHEMPS2_MASTER );
133 MPIchemps2::broadcast_array_double( contract, tot_dmrg_power6, MPI_CHEMPS2_MASTER );
142 const int LAS = ham->
getL();
143 int size = LAS * LAS * LAS * LAS * LAS * LAS;
146 for (
int diag = 0; diag < LAS; diag++ ){
147 if (( next_orb1 == diag ) && ( next_orb2 == diag )){
148 double prefactor = 0.5 * fockmx[ diag + LAS * diag ];
149 if ( fabs( prefactor ) > 0.0 ){
150 dmrgsolver->
Symm4RDM( work, diag, diag,
false );
151 daxpy_( &size, &prefactor, work, &inc1, result, &inc1 );
153 if ( diag == LAS - 1 ){
157 next_orb1 = diag + 1;
158 next_orb2 = diag + 1;
160 if ( CHECKPOINT ){
write_f4rdm_checkpoint( CheMPS2::DMRGSCF_f4rdm_name, &next_orb1, &next_orb2, size, result ); }
164 if ( PSEUDOCANONICAL ==
false ){
165 for (
int orb1 = 0; orb1 < LAS; orb1++ ){
166 for (
int orb2 = orb1 + 1; orb2 < LAS; orb2++ ){
167 if (( next_orb1 == orb1 ) && ( next_orb2 == orb2 )){
168 double prefactor = 0.5 * ( fockmx[ orb1 + LAS * orb2 ] + fockmx[ orb2 + LAS * orb1 ] );
170 dmrgsolver->
Symm4RDM( work, orb1, orb2,
false );
171 daxpy_( &size, &prefactor, work, &inc1, result, &inc1 );
173 if ( orb2 == LAS - 1 ){
174 next_orb1 = next_orb1 + 1;
175 next_orb2 = next_orb1 + 1;
177 next_orb2 = next_orb2 + 1;
189 double CheMPS2::CASSCF::caspt2(
const int Nelectrons,
const int TwoS,
const int Irrep,
ConvergenceScheme * OptScheme,
const int rootNum,
DMRGSCFoptions * scf_options,
const double IPEA,
const double IMAG,
const bool PSEUDOCANONICAL,
const bool CHECKPOINT,
const bool CUMULANT ){
191 #ifdef CHEMPS2_MPI_COMPILATION 194 const bool am_i_master =
true;
197 const int num_elec = Nelectrons - 2 * iHandler->
getNOCCsum();
198 assert( num_elec >= 0 );
202 cout <<
"CheMPS2::CASSCF::caspt2 : There are no CASPT2 excitations between the CORE, ACTIVE, and VIRTUAL orbital spaces." << endl;
208 const int maxlinsize = iHandler->
getNORBmax();
209 const long long fullsize = ((
long long) maxlinsize ) * ((
long long) maxlinsize ) * ((
long long) maxlinsize ) * ((
long long) maxlinsize );
210 const string tmp_filename = tmp_folder +
"/" + CheMPS2::DMRGSCF_eri_storage_name;
211 const int dmrgsize_power4 = nOrbDMRG * nOrbDMRG * nOrbDMRG * nOrbDMRG;
214 const int temp_work_size = (( fullsize > CheMPS2::DMRGSCF_max_mem_eri_tfo ) ? CheMPS2::DMRGSCF_max_mem_eri_tfo : fullsize );
215 const int work_mem_size = max( max( temp_work_size , maxlinsize * maxlinsize * 4 ) , dmrgsize_power4 );
216 const int tot_dmrg_power6 = dmrgsize_power4 * nOrbDMRG * nOrbDMRG;
217 double * mem1 =
new double[ work_mem_size ];
218 double * mem2 =
new double[ ( PSEUDOCANONICAL ) ? work_mem_size : max( work_mem_size, tot_dmrg_power6 ) ];
221 if ( successful_solve ==
false ){
224 struct stat file_info;
226 assert( file_stat == 0 );
229 #ifdef CHEMPS2_MPI_COMPILATION 230 unitary->broadcast( MPI_CHEMPS2_MASTER );
234 if ( PSEUDOCANONICAL ){
238 construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
239 block_diagonalize(
'O', theFmatrix, unitary, mem1, mem2, iHandler,
false, NULL, NULL, NULL );
240 block_diagonalize(
'A', theFmatrix, unitary, mem1, mem2, iHandler,
false, NULL, NULL, NULL );
241 block_diagonalize(
'V', theFmatrix, unitary, mem1, mem2, iHandler,
false, NULL, NULL, NULL );
249 Prob->SetupReorderD2h();
252 fillConstAndTmatDMRG( HamAS );
254 DMRGSCFrotations::rotate( VMAT_ORIG, HamAS->
getVmat(), NULL,
'A',
'A',
'A',
'A', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename );
256 #ifdef CHEMPS2_MPI_COMPILATION 257 HamAS->
getVmat()->broadcast( MPI_CHEMPS2_MASTER );
262 int * dmrg2ham =
new int[ nOrbDMRG ];
268 #ifdef CHEMPS2_MPI_COMPILATION 269 MPIchemps2::broadcast_array_int( dmrg2ham, nOrbDMRG, MPI_CHEMPS2_MASTER );
271 Prob->setup_reorder_custom( dmrg2ham );
275 double E_CASSCF = 0.0;
276 double * three_dm =
new double[ tot_dmrg_power6 ];
277 double * contract =
new double[ tot_dmrg_power6 ];
278 for (
int cnt = 0; cnt < tot_dmrg_power6; cnt++ ){ contract[ cnt ] = 0.0; }
280 int next_hamorb1 = 0;
281 int next_hamorb2 = 0;
282 const bool make_checkpt = (( CUMULANT == false ) && ( CHECKPOINT ));
283 bool checkpt_loaded =
false;
285 assert(( OptScheme != NULL ) || ( rootNum > 1 ));
286 checkpt_loaded =
read_f4rdm_checkpoint( CheMPS2::DMRGSCF_f4rdm_name, &next_hamorb1, &next_hamorb2, tot_dmrg_power6, contract );
290 if (( OptScheme == NULL ) && ( rootNum == 1 )){
293 const int nalpha = ( num_elec + TwoS ) / 2;
294 const int nbeta = ( num_elec - TwoS ) / 2;
295 const double workmem = 1000.0;
296 const int verbose = 2;
298 double * inoutput =
new double[ theFCI->
getVecLength(0) ];
302 theFCI->
Fill2RDM( inoutput, DMRG2DM );
303 theFCI->
Fill3RDM( inoutput, three_dm );
304 setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM );
306 construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
308 theFCI->
Fock4RDM( inoutput, three_dm, mem2, contract );
312 #ifdef CHEMPS2_MPI_COMPILATION 313 MPIchemps2::broadcast_array_double( &E_CASSCF, 1, MPI_CHEMPS2_MASTER );
314 MPIchemps2::broadcast_array_double( DMRG2DM, dmrgsize_power4, MPI_CHEMPS2_MASTER );
315 MPIchemps2::broadcast_array_double( three_dm, tot_dmrg_power6, MPI_CHEMPS2_MASTER );
316 MPIchemps2::broadcast_array_double( contract, tot_dmrg_power6, MPI_CHEMPS2_MASTER );
317 setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM );
322 assert( OptScheme != NULL );
323 for (
int cnt = 0; cnt < dmrgsize_power4; cnt++ ){ DMRG2DM[ cnt ] = 0.0; }
325 for (
int state = 0; state < rootNum; state++ ){
326 if ( state > 0 ){ theDMRG->
newExcitation( fabs( E_CASSCF ) ); }
327 if ( checkpt_loaded ==
false ){ E_CASSCF = theDMRG->
Solve(); }
332 setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM );
334 construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
339 fock_dot_4rdm( mem2, theDMRG, HamAS, next_hamorb1, next_hamorb2, three_dm, contract, make_checkpt, PSEUDOCANONICAL );
342 if (( CheMPS2::DMRG_storeMpsOnDisk ) && ( make_checkpt ==
false )){ theDMRG->
deleteStoredMPS(); }
351 if ( PSEUDOCANONICAL ==
false ){
352 if ( am_i_master ){ cout <<
"CASPT2 : Deviation from pseudocanonical = " <<
deviation_from_blockdiag( theFmatrix, iHandler ) << endl; }
353 block_diagonalize(
'O', theFmatrix, unitary, mem1, mem2, iHandler,
false, NULL, NULL, NULL );
354 block_diagonalize(
'A', theFmatrix, unitary, mem1, mem2, iHandler,
false, DMRG2DM, three_dm, contract );
355 block_diagonalize(
'V', theFmatrix, unitary, mem1, mem2, iHandler,
false, NULL, NULL, NULL );
356 setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM );
360 construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
365 DMRGSCFrotations::rotate( VMAT_ORIG, NULL, theRotatedTEI,
'C',
'C',
'F',
'F', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename );
366 DMRGSCFrotations::rotate( VMAT_ORIG, NULL, theRotatedTEI,
'C',
'V',
'C',
'V', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename );
367 delete_file( tmp_filename );
373 double E_CASPT2 = 0.0;
377 delete theRotatedTEI;
380 E_CASPT2 = myCASPT2->
solve( IMAG );
383 delete theRotatedTEI;
387 #ifdef CHEMPS2_MPI_COMPILATION 388 MPIchemps2::broadcast_array_double( &E_CASPT2, 1, MPI_CHEMPS2_MASTER );
398 for (
int irrep = 0; irrep < n_irreps; irrep++ ){
399 const int NORB = idx->
getNORB( irrep );
400 for (
int row = 0; row < NORB; row++){
401 for (
int col = 0; col < NORB; col++){
402 Fock->
set( irrep, row, col, Tmat->
get( irrep, row, col )
403 + Qocc->
get( irrep, row, col )
404 + Qact->
get( irrep, row, col ) );
413 double rms_deviation = 0.0;
415 for (
int irrep = 0; irrep < n_irreps; irrep++ ){
416 const int NOCC = idx->
getNOCC( irrep );
417 for (
int row = 0; row < NOCC; row++ ){
418 for (
int col = row + 1; col < NOCC; col++ ){
419 rms_deviation += matrix->
get( irrep, row, col ) * matrix->
get( irrep, row, col );
420 rms_deviation += matrix->
get( irrep, col, row ) * matrix->
get( irrep, col, row );
423 const int NACT = idx->
getNDMRG( irrep );
424 for (
int row = 0; row < NACT; row++ ){
425 for (
int col = row + 1; col < NACT; col++ ){
426 rms_deviation += matrix->
get( irrep, NOCC + row, NOCC + col ) * matrix->
get( irrep, NOCC + row, NOCC + col );
427 rms_deviation += matrix->
get( irrep, NOCC + col, NOCC + row ) * matrix->
get( irrep, NOCC + col, NOCC + row );
430 const int NVIR = idx->
getNVIRT( irrep );
431 const int N_OA = NOCC + NACT;
432 for (
int row = 0; row < NVIR; row++ ){
433 for (
int col = row + 1; col < NVIR; col++ ){
434 rms_deviation += matrix->
get( irrep, N_OA + row, N_OA + col ) * matrix->
get( irrep, N_OA + row, N_OA + col );
435 rms_deviation += matrix->
get( irrep, N_OA + col, N_OA + row ) * matrix->
get( irrep, N_OA + col, N_OA + row );
439 rms_deviation = sqrt( rms_deviation );
440 return rms_deviation;
static void write_f4rdm_checkpoint(const string f4rdm_file, int *hamorb1, int *hamorb2, const int tot_dmrg_power6, double *contract)
Write the checkpoint file for the contraction of the generalized Fock operator with the 4-RDM to disk...
int getNORB(const int irrep) const
Get the number of orbitals for an irrep.
int getNOCCsum() const
Get the total number of occupied orbitals.
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...
void Symm4RDM(double *output, const int ham_orb1, const int ham_orb2, const bool last_case)
Obtain the symmetrized 4-RDM terms 0.5 * ( Gamma4_ijkl,pqrt + Gamma4_ijkt,pqrl ) with l and t fixed...
double GSDavidson(double *inoutput=NULL, const int DVDSN_NUM_VEC=CheMPS2::DAVIDSON_NUM_VEC) const
Calculates the FCI ground state with Davidson's algorithm.
double solve(const double imag_shift, const bool CONJUGATE_GRADIENT=false) const
Solve for the CASPT2 energy (note that the IPEA shift has been set in the constructor) ...
static void copy_active(double *origin, DMRGSCFmatrix *result, const DMRGSCFindices *idx, const bool one_rdm)
Copy a one-orbital quantity from array format to DMRGSCFmatrix format.
void deleteStoredMPS()
Call "rm " + CheMPS2::DMRG_MPS_storage_prefix + "*.h5".
int getGroupNumber() const
Get the group number.
static void construct_fock(DMRGSCFmatrix *Fock, const DMRGSCFmatrix *Tmat, const DMRGSCFmatrix *Qocc, const DMRGSCFmatrix *Qact, const DMRGSCFindices *idx)
Construct the Fock matrix.
void loadU(const string filename=DMRGSCF_unitary_storage_name)
Load the unitary from disk.
int * getIrrepOfEachDMRGorbital()
Get an array with the irreps of each DMRG orbital.
int getOrbitalIrrep(const int nOrb) const
Get an orbital irrep number.
static int mpi_rank()
Get the rank of this MPI process.
static long long vector_length(const DMRGSCFindices *idx)
Return the vector length for the CASPT2 first order wavefunction (before diagonalization of the overl...
double getVmat(const int index1, const int index2, const int index3, const int index4) const
Get a Vmat element.
TwoDM * get2DM()
Get the pointer to the 2-RDM.
int getGroupNumber() const
Get the group number.
void set(const int irrep, const int p, const int q, const double val)
Set an element.
int getNORBmax() const
Get the maximum NORB.
unsigned int LowestEnergyDeterminant() const
Return the global counter of the Slater determinant with the lowest energy.
void saveU(const string filename=DMRGSCF_unitary_storage_name) const
Save the unitary to disk.
void fill_ham_index(const double alpha, const bool add, double *storage, const int last_orb_start, const int last_orb_num)
Perform storage[ :, :, :, :, :, : ] { = or += } alpha * 3-RDM[ :, :, :, :, :, last_orb_start: last_or...
static void copy2DMover(TwoDM *theDMRG2DM, const int LAS, double *two_dm)
Copy over the DMRG 2-RDM.
int getWhichActiveSpace() const
Get which active space should be considered in the DMRG routine.
double caspt2(const int Nelectrons, const int TwoS, const int Irrep, ConvergenceScheme *OptScheme, const int rootNum, DMRGSCFoptions *scf_options, const double IPEA, const double IMAG, const bool PSEUDOCANONICAL, const bool CHECKPOINT=false, const bool CUMULANT=false)
Calculate the caspt2 correction energy for a converged casscf wavefunction.
static void block_diagonalize(const char space, const DMRGSCFmatrix *Mat, DMRGSCFunitary *Umat, double *work1, double *work2, const DMRGSCFindices *idx, const bool invert, double *two_dm, double *three_dm, double *contract)
Block-diagonalize Mat.
void FiedlerGlobal(int *dmrg2ham) const
Permute the orbitals so that the bandwidth of the exchange matrix is (approximately) minimized...
void newExcitation(const double EshiftIn)
Push back current calculation and set everything up to calculate a (new) excitation.
static void fock_dot_4rdm(double *fockmx, CheMPS2::DMRG *dmrgsolver, CheMPS2::Hamiltonian *ham, int next_orb1, int next_orb2, double *work, double *result, const bool CHECKPOINT, const bool PSEUDOCANONICAL)
Build the contraction of the fock matrix with the 4-RDM.
double get(const int irrep, const int p, const int q) const
Get an element.
bool getStoreUnitary() const
Get whether the Orbital Rotation checkpoint should be stored to disk.
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...
static void setDMRG1DM(const int num_elec, const int LAS, double *one_dm, double *two_dm)
Construct the 1-RDM from the 2-RDM.
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 ) ) ) ) ].
static void ClearVector(const unsigned int vecLength, double *vec)
Set the entries of a vector to zero.
void activateExcitations(const int maxExcIn)
Activate the necessary storage and machinery to handle excitations.
static void gamma4_fock_contract_ham(const Problem *prob, const ThreeDM *the3DM, const TwoDM *the2DM, double *fock, double *result)
Contract the CASPT2 Fock operator with the cumulant approximation of in time, using HAM indices...
int getNDMRG(const int irrep) const
Get the number of active orbitals for an irrep.
ThreeDM * get3DM()
Get the pointer to the 3-RDM.
int getNOCC(const int irrep) const
Get the number of occupied orbitals for an irrep.
static bool read_f4rdm_checkpoint(const string f4rdm_file, int *hamorb1, int *hamorb2, const int tot_dmrg_power6, double *contract)
Read the checkpoint file for the contraction of the generalized Fock operator with the 4-RDM from dis...
void calc_rdms_and_correlations(const bool do_3rdm, const bool disk_3rdm=false)
Calculate the reduced density matrices and correlations. Afterwards the MPS is again in LLLLLLLC gaug...
void deleteStoredOperators()
Call "rm " + tempfolder + "/" + CheMPS2::DMRG_OPERATOR_storage_prefix + string(thePID) + "*...
static double deviation_from_blockdiag(DMRGSCFmatrix *matrix, const DMRGSCFindices *idx)
Return the RMS deviation from block-diagonal.
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...
int getNVIRT(const int irrep) const
Get the number of virtual orbitals for an irrep.
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 getL() const
Get the number of orbitals.
string getUnitaryStorageName() const
Get the Orbital Rotation checkpoint filename.
int getNirreps() const
Get the number of irreps.