Add NLCC support for phonon computations#1311
Conversation
|
I had to remove |
antoine-levitt
left a comment
There was a problem hiding this comment.
Haven't checked everything but looks reasonable!
| in reduced coordinates: | ||
| ``` | ||
| dynmat[β, t, α, s] = ∂²E/∂u_sα(-q)∂u_tβ(q). | ||
| ``` |
There was a problem hiding this comment.
really not a fan of this interpretation, defining it as the derivative of the R -> F map seems much simpler to me...
There was a problem hiding this comment.
That's basically what it is since dE/du is the force. But with an extra q dependency here. The main reason I put the formula there is to know in which order to write the dynmat entries, otherwise you can get the transpose by mistake.
There was a problem hiding this comment.
right but we don't use this notation elsewhere so maybe deltaF[alpha, s] = dynmat[] deltaR[]...? Any particular reason why it's beta alpha rather than alpha beta?
There was a problem hiding this comment.
I put it in that order such that the RHS matches Baroni, and it also makes sense to me with Julia's column-major indexing to write it like that, no?
There was a problem hiding this comment.
I mean it's usually xi = Aij xj, not xj = Aji xi
There was a problem hiding this comment.
I tried to write it like deltaF[alpha, s] = dynmat[] deltaR[] as well, but I had to give up because it's really confusing and unusual (it's difficult to keep track of what is R-periodic and what is not).
| # however since the potential is real, we conjugate to obtain the -q term: | ||
| # δV = Kxc (∂ρ/∂u_sα(-q) + ∂ρcore/∂u_sα(-q)) | ||
| # = conj( Kxc (∂ρ/∂u_sα( q) + ∂ρcore/∂u_sα( q)) ) | ||
| δV_αs = conj.(apply_kernel(term, basis, δρs[α, s] + δρcores[α, s]; ρ, q)) |
There was a problem hiding this comment.
Haven't followed the complete derivation but I'm scared by this line; the whole point of the explanation I gave in #1310 is that we never conjugate q stuff. Are you sure about this conj?
There was a problem hiding this comment.
Yes 100% sure. It's also there in the local term, just hidden by Parseval's theorem. For a real function (the density is real) the conjugate should always be fine. You only get problems if you directly conjugate the psis since those are complex. I am not sure how DFPT works for spin orbit coupling or magnetic fields. Surely Dal Corso has some paper about it, but I haven't read it.
|
@antoine-levitt do you want to review this or should I ask Michael? :D |
antoine-levitt
left a comment
There was a problem hiding this comment.
LGTM modulo the comments
| in reduced coordinates: | ||
| ``` | ||
| dynmat[β, t, α, s] = ∂²E/∂u_sα(-q)∂u_tβ(q). | ||
| ``` |
There was a problem hiding this comment.
right but we don't use this notation elsewhere so maybe deltaF[alpha, s] = dynmat[] deltaR[]...? Any particular reason why it's beta alpha rather than alpha beta?
| # ∂E/∂u_tβ(q) = ∫ Vxc ∂ρcore/∂u_tβ(q) | ||
| # Differentiate again wrt. u_sα(-q) to get the dynamical matrix element: | ||
| # ∂²E/∂u_sα(-q)∂u_tβ(q) = ∫ Kxc (∂ρ/∂u_sα(-q) + ∂ρcore/∂u_sα(-q)) (∂ρcore/∂u_tβ(q)) | ||
| # + ∫ Vxc ∂²ρcore/∂u_sα(-q)∂u_tβ(q) |
There was a problem hiding this comment.
I'm still not very comfortable with this d2E business, and it contrasts with the way everything else is written (as dR -> dF). Can't you write it like that?
There was a problem hiding this comment.
This is how Baroni writes it. I don't like to just use dF and dR as it doesn't make it clear which has q and which has -q. This derivation also directly matches the implementation
There was a problem hiding this comment.
What I don't understand is what's up with the -q? The supercell mapping from dR to dF is cell-periodic, and therefore bloch theorem applies so a displacement dR_q e^iqx produces a force dF_q e^iqx, and we compute the mapping dR_q -> dF_q. No need to involve -q. Should we zoom to discuss?
There was a problem hiding this comment.
Sure, since a displacement dR_q e^iqR produces a force dF_q e^iqR, you apply a displacement dR_q e^iqR, compute the corresponding force, and then multiply by e^-iqR to recover dF_q. So what you suggest is computing the force "normally" with d/du and then multiplying by e^-iqR. What I suggest is directly computing the force with the phase removed with d/du(-q). Does this make sense? The two should be equivalent, but I prefer the latter approach since I find the required code changes more obvious that way.
If you want we can have a call, maybe tomorrow somewhere between 13:30 and 16:00, or on Friday somewhere between 13:30 and 16:00?
| # Pre-allocation of large arrays for GPU efficiency | ||
| Gs = G_vectors(basis) | ||
| ρ = to_device(basis.architecture, zeros(Complex{T}, length(Gs))) | ||
| Gqs = map(G -> G+q, G_vectors(basis)) |
There was a problem hiding this comment.
I think we call those Gpk or something somewhere else?
There was a problem hiding this comment.
The naming is not super consistent. I used Gqs because that is what the local term (my inspiration) uses.
| @testset "Atomic $(string(typeof(method)))" for (method, elements) in zip(methods, elements) | ||
| basis = build_basis(elements, :none) | ||
| ρ = @inferred guess_density(basis, method) | ||
| ρ = guess_density(basis, method) |
There was a problem hiding this comment.
Just a remark that we had real trouble with type instabilities here, so this is why the @inferred tests exist. So this was not a GPU thing but a general performance thing. I think it's a bad sign you need to remove it again and we should think very carefully if this is the right thing to do (instead of fixing the issue)
There was a problem hiding this comment.
It was added in this PR, so it's presumably safe to remove as long as DFTK still runs on the GPU: #850.
A proper fix is to make the q==0 case encoded in the type system (i.e. with a different type), which I would consider out of scope for this PR.
There was a problem hiding this comment.
Well, probably (did you test ?).
In any case at least make sure we document this clearly, because with this sort of stuff you never know if does not end up biting us back some day. The density and guess densities go quite deep into the code and not having the type inferrable could easily have nasty performance regressions. So please add a comment about this here (i.e. that we had the @inferred here but had to remove it because the q handling breaks type inferability) and in the atomic superposition functions themselves with the proposed solution to have a ZeroVec3{T} type.
There was a problem hiding this comment.
Hmm yeah making all uses of ρ non-inferrable is quite bad. Maybe we have to bite the bullet and actually encode q==0 in the type system
|
FWIW it would be good if this PR would be merged rather soon as I have follow-up PRs that depend on this one. |
Cleaner than I expected. Nice framework that you built @epolack and @antoine-levitt, especially the automated testing!