jonniedie / ComponentArrays.jl

Arrays with arbitrarily nested named components.
MIT License
286 stars 34 forks source link

vcat ambiguity with SparseArrays method #222

Open visr opened 10 months ago

visr commented 10 months ago

I was looking at a question in Discourse and ran into a MethodError.

Reading the comment in https://github.com/jonniedie/ComponentArrays.jl/blob/v0.15.2/src/array_interface.jl#L34-L35 I guess this may be of interest here. Defining the "possible fix" from the error below fixes it:

Base.vcat(x::AbstractVector{<:Number}, y::ComponentVector{<:Number}) = vcat(x, getdata(y))
ERROR: MethodError: vcat(::Vector{Float64}, ::ComponentArrays.ComponentVector{Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{ComponentArrays.Axis{(cum_d_prec = 1, cum_d_rfal = 2, cum_d_sfal = 3, cum_d_rint = 4, cum_d_sint = 5, cum_d_rsno = 6, cum_d_rnet = 7, cum_d_smlt = 8, cum_d_evap = 9, cum_d_tran = 10, cum_d_irvp = 11, cum_d_isvp = 12, cum_d_slvp = 13, cum_d_snvp = 14, cum_d_pint = 15, cum_d_ptran = 16, cum_d_pslvp = 17, flow = 18, seep = 19, srfl = 20, slfl = 21, byfl = 22, dsfl = 23, gwfl = 24, vrfln = 25, cum_d_rthr = 26, cum_d_sthr = 27, StorageSWAT = 28, StorageWATER = 29, BALERD_SWAT = 30, BALERD_total = 31)}}}) is ambiguous.

Candidates:
  vcat(x::AbstractVector, y::ComponentArrays.ComponentVector)
    @ ComponentArrays C:\Users\visser_mn\.julia\dev\ComponentArrays\src\array_interface.jl:37
  vcat(X::Union{Number, AbstractVecOrMat{<:Number}}...)
    @ SparseArrays C:\Users\visser_mn\.julia\juliaup\julia-1.10.0-beta2+0.x64.w64.mingw32\share\julia\stdlib\v1.10\SparseArrays\src\sparsevector.jl:1229

Possible fix, define
  vcat(::AbstractVector{<:Number}, ::ComponentArrays.ComponentVector{<:Number})

Stacktrace:
  [1] _mapreduce(f::typeof(identity), op::typeof(vcat), ::IndexLinear, A::Vector{Any})
    @ Base .\reduce.jl:443
  [2] _mapreduce_dim
    @ LWFBrook90 .\reducedim.jl:365 [inlined]
  [3] mapreduce
    @ LWFBrook90 .\reducedim.jl:357 [inlined]
  [4] reduce
    @ LWFBrook90 .\reducedim.jl:406 [inlined]
  [5] norm_to_use(u::ComponentArrays.ComponentVector{Float64, Vector{Float64}, Tuple{ComponentArrays.Axis{…}}}, t::Float64)
    @ LWFBrook90 C:\Users\visser_mn\.julia\packages\LWFBrook90\7uNU3\src\func_DiffEq_definition_ode.jl:23
  [6] __init(prob::SciMLBase.ODEProblem{…}, alg::OrdinaryDiffEq.Tsit5{…}, timeseries_init::Tuple{}, ts_init::Tuple{}, ks_init::Tuple{}, recompile::Type{…}; saveat::StepRangeLen{…}, tstops::Tuple{}, d_discontinuities::Tuple{}, save_idxs::Nothing, save_everystep::Bool, 
save_on::Bool, save_start::Bool, save_end::Nothing, callback::SciMLBase.CallbackSet{…}, dense::Bool, calck::Bool, dt::Float64, dtmin::Nothing, dtmax::Float64, force_dtmin::Bool, adaptive::Bool, gamma::Rational{…}, abstol::Nothing, reltol::Float64, qmin::Rational{…}, qmax::Int64, qsteady_min::Int64, qsteady_max::Int64, beta1::Nothing, beta2::Nothing, qoldinit::Rational{…}, controller::Nothing, fullnormalize::Bool, failfactor::Int64, maxiters::Int64, internalnorm::typeof(LWFBrook90.norm_to_use), internalopnorm::typeof(LinearAlgebra.opnorm), isoutofdomain::typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), unstable_check::typeof(LWFBrook90.unstable_check_function), verbose::Bool, timeseries_errors::Bool, dense_errors::Bool, advance_to_tstop::Bool, stop_at_next_tstop::Bool, initialize_save::Bool, progress::Bool, progress_steps::Int64, progress_name::String, progress_message::typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), userdata::Nothing, allow_extrapolation::Bool, initialize_integrator::Bool, alias_u0::Bool, alias_du0::Bool, initializealg::OrdinaryDiffEq.DefaultInit, kwargs::@Kwargs{…})
    @ OrdinaryDiffEq C:\Users\visser_mn\.julia\packages\OrdinaryDiffEq\NH6if\src\solve.jl:300

It looks like #169 is related, not sure if that also fixes the issue, the branch needs work.

fabern commented 10 months ago

The underlying code in the package LWFBrook90.jl simplifies to the following MWE:

using ComponentArrays # version: [b0b7db55] ComponentArrays v0.15.2
u0 = ComponentArray(
    GWAT   = (mm = 0.0, d18O = 0.0, d2H = 0.0),
    INTS   = (mm = 0.0, d18O = 0.0, d2H = 0.0),
    INTR   = (mm = 0.0, d18O = 0.0, d2H = 0.0),
    accum  = (cum_d_prec = 0.0, ))
reduce(vcat, [u0.GWAT.mm, u0.INTS.mm, u0.INTR.mm])           # works
reduce(vcat, [u0.GWAT.mm, u0.INTS.mm, u0.INTR.mm, u0.accum]) # doesn't work

giving the error:

julia> reduce(vcat, [u0.GWAT.mm, u0.INTS.mm, u0.INTR.mm, u0.accum]) # doesn't work
ERROR: MethodError: vcat(::Vector{Float64}, ::ComponentVector{Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{Axis{(cum_d_prec = 1,)}}}) is ambiguous.

Candidates:
  vcat(x::AbstractVector, y::ComponentVector)
    @ ComponentArrays ~/.julia/packages/ComponentArrays/NnCVQ/src/array_interface.jl:37
  vcat(X::Union{Number, AbstractVecOrMat{<:Number}}...)
    @ SparseArrays ~/.julia/juliaup/julia-1.10.0-beta2+0.x64.apple.darwin14/share/julia/stdlib/v1.10/SparseArrays/src/sparsevector.jl:1229

Possible fix, define
  vcat(::AbstractVector{<:Number}, ::ComponentVector{<:Number})

Stacktrace:
 [1] _mapreduce(f::typeof(identity), op::typeof(vcat), ::IndexLinear, A::Vector{Any})
   @ Base ./reduce.jl:443
 [2] _mapreduce_dim(f::Function, op::Function, ::Base._InitialValue, A::Vector{Any}, ::Colon)
   @ Base ./reducedim.jl:365
 [3] mapreduce
   @ Base ./reducedim.jl:357 [inlined]
 [4] reduce(op::Function, A::Vector{Any})
   @ Base ./reducedim.jl:406
 [5] top-level scope
   @ REPL[8]:1
prbzrg commented 8 months ago

the vcat in v1.10 is breaking ReverseDiff too. https://github.com/JuliaDiff/ReverseDiff.jl/issues/242