Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/generators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ function Base.Array{T}(O::Operator) where {T}
return A
end

Base.Array(O::Operator) = Array{ComplexF64}(O)
Base.Array(O::Operator) = Array{eltype(O)}(O)


function Base.copy(O::Operator)
Expand All @@ -177,6 +177,8 @@ function Base.copyto!(tgt::Operator, src::Operator)
end

Base.size(O::Operator) = size(O.ops[1])
Base.size(O::Operator, dim::Integer) = size(O.ops[1], dim)
Base.eltype(::Type{Operator{OT,CT}}) where {OT,CT} = promote_type(eltype(OT), CT)


function LinearAlgebra.ishermitian(O::Operator{OT,CT}) where {OT,CT}
Expand Down Expand Up @@ -247,10 +249,13 @@ end

# fallback (less efficient, but doesn't assume Operator-OT)
Base.Array{T}(O::ScaledOperator{CT,OT}) where {T,CT,OT} = O.coeff * Array{T}(O.operator)
Base.Array(O::ScaledOperator) = Array{ComplexF64}(O)
Base.Array(O::ScaledOperator) = Array{eltype(O)}(O)


Base.size(O::ScaledOperator) = size(O.operator)
Base.size(O::ScaledOperator, dim::Integer) = size(O.operator, dim)
Base.eltype(::Type{ScaledOperator{CT,Operator{OOT,OCT}}}) where {CT,OOT,OCT} =
promote_type(CT, eltype(OOT), OCT)

LinearAlgebra.ishermitian(O::ScaledOperator) = (isreal(O.coeff) && ishermitian(O.operator))

Expand Down
56 changes: 56 additions & 0 deletions src/interfaces/operator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ verifies the given `op` relative to `state`. The `state` must pass
An "operator" is any object that [`evaluate`](@ref) returns when evaluating a
time-dependent dynamic generator. The specific requirements for `op` are:

* `eltype(op)` must be defined and return a numeric type
* `size(op)` must be defined and return a tuple of integers
* `size(op, dim)` must be defined for each dimension and be consistent with
`size(op)`
* `op` must not be time-dependent: [`evaluate(op, tlist, 1) ≡ op`](@ref evaluate)
* `op` must not contain any controls: [`length(get_controls(op)) == 0`](@ref get_controls)
* `op * state` must be defined
Expand Down Expand Up @@ -70,6 +74,58 @@ function check_operator(
success = false
end

try
T = eltype(op)
if !(T isa Type && T <: Number)
quiet || @error "$(px)`eltype(op)` must return a numeric type, not $T"
success = false
end
catch exc
quiet || @error(
"$(px)`eltype(op)` must be defined.",
exception = (exc, catch_abbreviated_backtrace())
)
success = false
end

try
s = size(op)
if !(s isa Tuple)
quiet || @error "$(px)`size(op)` must return a tuple, not $(typeof(s))"
success = false
elseif !all(d isa Integer for d in s)
quiet || @error "$(px)`size(op)` must return a tuple of integers, not $s"
success = false
else
for (dim, n) in enumerate(s)
try
n_dim = size(op, dim)
if !(n_dim isa Integer)
quiet ||
@error "$(px)`size(op, $dim)` must return an integer, not $(typeof(n_dim))"
success = false
elseif n_dim != n
quiet ||
@error "$(px)`size(op, $dim)` must be consistent with `size(op)`: $n_dim ≠ $n"
success = false
end
catch exc
quiet || @error(
"$(px)`size(op, $dim)` must be defined.",
exception = (exc, catch_abbreviated_backtrace())
)
success = false
end
end
end
catch exc
quiet || @error(
"$(px)`size(op)` must be defined.",
exception = (exc, catch_abbreviated_backtrace())
)
success = false
end

try
H = evaluate(op, tlist, 1)
if H ≢ op
Expand Down