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.
|
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!