-
Notifications
You must be signed in to change notification settings - Fork 8
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
Postlifts: mapping scalar mesh vertices to arbitrary hamiltonian parameters #76
Conversation
docs+tests cleanup
This required some subtle fixes to get CI back to green.
Since here we no longer automatically extend the dimensions of a symbolic In any case, if a mix of symbols and tuples are given for Finite differences in codiagonalizer needed a fix to disallow shifts along parameters when they are non-numeric. I also added some more useful error message in case a dimension mismatch is found between mesh vertices and Hamiltonian dimensions. |
Codecov Report
@@ Coverage Diff @@
## master #76 +/- ##
==========================================
+ Coverage 62.31% 62.41% +0.10%
==========================================
Files 15 15
Lines 2351 2360 +9
==========================================
+ Hits 1465 1473 +8
- Misses 886 887 +1
Continue to review full report at Codecov.
|
I do realize this PR might be increasing the complexity of our API quite a bit, since the user needs to understand two types of lifts instead of one (i.e. cut -> embedding mesh -> parameter/phase space). The need of this would be even clearer if we had more than one "cut"-like mesh (higher-order generalizations of Feedback welcome on the clarity of the change, or otherwise. |
So let us assume that a parametric Hamiltonian depends on a matrix. The user wants to plot some band structure along a cut in the bloch/parameter space. So he has to build a mesh with a If this is true, the user always has to define how a collection of Going to your example. In this proposal, the user does
Is this better than forcing the use to define the parametric Hamiltonian as:
? I understand that in some cases, if might be very cumbersome to write something of the form of
|
I did consider this, but I felt that in practice (because I'm actually using this stuff for a project), the verbosity of forcing scalar parameters was suboptimal, since typically the models can be complex. Allowing to write them in terms of arbitrary parameters seemed good. In any case I think I did not clearly explain myself. The used never has to define two lifts, only one, from the embedding mesh to the parameter/Bloch space. It is only internally that we need to define another lift in cases where the MeshSpec corresponds to a cut of the embedding mesh. But this is transparent for the user. She doesn't need to understand the postlift concept. She only needs to be aware that the source space is the embedding mesh (so it should be clear what that is, given a MeshSpec), and that the target space is parameter/Bloch space, so it is not so complicated. In usual full-bandstructure computations the mapping between these is the identity, so no need to define a lift at all (even when using linearmesh). It is only when using Does that change your perspective? |
One more thought that may clarify things further. Remember you once proposed to merge the lift into the Mesh itself, and I pushed back because I argued that the lift depends on the Hamiltonian? With the current lift/postlift perspective things are clearer. The first lift (from the cut to the embedding mesh) should indeed be part of the mesh object. It is only the postlift that should be separate. So an improvement here would be to refactor the MeshSpec type to be a general "cut mesh + lift to embedding mesh" object. A marchingmesh and linearmesh would both be specific instances of this, both with a clear concept of embedding mesh encoded into the type. Internally one could explicitly store the coordinates of the cut vertices both in the cut manifold and the embedding manifold, or just one of them plus a "prelift" function that maps between them. That should be a transparent implementation detail. Then, we are left with only one (post)lift outside of the mesh object. Maybe that's cleaner. |
The latter idea about storing prelifts inside MeshSpecs can be implemented orthogonally to this PR. I will merge this in a bit if there is no further feedback. |
Sorry for the late reply (busy week). prelift: Tuple{Float64} -> Tuple{Float64, Float64, Float64, Float64} [math/julia frankenstein notation] Now, the electric field is actuallly passed as a SVector. So we need a poslift that goes from the embeeding space to the target space of the parametric Hamiltonian: postlift: Tuple{Float64, Float64, Float64, Float64} -> Tuple{SVector{2, Float64}, Float64, Float64} I initially understood that with this proposal the user only actually needs to specify a function that is a composition of both: lift: Tuple{Float64} -> Tuple{SVector{2, Float64}, Float64, Float64} Is this correct? If so, why would we still want a |
Hey @BacAmorim, thanks for your post. That is not quite correct. The Now, when we want to "evaluate" the ParametricHamiltonian across this linear mesh, we need another mapping, from the 2D space to the parameter/bloch space. In this case it is So what this PR does is to first apply the prelift, as obtained by ^{*}: That is true as long as we don't begin to write things like |
Ok, I think I have a better understanding of the proposal. But the prelift/postlift destinction (even if not directly exposed to the user) still seems unnecessary to me. For this particular example, it would seem more natural for the user to just specify a Maybe my confusion is due to the name |
As usual, you make excellent points, so I'm going to delay merging this, and give us some time to elaborate. In particular, you are implicitly proposing an alternative to the whole cut/lift approach. You say, have a single kind of mesh, parametrized by dimension (we could just make do with Full band, with an
Straight bandcut, with an
Piecewise bandcut along a 1D cut from k = (0,0) to k = (0,pi), with an
Piecewise bandcut along a 1D cut with symbolic nodes
General parametric Hamiltonian
Parametric mapping from a 1D mesh, with the
The Please let me know how you feel about this alternative. It does indeed seem simpler... If you agree, I might close this and start a new PR where we can polish the details. |
I really like this! I also like the name One question: with the
vs
The only thing that matters is the number of points in the segment. Correct? I would suggest keeping in the API both |
Ok, let's move this over to an independent issue |
Closes #75
This PR does various changes to meshes and bandstructures
ParametricHamiltonian
s)lift
kwarg inbandstructure(h, meshspec; lift = ...)
that is now treated as a "post-lift": first, the vertices ofmesh = buildmesh(meshspec, h)
are lifted to the "embedding mesh", and then the user-provided lift is applied on the result.marchingmesh
to a 3D Brillouin zone. We now require the embedding mesh dimensions to match the hamiltonian's parameter/bloch phase space dimension (EDIT: if no postlift is provided thought thelift
option)The "embedding mesh" of a
linearmesh((0,0), (0,1))
is a 2D mesh (because vertices are 2D). For amarchingmesh((0,1), (0,1), (0,1))
it is 3D, because there are three axes. So lifting is done in two steps: first from the "cut" to the "embedding mesh" and then however the user specifies with his/herlift
. In practice, the user-provided lift (calledpostlift
only in the code, the kwarg is stilllift
) is the actual mapping from the embedding mesh to the parameter space of a ParametricHamiltonian. To understand this better, here is an example.Take a parametric graphene Hamiltonian, with a vectorial parameter
E
that represents an electric field (producing a lattice-periodic potentialE' * r
)Now, we can build a bandstructure along a cut in "electric-field-space" like this
This sweeps
E
fromSA[0,0]
toSA[1,1]
. First, the linear mesh coordinates are mapped to a 2D mesh space (where the nodes (0,0) and (1,1) live). Then the postlift(Ex, Ey) -> (SA[Ex,Ey], 0, 0)
converts the scalar 2D mesh vertices to a static vector, while fixes the bloch phases to zero. The result of the user-providedlift
is then always between the embedding mesh and the parameter/bloch phase space.