Ejemplo n.º 1
0
int main(void){

   #ifdef CHEMPS2_MPI_COMPILATION
   CheMPS2::MPIchemps2::mpi_init();
   #endif

   CheMPS2::Initialize::Init();
   
   //Square 2D Hubbard model with PBC
   const int L_linear = 3;                    // Linear size
   const int L_square = L_linear * L_linear;  // Number of orbitals
   const int group = 0;                       // C1 symmetry
   const double U =  5.0;                     // On-site repulsion
   const double T = -1.0;                     // Hopping term
   
   const int N = 9;                           // Number of electrons
   const int TwoS = 1;                        // Two times the spin
   const int Irrep = 0;                       // Irrep = A (C1 symmetry)
   
   //Create the Hamiltonian (eightfold permutation symmetry is OK for site basis)
   int * irreps = new int[L_square];
   for (int cnt=0; cnt<L_square; cnt++){ irreps[cnt] = 0; }
   //The Hamiltonian initializes all its matrix elements to 0.0
   CheMPS2::Hamiltonian * Ham = new CheMPS2::Hamiltonian(L_square, group, irreps);
   delete [] irreps;
   
   //Fill with the site-basis matrix elements
   for (int cnt=0; cnt<L_square; cnt++){ Ham->setVmat(cnt,cnt,cnt,cnt,U); }
   for (int ix=0; ix<L_linear; ix++){
      for (int iy=0; iy<L_linear; iy++){
          const int idx1 = ix + L_linear * iy;                        // This site
          const int idx2 = (( ix + 1 ) % L_linear) + L_linear * iy;   // Right neighbour (PBC)
          const int idx3 = ix + L_linear * ((( iy + 1 ) % L_linear)); //Upper neighbour (PBC)
          Ham->setTmat(idx1,idx2,T);
          Ham->setTmat(idx1,idx3,T);
      }
   }
   
   //The problem object
   CheMPS2::Problem * Prob = new CheMPS2::Problem(Ham, TwoS, N, Irrep);
   
   //The convergence scheme
   CheMPS2::ConvergenceScheme * OptScheme = new CheMPS2::ConvergenceScheme(2);
   //OptScheme->setInstruction(instruction, DSU(2), Econvergence, maxSweeps, noisePrefactor);
   OptScheme->setInstruction(0,  500, 1e-10,  3, 0.05);
   OptScheme->setInstruction(1, 1000, 1e-10, 10, 0.0 );
   
   //Run ground state calculation
   CheMPS2::DMRG * theDMRG = new CheMPS2::DMRG(Prob, OptScheme);
   const double EnergySite = theDMRG->Solve();
   theDMRG->calc2DMandCorrelations();
   
   //Clean up DMRG
   if (CheMPS2::DMRG_storeMpsOnDisk){ theDMRG->deleteStoredMPS(); }
   if (CheMPS2::DMRG_storeRenormOptrOnDisk){ theDMRG->deleteStoredOperators(); }
   delete theDMRG;
   
   //Hack: overwrite the matrix elements in momentum space (4-fold symmetry!!!) directly in the Problem object
   theDMRG = new CheMPS2::DMRG(Prob, OptScheme); // Prob->construct_mxelem() is called now
   for (int orb1=0; orb1<L_square; orb1++){
      const int k1x = orb1 % L_linear;
      const int k1y = orb1 / L_linear;
      const double Telem1 = 2*T*( cos((2*M_PI*k1x)/L_linear)
                                + cos((2*M_PI*k1y)/L_linear) );
      for (int orb2=0; orb2<L_square; orb2++){
         const int k2x = orb2 % L_linear;
         const int k2y = orb2 / L_linear;
         const double Telem2 = 2*T*( cos((2*M_PI*k2x)/L_linear)
                                   + cos((2*M_PI*k2y)/L_linear) );
         for (int orb3=0; orb3<L_square; orb3++){
            const int k3x = orb3 % L_linear;
            const int k3y = orb3 / L_linear;
            for (int orb4=0; orb4<L_square; orb4++){
               const int k4x = orb4 % L_linear;
               const int k4y = orb4 / L_linear;
               const bool kx_conservation = (((k1x+k2x) % L_linear) == ((k3x+k4x) % L_linear))?true:false;
               const bool ky_conservation = (((k1y+k2y) % L_linear) == ((k3y+k4y) % L_linear))?true:false;
               double temp = 0.0;
               if ( kx_conservation && ky_conservation ){ temp += U/L_square; }
               if (( orb1 == orb3 ) && ( orb2 == orb4 )){ temp += (Telem1+Telem2)/(N-1); }
               Prob->setMxElement(orb1,orb2,orb3,orb4,temp);
            }
         }
      }
   }
   theDMRG->PreSolve(); // New matrix elements require reconstruction of complementary renormalized operators
   const double EnergyMomentum = theDMRG->Solve();
   theDMRG->calc2DMandCorrelations();
   
   //Clean up
   if (CheMPS2::DMRG_storeMpsOnDisk){ theDMRG->deleteStoredMPS(); }
   if (CheMPS2::DMRG_storeRenormOptrOnDisk){ theDMRG->deleteStoredOperators(); }
   delete theDMRG;
   delete OptScheme;
   delete Prob;
   delete Ham;
   
   //Check succes
   const bool success = ( fabs( EnergySite - EnergyMomentum ) < 1e-8 ) ? true : false;
   
   #ifdef CHEMPS2_MPI_COMPILATION
   CheMPS2::MPIchemps2::mpi_finalize();
   #endif
   
   cout << "================> Did test 10 succeed : ";
   if (success){
      cout << "yes" << endl;
      return 0; //Success
   }
   cout << "no" << endl;
   return 7; //Fail

}
Ejemplo n.º 2
0
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 ){

   #ifdef CHEMPS2_MPI_COMPILATION
      const bool am_i_master = ( MPIchemps2::mpi_rank() == MPI_CHEMPS2_MASTER );
   #else
      const bool am_i_master = true;
   #endif

   const int num_elec = Nelectrons - 2 * iHandler->getNOCCsum();
   assert( num_elec >= 0 );

   if ( CASPT2::vector_length( iHandler ) == 0 ){
      if ( am_i_master ){
         cout << "CheMPS2::CASSCF::caspt2 : There are no CASPT2 excitations between the CORE, ACTIVE, and VIRTUAL orbital spaces." << endl;
      }
      return 0.0;
   }

   //Determine the maximum NORB(irrep) and the max_block_size for the ERI orbital rotation
   const int maxlinsize      = iHandler->getNORBmax();
   const long long fullsize  = ((long long) maxlinsize ) * ((long long) maxlinsize ) * ((long long) maxlinsize ) * ((long long) maxlinsize );
   const string tmp_filename = tmp_folder + "/" + CheMPS2::DMRGSCF_eri_storage_name;
   const int dmrgsize_power4 = nOrbDMRG * nOrbDMRG * nOrbDMRG * nOrbDMRG;
   //For (ERI rotation, update unitary, block diagonalize, orbital localization)
   DMRGSCFintegrals * theRotatedTEI = new DMRGSCFintegrals( iHandler );
   const int temp_work_size = (( fullsize > CheMPS2::DMRGSCF_max_mem_eri_tfo ) ? CheMPS2::DMRGSCF_max_mem_eri_tfo : fullsize );
   const int work_mem_size  = max( max( temp_work_size , maxlinsize * maxlinsize * 4 ) , dmrgsize_power4 );
   const int tot_dmrg_power6 = dmrgsize_power4 * nOrbDMRG * nOrbDMRG;
   double * mem1 = new double[ work_mem_size ];
   double * mem2 = new double[ ( PSEUDOCANONICAL ) ? work_mem_size : max( work_mem_size, tot_dmrg_power6 ) ];

   // Rotate to pseudocanonical orbitals
   if ( PSEUDOCANONICAL ){
      assert( successful_solve ); // DMRG1RDM needs to be set by CASSCF::solve for buildQmatACT()
      buildTmatrix();
      buildQmatOCC();
      buildQmatACT();
      construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
      block_diagonalize( 'O', theFmatrix, unitary, mem1, mem2, iHandler, false, NULL, NULL, NULL );
      block_diagonalize( 'A', theFmatrix, unitary, mem1, mem2, iHandler, false, NULL, NULL, NULL );
      block_diagonalize( 'V', theFmatrix, unitary, mem1, mem2, iHandler, false, NULL, NULL, NULL );
   } else {
      if ( successful_solve == false ){
         assert( scf_options->getStoreUnitary() );
         if ( am_i_master ){
            struct stat file_info;
            const int file_stat = stat( (scf_options->getUnitaryStorageName()).c_str(), &file_info );
            assert( file_stat == 0 );
            unitary->loadU( scf_options->getUnitaryStorageName() );
         }
         #ifdef CHEMPS2_MPI_COMPILATION
         unitary->broadcast( MPI_CHEMPS2_MASTER );
         #endif
      }
   }

   // Fill active space Hamiltonian
   Hamiltonian * HamAS = new Hamiltonian( nOrbDMRG, SymmInfo.getGroupNumber(), iHandler->getIrrepOfEachDMRGorbital() );
   Problem * Prob = new Problem( HamAS, TwoS, num_elec, Irrep );
   Prob->SetupReorderD2h(); // Doesn't matter if the group isn't D2h, Prob checks it.
   buildTmatrix();
   buildQmatOCC();
   fillConstAndTmatDMRG( HamAS );
   if ( am_i_master ){
      DMRGSCFrotations::rotate( VMAT_ORIG, HamAS->getVmat(), NULL, 'A', 'A', 'A', 'A', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename );
   }
   #ifdef CHEMPS2_MPI_COMPILATION
   HamAS->getVmat()->broadcast( MPI_CHEMPS2_MASTER );
   #endif

   double E_CASSCF = 0.0;
   double * three_dm = new double[ tot_dmrg_power6 ];
   double * contract = new double[ tot_dmrg_power6 ];
   for ( int cnt = 0; cnt < tot_dmrg_power6; cnt++ ){ contract[ cnt ] = 0.0; }

   int next_hamorb1 = 0;
   int next_hamorb2 = 0;
   const bool make_checkpt = (( CUMULANT == false ) && ( CHECKPOINT ));
   bool checkpt_loaded = false;
   if ( make_checkpt ){
      assert(( OptScheme != NULL ) || ( rootNum > 1 ));
      checkpt_loaded = read_f4rdm_checkpoint( CheMPS2::DMRGSCF_f4rdm_name, &next_hamorb1, &next_hamorb2, tot_dmrg_power6, contract );
   }

   // Solve the active space problem
   if (( OptScheme == NULL ) && ( rootNum == 1 )){ // Do FCI

      if ( am_i_master ){
         const int nalpha = ( num_elec + TwoS ) / 2;
         const int nbeta  = ( num_elec - TwoS ) / 2;
         const double workmem = 1000.0; // 1GB
         const int verbose = 2;
         CheMPS2::FCI * theFCI = new CheMPS2::FCI( HamAS, nalpha, nbeta, Irrep, workmem, verbose );
         double * inoutput = new double[ theFCI->getVecLength(0) ];
         theFCI->ClearVector( theFCI->getVecLength(0), inoutput );
         inoutput[ theFCI->LowestEnergyDeterminant() ] = 1.0;
         E_CASSCF = theFCI->GSDavidson( inoutput );
         theFCI->Fill2RDM( inoutput, DMRG2DM );                     // 2-RDM
         theFCI->Fill3RDM( inoutput, three_dm );                    // 3-RDM
         setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM );        // 1-RDM
         buildQmatACT();
         construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
         copy_active( theFmatrix, mem2, iHandler );                 // Fock
         theFCI->Fock4RDM( inoutput, three_dm, mem2, contract );    // trace( Fock * 4-RDM )
         delete theFCI;
         delete [] inoutput;
      }
      #ifdef CHEMPS2_MPI_COMPILATION
      MPIchemps2::broadcast_array_double( &E_CASSCF, 1, MPI_CHEMPS2_MASTER );
      MPIchemps2::broadcast_array_double(  DMRG2DM, dmrgsize_power4, MPI_CHEMPS2_MASTER );
      MPIchemps2::broadcast_array_double( three_dm, tot_dmrg_power6, MPI_CHEMPS2_MASTER );
      MPIchemps2::broadcast_array_double( contract, tot_dmrg_power6, MPI_CHEMPS2_MASTER );
      setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM );
      #endif

   } else { // Do the DMRG sweeps

      assert( OptScheme != NULL );
      for ( int cnt = 0; cnt < dmrgsize_power4; cnt++ ){ DMRG2DM[ cnt ] = 0.0; } // Clear the 2-RDM
      CheMPS2::DMRG * theDMRG = new DMRG( Prob, OptScheme, make_checkpt, tmp_folder );
      for ( int state = 0; state < rootNum; state++ ){
         if ( state > 0 ){ theDMRG->newExcitation( fabs( E_CASSCF ) ); }
         if ( checkpt_loaded == false ){ E_CASSCF = theDMRG->Solve(); }
         if (( state == 0 ) && ( rootNum > 1 )){ theDMRG->activateExcitations( rootNum - 1 ); }
      }
      theDMRG->calc_rdms_and_correlations( true );
      copy2DMover( theDMRG->get2DM(), nOrbDMRG, DMRG2DM ); // 2-RDM
      setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM ); // 1-RDM
      buildQmatACT();
      construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler );
      copy_active( theFmatrix, mem2, iHandler ); // Fock
      if ( CUMULANT ){
         CheMPS2::Cumulant::gamma4_fock_contract_ham( Prob, theDMRG->get3DM(), theDMRG->get2DM(), mem2, contract );
      } else {
         for ( int ham_orbz = 0; ham_orbz < nOrbDMRG; ham_orbz++ ){
            if (( next_hamorb1 == ham_orbz ) && ( next_hamorb2 == ham_orbz )){
               theDMRG->Symm4RDM( three_dm, ham_orbz, ham_orbz, false );
               int size = tot_dmrg_power6;
               double f_zz = 0.5 * mem2[ ham_orbz + nOrbDMRG * ham_orbz ];
               int inc1 = 1;
               daxpy_( &size, &f_zz, three_dm, &inc1, contract, &inc1 ); // trace( Fock * 4-RDM )
               if ( ham_orbz == nOrbDMRG - 1 ){
                  next_hamorb1 = 0;
                  next_hamorb2 = 1;
               } else {
                  next_hamorb1 = ham_orbz + 1;
                  next_hamorb2 = ham_orbz + 1;
               }
               if ( make_checkpt ){ write_f4rdm_checkpoint( CheMPS2::DMRGSCF_f4rdm_name, &next_hamorb1, &next_hamorb2, tot_dmrg_power6, contract ); }
            }
         }
         if ( PSEUDOCANONICAL == false ){
            for ( int ham_orb1 = 0; ham_orb1 < nOrbDMRG; ham_orb1++ ){
               for ( int ham_orb2 = ham_orb1 + 1; ham_orb2 < nOrbDMRG; ham_orb2++ ){
                  if (( next_hamorb1 == ham_orb1 ) && ( next_hamorb2 == ham_orb2 )){
                     if ( HamAS->getOrbitalIrrep( ham_orb1 ) == HamAS->getOrbitalIrrep( ham_orb2 ) ){
                        theDMRG->Symm4RDM( three_dm, ham_orb1, ham_orb2, false );
                        int size = tot_dmrg_power6;
                        double f_12 = 0.5 * ( mem2[ ham_orb1 + nOrbDMRG * ham_orb2 ] + mem2[ ham_orb2 + nOrbDMRG * ham_orb1 ] );
                        int inc1 = 1;
                        daxpy_( &size, &f_12, three_dm, &inc1, contract, &inc1 ); // trace( Fock * 4-RDM )
                     }
                     if ( ham_orb2 == nOrbDMRG - 1 ){
                        next_hamorb1 = next_hamorb1 + 1;
                        next_hamorb2 = next_hamorb1 + 1;
                     } else {
                        next_hamorb2 = next_hamorb2 + 1;
                     }
                     if (( HamAS->getOrbitalIrrep( ham_orb1 ) == HamAS->getOrbitalIrrep( ham_orb2 ) ) && ( make_checkpt )){
                        write_f4rdm_checkpoint( CheMPS2::DMRGSCF_f4rdm_name, &next_hamorb1, &next_hamorb2, tot_dmrg_power6, contract );
                     }
                  }
               }
            }
         }
      }
      theDMRG->get3DM()->fill_ham_index( 1.0, false, three_dm, 0, nOrbDMRG );
      if (( CheMPS2::DMRG_storeMpsOnDisk ) && ( make_checkpt == false )){ theDMRG->deleteStoredMPS(); }
      if ( CheMPS2::DMRG_storeRenormOptrOnDisk ){ theDMRG->deleteStoredOperators(); }
      delete theDMRG;

   }

   delete Prob;
   delete HamAS;

   if ( PSEUDOCANONICAL == false ){
      if ( am_i_master ){ cout << "CASPT2 : Deviation from pseudocanonical = " << deviation_from_blockdiag( theFmatrix, iHandler ) << endl; }
      block_diagonalize( 'O', theFmatrix, unitary, mem1, mem2, iHandler, false, NULL, NULL, NULL );
      block_diagonalize( 'A', theFmatrix, unitary, mem1, mem2, iHandler, false, DMRG2DM, three_dm, contract ); // 2-RDM, 3-RDM, and trace( Fock * cu(4)-4-RDM )
      block_diagonalize( 'V', theFmatrix, unitary, mem1, mem2, iHandler, false, NULL, NULL, NULL );
      setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM ); // 1-RDM
      buildTmatrix();
      buildQmatOCC();
      buildQmatACT();
      construct_fock( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler ); // Fock
   }

   // Calculate the matrix elements needed to calculate the CASPT2 V-vector
   if ( am_i_master ){
      DMRGSCFrotations::rotate( VMAT_ORIG, NULL, theRotatedTEI, 'C', 'C', 'F', 'F', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename );
      DMRGSCFrotations::rotate( VMAT_ORIG, NULL, theRotatedTEI, 'C', 'V', 'C', 'V', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename );
      delete_file( tmp_filename );
   }

   delete [] mem1;
   delete [] mem2;

   double E_CASPT2 = 0.0;
   if ( am_i_master ){
      cout << "CASPT2 : Deviation from pseudocanonical = " << deviation_from_blockdiag( theFmatrix, iHandler ) << endl;
      CheMPS2::CASPT2 * myCASPT2 = new CheMPS2::CASPT2( iHandler, theRotatedTEI, theTmatrix, theFmatrix, DMRG1DM, DMRG2DM, three_dm, contract, IPEA );
      delete theRotatedTEI;
      delete [] three_dm;
      delete [] contract;
      E_CASPT2 = myCASPT2->solve( IMAG );
      delete myCASPT2;
   } else {
      delete theRotatedTEI;
      delete [] three_dm;
      delete [] contract;
   }
   #ifdef CHEMPS2_MPI_COMPILATION
   MPIchemps2::broadcast_array_double( &E_CASPT2, 1, MPI_CHEMPS2_MASTER );
   #endif

   return E_CASPT2;

}
Ejemplo n.º 3
0
int main(void){

   #ifdef CHEMPS2_MPI_COMPILATION
   CheMPS2::MPIchemps2::mpi_init();
   #endif

   CheMPS2::Initialize::Init();
   
   //The Hamiltonian: 1D Hubbard model
   const int L = 10;
   const int Group = 0;
   const double U = 2.0;
   const double T = -1.0;
   int * irreps = new int[L];
   for (int cnt=0; cnt<L; cnt++){ irreps[cnt] = 0; }
   //The Hamiltonian initializes all its matrix elements to 0.0
   CheMPS2::Hamiltonian * Ham = new CheMPS2::Hamiltonian(L, Group, irreps);
   delete [] irreps;
   for (int cnt=0; cnt<L; cnt++){ Ham->setVmat(cnt,cnt,cnt,cnt,U); }
   for (int cnt=0; cnt<L-1; cnt++){ Ham->setTmat(cnt,cnt+1,T); }
   
   //The targeted state
   const int TwoS = 5;
   const int N = 9;
   const int Irrep = 0;
   CheMPS2::Problem * Prob = new CheMPS2::Problem(Ham, TwoS, N, Irrep);
   
   //The convergence scheme
   CheMPS2::ConvergenceScheme * OptScheme = new CheMPS2::ConvergenceScheme(2);
   //OptScheme->setInstruction(instruction, DSU(2), Econvergence, maxSweeps, noisePrefactor);
   OptScheme->setInstruction(0,   30, 1e-10,  3, 0.1);
   OptScheme->setInstruction(1, 1000, 1e-10, 10, 0.0);
   
   //Run ground state calculation
   CheMPS2::DMRG * theDMRG = new CheMPS2::DMRG(Prob, OptScheme);
   const double EnergyDMRG = theDMRG->Solve();
   theDMRG->calc2DMandCorrelations();
   #ifdef CHEMPS2_MPI_COMPILATION
   if ( CheMPS2::MPIchemps2::mpi_rank() == MPI_CHEMPS2_MASTER )
   #endif
   {
      theDMRG->getCorrelations()->Print();
   }
   
   //Clean up DMRG
   if (CheMPS2::DMRG_storeMpsOnDisk){ theDMRG->deleteStoredMPS(); }
   if (CheMPS2::DMRG_storeRenormOptrOnDisk){ theDMRG->deleteStoredOperators(); }
   delete theDMRG;
   delete OptScheme;
   delete Prob;
   
   //Calculate FCI reference energy
   double EnergyFCI = 0.0;
   #ifdef CHEMPS2_MPI_COMPILATION
   if ( CheMPS2::MPIchemps2::mpi_rank() == MPI_CHEMPS2_MASTER )
   #endif
   {
      const int Nel_up   = ( N + TwoS ) / 2;
      const int Nel_down = ( N - TwoS ) / 2;
      const double maxMemWorkMB = 10.0;
      const int FCIverbose = 1;
      CheMPS2::FCI * theFCI = new CheMPS2::FCI(Ham, Nel_up, Nel_down, Irrep, maxMemWorkMB, FCIverbose);
      EnergyFCI = theFCI->GSDavidson(NULL);
      delete theFCI;
   }
   #ifdef CHEMPS2_MPI_COMPILATION
   CheMPS2::MPIchemps2::broadcast_array_double( &EnergyFCI, 1, MPI_CHEMPS2_MASTER );
   #endif
   
   //Clean up the Hamiltonian
   delete Ham;
   
   //Check succes
   const bool success = ( fabs( EnergyDMRG - EnergyFCI ) < 1e-8 ) ? true : false;
   
   #ifdef CHEMPS2_MPI_COMPILATION
   CheMPS2::MPIchemps2::mpi_finalize();
   #endif
   
   cout << "================> Did test 4 succeed : ";
   if (success){
      cout << "yes" << endl;
      return 0; //Success
   }
   cout << "no" << endl;
   return 7; //Fail

}