Skip to content

Commit d1345a4

Browse files
committed
Reworked diagonalisation of ham-spin and updated main
The main now has support for the ham-spin
1 parent 778ac29 commit d1345a4

File tree

4 files changed

+101
-146
lines changed

4 files changed

+101
-146
lines changed

ham-spin.cpp

+30-136
Original file line numberDiff line numberDiff line change
@@ -78,82 +78,15 @@ void SpinHamiltonian::BuildBase()
7878
* Builds the SpinHamiltonian matrix blocks for S = myS
7979
* @param myS the spin to use
8080
*/
81-
void SpinHamiltonian::BuildHamWithS(int myS)
81+
void SpinHamiltonian::BuildFullHam()
8282
{
83-
std::vector< std::unique_ptr<matrix> > tmp_blockmat(spinbasis->getnumblocks());
84-
85-
#pragma omp parallel for
86-
for(int i=0;i<spinbasis->getnumblocks();i++)
87-
{
88-
int K = spinbasis->getKS(i).first;
89-
int S = spinbasis->getKS(i).second;
90-
91-
if(S!=myS)
92-
continue;
93-
94-
std::cout << "Building K=" << K << " S=" << S << std::endl;
95-
96-
int cur_dim = spinbasis->getBlock(i).getspacedim();
97-
98-
// calculate all elements for this block first
99-
std::unique_ptr<double []> hop(new double[cur_dim]);
100-
std::unique_ptr<int []> interact(new int[cur_dim*cur_dim]);
101-
102-
for(int a=0;a<cur_dim;a++)
103-
{
104-
auto bra = spinbasis->getBlock(i).Get(a);
105-
hop[a] = hopping(bra.first) + hopping(bra.second);
106-
107-
for(int b=a;b<cur_dim;b++)
108-
{
109-
auto ket = spinbasis->getBlock(i).Get(b);
110-
111-
interact[b+a*cur_dim] = interaction(bra.first, bra.second, ket.first, ket.second);
112-
interact[a+b*cur_dim] = interact[b+a*cur_dim];
113-
}
114-
}
115-
116-
std::cout << "Filling hamiltonian" << std::endl;
117-
118-
int mydim = spinbasis->getBlock(i).getdim();
119-
std::unique_ptr<matrix> tmp (new matrix (mydim,mydim));
120-
121-
auto &sparse = spinbasis->getBlock(i).getSparse();
122-
123-
#pragma omp parallel for schedule(guided)
124-
for(int a=0;a<mydim;a++)
125-
{
126-
for(int b=a;b<mydim;b++)
127-
{
128-
(*tmp)(a,b) = 0;
129-
130-
for(int k=0;k<sparse.NumOfElInCol(a);k++)
131-
for(int l=0;l<sparse.NumOfElInCol(b);l++)
132-
{
133-
if(sparse.GetElementRowIndexInCol(a,k) == sparse.GetElementRowIndexInCol(b,l) )
134-
(*tmp)(a,b) += sparse.GetElementInCol(a,k) * sparse.GetElementInCol(b,l) * \
135-
J * hop[sparse.GetElementRowIndexInCol(a,k)];
136-
137-
(*tmp)(a,b) += sparse.GetElementInCol(a,k) * sparse.GetElementInCol(b,l) * U/L * \
138-
interact[sparse.GetElementRowIndexInCol(a,k) + cur_dim * sparse.GetElementRowIndexInCol(b,l)];
139-
}
140-
141-
(*tmp)(b,a) = (*tmp)(a,b);
142-
}
143-
}
144-
145-
tmp_blockmat[i] = std::move(tmp);
146-
}
147-
148-
for(int i=0;i<tmp_blockmat.size();i++)
149-
if(tmp_blockmat[i])
150-
blockmat.push_back(std::move(tmp_blockmat[i]));
83+
BuildHamWithS(-1);
15184
}
15285

