Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Benchmarks for ExpRK and IMEX methods #31

Closed
wants to merge 3 commits into from

Conversation

MSeeker1340
Copy link

nbview for this branch

This is initially intended to resolve #30 but I find it natural to combine both ExpRK and IMEX methods, and also work on tailored semilinear problems instead of appending to exisiting stiff ODE benchmarks. The reason is that these methods aren't really suited to most of the existing benchmark equations: they are usually highly non-linear, has only a few variables and sometimes large positive eigenvalues in their Jacobian. On the other hand, ExpRK/IMEX's target problems are usually semilinear PDE (thus high dimension), with stiffness in the form of large negative eigenvalues in the linear term. (For EPIRK, although it doesn't use the semilinear form, the other criteria still apply). The best we can do about the exisiting stiff ODE benchmarks is to add caching ExpRK methods, which requires rewriting the equations in semilinear form and is unstable if the linear term has large positive eigenvalues (e.g. Van der Pol).

The equations I want to benchmark are (mostly taken from the Tokman EPIRK paper):

  • Burgers equation
  • Allen-Cahn equation (1D & 2D)
  • 2D Brusselator (use existing implementation in DiffEqProblemLibrary?)
  • (maybe) nonlinear Schrodinger equation; ExpRK should work in complex but I'm not sure about IMEX

The 2D problems can be a bit tricky as DiffEqOperators support hasn't followed up yet. But I can always hand-write the matrix-free derivative operators for the Krylov ExpRK and IMEX methods (both work well with matrix-free operators). And since the derivative operators are just convolutions it might not be far fetched to use GPU acceleration for that (I presume that it's convenient to wrap a mul! call with cuBLAS matmul in Julia?). And speaking of matrix-free operators, spectral methods and ApproxFun also comes to mind.

BTW, the notebooks in this repo is in dire need of an update...

@ChrisRackauckas
Copy link
Member

Great to see this. Yes these are good test equations. However, you are missing all of the interesting comparisons. You need to compare between classes of methods. For example, from the plots it's not clear if one should be using CNAB2 or ETDRK2, or when one should be switching to ETDRK4. It's not clear how these compare to other methods like Rosenbrock23, CVODE_BDF, or Rodas5. Within class benchmarks are used to establish a "champion", and then you show the champion of each class of methods against each other to determine performs best.

Two things to mention about

setups = [Dict(:alg => KenCarp3(linsolve=LinSolveFactorize(lu))),
          Dict(:alg => KenCarp4(linsolve=LinSolveFactorize(lu))),
          Dict(:alg => KenCarp5(linsolve=LinSolveFactorize(lu))),
          Dict(:alg => ARKODE(Sundials.Implicit(), order=3, linear_solver=:GMRES)),
          Dict(:alg => ARKODE(Sundials.Implicit(), order=4, linear_solver=:GMRES)),
          Dict(:alg => ARKODE(Sundials.Implicit(), order=5, linear_solver=:GMRES))]

For one, we should make our default handling automatically do well on sparse matrices and switch to lu. But secondly, you should time ARKODE with and without GMRES, and do one with IterativeSolvers.jl's GMRES on KenCarps. From your benchmarks I do not know anything about the performance differences. Is ARKODE faster, or is using a GMRES linear solver just better on this problem? (Given the previous benchmarks between these methods I'd guess the latter!)

@MSeeker1340
Copy link
Author

@ChrisRackauckas Not sure why using GMRES on KenCarp3/4/5 exceeds the maxiter limit. Might be worth looking into?

For the implicit/ExpRK comparison: To gain more insight (say for the presentation next year) we should probably probe into the integrators and count how many Krylov iterations are carried out for each time step. The fact that ExpRK (in its current state) is fixed-dt may also contribute to their under-performance. I'll be curious to see how the adaptive Exprb (and EPIRK methods to some extend) compares with regular implicit methods on a non-semilinear formulated problem.

@ChrisRackauckas
Copy link
Member

Not sure why using GMRES on KenCarp3/4/5 exceeds the maxiter limit. Might be worth looking into?

Yes, that's worth looking into. Maybe tweak some of the algorithm options around and see what happens? Take a look at the options on ARKODE and see if changing the KenCarp one closer to the ARKODE defaults leads to better results there. Their defaults are really really bad for highly nonlinear ODE, but I suspected they must do better on semi-stiff PDE. This seems to be the case. The algorithms are very similar except for these defaults so I'd like to see if we can get them inline or even faster. Though we may also want to play with step acceleration on KenCarp. This is a benchmark worth optimizing on.

To gain more insight (say for the presentation next year) we should probably probe into the integrators and count how many Krylov iterations are carried out for each time step.

Yes. SciML/DiffEqBase.jl#54 . This would be a good issue for us to get solved, but it would require a lot of work since every method has a different number of f calls per perform_step!, and some (implicit methods) have variable number of f calls...

@MSeeker1340
Copy link
Author

Ran the benchmarks on the Umaryland server. Also changed the GMRES linear solvers to only use 5 Krylov iterations (which is the default of ARKODE). I still get "maxiters reached" warning for KenCarp3/4/5 but the results seemed ok.

One thing to note is that unlike on my local machine, ARKODE and ETDRK4 actually doesn't differ that much. Maybe a result of BLAS optimizations?

@ChrisRackauckas
Copy link
Member

One thing to note is that unlike on my local machine, ARKODE and ETDRK4 actually doesn't differ that much. Maybe a result of BLAS optimizations?

Sundials can't use BLAS with 64-bit (I know, right? Right?), so our methods will scale better to more cores. This is seen in other benchmarks as well.

@ChrisRackauckas
Copy link
Member

I still get "maxiters reached" warning for KenCarp3/4/5 but the results seemed ok.

They aren't exiting early?

@ChrisRackauckas
Copy link
Member

Incorporated into #48 . Thanks!

ChrisRackauckas added a commit that referenced this pull request Sep 11, 2023
Since the objective function is now type-stable:

```julia
prob = build_opf_optimization_prob(dataset)
@code_warntype prob.f.f(test_u0, nothing)
```

