@@ -78,82 +78,15 @@ void SpinHamiltonian::BuildBase()
78
78
* Builds the SpinHamiltonian matrix blocks for S = myS
79
79
* @param myS the spin to use
80
80
*/
81
- void SpinHamiltonian::BuildHamWithS ( int myS )
81
+ void SpinHamiltonian::BuildFullHam ( )
82
82
{
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 );
151
84
}
152
85
153
86
/* *
154
87
* Builds the full SpinHamiltonian matrix
155
88
*/
156
- void SpinHamiltonian::BuildFullHam ( )
89
+ void SpinHamiltonian::BuildHamWithS ( int myS )
157
90
{
158
91
blockmat.resize (spinbasis->getnumblocks ());
159
92
@@ -163,6 +96,9 @@ void SpinHamiltonian::BuildFullHam()
163
96
int K = spinbasis->getKS (i).first ;
164
97
int S = spinbasis->getKS (i).second ;
165
98
99
+ if (myS != -1 && S != myS)
100
+ continue ;
101
+
166
102
std::cout << " Building K=" << K << " S=" << S << std::endl;
167
103
168
104
int cur_dim = spinbasis->getBlock (i).getspacedim ();
@@ -444,12 +380,21 @@ void SpinHamiltonian::mvprod(double *x, double *y, double alpha) const
444
380
*/
445
381
std::vector<double > SpinHamiltonian::ExactDiagonalizeFull (bool calc_eigenvectors)
446
382
{
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);
448
390
449
391
int offset = 0 ;
450
392
451
393
for (int B=0 ;B<blockmat.size ();B++)
452
394
{
395
+ if (!blockmat[B])
396
+ continue ;
397
+
453
398
int dim = blockmat[B]->getn ();
454
399
455
400
Diagonalize (dim, blockmat[B]->getpointer (), &eigenvalues[offset], calc_eigenvectors);
@@ -464,96 +409,45 @@ std::vector<double> SpinHamiltonian::ExactDiagonalizeFull(bool calc_eigenvectors
464
409
465
410
/* *
466
411
* 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.
468
413
* @param calc_eigenvectors set to true to calculate the eigenvectors. The hamiltonian
469
414
* 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.
472
417
*/
473
418
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)
518
419
{
519
420
std::vector< std::tuple<int , int , double > > energy;
520
421
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 ());
524
423
525
424
#pragma omp parallel for
526
425
for (int B=0 ;B<blockmat.size ();B++)
527
426
{
427
+ if (!blockmat[B])
428
+ continue ;
429
+
528
430
int K = spinbasis->getKS (B).first ;
529
431
int S = spinbasis->getKS (B).second ;
530
432
531
- if ( S != myS)
532
- continue ;
533
-
534
433
int mydim = blockmat[B]->getn ();
535
434
536
- std::unique_ptr< double []> cur_eigs (new double [ mydim] );
435
+ matrix cur_eigs (mydim, 1 );
537
436
538
- Diagonalize (mydim, blockmat[B]->getpointer (), cur_eigs.get (), calc_eigenvectors);
437
+ Diagonalize (mydim, blockmat[B]->getpointer (), cur_eigs.getpointer (), calc_eigenvectors);
539
438
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));
543
440
}
544
441
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]));
551
445
552
446
// sort to energy
553
447
std::sort (energy.begin (), energy.end (),
554
448
[](const std::tuple<int ,int ,double > & a, const std::tuple<int ,int ,double > & b) -> bool
555
449
{
556
- return std::get<2 >(a) < std::get<2 >(b);
450
+ return std::get<2 >(a) < std::get<2 >(b);
557
451
});
558
452
559
453
return energy;
0 commit comments