15386
/**
15487
* Builds the full SpinHamiltonian matrix
15588
*/
156-
void SpinHamiltonian::BuildFullHam()
89+
void SpinHamiltonian::BuildHamWithS(int myS)
15790
{
15891
blockmat.resize(spinbasis->getnumblocks());
15992

@@ -163,6 +96,9 @@ void SpinHamiltonian::BuildFullHam()
16396
int K = spinbasis->getKS(i).first;
16497
int S = spinbasis->getKS(i).second;
16598

99+
if(myS != -1 && S != myS)
100+
continue;
101+
166102
std::cout << "Building K=" << K << " S=" << S << std::endl;
167103

168104
int cur_dim = spinbasis->getBlock(i).getspacedim();
@@ -444,12 +380,21 @@ void SpinHamiltonian::mvprod(double *x, double *y, double alpha) const
444380
*/
445381
std::vector<double> SpinHamiltonian::ExactDiagonalizeFull(bool calc_eigenvectors)
446382
{
447-
std::vector<double> eigenvalues(dim);
383+
int mydim = 0;
384+
385+
for(int B=0;B<blockmat.size();B++)
386+
if(blockmat[B])
387+
mydim += blockmat[B]->getn();
388+
389+
std::vector<double> eigenvalues(mydim);
448390

449391
int offset = 0;
450392

451393
for(int B=0;B<blockmat.size();B++)
452394
{
395+
if(!blockmat[B])
396+
continue;
397+
453398
int dim = blockmat[B]->getn();
454399

455400
Diagonalize(dim, blockmat[B]->getpointer(), &eigenvalues[offset], calc_eigenvectors);
@@ -464,96 +409,45 @@ std::vector<double> SpinHamiltonian::ExactDiagonalizeFull(bool calc_eigenvectors
464409

465410
/**
466411
* Diagonalize the block diagonal matrix. Needs lapack. Differs from SpinHamiltonian::ExactDiagonalizeFull that
467-
* is diagonalize block per block and keeps the momentum associated with each eigenvalue.
412+
* is diagonalize block per block and keeps the momentum and spin associated with each eigenvalue.
468413
* @param calc_eigenvectors set to true to calculate the eigenvectors. The hamiltonian
469414
* matrix is then overwritten by the vectors.
470-
* @return a vector of pairs. The first member of the pair is the momentum, the second is
471-
* the eigenvalue. The vector is sorted to the eigenvalues.
415+
* @return a vector of tuples. The first member of the pair is the momentum, the second is
416+
* the spin and the thirth the actual eigenvalue. The vector is sorted to the eigenvalues.
472417
*/
473418
std::vector< std::tuple<int,int,double> > SpinHamiltonian::ExactSpinDiagonalizeFull(bool calc_eigenvectors)
474-
{
475-
std::vector< std::tuple<int, int, double> > energy(dim);
476-
477-
#pragma omp parallel for
478-
for(int B=0;B<blockmat.size();B++)
479-
{
480-
int K = spinbasis->getKS(B).first;
481-
int S = spinbasis->getKS(B).second;
482-
483-
int offset = 0;
484-
for(int i=0;i<B;i++)
485-
offset += blockmat[i]->getn();
486-
487-
int mydim = blockmat[B]->getn();
488-
489-
std::unique_ptr<double []> eigs(new double [mydim]);
490-
491-
Diagonalize(mydim, blockmat[B]->getpointer(), eigs.get(), calc_eigenvectors);
492-
493-
for(int i=0;i<mydim;i++)
494-
energy[i+offset] = std::make_tuple(K,S,eigs[i]);
495-
}
496-
497-
// sort to energy
498-
std::sort(energy.begin(), energy.end(),
499-
[](const std::tuple<int,int,double> & a, const std::tuple<int,int,double> & b) -> bool
500-
{
501-
return std::get<2>(a) < std::get<2>(b);
502-
});
503-
504-
return energy;
505-
}
506-
507-
/**
508-
* Diagonalize the block diagonal matrix for a certian spin.
509-
* Needs lapack. Differs from SpinHamiltonian::ExactDiagonalizeFull that
510-
* is diagonalize block per block and keeps the momentum associated with each eigenvalue.
511-
* @param myS the S of the blocks to diagonalize
512-
* @param calc_eigenvectors set to true to calculate the eigenvectors. The hamiltonian
513-
* matrix is then overwritten by the vectors.
514-
* @return a vector of pairs. The first member of the pair is the momentum, the second is
515-
* the eigenvalue. The vector is sorted to the eigenvalues.
516-
*/
517-
std::vector< std::tuple<int,int,double> > SpinHamiltonian::ExactSpinDiagonalize(int myS, bool calc_eigenvectors)
518419
{
519420
std::vector< std::tuple<int, int, double> > energy;
520421

521-
std::vector< std::unique_ptr<double []> > eigs(L);
522-
std::vector<int> eigs_dim(L);
523-
int totaldim = 0;
422+
std::vector< std::tuple<int,int,class matrix> > eigs (blockmat.size());
524423

525424
#pragma omp parallel for
526425
for(int B=0;B<blockmat.size();B++)
527426
{
427+
if(!blockmat[B])
428+
continue;
429+
528430
int K = spinbasis->getKS(B).first;
529431
int S = spinbasis->getKS(B).second;
530432

531-
if( S != myS)
532-
continue;
533-
534433
int mydim = blockmat[B]->getn();
535434

536-
std::unique_ptr<double []> cur_eigs(new double [mydim]);
435+
matrix cur_eigs(mydim,1);
537436

538-
Diagonalize(mydim, blockmat[B]->getpointer(), cur_eigs.get(), calc_eigenvectors);
437+
Diagonalize(mydim, blockmat[B]->getpointer(), cur_eigs.getpointer(), calc_eigenvectors);
539438

540-
eigs[K] = std::move(cur_eigs);
541-
eigs_dim[K] = mydim;
542-
totaldim += mydim;
439+
eigs[B] = std::make_tuple(K, S, std::move(cur_eigs));
543440
}
544441

545-
energy.reserve(totaldim);
546-
547-
for(int K=0;K<L;K++)
548-
if(eigs[K])
549-
for(int i=0;i<eigs_dim[K];i++)
550-
energy.push_back(std::make_tuple(K,myS,eigs[K][i]));
442+
for(int i=0;i<eigs.size();i++)
443+
for(int j=0;j<std::get<2>(eigs[i]).getn();j++)
444+
energy.push_back(std::make_tuple(std::get<0>(eigs[i]), std::get<1>(eigs[i]), std::get<2>(eigs[i])[j]));
551445

552446
// sort to energy
553447
std::sort(energy.begin(), energy.end(),
554448
[](const std::tuple<int,int,double> & a, const std::tuple<int,int,double> & b) -> bool
555449
{
556-
return std::get<2>(a) < std::get<2>(b);
450+
return std::get<2>(a) < std::get<2>(b);
557451
});
558452

559453
return energy;

helpers.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@
3434
// constant used in BasisList
3535
const int BasisList::EMPTY = -1;
3636

37+
/**
38+
* Empty matrix constructor. Don't use it
39+
* unless you know what you're doing
40+
*/
41+
matrix::matrix()
42+
{
43+
this->n = 0;
44+
this->m = 0;
45+
}
46+
3747
/**
3848
* @param n_ number of rows
3949
* @param m_ number of columns

helpers.h

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
class matrix
3535
{
3636
public:
37+
matrix();
38+
3739
matrix(int n_, int m_);
3840

3941
matrix(const matrix &orig);

0 commit comments

Comments
 (0)