qojulia/QuantumOptics.jl

Feature: Floquet spectrum

oameye opened this issue · 1 comments

Is there some interest that I add an example in docs or even a function to construct the quasienergy operator in Floquet theory. Once diagonalized it provides the Floquet spectrum of the time-periodic Hamiltonian.
image

Here is some code example to create a the basis

struct FloquetBasis <: Basis
    shape::Vector{Int}
    m::Int
    FloquetBasis(m::Int) = new(Int[2*m+1], m) # Constructor
end

function QuantumOptics.number(b::FloquetBasis)
    N = first(b.shape)
    diag = ComplexF64.(N:-1:1)
    data = spdiagm(0 => diag)
    SparseOperator(b, data)
end

function floquet_cell(v::Ket)
    fock, floquet = v.basis.bases
    m̄ = identityoperator(fock)  number(floquet)
    real(expect(m̄, v))
end

function photon_number(v::Ket)
    fock, floquet = v.basis.bases
    n̄ = number(fock)  identityoperator(floquet)
    real(expect(n̄, v))
end

function parity(v::Ket)
    fock, floquet = v.basis.bases
    diag_vec = Complex[(-1)^(i-1) for i in 1:first(fock.shape)]
    p = Operator(fock, Diagonal(diag_vec));    
    p̄ = p  identityoperator(floquet)
    round(Int,real(expect(p̄, v)))
end
function get_quasienergy_operator(b; ω, ω₀=1.0, F=0.0, α=0.0, f::Function=isinteger)
    dim_floquet = b.shape[2]
    m = (dim_floquet-1)/2

    # Fundamental operators
    a = destroy(b.bases[1])
    at = create(b.bases[1])
    n = number(b.bases[1])
    I = identityoperator(b.bases[1])
    zero = spzeros(ComplexF64, size(I))

    # Hamiltonians
    H₀ᵃ(ω) = -((ω - ω₀) - 3*α/(4*ω₀))*n - (F/√(8*ω₀))*(a + at) + (3*α/(8*ω₀^2))*at*at*a*a
    H₋₂ᵃ(ω) = - (F/√(8*ω₀))*a + (3*α/(4*ω₀^2))*a*a +/(4*ω₀^2))*at*a*a*a
    H₂ᵃ(ω) =  - (F/√(8*ω₀))*at + (3*α/(4*ω₀^2))*at*at +/(4*ω₀^2))*at*at*at*a
    H₋₄ᵃ(ω) =/(16*ω₀^2))*a*a*a*a
    H₄ᵃ(ω) =/(16*ω₀^2))*at*at*at*at

    matrix_of_matrix = [zero for i in 1:dim_floquet, j in 1:dim_floquet]

    filter_f(lin_idxs, M=matrix_of_matrix) = LinearIndices(M)[filter(idx -> !any(iszero.(M[get_diag_idxs(idx)])), CartesianIndices(M)[lin_idxs])]

    matrix_of_matrix[diagind(matrix_of_matrix)] = [f(i) ? getfield(H₀ᵃ(ω) + i*ω*I, :data) : zero for i in -m:m]
    matrix_of_matrix[filter_f(diagind(matrix_of_matrix,-2), matrix_of_matrix)] .= [H₂ᵃ(ω).data]
    matrix_of_matrix[filter_f(diagind(matrix_of_matrix,2), matrix_of_matrix)] .= [H₋₂ᵃ(ω).data]
    matrix_of_matrix[filter_f(diagind(matrix_of_matrix,-4), matrix_of_matrix)] .= [H₄ᵃ(ω).data]
    matrix_of_matrix[filter_f(diagind(matrix_of_matrix,4), matrix_of_matrix)] .= [H₋₄ᵃ(ω).data]
    matrix = reduce(vcat, [reduce(hcat, matrix_of_matrix[i, :]) for i in 1:dim_floquet])

    return SparseOperator(b, matrix)
end

Qᵃ =  get_quasienergy_operator_a(basis; ω=1.02, ω₀=1, F=0.0001, α=0.01)
Qᵃ.data

qutip floquet

Apologies for the slow answer. There is certainly a lot of interest in this being added. Please feel free to create a PR with this, even if it is in an unfinished state (maybe another community member will be able to help finish it).