pablosanjose / Quantica.jl

Simulation of quantum systems on a lattice
Other
70 stars 8 forks source link

Broken closure in GreenFunction #267

Closed pablosanjose closed 6 months ago

pablosanjose commented 6 months ago

How does call!(g::GreenFunction, ω; params...) work?

g encloses a parent::AbstractHamiltonian and a solver::AppliedGreenSolver. Here, solver was obtained with solver = apply(s::AbstractGreenSolver, parent, contacts), so it is a closure over parent. Hence, to call solver on some ω and params, we do call!(parent; params...) that applies params... and then we do solver(ω, Σblocks, corbs) to obtain a GreenSlicer.

There is a crucial flaw in this design: it relies on the closure being preserved. If we do minimcal_callsafe_copy(g) this makes a copy of parent and a copy of solver. The closure relation is now broken, and call! gives wrong results silently.

MWE:

julia> g = LP.linear() |> hamiltonian(@hopping((; q = 1) -> q*I), orbitals = 2) |> greenfunction;

julia> g´ = Quantica.minimal_callsafe_copy(g);

julia> g(0.2; q = 2)[cells = 1]
2×2 OrbitalSliceMatrix{Matrix{ComplexF64}}:
 4.67412e-11-0.250313im          0.0+0.0im
         0.0+0.0im       4.67413e-11-0.250313im

julia> g´(0.2; q = 2)[cells = 1]
2×2 OrbitalSliceMatrix{Matrix{ComplexF64}}:
 3.78188e-10-0.502519im          0.0+0.0im
         0.0+0.0im       3.78188e-10-0.502519im

julia> g´(0.2; q = 2)[cells = 1] == g´(0.2; q = 1)[cells = 1] == g(0.2; q = 1)[cells = 1]
true

One possible solution is to move parent into solver, and change api so that the GreenSlicer is obtained with solver(ω, Σblocks, corbs; params...)

pablosanjose commented 6 months ago

I suspect the solution of moving parent into solver is not optimal. The reason is that some solvers, such as AppliedSchurGreenSolver, gets called several times when computing a GreenSolution or when doing call!(::SelfEnergy, ω; params...) of the corresponding Green functions.

Rather, we could leave parent::AbstractHamiltonian as a field of GreenFunction and change minimal_callsafe_copy(::AppliedGreenSolver) to minimal_callsafe_copy(::AppliedGreenSolver, parentham), to restore aliases. minimal_callsafe_copy(::SelfEnergySolver) should also be modified to restore any internal aliases the solver has.