8 #include "DOCIHamtilonian.h"
20 molecule.reset(mol.
clone());
22 if(molecule->get_n_electrons() % 2 != 0)
23 throw(
"We need even number of electrons!");
37 molecule.reset(mol.
clone());
39 if(molecule->get_n_electrons() % 2 != 0)
40 throw(
"We need even number of electrons!");
42 permutations.reset(
new Permutation(molecule->get_n_electrons()/2));
50 molecule.reset(mol.
move());
52 if(molecule->get_n_electrons() % 2 != 0)
53 throw(
"We need even number of electrons!");
55 permutations.reset(
new Permutation(molecule->get_n_electrons()/2));
64 permutations.reset(
new Permutation(*orig.permutations));
65 molecule.reset(orig.molecule->clone());
71 permutations.reset(
new Permutation(*orig.permutations));
72 molecule.reset(orig.molecule->clone());
115 auto num_t = omp_get_max_threads();
116 unsigned long long num_elems = (
getdim()*1ul*(
getdim()+1ul))/2;
117 unsigned long long size_part = num_elems/num_t + 1;
121 std::vector<unsigned long long> workload(num_t+1);
122 workload.front() = 0;
123 workload.back() =
getdim();
125 for(
int i=1;i<num_t;i++)
127 auto num_lines = workload[i-1];
128 unsigned long long num_elems = 0;
130 while(num_elems < size_part)
131 num_elems +=
getdim() - num_lines++;
136 workload[i] = num_lines;
139 std::vector< std::unique_ptr<helpers::SparseMatrix_CRS> > smat_parts(num_t);
141 std::cout <<
"Running with " << num_t <<
" threads." << std::endl;
143 permutations->reset();
147 auto start = std::chrono::high_resolution_clock::now();
148 auto me = omp_get_thread_num();
153 for(
auto idx_begin=0;idx_begin<workload[me];++idx_begin)
158 auto my_mol = std::unique_ptr<Molecule> (molecule->clone());
160 Build_iter(my_perm, (*smat_parts[me]), workload[me], workload[me+1], *my_mol);
162 auto end = std::chrono::high_resolution_clock::now();
165 std::cout << me <<
"\t" << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
168 mat->AddList(smat_parts);
181 auto &perm_bra = perm;
183 for(
auto i=i_start;i<i_end;++i)
185 const auto bra = perm_bra.
get();
197 auto ksp = cur & (~cur + 1);
205 tmp += 2 * mol.
getT(s, s);
208 tmp += mol.
getV(s, s, s, s);
215 auto ksp2 = cur2 & (~cur2 + 1);
231 tmp += 4 * mol.
getV(r, s, r, s);
232 tmp -= 2 * mol.
getV(r, s, s, r);
240 for(
auto j=i+1;j<
getdim();++j)
242 const auto ket = perm_ket.next();
244 const auto diff = bra ^ ket;
252 auto ksp1 = diff_c & (~diff_c + 1);
256 auto ksp2 = diff_c & (~diff_c + 1);
279 std::vector<double> eigv(mat->
gn());
281 Diagonalize_arpack(energy,eigv,
true);
283 return std::make_pair(energy, std::move(eigv));
294 std::vector<double> eigv(0);
296 Diagonalize_arpack(energy,eigv,
false);
308 void DOCIHamiltonian::Diagonalize_arpack(
double &energy, std::vector<double> &eigv,
bool eigvec)
const
321 char which[] = {
'S',
'A'};
326 std::unique_ptr<double []> resid(
new double[n]);
338 std::unique_ptr<double []> v(
new double[ldv*ncv]);
340 std::unique_ptr<int []> iparam(
new int[11]);
350 std::unique_ptr<int []> ipntr(
new int[11]);
355 std::unique_ptr<double []> workd(
new double[3*n]);
356 for(
int i=0;i<3*n;i++)
359 auto lworkl = ncv*(ncv+8);
360 std::unique_ptr<double []> workl(
new double[lworkl]);
375 std::unique_ptr<int []> select;
378 select.reset(
new int[ncv]);
381 std::unique_ptr<double []> d(
new double[nev]);
390 dsaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid.get(), &ncv, v.get(), &ldv, iparam.get(), ipntr.get(), workd.get(), workl.get(), &lworkl, &info);
395 mat->
mvprod(workd.get()+ipntr[0]-1, workd.get()+ipntr[1]-1);
397 dsaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid.get(), &ncv, v.get(), &ldv, iparam.get(), ipntr.get(), workd.get(), workl.get(), &lworkl, &info);
401 std::cerr <<
"Error with dsaupd, info = " << info << std::endl;
402 else if ( info == 1 )
403 std::cerr <<
"Maximum number of Lanczos iterations reached." << std::endl;
404 else if ( info == 3 )
405 std::cerr <<
"No shifts could be applied during implicit Arnoldi update, try increasing NCV." << std::endl;
407 dseupd_(&rvec, &howmny, select.get(), d.get(), eigv.data(), &ldv, &sigma, &bmat, &n, which, &nev, &tol, resid.get(), &ncv, v.get(), &ldv, iparam.get(), ipntr.get(), workd.get(), workl.get(), &lworkl, &info);
410 std::cerr <<
"Error with dseupd, info = " << info << std::endl;
430 std::vector<double> eigs(n);
434 std::unique_ptr<double []> work (
new double [lwork]);
438 dsyev_(&jobz,&uplo,&n,fullmat->getpointer(),&n,eigs.data(),work.get(),&lwork,&info);
441 std::cerr <<
"dsyev failed. info = " << info << std::endl;
443 return std::make_pair(std::move(eigs), std::move(*fullmat));
454 return __builtin_popcountl(bits);
455 #elif defined(USELONGLONG)
456 return __builtin_popcountll(bits);
469 assert(i<j &&
"Order indices correctly!");
472 auto sign =
CountBits(( ((1<<j) - 1) ^ ((1<<(i+1)) - 1) ) & a);
520 char which[] = {
'S',
'A'};
525 std::unique_ptr<double []> resid(
new double[n]);
537 std::unique_ptr<double []> v(
new double[ldv*ncv]);
539 std::unique_ptr<int []> iparam(
new int[11]);
549 std::unique_ptr<int []> ipntr(
new int[11]);
554 std::unique_ptr<double []> workd(
new double[3*n]);
555 for(
int i=0;i<3*n;i++)
558 auto lworkl = ncv*(ncv+8);
559 std::unique_ptr<double []> workl(
new double[lworkl]);
572 std::unique_ptr<int []> select;
575 select.reset(
new int[ncv]);
578 std::vector<double> d(nev);
584 dsaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid.get(), &ncv, v.get(), &ldv, iparam.get(), ipntr.get(), workd.get(), workl.get(), &lworkl, &info);
589 mat->
mvprod(workd.get()+ipntr[0]-1, workd.get()+ipntr[1]-1);
591 dsaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid.get(), &ncv, v.get(), &ldv, iparam.get(), ipntr.get(), workd.get(), workl.get(), &lworkl, &info);
595 std::cerr <<
"Error with dsaupd, info = " << info << std::endl;
596 else if ( info == 1 )
597 std::cerr <<
"Maximum number of Lanczos iterations reached." << std::endl;
598 else if ( info == 3 )
599 std::cerr <<
"No shifts could be applied during implicit Arnoldi update, try increasing NCV." << std::endl;
601 dseupd_(&rvec, &howmny, select.get(), d.data(), 0, &ldv, &sigma, &bmat, &n, which, &nev, &tol, resid.get(), &ncv, v.get(), &ldv, iparam.get(), ipntr.get(), workd.get(), workl.get(), &lworkl, &info);
604 std::cerr <<
"Error with dseupd, info = " << info << std::endl;
void dsaupd_(int *ido, char *bmat, int *n, char *which, int *nev, double *tol, double *resid, int *ncv, double *v, int *ldv, int *iparam, int *ipntr, double *workd, double *workl, int *lworkl, int *info)
virtual Molecule * clone() const =0
std::pair< double, std::vector< double > > Diagonalize() const
static int CalcSign(unsigned int i, unsigned int j, const mybitset a)
void ReadFromFile(std::string)
void dseupd_(int *rvec, char *All, int *select, double *d, double *z, int *ldz, double *sigma, char *bmat, int *n, char *which, int *nev, double *tol, double *resid, int *ncv, double *v, int *ldv, int *iparam, int *ipntr, double *workd, double *workl, int *lworkl, int *info)
DOCIHamiltonian(const Permutation &, const Molecule &)
Molecule const & getMolecule() const
static unsigned int CountBits(mybitset)
void SaveToFile(std::string) const
DOCIHamiltonian & operator=(const DOCIHamiltonian &)
static unsigned long long CalcCombinations(unsigned int, unsigned int)
void ConvertToMatrix(helpers::matrix &dense) const
virtual mybitset get() const
double CalcEnergy() const
void PushToRowNext(unsigned int j, double value)
virtual double getT(int, int) const =0
std::pair< std::vector< double >, helpers::matrix > DiagonalizeFull() const
unsigned int getdim() const
virtual Molecule * move()=0
virtual double getV(int, int, int, int) const =0
Permutation const & getPermutation() const
int ReadFromFile(const char *, const char *)
void dsyev_(char *jobz, char *uplo, int *n, double *A, int *lda, double *W, double *work, int *lwork, int *info)
int WriteToFile(const char *, const char *, bool=false) const
void mvprod(const double *, double *) const