```julia
MethodInstance for (::var"#opf_objective#497"{Dict{Int64, Vector{Float64}}, Dict{Int64, Int64}, Vector{Int64}})(::Vector{Float64}, ::Nothing)
  from (::var"#opf_objective#497")(x, param) @ Main c:\Users\accou\.julia\dev\SciMLBenchmarks\benchmarks\OptimizationFrameworks\optimal_powerflow.jmd:329
Arguments
  #self#::var"#opf_objective#497"{Dict{Int64, Vector{Float64}}, Dict{Int64, Int64}, Vector{Int64}}
  x::Vector{Float64}
  param::Core.Const(nothing)
Locals
  @_4::Union{Nothing, Tuple{Int64, Int64}}
  cost::Float64
  i::Int64
  _cost_arr::Vector{Float64}
  pg::Float64
Body::Float64
1 ─       (cost = 0.0)
│   %2  = Core.getfield(#self#, :ref_gen_idxs)::Vector{Int64}
│         (@_4 = Base.iterate(%2))
│   %4  = (@_4 === nothing)::Bool
│   %5  = Base.not_int(%4)::Bool
└──       goto #4 if not %5
2 ┄ %7  = @_4::Tuple{Int64, Int64}
│         (i = Core.getfield(%7, 1))
│   %9  = Core.getfield(%7, 2)::Int64
│   %10 = Core.getfield(#self#, :lookup_pg)::Dict{Int64, Int64}
│   %11 = Base.getindex(%10, i)::Int64
│         (pg = Base.getindex(x, %11))
│   %13 = Core.getfield(#self#, :cost_arrs)::Dict{Int64, Vector{Float64}}
│         (_cost_arr = Base.getindex(%13, i))
│   %15 = cost::Float64
│   %16 = Base.getindex(_cost_arr, 1)::Float64
│   %17 = Main.:^::Core.Const(^)
│   %18 = pg::Float64
│   %19 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│   %20 = (%19)()::Core.Const(Val{2}())
│   %21 = Base.literal_pow(%17, %18, %20)::Float64
│   %22 = (%16 * %21)::Float64
│   %23 = Base.getindex(_cost_arr, 2)::Float64
│   %24 = (%23 * pg)::Float64
│   %25 = Base.getindex(_cost_arr, 3)::Float64
│   %26 = (%22 + %24 + %25)::Float64
│         (cost = %15 + %26)
│         (@_4 = Base.iterate(%2, %9))
│   %29 = (@_4 === nothing)::Bool
│   %30 = Base.not_int(%29)::Bool
└──       goto #4 if not %30
3 ─       goto #2
4 ┄       return cost
```

Along with the constraint function

```julia
ret = zeros(length(prob.lcons))
@code_warntype prob.f.cons(ret, test_u0, nothing)
```

