Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
kwant-bot
@kwant-bot
xavier:
Perhaps the following: First notice that d epsilon_alpha/dE <0. this can be shown from eq.(17) since dHeff/dE is a diagonal matrix with only -1 or 0 as eigenvalues. So the function must go down unless there is a jump. But in order for having a jump, the funciton ust be negative. Hence we must have alternative zeros and jumps. The jumps occur when the #1 eigenvalue (in magnitude) is negative is equal to the #2 one (which is positive) in magnitude, i.e. when #1 + #2 = 0. We could start from the left and look at the first root using some variation of gradient decent. If one takes a conservative time step it should find the first root. Then we can find the first jump by looking at the root of #1 + #2 and proceed to the second root...until we reach E_max. It sounds like a plan, doesn't it?
kwant-bot
@kwant-bot

jbweston:

First notice that d epsilon_alpha/dE <0

This does not appear to be the case for the majorana example

kwant-bot
@kwant-bot
xavier:
Let's look at the proof. We have H(E) Psi(E) = e(E) Psi(E) with Psi(E) normalized to 1. e(E) = <Psi | H | Psi>. Then de/dE conains 3 terms. <Psi|Psi>=1 implies <dPsi/dE |Psi >+ <Psi|dPsi/dE> = 0 so that 2 of these terms vanish. We are left with de/dE = <Psi |dH/dE|Psi>. dH/dE is a negative diagonal matrix with -1 or 0 entries. We arrive at de/dE = - sum_i |Psi_sr(i)|^2 <0. I cannot see any failure mode in this proof.
jbweston:
this is the plot of the eigenvalues of H_eff(E) as a function of E for the majorana system

jbweston:

dH/dE is a negative diagonal matrix with -1 or 0 entries

This part is not obvious to me

kwant-bot
@kwant-bot
jbweston:
there are definitely parts with positive gradient
jbweston:
i.e. not obvious that the lower-right block of dH/dE is such a thing; I see how the upper-left block is
kwant-bot
@kwant-bot
xavier:
Yeah, my mistake! Obviously it violates the symmetry of a BdG Hamiltonian.
xavier:
It does not nullify everything I wrote above though. (1) The jumps still occur when there are competing negative and positive eigenvalues, hence for #1+#2=0 in the case #1 x #2 <0. Do we agree on (1)?
kwant-bot
@kwant-bot
jbweston:
except when there are jumps when modes open
jbweston:
consider the green mode on the left above, and the purple mode right after the jump
xavier:
yes. But these we can precalculate.
kwant-bot
@kwant-bot
jbweston:
@xavier @anton I opened https://gitlab.kwant-project.org/kwant/kwant/merge_requests/320 that implements what I've done so far
jbweston:
the searching algorithm is still the naive gridding one that I proposed originally
anton:
Noice
kwant-bot
@kwant-bot
xavier:
:thumbsup:
kwant-bot
@kwant-bot
jbweston:
I just tried applying this to a graphene flake and the results are not pretty
kwant-bot
@kwant-bot
cwg:
Hi, I've been looking at the new vectorized systems and I tend to think that having a single class for both old and new systems was perhaps not such a good idea.
cwg:
Here's an example.
cwg:
I noticed the following chunk of code:
cwg:
    site_offsets = np.cumsum([0] + [len(arr) for arr in self.site_arrays])
    # Site array where next cell starts
    next_cell = bisect.bisect(site_offsets, self.cell_size) - 1
cwg:
It occurs twice in _system.py and serves to find the index of the first site array that corresponds to the "next cell".
cwg:
Now it seems clumsy to calculate next_cell from cell_size. It would be more robust and simpler to simply store next_cell directly. However, this does not seem possible, because cell_size is actually provided directly by someone who implements the system API.
cwg:
If the new systems where separate classes, we would be free with the choice of an appropriate API.
cwg:
They would, of course, still implement the old API.
cwg:
But that's a difference to the current situations, where the old API actually puts constraints on the new class: A valid implementation of the old API must be also a valid implementation of the new one.
kwant-bot
@kwant-bot
cwg:
I have the impression that this may be too much of backwards compatibility.
cwg:
Another example of the same problem is that someone who wants to provide new-style systems, still has to provide the old API (e.g. hamiltonian).
cwg:
That's just some idea I had. Please let me know if I've overseen other important aspects.
cwg:
What do you think?
kwant-bot
@kwant-bot
jbweston:
but having 2 classes will make interfacing with systems harder I think. e.g. operators would have to have code to deal with old systems that uses hamiltonian, but also new systems that uses hamiltonian_term
cwg:
Good point! Thinking...
kwant-bot
@kwant-bot
cwg:
Put differently, the question is also whether we need forward compatility: should it be possible to use new functionality (that expect vectorized systems) with old-style unvectorized systems? I do not think that we have to promise that. That's more than backwards-compatibility and it comes at additional cost (in work and complexity for us).
kwant-bot
@kwant-bot

