Ungraceful failure for certain ill-defined circuits
Consider:
function nlshort()
return ACME.Element(mv=[1], mi=[0], mq=[1], u0=[0],
nonlinear_eq = @inline function(q)
res = @SVector [q[1]]
J = @SMatrix [1.0]
return (res, J)
end)
end
circ=@circuit begin
Vin=voltagesource()
short=nlshort(), [1] == Vin[+], [2] == Vin[-]
end
model=DiscreteModel(circ, 1)
Here nlshort() defines a short-circuit via a non-linearity: The current is arbitrary, the voltage is forced to zero by the nonlinear equation. Thus, when running this model with the input being zero, there is a solution where the current is undefined but that should be ok since nothing depends on the current. For non-zero input, there is no solution, but as nothing depends on the voltage either, this could just be ignored (that is what happens if resistor(0) is used instead of nlshort()); alternatively, an error to converge could be emitted.
But what actually happens is that the call to DiscreteModel fails with
ERROR: BoundsError: attempt to access 1×0 Array{Rational{BigInt},2} at index [1:1, 1:1]
Stacktrace:
[1] throw_boundserror(::Array{Rational{BigInt},2}, ::Tuple{UnitRange{Int64},UnitRange{Int64}}) at ./abstractarray.jl:537
[2] checkbounds at ./abstractarray.jl:502 [inlined]
[3] _getindex at ./multidimensional.jl:726 [inlined]
[4] getindex at ./abstractarray.jl:980 [inlined]
[5] #136 at ./none:0 [inlined]
[6] iterate at ./generator.jl:47 [inlined]
[7] collect(::Base.Generator{Base.Iterators.ProductIterator{Tuple{Array{UnitRange{Int64},1},Array{UnitRange{Int64},1}}},ACME.var"#136#137"{Array{Rational{BigInt},2}}}) at ./array.jl:636
[8] matsplit(::Array{Rational{BigInt},2}, ::Array{Int64,1}, ::Array{Int64,1}) at ACME/src/ACME.jl:739
[9] (::ACME.var"#117#118"{Dict{Symbol,Array},Array{Int64,1}})(::Array{Int64,1}) at ./none:0
[10] iterate(::Base.Generator{Array{Array{Int64,1},1},ACME.var"#117#118"{Dict{Symbol,Array},Array{Int64,1}}}) at ./generator.jl:47
[11] split_nl_model_matrices!(::Dict{Symbol,Array}, ::Array{Array{Int64,1},1}, ::Array{Int64,1}) at ACME/src/ACME.jl:375
[12] DiscreteModel(::Circuit, ::Int64, ::Type{HomotopySolver{CachingSolver{SimpleSolver}}}; decompose_nonlinearity::Bool) at ACME/src/ACME.jl:161
[13] DiscreteModel at ACME/src/ACME.jl:149 [inlined] (repeats 2 times)
ACME realizes that solving the nonlinearity at runtime is unnecessary (nothing depends on it) and optimizes it out. But then it realizes that there is an undefined quantity (the current) and assumes that there has to be a nonlinearity to fix it.
In a more complicated case, the nonlinearity could have a second port and be defined (and used) in a way that there always is a solution, by still leave a quantity undefined, which leads to the same error.