```julia
MethodInstance for (::var"#opf_constraints#498"{Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Vector{Tuple{Int64, Int64, Int64}}, Vector{Tuple{Int64, Int64, Int64}}, Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}}, Dict{Int64, Vector{Int64}}, Vector{Int64}, Vector{Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}})(::Vector{Float64}, ::Vector{Float64}, ::Nothing)
  from (::var"#opf_constraints#498")(ret, x, param) @ Main c:\Users\accou\.julia\dev\SciMLBenchmarks\benchmarks\OptimizationFrameworks\optimal_powerflow.jmd:341
Arguments
  #self#::var"#opf_constraints#498"{Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Int64, Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Dict{Tuple{Int64, Int64, Int64}, Int64}, Vector{Tuple{Int64, Int64, Int64}}, Vector{Tuple{Int64, Int64, Int64}}, Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}}, Dict{Int64, Vector{Int64}}, Vector{Int64}, Vector{Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}, Dict{Int64, Int64}}
  ret::Vector{Float64}
  x::Vector{Float64}
  param::Core.Const(nothing)
Locals
  @_5::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_6::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_7::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_8::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_9::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_10::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_11::Union{Nothing, Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}}
  @_12::Union{Nothing, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}}
  @_13::Union{Nothing, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}}
  @_14::Union{Nothing, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}}
  offsetidx::Int64
  @_16::Int64
  i@_17::Int64
  reti@_18::Int64
  #494::var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}
  #493::var"#493#499"{Vector{Float64}, Dict{Int64, Int64}}
  @_21::Int64
  i@_22::Int64
  reti@_23::Int64
  #496::var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}
  #495::var"#495#501"{Vector{Float64}, Dict{Int64, Int64}}
  @_26::Int64
  i@_27::Int64
  reti@_28::Int64
  @_29::Int64
  @_30::Int64
  j@_31::Int64
  l@_32::Int64
  i@_33::Int64
  reti@_34::Int64
  @_35::Int64
  @_36::Int64
  j@_37::Int64
  i@_38::Int64
  l@_39::Int64
  reti@_40::Int64
  @_41::Int64
  @_42::Int64
  j@_43::Int64
  i@_44::Int64
  l@_45::Int64
  reti@_46::Int64
  @_47::Int64
  @_48::Int64
  j@_49::Int64
  i@_50::Int64
  l@_51::Int64
  reti@_52::Int64
  @_53::Int64
  @_54::Int64
  j@_55::Int64
  i@_56::Int64
  l@_57::Int64
  reti@_58::Int64
  @_59::Int64
  @_60::Int64
  j@_61::Int64
  i@_62::Int64
  l@_63::Int64
  reti@_64::Int64
  @_65::Int64
  @_66::Int64
  j@_67::Int64
  i@_68::Int64
  l@_69::Int64
  reti@_70::Int64
Body::Nothing
1 ──        Core.NewvarNode(:(@_5))
│           Core.NewvarNode(:(@_6))
│           Core.NewvarNode(:(@_7))
│           Core.NewvarNode(:(@_8))
│           Core.NewvarNode(:(@_9))
│           Core.NewvarNode(:(@_10))
│           Core.NewvarNode(:(@_11))
│           Core.NewvarNode(:(@_12))
│           Core.NewvarNode(:(@_13))
│           (offsetidx = 0)
│    %11  = Core.getfield(#self#, :ref_buses_idxs)::Vector{Int64}
│    %12  = Main.enumerate(%11)::Base.Iterators.Enumerate{Vector{Int64}}
│           (@_14 = Base.iterate(%12))
│    %14  = (@_14 === nothing)::Bool
│    %15  = Base.not_int(%14)::Bool
└───        goto #4 if not %15
2 ┄─ %17  = @_14::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}
│    %18  = Core.getfield(%17, 1)::Tuple{Int64, Int64}
│    %19  = Base.indexed_iterate(%18, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_18 = Core.getfield(%19, 1))
│           (@_16 = Core.getfield(%19, 2))
│    %22  = Base.indexed_iterate(%18, 2, @_16::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_17 = Core.getfield(%22, 1))
│    %24  = Core.getfield(%17, 2)::Tuple{Int64, Int64}
│    %25  = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %26  = Base.getindex(%25, i@_17)::Int64
│    %27  = Base.getindex(x, %26)::Float64
│    %28  = (reti@_18 + offsetidx::Core.Const(0))::Int64
│           Base.setindex!(ret, %27, %28)
│           (@_14 = Base.iterate(%12, %24))
│    %31  = (@_14 === nothing)::Bool
│    %32  = Base.not_int(%31)::Bool
└───        goto #4 if not %32
3 ──        goto #2
4 ┄─ %35  = offsetidx::Core.Const(0)
│    %36  = Core.getfield(#self#, :ref_buses_idxs)::Vector{Int64}
│    %37  = Main.length(%36)::Int64
│           (offsetidx = %35 + %37)
│    %39  = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64}
│    %40  = Main.enumerate(%39)::Base.Iterators.Enumerate{Vector{Int64}}
│           (@_13 = Base.iterate(%40))
│    %42  = (@_13 === nothing)::Bool
│    %43  = Base.not_int(%42)::Bool
└───        goto #7 if not %43
5 ┄─ %45  = @_13::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}
│    %46  = Core.getfield(%45, 1)::Tuple{Int64, Int64}
│    %47  = Base.indexed_iterate(%46, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_23 = Core.getfield(%47, 1))
│           (@_21 = Core.getfield(%47, 2))
│    %50  = Base.indexed_iterate(%46, 2, @_21::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_22 = Core.getfield(%50, 1))
│    %52  = Core.getfield(%45, 2)::Tuple{Int64, Int64}
│    %53  = Main.:(var"#493#499")::Core.Const(var"#493#499")
│    %54  = Core.typeof(x)::Core.Const(Vector{Float64})
│    %55  = Core.getfield(#self#, :lookup_pg)::Dict{Int64, Int64}
│    %56  = Core.typeof(%55)::Core.Const(Dict{Int64, Int64})
│    %57  = Core.apply_type(%53, %54, %56)::Core.Const(var"#493#499"{Vector{Float64}, Dict{Int64, Int64}})
│    %58  = Core.getfield(#self#, :lookup_pg)::Dict{Int64, Int64}
│           (#493 = %new(%57, x, %58))
│    %60  = #493::var"#493#499"{Vector{Float64}, Dict{Int64, Int64}}
│    %61  = Core.getfield(#self#, :ref_bus_gens)::Dict{Int64, Vector{Int64}}
│    %62  = Base.getindex(%61, i@_22)::Vector{Int64}
│    %63  = Base.Generator(%60, %62)::Base.Generator{Vector{Int64}, var"#493#499"{Vector{Float64}, Dict{Int64, Int64}}}
│    %64  = (:init,)::Core.Const((:init,))
│    %65  = Core.apply_type(Core.NamedTuple, %64)::Core.Const(NamedTuple{(:init,)})
│    %66  = Core.tuple(0.0)::Core.Const((0.0,))
│    %67  = (%65)(%66)::Core.Const((init = 0.0,))
│    %68  = Core.kwcall(%67, Main.sum, %63)::Float64
│    %69  = Core.getfield(#self#, :bus_pd)::Dict{Int64, Float64}
│    %70  = Base.getindex(%69, i@_22)::Float64
│    %71  = (%68 - %70)::Float64
│    %72  = Core.getfield(#self#, :bus_gs)::Dict{Int64, Float64}
│    %73  = Base.getindex(%72, i@_22)::Float64
│    %74  = Main.:^::Core.Const(^)
│    %75  = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %76  = Base.getindex(%75, i@_22)::Int64
│    %77  = Base.getindex(x, %76)::Float64
│    %78  = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %79  = (%78)()::Core.Const(Val{2}())
│    %80  = Base.literal_pow(%74, %77, %79)::Float64
│    %81  = (%73 * %80)::Float64
│    %82  = (%71 - %81)::Float64
│    %83  = Main.:(var"#494#500")::Core.Const(var"#494#500")
│    %84  = Core.typeof(x)::Core.Const(Vector{Float64})
│    %85  = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %86  = Core.typeof(%85)::Core.Const(Dict{Tuple{Int64, Int64, Int64}, Int64})
│    %87  = Core.apply_type(%83, %84, %86)::Core.Const(var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}})
│    %88  = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│           (#494 = %new(%87, x, %88))
│    %90  = #494::var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}
│    %91  = Core.getfield(#self#, :ref_bus_arcs)::Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}}
│    %92  = Base.getindex(%91, i@_22)::Vector{Tuple{Int64, Int64, Int64}}
│    %93  = Base.Generator(%90, %92)::Base.Generator{Vector{Tuple{Int64, Int64, Int64}}, var"#494#500"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}}
│    %94  = Main.sum(%93)::Float64
│    %95  = (%82 - %94)::Float64
│    %96  = (reti@_23 + offsetidx)::Int64
│           Base.setindex!(ret, %95, %96)
│           (@_13 = Base.iterate(%40, %52))
│    %99  = (@_13 === nothing)::Bool
│    %100 = Base.not_int(%99)::Bool
└───        goto #7 if not %100
6 ──        goto #5
7 ┄─ %103 = offsetidx::Int64
│    %104 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64}
│    %105 = Main.length(%104)::Int64
│           (offsetidx = %103 + %105)
│    %107 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64}
│    %108 = Main.enumerate(%107)::Base.Iterators.Enumerate{Vector{Int64}}
│           (@_12 = Base.iterate(%108))
│    %110 = (@_12 === nothing)::Bool
│    %111 = Base.not_int(%110)::Bool
└───        goto #10 if not %111
8 ┄─ %113 = @_12::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}
│    %114 = Core.getfield(%113, 1)::Tuple{Int64, Int64}
│    %115 = Base.indexed_iterate(%114, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_28 = Core.getfield(%115, 1))
│           (@_26 = Core.getfield(%115, 2))
│    %118 = Base.indexed_iterate(%114, 2, @_26::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_27 = Core.getfield(%118, 1))
│    %120 = Core.getfield(%113, 2)::Tuple{Int64, Int64}
│    %121 = Main.:(var"#495#501")::Core.Const(var"#495#501")
│    %122 = Core.typeof(x)::Core.Const(Vector{Float64})
│    %123 = Core.getfield(#self#, :lookup_qg)::Dict{Int64, Int64}
│    %124 = Core.typeof(%123)::Core.Const(Dict{Int64, Int64})
│    %125 = Core.apply_type(%121, %122, %124)::Core.Const(var"#495#501"{Vector{Float64}, Dict{Int64, Int64}})
│    %126 = Core.getfield(#self#, :lookup_qg)::Dict{Int64, Int64}
│           (#495 = %new(%125, x, %126))
│    %128 = #495::var"#495#501"{Vector{Float64}, Dict{Int64, Int64}}
│    %129 = Core.getfield(#self#, :ref_bus_gens)::Dict{Int64, Vector{Int64}}
│    %130 = Base.getindex(%129, i@_27)::Vector{Int64}
│    %131 = Base.Generator(%128, %130)::Base.Generator{Vector{Int64}, var"#495#501"{Vector{Float64}, Dict{Int64, Int64}}}
│    %132 = (:init,)::Core.Const((:init,))
│    %133 = Core.apply_type(Core.NamedTuple, %132)::Core.Const(NamedTuple{(:init,)})
│    %134 = Core.tuple(0.0)::Core.Const((0.0,))
│    %135 = (%133)(%134)::Core.Const((init = 0.0,))
│    %136 = Core.kwcall(%135, Main.sum, %131)::Float64
│    %137 = Core.getfield(#self#, :bus_qd)::Dict{Int64, Float64}
│    %138 = Base.getindex(%137, i@_27)::Float64
│    %139 = (%136 - %138)::Float64
│    %140 = Core.getfield(#self#, :bus_bs)::Dict{Int64, Float64}
│    %141 = Base.getindex(%140, i@_27)::Float64
│    %142 = Main.:^::Core.Const(^)
│    %143 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %144 = Base.getindex(%143, i@_27)::Int64
│    %145 = Base.getindex(x, %144)::Float64
│    %146 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %147 = (%146)()::Core.Const(Val{2}())
│    %148 = Base.literal_pow(%142, %145, %147)::Float64
│    %149 = (%141 * %148)::Float64
│    %150 = (%139 + %149)::Float64
│    %151 = Main.:(var"#496#502")::Core.Const(var"#496#502")
│    %152 = Core.typeof(x)::Core.Const(Vector{Float64})
│    %153 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %154 = Core.typeof(%153)::Core.Const(Dict{Tuple{Int64, Int64, Int64}, Int64})
│    %155 = Core.apply_type(%151, %152, %154)::Core.Const(var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}})
│    %156 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│           (#496 = %new(%155, x, %156))
│    %158 = #496::var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}
│    %159 = Core.getfield(#self#, :ref_bus_arcs)::Dict{Int64, Vector{Tuple{Int64, Int64, Int64}}}
│    %160 = Base.getindex(%159, i@_27)::Vector{Tuple{Int64, Int64, Int64}}
│    %161 = Base.Generator(%158, %160)::Base.Generator{Vector{Tuple{Int64, Int64, Int64}}, var"#496#502"{Vector{Float64}, Dict{Tuple{Int64, Int64, Int64}, Int64}}}
│    %162 = Main.sum(%161)::Float64
│    %163 = (%150 - %162)::Float64
│    %164 = (reti@_28 + offsetidx)::Int64
│           Base.setindex!(ret, %163, %164)
│           (@_12 = Base.iterate(%108, %120))
│    %167 = (@_12 === nothing)::Bool
│    %168 = Base.not_int(%167)::Bool
└───        goto #10 if not %168
9 ──        goto #8
10 ┄ %171 = offsetidx::Int64
│    %172 = Core.getfield(#self#, :ref_bus_idxs)::Vector{Int64}
│    %173 = Main.length(%172)::Int64
│           (offsetidx = %171 + %173)
│    %175 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %176 = Main.enumerate(%175)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_11 = Base.iterate(%176))
│    %178 = (@_11 === nothing)::Bool
│    %179 = Base.not_int(%178)::Bool
└───        goto #13 if not %179
11 ┄ %181 = @_11::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %182 = Core.getfield(%181, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %183 = Base.indexed_iterate(%182, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_34 = Core.getfield(%183, 1))
│           (@_30 = Core.getfield(%183, 2))
│    %186 = Base.indexed_iterate(%182, 2, @_30::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %187 = Core.getfield(%186, 1)::Tuple{Int64, Int64, Int64}
│    %188 = Base.indexed_iterate(%187, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_32 = Core.getfield(%188, 1))
│           (@_29 = Core.getfield(%188, 2))
│    %191 = Base.indexed_iterate(%187, 2, @_29::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_33 = Core.getfield(%191, 1))
│           (@_29 = Core.getfield(%191, 2))
│    %194 = Base.indexed_iterate(%187, 3, @_29::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_31 = Core.getfield(%194, 1))
│    %196 = Core.getfield(%181, 2)::Tuple{Int64, Int64}
│    %197 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %198 = Base.getindex(%197, l@_32)::Float64
│    %199 = Core.getfield(#self#, :br_g_fr)::Dict{Int64, Float64}
│    %200 = Base.getindex(%199, l@_32)::Float64
│    %201 = (%198 + %200)::Float64
│    %202 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %203 = Base.getindex(%202, l@_32)::Float64
│    %204 = (%201 / %203)::Float64
│    %205 = Main.:^::Core.Const(^)
│    %206 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %207 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %208 = Base.getindex(%207, l@_32)::Int64
│    %209 = Base.getindex(%206, %208)::Int64
│    %210 = Base.getindex(x, %209)::Float64
│    %211 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %212 = (%211)()::Core.Const(Val{2}())
│    %213 = Base.literal_pow(%205, %210, %212)::Float64
│    %214 = (%204 * %213)::Float64
│    %215 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %216 = Base.getindex(%215, l@_32)::Float64
│    %217 = -%216::Float64
│    %218 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %219 = Base.getindex(%218, l@_32)::Float64
│    %220 = (%217 * %219)::Float64
│    %221 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %222 = Base.getindex(%221, l@_32)::Float64
│    %223 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %224 = Base.getindex(%223, l@_32)::Float64
│    %225 = (%222 * %224)::Float64
│    %226 = (%220 + %225)::Float64
│    %227 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %228 = Base.getindex(%227, l@_32)::Float64
│    %229 = (%226 / %228)::Float64
│    %230 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %231 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %232 = Base.getindex(%231, l@_32)::Int64
│    %233 = Base.getindex(%230, %232)::Int64
│    %234 = Base.getindex(x, %233)::Float64
│    %235 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %236 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %237 = Base.getindex(%236, l@_32)::Int64
│    %238 = Base.getindex(%235, %237)::Int64
│    %239 = Base.getindex(x, %238)::Float64
│    %240 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %241 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %242 = Base.getindex(%241, l@_32)::Int64
│    %243 = Base.getindex(%240, %242)::Int64
│    %244 = Base.getindex(x, %243)::Float64
│    %245 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %246 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %247 = Base.getindex(%246, l@_32)::Int64
│    %248 = Base.getindex(%245, %247)::Int64
│    %249 = Base.getindex(x, %248)::Float64
│    %250 = (%244 - %249)::Float64
│    %251 = Main.cos(%250)::Float64
│    %252 = (%234 * %239 * %251)::Float64
│    %253 = (%229 * %252)::Float64
│    %254 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %255 = Base.getindex(%254, l@_32)::Float64
│    %256 = -%255::Float64
│    %257 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %258 = Base.getindex(%257, l@_32)::Float64
│    %259 = (%256 * %258)::Float64
│    %260 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %261 = Base.getindex(%260, l@_32)::Float64
│    %262 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %263 = Base.getindex(%262, l@_32)::Float64
│    %264 = (%261 * %263)::Float64
│    %265 = (%259 - %264)::Float64
│    %266 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %267 = Base.getindex(%266, l@_32)::Float64
│    %268 = (%265 / %267)::Float64
│    %269 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %270 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %271 = Base.getindex(%270, l@_32)::Int64
│    %272 = Base.getindex(%269, %271)::Int64
│    %273 = Base.getindex(x, %272)::Float64
│    %274 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %275 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %276 = Base.getindex(%275, l@_32)::Int64
│    %277 = Base.getindex(%274, %276)::Int64
│    %278 = Base.getindex(x, %277)::Float64
│    %279 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %280 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %281 = Base.getindex(%280, l@_32)::Int64
│    %282 = Base.getindex(%279, %281)::Int64
│    %283 = Base.getindex(x, %282)::Float64
│    %284 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %285 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %286 = Base.getindex(%285, l@_32)::Int64
│    %287 = Base.getindex(%284, %286)::Int64
│    %288 = Base.getindex(x, %287)::Float64
│    %289 = (%283 - %288)::Float64
│    %290 = Main.sin(%289)::Float64
│    %291 = (%273 * %278 * %290)::Float64
│    %292 = (%268 * %291)::Float64
│    %293 = (%214 + %253 + %292)::Float64
│    %294 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %295 = Core.tuple(l@_32, i@_33, j@_31)::Tuple{Int64, Int64, Int64}
│    %296 = Base.getindex(%294, %295)::Int64
│    %297 = Base.getindex(x, %296)::Float64
│    %298 = (%293 - %297)::Float64
│    %299 = (reti@_34 + offsetidx)::Int64
│           Base.setindex!(ret, %298, %299)
│           (@_11 = Base.iterate(%176, %196))
│    %302 = (@_11 === nothing)::Bool
│    %303 = Base.not_int(%302)::Bool
└───        goto #13 if not %303
12 ─        goto #11
13 ┄ %306 = offsetidx::Int64
│    %307 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %308 = Main.length(%307)::Int64
│           (offsetidx = %306 + %308)
│    %310 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}}
│    %311 = Main.enumerate(%310)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_10 = Base.iterate(%311))
│    %313 = (@_10 === nothing)::Bool
│    %314 = Base.not_int(%313)::Bool
└───        goto #16 if not %314
14 ┄ %316 = @_10::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %317 = Core.getfield(%316, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %318 = Base.indexed_iterate(%317, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_40 = Core.getfield(%318, 1))
│           (@_36 = Core.getfield(%318, 2))
│    %321 = Base.indexed_iterate(%317, 2, @_36::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %322 = Core.getfield(%321, 1)::Tuple{Int64, Int64, Int64}
│    %323 = Base.indexed_iterate(%322, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_39 = Core.getfield(%323, 1))
│           (@_35 = Core.getfield(%323, 2))
│    %326 = Base.indexed_iterate(%322, 2, @_35::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_38 = Core.getfield(%326, 1))
│           (@_35 = Core.getfield(%326, 2))
│    %329 = Base.indexed_iterate(%322, 3, @_35::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_37 = Core.getfield(%329, 1))
│    %331 = Core.getfield(%316, 2)::Tuple{Int64, Int64}
│    %332 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %333 = Base.getindex(%332, l@_39)::Float64
│    %334 = Core.getfield(#self#, :br_g_to)::Dict{Int64, Float64}
│    %335 = Base.getindex(%334, l@_39)::Float64
│    %336 = (%333 + %335)::Float64
│    %337 = Main.:^::Core.Const(^)
│    %338 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %339 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %340 = Base.getindex(%339, l@_39)::Int64
│    %341 = Base.getindex(%338, %340)::Int64
│    %342 = Base.getindex(x, %341)::Float64
│    %343 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %344 = (%343)()::Core.Const(Val{2}())
│    %345 = Base.literal_pow(%337, %342, %344)::Float64
│    %346 = (%336 * %345)::Float64
│    %347 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %348 = Base.getindex(%347, l@_39)::Float64
│    %349 = -%348::Float64
│    %350 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %351 = Base.getindex(%350, l@_39)::Float64
│    %352 = (%349 * %351)::Float64
│    %353 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %354 = Base.getindex(%353, l@_39)::Float64
│    %355 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %356 = Base.getindex(%355, l@_39)::Float64
│    %357 = (%354 * %356)::Float64
│    %358 = (%352 - %357)::Float64
│    %359 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %360 = Base.getindex(%359, l@_39)::Float64
│    %361 = (%358 / %360)::Float64
│    %362 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %363 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %364 = Base.getindex(%363, l@_39)::Int64
│    %365 = Base.getindex(%362, %364)::Int64
│    %366 = Base.getindex(x, %365)::Float64
│    %367 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %368 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %369 = Base.getindex(%368, l@_39)::Int64
│    %370 = Base.getindex(%367, %369)::Int64
│    %371 = Base.getindex(x, %370)::Float64
│    %372 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %373 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %374 = Base.getindex(%373, l@_39)::Int64
│    %375 = Base.getindex(%372, %374)::Int64
│    %376 = Base.getindex(x, %375)::Float64
│    %377 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %378 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %379 = Base.getindex(%378, l@_39)::Int64
│    %380 = Base.getindex(%377, %379)::Int64
│    %381 = Base.getindex(x, %380)::Float64
│    %382 = (%376 - %381)::Float64
│    %383 = Main.cos(%382)::Float64
│    %384 = (%366 * %371 * %383)::Float64
│    %385 = (%361 * %384)::Float64
│    %386 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %387 = Base.getindex(%386, l@_39)::Float64
│    %388 = -%387::Float64
│    %389 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %390 = Base.getindex(%389, l@_39)::Float64
│    %391 = (%388 * %390)::Float64
│    %392 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %393 = Base.getindex(%392, l@_39)::Float64
│    %394 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %395 = Base.getindex(%394, l@_39)::Float64
│    %396 = (%393 * %395)::Float64
│    %397 = (%391 + %396)::Float64
│    %398 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %399 = Base.getindex(%398, l@_39)::Float64
│    %400 = (%397 / %399)::Float64
│    %401 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %402 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %403 = Base.getindex(%402, l@_39)::Int64
│    %404 = Base.getindex(%401, %403)::Int64
│    %405 = Base.getindex(x, %404)::Float64
│    %406 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %407 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %408 = Base.getindex(%407, l@_39)::Int64
│    %409 = Base.getindex(%406, %408)::Int64
│    %410 = Base.getindex(x, %409)::Float64
│    %411 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %412 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %413 = Base.getindex(%412, l@_39)::Int64
│    %414 = Base.getindex(%411, %413)::Int64
│    %415 = Base.getindex(x, %414)::Float64
│    %416 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %417 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %418 = Base.getindex(%417, l@_39)::Int64
│    %419 = Base.getindex(%416, %418)::Int64
│    %420 = Base.getindex(x, %419)::Float64
│    %421 = (%415 - %420)::Float64
│    %422 = Main.sin(%421)::Float64
│    %423 = (%405 * %410 * %422)::Float64
│    %424 = (%400 * %423)::Float64
│    %425 = (%346 + %385 + %424)::Float64
│    %426 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %427 = Core.tuple(l@_39, i@_38, j@_37)::Tuple{Int64, Int64, Int64}
│    %428 = Base.getindex(%426, %427)::Int64
│    %429 = Base.getindex(x, %428)::Float64
│    %430 = (%425 - %429)::Float64
│    %431 = (reti@_40 + offsetidx)::Int64
│           Base.setindex!(ret, %430, %431)
│           (@_10 = Base.iterate(%311, %331))
│    %434 = (@_10 === nothing)::Bool
│    %435 = Base.not_int(%434)::Bool
└───        goto #16 if not %435
15 ─        goto #14
16 ┄ %438 = offsetidx::Int64
│    %439 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}}
│    %440 = Main.length(%439)::Int64
│           (offsetidx = %438 + %440)
│    %442 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %443 = Main.enumerate(%442)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_9 = Base.iterate(%443))
│    %445 = (@_9 === nothing)::Bool
│    %446 = Base.not_int(%445)::Bool
└───        goto #19 if not %446
17 ┄ %448 = @_9::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %449 = Core.getfield(%448, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %450 = Base.indexed_iterate(%449, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_46 = Core.getfield(%450, 1))
│           (@_42 = Core.getfield(%450, 2))
│    %453 = Base.indexed_iterate(%449, 2, @_42::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %454 = Core.getfield(%453, 1)::Tuple{Int64, Int64, Int64}
│    %455 = Base.indexed_iterate(%454, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_45 = Core.getfield(%455, 1))
│           (@_41 = Core.getfield(%455, 2))
│    %458 = Base.indexed_iterate(%454, 2, @_41::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_44 = Core.getfield(%458, 1))
│           (@_41 = Core.getfield(%458, 2))
│    %461 = Base.indexed_iterate(%454, 3, @_41::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_43 = Core.getfield(%461, 1))
│    %463 = Core.getfield(%448, 2)::Tuple{Int64, Int64}
│    %464 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %465 = Base.getindex(%464, l@_45)::Float64
│    %466 = Core.getfield(#self#, :br_b_fr)::Dict{Int64, Float64}
│    %467 = Base.getindex(%466, l@_45)::Float64
│    %468 = (%465 + %467)::Float64
│    %469 = -%468::Float64
│    %470 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %471 = Base.getindex(%470, l@_45)::Float64
│    %472 = (%469 / %471)::Float64
│    %473 = Main.:^::Core.Const(^)
│    %474 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %475 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %476 = Base.getindex(%475, l@_45)::Int64
│    %477 = Base.getindex(%474, %476)::Int64
│    %478 = Base.getindex(x, %477)::Float64
│    %479 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %480 = (%479)()::Core.Const(Val{2}())
│    %481 = Base.literal_pow(%473, %478, %480)::Float64
│    %482 = (%472 * %481)::Float64
│    %483 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %484 = Base.getindex(%483, l@_45)::Float64
│    %485 = -%484::Float64
│    %486 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %487 = Base.getindex(%486, l@_45)::Float64
│    %488 = (%485 * %487)::Float64
│    %489 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %490 = Base.getindex(%489, l@_45)::Float64
│    %491 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %492 = Base.getindex(%491, l@_45)::Float64
│    %493 = (%490 * %492)::Float64
│    %494 = (%488 - %493)::Float64
│    %495 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %496 = Base.getindex(%495, l@_45)::Float64
│    %497 = (%494 / %496)::Float64
│    %498 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %499 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %500 = Base.getindex(%499, l@_45)::Int64
│    %501 = Base.getindex(%498, %500)::Int64
│    %502 = Base.getindex(x, %501)::Float64
│    %503 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %504 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %505 = Base.getindex(%504, l@_45)::Int64
│    %506 = Base.getindex(%503, %505)::Int64
│    %507 = Base.getindex(x, %506)::Float64
│    %508 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %509 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %510 = Base.getindex(%509, l@_45)::Int64
│    %511 = Base.getindex(%508, %510)::Int64
│    %512 = Base.getindex(x, %511)::Float64
│    %513 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %514 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %515 = Base.getindex(%514, l@_45)::Int64
│    %516 = Base.getindex(%513, %515)::Int64
│    %517 = Base.getindex(x, %516)::Float64
│    %518 = (%512 - %517)::Float64
│    %519 = Main.cos(%518)::Float64
│    %520 = (%502 * %507 * %519)::Float64
│    %521 = (%497 * %520)::Float64
│    %522 = (%482 - %521)::Float64
│    %523 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %524 = Base.getindex(%523, l@_45)::Float64
│    %525 = -%524::Float64
│    %526 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %527 = Base.getindex(%526, l@_45)::Float64
│    %528 = (%525 * %527)::Float64
│    %529 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %530 = Base.getindex(%529, l@_45)::Float64
│    %531 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %532 = Base.getindex(%531, l@_45)::Float64
│    %533 = (%530 * %532)::Float64
│    %534 = (%528 + %533)::Float64
│    %535 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %536 = Base.getindex(%535, l@_45)::Float64
│    %537 = (%534 / %536)::Float64
│    %538 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %539 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %540 = Base.getindex(%539, l@_45)::Int64
│    %541 = Base.getindex(%538, %540)::Int64
│    %542 = Base.getindex(x, %541)::Float64
│    %543 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %544 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %545 = Base.getindex(%544, l@_45)::Int64
│    %546 = Base.getindex(%543, %545)::Int64
│    %547 = Base.getindex(x, %546)::Float64
│    %548 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %549 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %550 = Base.getindex(%549, l@_45)::Int64
│    %551 = Base.getindex(%548, %550)::Int64
│    %552 = Base.getindex(x, %551)::Float64
│    %553 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %554 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %555 = Base.getindex(%554, l@_45)::Int64
│    %556 = Base.getindex(%553, %555)::Int64
│    %557 = Base.getindex(x, %556)::Float64
│    %558 = (%552 - %557)::Float64
│    %559 = Main.sin(%558)::Float64
│    %560 = (%542 * %547 * %559)::Float64
│    %561 = (%537 * %560)::Float64
│    %562 = (%522 + %561)::Float64
│    %563 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %564 = Core.tuple(l@_45, i@_44, j@_43)::Tuple{Int64, Int64, Int64}
│    %565 = Base.getindex(%563, %564)::Int64
│    %566 = Base.getindex(x, %565)::Float64
│    %567 = (%562 - %566)::Float64
│    %568 = (reti@_46 + offsetidx)::Int64
│           Base.setindex!(ret, %567, %568)
│           (@_9 = Base.iterate(%443, %463))
│    %571 = (@_9 === nothing)::Bool
│    %572 = Base.not_int(%571)::Bool
└───        goto #19 if not %572
18 ─        goto #17
19 ┄ %575 = offsetidx::Int64
│    %576 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %577 = Main.length(%576)::Int64
│           (offsetidx = %575 + %577)
│    %579 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}}
│    %580 = Main.enumerate(%579)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_8 = Base.iterate(%580))
│    %582 = (@_8 === nothing)::Bool
│    %583 = Base.not_int(%582)::Bool
└───        goto #22 if not %583
20 ┄ %585 = @_8::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %586 = Core.getfield(%585, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %587 = Base.indexed_iterate(%586, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_52 = Core.getfield(%587, 1))
│           (@_48 = Core.getfield(%587, 2))
│    %590 = Base.indexed_iterate(%586, 2, @_48::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %591 = Core.getfield(%590, 1)::Tuple{Int64, Int64, Int64}
│    %592 = Base.indexed_iterate(%591, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_51 = Core.getfield(%592, 1))
│           (@_47 = Core.getfield(%592, 2))
│    %595 = Base.indexed_iterate(%591, 2, @_47::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_50 = Core.getfield(%595, 1))
│           (@_47 = Core.getfield(%595, 2))
│    %598 = Base.indexed_iterate(%591, 3, @_47::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_49 = Core.getfield(%598, 1))
│    %600 = Core.getfield(%585, 2)::Tuple{Int64, Int64}
│    %601 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %602 = Base.getindex(%601, l@_51)::Float64
│    %603 = Core.getfield(#self#, :br_b_to)::Dict{Int64, Float64}
│    %604 = Base.getindex(%603, l@_51)::Float64
│    %605 = (%602 + %604)::Float64
│    %606 = -%605::Float64
│    %607 = Main.:^::Core.Const(^)
│    %608 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %609 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %610 = Base.getindex(%609, l@_51)::Int64
│    %611 = Base.getindex(%608, %610)::Int64
│    %612 = Base.getindex(x, %611)::Float64
│    %613 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %614 = (%613)()::Core.Const(Val{2}())
│    %615 = Base.literal_pow(%607, %612, %614)::Float64
│    %616 = (%606 * %615)::Float64
│    %617 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %618 = Base.getindex(%617, l@_51)::Float64
│    %619 = -%618::Float64
│    %620 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %621 = Base.getindex(%620, l@_51)::Float64
│    %622 = (%619 * %621)::Float64
│    %623 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %624 = Base.getindex(%623, l@_51)::Float64
│    %625 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %626 = Base.getindex(%625, l@_51)::Float64
│    %627 = (%624 * %626)::Float64
│    %628 = (%622 + %627)::Float64
│    %629 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %630 = Base.getindex(%629, l@_51)::Float64
│    %631 = (%628 / %630)::Float64
│    %632 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %633 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %634 = Base.getindex(%633, l@_51)::Int64
│    %635 = Base.getindex(%632, %634)::Int64
│    %636 = Base.getindex(x, %635)::Float64
│    %637 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %638 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %639 = Base.getindex(%638, l@_51)::Int64
│    %640 = Base.getindex(%637, %639)::Int64
│    %641 = Base.getindex(x, %640)::Float64
│    %642 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %643 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %644 = Base.getindex(%643, l@_51)::Int64
│    %645 = Base.getindex(%642, %644)::Int64
│    %646 = Base.getindex(x, %645)::Float64
│    %647 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %648 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %649 = Base.getindex(%648, l@_51)::Int64
│    %650 = Base.getindex(%647, %649)::Int64
│    %651 = Base.getindex(x, %650)::Float64
│    %652 = (%646 - %651)::Float64
│    %653 = Main.cos(%652)::Float64
│    %654 = (%636 * %641 * %653)::Float64
│    %655 = (%631 * %654)::Float64
│    %656 = (%616 - %655)::Float64
│    %657 = Core.getfield(#self#, :br_g)::Dict{Int64, Float64}
│    %658 = Base.getindex(%657, l@_51)::Float64
│    %659 = -%658::Float64
│    %660 = Core.getfield(#self#, :br_tr)::Dict{Int64, Float64}
│    %661 = Base.getindex(%660, l@_51)::Float64
│    %662 = (%659 * %661)::Float64
│    %663 = Core.getfield(#self#, :br_b)::Dict{Int64, Float64}
│    %664 = Base.getindex(%663, l@_51)::Float64
│    %665 = Core.getfield(#self#, :br_ti)::Dict{Int64, Float64}
│    %666 = Base.getindex(%665, l@_51)::Float64
│    %667 = (%664 * %666)::Float64
│    %668 = (%662 - %667)::Float64
│    %669 = Core.getfield(#self#, :br_ttm)::Dict{Int64, Float64}
│    %670 = Base.getindex(%669, l@_51)::Float64
│    %671 = (%668 / %670)::Float64
│    %672 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %673 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %674 = Base.getindex(%673, l@_51)::Int64
│    %675 = Base.getindex(%672, %674)::Int64
│    %676 = Base.getindex(x, %675)::Float64
│    %677 = Core.getfield(#self#, :lookup_vm)::Dict{Int64, Int64}
│    %678 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %679 = Base.getindex(%678, l@_51)::Int64
│    %680 = Base.getindex(%677, %679)::Int64
│    %681 = Base.getindex(x, %680)::Float64
│    %682 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %683 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %684 = Base.getindex(%683, l@_51)::Int64
│    %685 = Base.getindex(%682, %684)::Int64
│    %686 = Base.getindex(x, %685)::Float64
│    %687 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %688 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %689 = Base.getindex(%688, l@_51)::Int64
│    %690 = Base.getindex(%687, %689)::Int64
│    %691 = Base.getindex(x, %690)::Float64
│    %692 = (%686 - %691)::Float64
│    %693 = Main.sin(%692)::Float64
│    %694 = (%676 * %681 * %693)::Float64
│    %695 = (%671 * %694)::Float64
│    %696 = (%656 + %695)::Float64
│    %697 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %698 = Core.tuple(l@_51, i@_50, j@_49)::Tuple{Int64, Int64, Int64}
│    %699 = Base.getindex(%697, %698)::Int64
│    %700 = Base.getindex(x, %699)::Float64
│    %701 = (%696 - %700)::Float64
│    %702 = (reti@_52 + offsetidx)::Int64
│           Base.setindex!(ret, %701, %702)
│           (@_8 = Base.iterate(%580, %600))
│    %705 = (@_8 === nothing)::Bool
│    %706 = Base.not_int(%705)::Bool
└───        goto #22 if not %706
21 ─        goto #20
22 ┄ %709 = offsetidx::Int64
│    %710 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}}
│    %711 = Main.length(%710)::Int64
│           (offsetidx = %709 + %711)
│    %713 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %714 = Main.enumerate(%713)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_7 = Base.iterate(%714))
│    %716 = (@_7 === nothing)::Bool
│    %717 = Base.not_int(%716)::Bool
└───        goto #25 if not %717
23 ┄ %719 = @_7::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %720 = Core.getfield(%719, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %721 = Base.indexed_iterate(%720, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_58 = Core.getfield(%721, 1))
│           (@_54 = Core.getfield(%721, 2))
│    %724 = Base.indexed_iterate(%720, 2, @_54::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %725 = Core.getfield(%724, 1)::Tuple{Int64, Int64, Int64}
│    %726 = Base.indexed_iterate(%725, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_57 = Core.getfield(%726, 1))
│           (@_53 = Core.getfield(%726, 2))
│    %729 = Base.indexed_iterate(%725, 2, @_53::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_56 = Core.getfield(%729, 1))
│           (@_53 = Core.getfield(%729, 2))
│    %732 = Base.indexed_iterate(%725, 3, @_53::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_55 = Core.getfield(%732, 1))
│    %734 = Core.getfield(%719, 2)::Tuple{Int64, Int64}
│    %735 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %736 = Core.getfield(#self#, :f_bus)::Dict{Int64, Int64}
│    %737 = Base.getindex(%736, l@_57)::Int64
│    %738 = Base.getindex(%735, %737)::Int64
│    %739 = Base.getindex(x, %738)::Float64
│    %740 = Core.getfield(#self#, :lookup_va)::Dict{Int64, Int64}
│    %741 = Core.getfield(#self#, :t_bus)::Dict{Int64, Int64}
│    %742 = Base.getindex(%741, l@_57)::Int64
│    %743 = Base.getindex(%740, %742)::Int64
│    %744 = Base.getindex(x, %743)::Float64
│    %745 = (%739 - %744)::Float64
│    %746 = (reti@_58 + offsetidx)::Int64
│           Base.setindex!(ret, %745, %746)
│           (@_7 = Base.iterate(%714, %734))
│    %749 = (@_7 === nothing)::Bool
│    %750 = Base.not_int(%749)::Bool
└───        goto #25 if not %750
24 ─        goto #23
25 ┄ %753 = offsetidx::Int64
│    %754 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %755 = Main.length(%754)::Int64
│           (offsetidx = %753 + %755)
│    %757 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %758 = Main.enumerate(%757)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_6 = Base.iterate(%758))
│    %760 = (@_6 === nothing)::Bool
│    %761 = Base.not_int(%760)::Bool
└───        goto #28 if not %761
26 ┄ %763 = @_6::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %764 = Core.getfield(%763, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %765 = Base.indexed_iterate(%764, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_64 = Core.getfield(%765, 1))
│           (@_60 = Core.getfield(%765, 2))
│    %768 = Base.indexed_iterate(%764, 2, @_60::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %769 = Core.getfield(%768, 1)::Tuple{Int64, Int64, Int64}
│    %770 = Base.indexed_iterate(%769, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_63 = Core.getfield(%770, 1))
│           (@_59 = Core.getfield(%770, 2))
│    %773 = Base.indexed_iterate(%769, 2, @_59::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_62 = Core.getfield(%773, 1))
│           (@_59 = Core.getfield(%773, 2))
│    %776 = Base.indexed_iterate(%769, 3, @_59::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_61 = Core.getfield(%776, 1))
│    %778 = Core.getfield(%763, 2)::Tuple{Int64, Int64}
│    %779 = Main.:^::Core.Const(^)
│    %780 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %781 = Core.tuple(l@_63, i@_62, j@_61)::Tuple{Int64, Int64, Int64}
│    %782 = Base.getindex(%780, %781)::Int64
│    %783 = Base.getindex(x, %782)::Float64
│    %784 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %785 = (%784)()::Core.Const(Val{2}())
│    %786 = Base.literal_pow(%779, %783, %785)::Float64
│    %787 = Main.:^::Core.Const(^)
│    %788 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %789 = Core.tuple(l@_63, i@_62, j@_61)::Tuple{Int64, Int64, Int64}
│    %790 = Base.getindex(%788, %789)::Int64
│    %791 = Base.getindex(x, %790)::Float64
│    %792 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %793 = (%792)()::Core.Const(Val{2}())
│    %794 = Base.literal_pow(%787, %791, %793)::Float64
│    %795 = (%786 + %794)::Float64
│    %796 = (reti@_64 + offsetidx)::Int64
│           Base.setindex!(ret, %795, %796)
│           (@_6 = Base.iterate(%758, %778))
│    %799 = (@_6 === nothing)::Bool
│    %800 = Base.not_int(%799)::Bool
└───        goto #28 if not %800
27 ─        goto #26
28 ┄ %803 = offsetidx::Int64
│    %804 = Core.getfield(#self#, :ref_arcs_from)::Vector{Tuple{Int64, Int64, Int64}}
│    %805 = Main.length(%804)::Int64
│           (offsetidx = %803 + %805)
│    %807 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}}
│    %808 = Main.enumerate(%807)::Base.Iterators.Enumerate{Vector{Tuple{Int64, Int64, Int64}}}
│           (@_5 = Base.iterate(%808))
│    %810 = (@_5 === nothing)::Bool
│    %811 = Base.not_int(%810)::Bool
└───        goto #31 if not %811
29 ┄ %813 = @_5::Tuple{Tuple{Int64, Tuple{Int64, Int64, Int64}}, Tuple{Int64, Int64}}
│    %814 = Core.getfield(%813, 1)::Tuple{Int64, Tuple{Int64, Int64, Int64}}
│    %815 = Base.indexed_iterate(%814, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (reti@_70 = Core.getfield(%815, 1))
│           (@_66 = Core.getfield(%815, 2))
│    %818 = Base.indexed_iterate(%814, 2, @_66::Core.Const(2))::Core.PartialStruct(Tuple{Tuple{Int64, Int64, Int64}, Int64}, Any[Tuple{Int64, Int64, Int64}, Core.Const(3)])
│    %819 = Core.getfield(%818, 1)::Tuple{Int64, Int64, Int64}
│    %820 = Base.indexed_iterate(%819, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
│           (l@_69 = Core.getfield(%820, 1))
│           (@_65 = Core.getfield(%820, 2))
│    %823 = Base.indexed_iterate(%819, 2, @_65::Core.Const(2))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(3)])
│           (i@_68 = Core.getfield(%823, 1))
│           (@_65 = Core.getfield(%823, 2))
│    %826 = Base.indexed_iterate(%819, 3, @_65::Core.Const(3))::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(4)])
│           (j@_67 = Core.getfield(%826, 1))
│    %828 = Core.getfield(%813, 2)::Tuple{Int64, Int64}
│    %829 = Main.:^::Core.Const(^)
│    %830 = Core.getfield(#self#, :p_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %831 = Core.tuple(l@_69, i@_68, j@_67)::Tuple{Int64, Int64, Int64}
│    %832 = Base.getindex(%830, %831)::Int64
│    %833 = Base.getindex(x, %832)::Float64
│    %834 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %835 = (%834)()::Core.Const(Val{2}())
│    %836 = Base.literal_pow(%829, %833, %835)::Float64
│    %837 = Main.:^::Core.Const(^)
│    %838 = Core.getfield(#self#, :q_idxmap)::Dict{Tuple{Int64, Int64, Int64}, Int64}
│    %839 = Core.tuple(l@_69, i@_68, j@_67)::Tuple{Int64, Int64, Int64}
│    %840 = Base.getindex(%838, %839)::Int64
│    %841 = Base.getindex(x, %840)::Float64
│    %842 = Core.apply_type(Base.Val, 2)::Core.Const(Val{2})
│    %843 = (%842)()::Core.Const(Val{2}())
│    %844 = Base.literal_pow(%837, %841, %843)::Float64
│    %845 = (%836 + %844)::Float64
│    %846 = (reti@_70 + offsetidx)::Int64
│           Base.setindex!(ret, %845, %846)
│           (@_5 = Base.iterate(%808, %828))
│    %849 = (@_5 === nothing)::Bool
│    %850 = Base.not_int(%849)::Bool
└───        goto #31 if not %850
30 ─        goto #29
31 ┄ %853 = offsetidx::Int64
│    %854 = Core.getfield(#self#, :ref_arcs_to)::Vector{Tuple{Int64, Int64, Int64}}
│    %855 = Main.length(%854)::Int64
│           (offsetidx = %853 + %855)
│    %857 = offsetidx::Int64
│    %858 = Main.length(ret)::Int64
│    %859 = (%857 == %858)::Bool
└───        goto #33 if not %859
32 ─        goto #34
33 ─ %862 = Base.AssertionError("offsetidx == length(ret)")::Any
└───        Base.throw(%862)
34 ┄        return Main.nothing
```

In theory it should be possible to use Enzyme here now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Benchmarks for ExpRK methods
2 participants