cwg:
It seems to me that this wouldn't be a problem. There's no problem with consumers that use hamiltonian_submatrix(): user code using this remains efficient even after vectorization. Consumers that use hamiltonian directly (like tkwant or kwant.operator) have to be rewritten anyway (or they don't profit from vectorization). The rewriting can work such that there's a case distinction: the old code (that is already written) is used for old-style systems, and new code is used for new systems.

That means some additional if clauses, but the overall complexity should be smaller, because we do not have to be careful to write the new code in such a way that it remains efficient for old systems. It also means that it will be easy to remove old cruft once we no longer support old systems.

kwant-bot
@kwant-bot
jbweston:
do you have any idea how the abstract system class hierarchy would look
jbweston:
in many places we check isinstance(syst, system.FiniteSystem) for instance
kwant-bot
@kwant-bot

cwg:
Actually, I realize, vectorized low-level systems do not even have to implement the old API. That doesn't break backwards-compatibility, because old code is not supposed to trigger vectorization.

The only thing that matters is that it remains reasonably simple to accept either old or new systems. Taking the example that you gave, we could add a method is_finite() (or number_of_dimensions() or something similar), and add it also to old systems. Instead of continuing to provide the old API, we would define a new API, and inject small bits of it into the old systems, so that old systems partially ducktype as new ones.

I think the hierarchy of the new systems would be simple: a single class System2

jbweston:
but then all the isinstance checks break
anton:
@cwg what do we stand to gain from the separation?
kwant-bot
@kwant-bot
cwg:
  • The freedom to define the API as it fits. We can get rid of cell_size, graph, and lots of other cruft. That means less historical ballast in the future and simpler code in the long run.
  • Simplicity of implementation of classes that implement the new low-level system API (they only have to provide the new API, not both the old and the new one).
  • Performance (old systems just work as they did before, new ones are perhaps less encumbered)
cwg:
Yes, we would have to replace them.
kwant-bot
@kwant-bot
cwg:
Joe's commit series is very clean, so it shouldn't be actually a lot of work. The old code is written, the new one as well (up to some simplifications).
anton:
Hmm, but isn't this contrary to the original idea of evolving the interface while maintaining compatibility?
kwant-bot
@kwant-bot

cwg:
In https://gitlab.kwant-project.org/kwant/kwant/issues/302, I wrote: "I propose to extend the low-level system API in the following way", so indeed that's what I had in mind. But recently I've been wondering whether making a cleaner cut wouldn't be preferable (for the above-stated reasons). Of course there would be still backwards compatibility, in the sense that old scripts would continue to work. It would be even higher compatibility, since the MR introduces some restrictions also on old systems.

The downside of splitting is that system consumers will have to adapt, but they have to anyway, if they want to profit from vectorization. And I'm not aware of any third-party system consumers beyond tkwant.

kwant-bot
@kwant-bot
anton:
What about the codebase size?
kwant-bot
@kwant-bot
anton:
Another problem that I see is communicating to the users and writing documentation. It seems weird to have a version where we'd have to say "you may do A, but you should really do B, which is quite different instead"
kwant-bot
@kwant-bot
cwg:
Looking at the relevant commits, the changes are mostly complete rewrites of functions. There would be substantial old code that remains (e.g. all the old code in _system.pyx and the old finalization code in builder). But, on the other hand, the new code would be simpler. For example, the new "logarithmic" hamiltonian() wouldn't be necessary, neither builder._Sites. So overall, the number of lines to be actively maintained would decrease. Also, backwards compatibility would be better: for example, the old fully general hamiltonian_submatrix would continue to exist.
anton:
I understand and don't object against those points. Except of course the need to also duplicate the operator.

cwg:
I think we could only explain vectorized usage (in the tutorial) and state that non-vectorized usage is still supported for backwards compatibility.

In the reference, non-vectorized stuff should be marked as deprecated.

Is there a difference in this respectto the current MR?