void Wfcgrid::update_potential_1D(Hamiltonian& ham){ /** \brief Update the Hamiltonian for 1D grid \param[in,out] ham The Hamiltonian object. The internal state of the object will be updated Eventually, it will correspond to that of the last point on the grid. Here, we use this Hamiltonian object only as the functor (it defines how to compute potential and couplings), but we don't care about the final state of the ham variable. The results for each point of the grid will be saved internally in H matrix. This function recomputes the Hamiltonian for all points working in atomic units: hbar = 1 */ vector<double> q(1, 0.0); // Precompute H, d_ij, ... along grid for(int nx=0;nx<Nx;nx++){ // For all r points of the grid compute local(potential energy) part q[0] = real(X->M[nx]); ham.set_q(q); ham.compute(); for(int nst=0;nst<nstates;nst++){ for(int nst1=0;nst1<nstates;nst1++){ H[nst][nst1].M[nx] = ham.Hvib(nst, nst1); }// for nst1 }// for nst }// for nx }// update_potential_1D
/** * copy constructor * @param ham_c object to copy */ Hamiltonian::Hamiltonian(const Hamiltonian &ham_c){ this->delta = ham_c.gdelta(); this->L = ham_c.gL(); this->R = ham_c.gR(); this->coef_n = ham_c.gcoef_n(); this->coef_nn = ham_c.gcoef_nn(); }
DTM NdnNdn( const std::vector<Basis> &Bases, const DTV &Vec, Hamiltonian<DT> &ham ){ DTM out = DTM::Zero( Bases.at(0).getL(), Bases.at(1).getL() ); std::vector< int > f1 = Bases.at(0).getFStates(); std::vector< int > f2 = Bases.at(1).getFStates(); size_t f1id = 0, f2id = 0; for ( int &nf2 : f2 ){ std::vector<size_t> ids(2,f2id); f1id = 0; for ( int &nf1 : f1 ){ ids.at(0) = f1id; size_t id = ham.DetermineTotalIndex(ids); for (size_t cnt1 = 0; cnt1 < Bases.at(1).getL(); cnt1++) { for (size_t cnt2 = 0; cnt2 < Bases.at(1).getL(); cnt2++) { if ( btest(nf2, cnt1) && btest(nf2, cnt2) ) { out(cnt1, cnt2) += std::pow(std::abs(Vec(id)), 2);//Vec(id) * std::conj( Vec(id) ); } } } f1id++; } f2id++; } return out; }
std::vector< DTV > Ni( const std::vector<Basis> &Bases, const DTV &Vec, Hamiltonian<DT> &ham ){ std::vector< DTV > out; DTV tmp1 = DTV::Zero(Bases.at(0).getL());//(Bases.at(0).getL(), 0.0e0); DTV tmp2 = DTV::Zero(Bases.at(1).getL());//(Bases.at(1).getL(), 0.0e0); std::vector< int > f1 = Bases.at(0).getFStates(); std::vector< int > f2 = Bases.at(1).getFStates(); size_t f1id = 0, f2id = 0; for ( int &nf2 : f2 ){ std::vector<size_t> ids(2,f2id); f1id = 0; for ( int &nf1 : f1 ){ ids.at(0) = f1id; size_t id = ham.DetermineTotalIndex(ids); for (size_t cnt = 0; cnt < Bases.at(0).getL(); cnt++) { if ( btest(nf1, cnt) ) tmp1(cnt) += std::pow(std::abs(Vec(id)), 2);//Vec(id) * std::conj( Vec(id) ); } for (size_t cnt = 0; cnt < Bases.at(1).getL(); cnt++) { if ( btest(nf2, cnt) ) tmp2(cnt) += std::pow(std::abs(Vec(id)), 2);//Vec(id) * std::conj( Vec(id) ); } f1id++; } f2id++; } out.push_back(tmp1); out.push_back(tmp2); return out; }
Fields::Fields(Hamiltonian &ham, ExtrinsicCurvature kij) : k(kij) { // Get data from the Hamiltonian. mass = ham.getBareMass(); sigma = ham.getSingularAngularPart(); regPower = ham.getSingularPower(); u = ham.getRemainder(); // Set up the basis. int* ranks = ham.getRanks(); basis.setRanks(ranks[0], ranks[1]); basis.setMaximumRadius(ham.getMaximumRadius()); computeDerivatives(); delete[] ranks; }
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; }
int main(int argc, const char * argv[]) { /** %%%%%%%%%%%%%%%%%%%% INITIALIZING %%%%%%%%%%%%%%%%%%%% */ const char *dis=argv[argc-1]; //string c="dis_in.txt"; string line; int dum=0; VectorXd a; ifstream input ("dis_in.txt"); if (input.is_open()) { while (getline(input,line)) { if (line[0]=='!'){dum=dum+1;} else { if (dum==1) { size=atoi(line.c_str()); occfile=occfile.append(line.c_str()); rndfile=rndfile.append(line.c_str()); outfile=outfile.append(line.c_str()); outfile=outfile.append("_"); } else if (dum==2) { if (line.compare("Long")==0) { range=size*2.0; outfile=outfile.append("LR"); outfile=outfile.append("_"); } else { range=atoi(line.c_str()); outfile=outfile.append(line.c_str()); outfile=outfile.append("NN_"); } } else if (dum==3){Gamma=atof(line.c_str());} else if (dum==4){zhop=atoi(line.c_str());} else if (dum==5) { pvac=atoi(line.c_str()); occfile=occfile.append(line.c_str()); rndfile=rndfile.append(line.c_str()); outfile=outfile.append(line.c_str()); outfile=outfile.append("_"); } /* else if (dum==6) { cout<<'\t'<<dum<<endl; occfile=occfile.append(line.c_str()); rndfile=rndfile.append(line.c_str()); } */ } } input.close(); } else {cout<<"Unable to open file: "<<"dis_in.txt"<< " \n";}; occfile=occfile.append(dis); rndfile=rndfile.append(dis); outfile=outfile.append(dis); occfile=occfile.append(".txt"); rndfile=rndfile.append(".txt"); cout<<"lattice size = "<<size<<endl; cout<<"range = "<<range<<endl; cout<<"decay = "<<Gamma<<endl; cout<<"symmetrical? "<<zhop<<endl; cout<<"percent of vacancy: "<<pvac<<endl; cout<<"occupation file: "<<occfile<<endl; cout<<"on-site energy file: "<<rndfile<<endl; /** %%%%%%%%%%%%%%%%%%%% END OF INITIALIZATION %%%%%%%%%%%%%%%%%%%% */ Hamiltonian C; double* H; C.Hami(size, occfile, rndfile, range, zhop, Gamma, H, occnum); //Lapack int numEigvals; double* eigvals; int presInt = 16; eigvals = new double [occnum]; dsyevrEigvalsInterface(H, occnum, &numEigvals, eigvals); cout << "NumEvals: " << numEigvals << endl; cout << "Eigenvalues: " << endl; cout << setprecision(presInt); ofstream myfile2; myfile2.open((outfile+"_Eval.txt").c_str()); myfile2 << setprecision(presInt); for (int i=0; i<numEigvals; i++) { cout << eigvals[i] << endl; myfile2<< eigvals[i] <<endl; } myfile2.close(); delete [] eigvals; delete [] H; }
double TheBlock::lanczos(const Hamiltonian& ham, const effectiveHams& compBlockParts, rmMatrixX_t& seed, double lancTolerance) const { int hamDimension = blockParts.m * d * compBlockParts.m * d; const int minIters = std::min(hamDimension, globalMinLancIters), maxIters = std::min(hamDimension, globalMaxLancIters); std::vector<double> a, b; a.reserve(minIters); b.reserve(minIters); MatrixX_t basisVecs = seed; VectorX_t x = ham.act(blockParts, compBlockParts, basisVecs); a.push_back(re(seed.col(0).dot(x))); b.push_back(0.); VectorX_t oldGS; int i = 0; // iteration counter char JOBZ = 'V', // define dstemr arguments RANGE = 'I'; int N = 1; std::vector<double> D, E; D.reserve(minIters); E.reserve(minIters); double VL, VU; int IL = 1, IU = 1, M; std::vector<double> W; W.reserve(minIters); VectorXd Z; int LDZ, NZC = 1, ISUPPZ[2]; bool TRYRAC = true; double optLWORK; std::vector<double> WORK; int LWORK, optLIWORK; std::vector<int> IWORK; int LIWORK, INFO; double gStateDiff; // change in ground state vector across subsequent Lanczos iterations do { i++; oldGS = seed; // Lanczos stage 1: Lanczos iteration x -= a[i - 1] * basisVecs.col(i - 1); b.push_back(x.norm()); basisVecs.conservativeResize(NoChange, i + 1); basisVecs.col(i) = x / b[i]; x.noalias() = ham.act(blockParts, compBlockParts, basisVecs.col(i)) - b[i] * basisVecs.col(i - 1); a.push_back(re(basisVecs.col(i).dot(x))); // Lanczos stage 2: diagonalize tridiagonal matrix N++; D = a; E.assign(b.begin() + 1, b.end()); E.resize(N); W.resize(N); Z.resize(N); LDZ = N; LWORK = -1; LIWORK = -1; dstemr_(&JOBZ, &RANGE, &N, D.data(), E.data(), &VL, &VU, &IL, &IU, &M, W.data(), Z.data(), &LDZ, &NZC, ISUPPZ, &TRYRAC, &optLWORK, &LWORK, &optLIWORK, &LIWORK, &INFO); // query for optimal workspace allocations LWORK = int(optLWORK); WORK.resize(LWORK); LIWORK = optLIWORK; IWORK.resize(LIWORK); dstemr_(&JOBZ, &RANGE, &N, D.data(), E.data(), &VL, &VU, &IL, &IU, &M, W.data(), Z.data(), &LDZ, &NZC, ISUPPZ, &TRYRAC, WORK.data(), &LWORK, IWORK.data(), &LIWORK, &INFO); // calculate ground state seed = (basisVecs * Z).normalized(); gStateDiff = std::abs(1 - std::abs(seed.col(0).dot(oldGS))); } while(N < minIters || (N < maxIters && gStateDiff > lancTolerance)); if(N == maxIters && gStateDiff > lancTolerance) // check if last iteration converges to an eigenstate { double gStateError = std::abs(1 - std::abs(seed.col(0) .dot(ham.act(blockParts, compBlockParts, seed).normalized()))); std::cout << "Warning: final Lanczos iteration reached. The inner " << "product of the final approximate ground state and its " << "normalized image differs from 1 by " << gStateError << std::endl; if(gStateError > fallbackLancTolerance) { std::cerr << "Lanczos algorithm failed to converge after " << maxIters << " iterations." << std::endl; exit(EXIT_FAILURE); }; }; return W.front(); };
double CheMPS2::CASSCF::solve( const int Nelectrons, const int TwoS, const int Irrep, ConvergenceScheme * OptScheme, const int rootNum, DMRGSCFoptions * scf_options ){ const int num_elec = Nelectrons - 2 * iHandler->getNOCCsum(); assert( num_elec >= 0 ); assert(( OptScheme != NULL ) || (( OptScheme == NULL ) && ( rootNum == 1 ))); // Convergence variables double gradNorm = 1.0; double updateNorm = 1.0; double * gradient = new double[ unitary->getNumVariablesX() ]; for ( int cnt = 0; cnt < unitary->getNumVariablesX(); cnt++ ){ gradient[ cnt ] = 0.0; } double * diis_vec = NULL; double Energy = 1e8; // The CheMPS2::Problem for the inner DMRG calculation Hamiltonian * HamDMRG = new Hamiltonian(nOrbDMRG, SymmInfo.getGroupNumber(), iHandler->getIrrepOfEachDMRGorbital()); Problem * Prob = new Problem(HamDMRG, TwoS, num_elec, Irrep); Prob->SetupReorderD2h(); //Doesn't matter if the group isn't D2h, Prob checks it. // 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 = CheMPS2::defaultTMPpath + "/" + CheMPS2::DMRGSCF_eri_storage_name; const int dmrgsize_power4 = nOrbDMRG * nOrbDMRG * nOrbDMRG * nOrbDMRG; //For (ERI rotation, update unitary, block diagonalize, orbital localization) 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 ); double * mem1 = new double[ work_mem_size ]; double * mem2 = new double[ work_mem_size ]; //The two-body rotator and Edmiston-Ruedenberg active space localizer EdmistonRuedenberg * theLocalizer = NULL; if ( scf_options->getWhichActiveSpace() == 2 ){ theLocalizer = new EdmistonRuedenberg( HamDMRG->getVmat(), iHandler->getGroupNumber() ); } //Load unitary from disk if ( scf_options->getStoreUnitary() ){ struct stat file_info; int master_stat = stat( (scf_options->getUnitaryStorageName()).c_str(), &file_info ); if ( master_stat == 0 ){ unitary->loadU( scf_options->getUnitaryStorageName() ); } } //Load DIIS from disk DIIS * diis = NULL; if (( scf_options->getDoDIIS() ) && ( scf_options->getStoreDIIS() )){ struct stat file_info; int master_stat = stat( (scf_options->getDIISStorageName()).c_str(), &file_info ); if ( master_stat == 0 ){ const int diis_vec_size = iHandler->getROTparamsize(); diis = new DIIS( diis_vec_size, unitary->getNumVariablesX(), scf_options->getNumDIISVecs() ); diis->loadDIIS( scf_options->getDIISStorageName() ); diis_vec = new double[ diis_vec_size ]; } } int nIterations = 0; /******************************* *** Actual DMRGSCF loops *** *******************************/ while (( gradNorm > scf_options->getGradientThreshold() ) && ( nIterations < scf_options->getMaxIterations() )){ nIterations++; //Update the unitary transformation if ( unitary->getNumVariablesX() > 0 ){ unitary->updateUnitary( mem1, mem2, gradient, true, true ); //multiply = compact = true if (( scf_options->getDoDIIS() ) && ( updateNorm <= scf_options->getDIISGradientBranch() )){ if ( scf_options->getWhichActiveSpace() == 1 ){ cout << "DMRGSCF::solve : DIIS has started. Active space not rotated to NOs anymore!" << endl; } if ( scf_options->getWhichActiveSpace() == 2 ){ cout << "DMRGSCF::solve : DIIS has started. Active space not rotated to localized orbitals anymore!" << endl; } if ( diis == NULL ){ const int diis_vec_size = iHandler->getROTparamsize(); diis = new DIIS( diis_vec_size, unitary->getNumVariablesX(), scf_options->getNumDIISVecs() ); diis_vec = new double[ diis_vec_size ]; unitary->makeSureAllBlocksDetOne( mem1, mem2 ); } unitary->getLog( diis_vec, mem1, mem2 ); diis->appendNew( gradient, diis_vec ); diis->calculateParam( diis_vec ); unitary->updateUnitary( mem1, mem2, diis_vec, false, false ); //multiply = compact = false } } if (( scf_options->getStoreUnitary() ) && ( gradNorm != 1.0 )){ unitary->saveU( scf_options->getUnitaryStorageName() ); } if (( scf_options->getStoreDIIS() ) && ( updateNorm != 1.0 ) && ( diis != NULL )){ diis->saveDIIS( scf_options->getDIISStorageName() ); } int master_diis = (( diis != NULL ) ? 1 : 0 ); //Fill HamDMRG buildQmatOCC(); buildTmatrix(); fillConstAndTmatDMRG( HamDMRG ); DMRGSCFVmatRotations::rotate( VMAT_ORIG, HamDMRG->getVmat(), NULL, 'A', 'A', 'A', 'A', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename ); //Localize the active space and reorder the orbitals within each irrep based on the exchange matrix if (( scf_options->getWhichActiveSpace() == 2 ) && ( master_diis == 0 )){ //When the DIIS has started: stop theLocalizer->Optimize(mem1, mem2, scf_options->getStartLocRandom()); //Default EDMISTONRUED_gradThreshold and EDMISTONRUED_maxIter used theLocalizer->FiedlerExchange(maxlinsize, mem1, mem2); fillLocalizedOrbitalRotations(theLocalizer->getUnitary(), iHandler, mem1); unitary->rotateActiveSpaceVectors(mem1, mem2); buildQmatOCC(); //With an updated unitary, the Qocc, Tmat, and HamDMRG objects need to be updated as well. buildTmatrix(); fillConstAndTmatDMRG( HamDMRG ); DMRGSCFVmatRotations::rotate( VMAT_ORIG, HamDMRG->getVmat(), NULL, 'A', 'A', 'A', 'A', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename ); cout << "DMRGSCF::solve : Rotated the active space to localized orbitals, sorted according to the exchange matrix." << endl; } if (( OptScheme == NULL ) && ( rootNum == 1 )){ // Do FCI, and calculate the 2DM 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( HamDMRG, nalpha, nbeta, Irrep, workmem, verbose ); double * inoutput = new double[ theFCI->getVecLength(0) ]; theFCI->ClearVector( theFCI->getVecLength(0), inoutput ); inoutput[ theFCI->LowestEnergyDeterminant() ] = 1.0; Energy = theFCI->GSDavidson( inoutput ); theFCI->Fill2RDM( inoutput, DMRG2DM ); delete theFCI; delete [] inoutput; } else { //Do the DMRG sweeps, and calculate the 2DM for ( int cnt = 0; cnt < dmrgsize_power4; cnt++ ){ DMRG2DM[ cnt ] = 0.0; } //Clear the 2-RDM (to allow for state-averaged calculations) DMRG * theDMRG = new DMRG(Prob, OptScheme); for (int state = 0; state < rootNum; state++){ if (state > 0){ theDMRG->newExcitation( fabs( Energy ) ); } Energy = theDMRG->Solve(); if ( scf_options->getStateAveraging() ){ // When SA-DMRGSCF: 2DM += current 2DM theDMRG->calc2DMandCorrelations(); copy2DMover( theDMRG->get2DM(), nOrbDMRG, DMRG2DM ); } if ((state == 0) && (rootNum > 1)){ theDMRG->activateExcitations( rootNum-1 ); } } if ( !( scf_options->getStateAveraging() )){ // When SS-DMRGSCF: 2DM += last 2DM theDMRG->calc2DMandCorrelations(); copy2DMover( theDMRG->get2DM(), nOrbDMRG, DMRG2DM ); } if (scf_options->getDumpCorrelations()){ theDMRG->getCorrelations()->Print(); } // Correlations have been calculated in the loop (SA) or outside of the loop (SS) if (CheMPS2::DMRG_storeMpsOnDisk){ theDMRG->deleteStoredMPS(); } if (CheMPS2::DMRG_storeRenormOptrOnDisk){ theDMRG->deleteStoredOperators(); } delete theDMRG; if ((scf_options->getStateAveraging()) && (rootNum > 1)){ const double averagingfactor = 1.0 / rootNum; for ( int cnt = 0; cnt < dmrgsize_power4; cnt++ ){ DMRG2DM[ cnt ] *= averagingfactor; } } } setDMRG1DM(num_elec, nOrbDMRG, DMRG1DM, DMRG2DM); //Possibly rotate the active space to the natural orbitals if (( scf_options->getWhichActiveSpace() == 1 ) && ( master_diis == 0 )){ //When the DIIS has started: stop copy_active( DMRG1DM, theQmatWORK, iHandler, true ); block_diagonalize( 'A', theQmatWORK, unitary, mem1, mem2, iHandler, true, DMRG2DM ); // Unitary is updated and DMRG2DM rotated setDMRG1DM( num_elec, nOrbDMRG, DMRG1DM, DMRG2DM ); buildQmatOCC(); //With an updated unitary, the Qocc and Tmat matrices need to be updated as well. buildTmatrix(); cout << "DMRGSCF::solve : Rotated the active space to natural orbitals, sorted according to the NOON." << endl; } //Calculate the matrix elements needed to calculate the gradient and hessian buildQmatACT(); DMRGSCFVmatRotations::rotate( VMAT_ORIG, NULL, theRotatedTEI, 'C', 'C', 'F', 'F', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename ); DMRGSCFVmatRotations::rotate( VMAT_ORIG, NULL, theRotatedTEI, 'C', 'V', 'C', 'V', iHandler, unitary, mem1, mem2, work_mem_size, tmp_filename ); buildFmat( theFmatrix, theTmatrix, theQmatOCC, theQmatACT, iHandler, theRotatedTEI, DMRG2DM, DMRG1DM); buildWtilde(wmattilde, theTmatrix, theQmatOCC, theQmatACT, iHandler, theRotatedTEI, DMRG2DM, DMRG1DM); //Calculate the gradient, hessian and corresponding update. On return, gradient contains the rescaled gradient == the update. augmentedHessianNR(theFmatrix, wmattilde, iHandler, unitary, gradient, &updateNorm, &gradNorm); } delete [] mem1; delete [] mem2; delete_file( tmp_filename ); delete Prob; delete HamDMRG; delete [] gradient; if ( diis_vec != NULL ){ delete [] diis_vec; } if ( diis != NULL ){ delete diis; } if ( theLocalizer != NULL ){ delete theLocalizer; } return Energy; }
bool Hamiltonian::operator==(const Hamiltonian& src) const { return (this == &src) || (this->potentials == src.getPotentialFuncts()); };
Hamiltonian::Hamiltonian(const Hamiltonian& _H) : Hamiltonian(_H.getPotentialFuncts()) {};
void end_update_p(typename Hamiltonian::PointType& z, Hamiltonian& hamiltonian, double epsilon, callbacks::logger& logger) { z.p -= epsilon * hamiltonian.dphi_dq(z, logger); }
void update_q(typename Hamiltonian::PointType& z, Hamiltonian& hamiltonian, double epsilon, callbacks::logger& logger) { z.q += epsilon * hamiltonian.dtau_dp(z); hamiltonian.update_potential_gradient(z, logger); }