-
Notifications
You must be signed in to change notification settings - Fork 6
Model Hamiltonians #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
5175a96
ebb7ef4
84b219d
65f56b3
e0ef771
9ab4627
d56989c
614f5ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #pragma once | ||
|
|
||
| #include <macis/types.hpp> | ||
|
|
||
| namespace macis { | ||
|
|
||
| /** | ||
| * @brief Generate Hamiltonian Data for 1D Hubbard | ||
| */ | ||
| void hubbard_1d(size_t nsites, double t, double U, std::vector<double>& T, | ||
| std::vector<double>& V); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #include <macis/model/hubbard.hpp> | ||
|
|
||
| namespace macis { | ||
|
|
||
| void hubbard_1d(size_t nsites, double t, double U, std::vector<double>& T, | ||
| std::vector<double>& V) { | ||
|
|
||
|
|
||
| T.resize(nsites * nsites); | ||
| V.resize(nsites * nsites * nsites * nsites); | ||
|
|
||
|
|
||
| for(size_t p = 0; p < nsites; ++p) { | ||
| // Half-filling Chemical Potential | ||
| T[p * (nsites+1)] = -U/2; | ||
|
||
|
|
||
| // On-Site Interaction | ||
| V[p * (nsites*nsites*nsites + nsites*nsites + nsites + 1)] = U; | ||
|
|
||
| // Hopping | ||
| if(p < nsites-1) { | ||
| T[p + (p+1)*nsites] = -t; | ||
| T[(p+1) + p*nsites] = -t; | ||
| } | ||
wavefunction91 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
|
|
||
|
|
||
| #include <iostream> | ||
| #include <spdlog/sinks/null_sink.h> | ||
| #include <spdlog/spdlog.h> | ||
|
|
||
| #include <macis/model/hubbard.hpp> | ||
|
|
||
| #include "ut_common.hpp" | ||
|
|
||
| TEST_CASE("Hubbard") { | ||
| ROOT_ONLY(MPI_COMM_WORLD); | ||
|
|
||
| const size_t nsites = 4; | ||
| const size_t nsites2 = nsites*nsites; | ||
| const size_t nsites3 = nsites2*nsites; | ||
| const double t = 1.0, U = 4.0; | ||
| std::vector<double> T,V; | ||
|
|
||
| SECTION("1D") { | ||
| macis::hubbard_1d( nsites, t, U, T, V ); | ||
|
|
||
| // Check two-body term | ||
| for(int p = 0; p < nsites; ++p) | ||
| for(int q = 0; q < nsites; ++q) | ||
| for(int r = 0; r < nsites; ++r) | ||
| for(int s = 0; s < nsites; ++s) { | ||
| const auto mat_el = V[p + nsites*q + nsites2*r + nsites3*s]; | ||
| if(p==q and p==r and p==s) | ||
| REQUIRE(mat_el == U); | ||
| else | ||
| REQUIRE(mat_el == 0.0); | ||
| } | ||
|
|
||
| // Check 1-body term | ||
| for(int p = 0; p < nsites; ++p) | ||
| for(int q = 0; q < nsites; ++q) { | ||
| const auto mat_el = T[p + q*nsites]; | ||
| if(p == q) | ||
| REQUIRE(mat_el == Approx(-U/2)); | ||
| else if( std::abs(p-q) == 1 ) | ||
| REQUIRE(mat_el == -t); | ||
| else | ||
| REQUIRE(mat_el == 0.0); | ||
| } | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For model Hamiltonians like this one, it will make sense to add a new HamiltonianGenerator class that implements the single/double search instead of the double loop (Incidentally, it could make sense to add it to this branch. I could take charge of that, since I've already implemented something in these lines). This is especially true since many of the model systems have an extremely sparse V tensor, which makes this type of Hamiltonian build very efficient. To this end, we could consider the option of having these "integral building functions" return a vector listing the orbitals which have a non-sparse V sub-tensor. In the example of the Hubbard model, this will always be empty, since V is completely diagonal, and hence does not generate any double (or single) excitations. For an impurity model, this would be just the impurity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good idea, If you can mock something up and push to this branch, that would be helpful. We can iterate on the design once something is in place.
Re Sparse vs dense storage, that's a good point. I'm hesitant to do this ad hoc though, if we're going to support sparse integrals, we should build up proper sparse tensor infrastructure (
sparsexxcan already cover the Matrix case, we would just need to generalize the CSR/CSV/COO to tensors which is relatively straight forward). However, even for some the largest cases that folks can do ED on for these types of problems (26-28 sites), integral storage is trivial compared to the CI vectors, so this kind of optimization may be premature. But I can definitely see the desire to have this in general, so we should figure out how to do it properly - I would say we should punt on that for a bit and maybe open an issue so we don't forget to cover it eventually.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll put what I have and push it in.
I didn't mean using a sparse tensor for the V's, I agree that's a bit premature (though useful at some point). I was thinking of storing the dense V, full of zeros, but having the HamiltonianGenerator instance only look for doubles/singles among a subset of orbitals. For example, in the Hubbard model, you want to tell it to look for singles everywhere, but for doubles nowhere (there are no doubles, at least in real space). This will dramatically reduce the cost of the Hamiltonian build. For impurity models, you want to look for singles everywhere, and for doubles only among the impurity orbitals (since the bath is non-interacting by construction, at least in DMFT). Since the impurity is typically much smaller than the bath, this again is an important speed-up.