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
2 changes: 2 additions & 0 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: TagBot

on:
issue_comment:
types:
- created
workflow_dispatch:

jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ on:
- main
tags: '*'

# needed to allow julia-actions/cache to delete old caches that it has created
# Needed to allow julia-actions/cache to delete old caches that it has created
permissions:
actions: write
contents: read

jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
Expand Down
4 changes: 2 additions & 2 deletions examples/algebraic_model.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,12 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": null,
"id": "3cf0c250",
"metadata": {},
"outputs": [],
"source": [
"register_nlsystem(model, system, obj, [g1, g2]);"
"register_nlsystem(model, system, obj, [g1, g2])"
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions examples/ode_model.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,12 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"id": "9b15d798",
"metadata": {},
"outputs": [],
"source": [
"register_odesystem(model, system, tspan, tstep, \"EE\");"
"register_odesystem(model, system, tspan, tstep, \"EE\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/ode_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ include("kinetic_intensity_data.jl")
intensity(x_A, x_B, x_D) = x_A + 2/21*x_B + 2/21*x_D

# Create JuMP model
model = Model(EAGO.Optimizer)
model = Model(Ipopt.Optimizer)

# Retrieve decision variables from ModelingToolkit system
# Returns [x_Z(t), x_Y(t), x_D(t), x_B(t), x_A(t), k_2f, k_3f, k_4]
Expand Down
1 change: 0 additions & 1 deletion src/basefuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,4 @@ function mtk_generate_reduced_expression(expr::Symbolics.Num, sys::ModelingToolk
expr = SymbolicUtils.substitute(expr, sub_dict)
end
return Symbolics.build_function(expr, EOptInterface.decision_vars(sys)..., expression = Val{false})

end
19 changes: 12 additions & 7 deletions src/userfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function register_nlsystem(model::JuMP.Model, sys::ModelingToolkit.System, obj::
JuMP.@constraint(model, [i in eachindex(h)], h[i](JuMP.all_variables(model)...) == 0)
JuMP.@constraint(model, [i in eachindex(g)], g[i](JuMP.all_variables(model)...) ≤ 0)
JuMP.@objective(model, Min, f(JuMP.all_variables(model)...))
return
end

"""
Expand All @@ -56,14 +57,19 @@ Automatically applies forward transcription and registers the discretized ODE Mo

# Arguments
- `model::JuMP.Model`: the JuMP model
- `sys::ModelingToolkit.System`: the ModelingToolkit model
- `sys::ModelingToolkit.System`: the ModelingToolkit system
- `tspan::Tuple{Real,Real}`: the time span over which the dynamic model is simulated
- `tstep::Real`: the time step used in the integration scheme
- `integrator::String`: integration scheme used in discretization, `"EE"` for explicit Euler or `"IE"` for implicit Euler
"""
function register_odesystem(model::JuMP.Model, odesys::ModelingToolkit.System, tspan::Tuple{Real,Real}, tstep::Real, integrator::String)
N = Int(floor((tspan[2] - tspan[1])/tstep)) + 1 # Number of discrete time nodes
V = length(ModelingToolkit.unknowns(odesys)) # Number of ode variables
if integrator != "EE" && integrator != "IE"
error("Available integrators: EE, IE")
end
# Number of discrete time nodes
N = Int(floor((tspan[2] - tspan[1])/tstep)) + 1
# Number of ODE variables
V = length(ModelingToolkit.unknowns(odesys))
param_dict = copy(ModelingToolkit.defaults(odesys))
for var in ModelingToolkit.unknowns(odesys)
pop!(param_dict, var)
Expand All @@ -82,18 +88,17 @@ function register_odesystem(model::JuMP.Model, odesys::ModelingToolkit.System, t
)
push!(dx, dxj)
end
ps = JuMP.all_variables(model)[end-length(setdiff(EOptInterface.decision_vars(odesys),ModelingToolkit.unknowns(odesys)))+1:end]
xs = reshape(setdiff(JuMP.all_variables(model),ps), V, N)
ps = JuMP.all_variables(model)[end-length(setdiff(EOptInterface.decision_vars(odesys), ModelingToolkit.unknowns(odesys)))+1:end]
xs = reshape(setdiff(JuMP.all_variables(model), ps), V, N)
# Extract initial conditions from the ModelingToolkit system and fix them in the JuMP model for x[1:V,1]
JuMP.fix.(xs[:,1], [ModelingToolkit.defaults(odesys)[ModelingToolkit.unknowns(odesys)[i]] for i in eachindex(ModelingToolkit.unknowns(odesys))], force=true)
# Formulate JuMP constraints based on chosen ODE discretization method
if integrator == "EE"
JuMP.@constraint(model, [j in 1:V, i in 1:(N-1)], xs[j,i+1] == xs[j,i] + tstep*dx[j](xs[:,i]..., ps...))
elseif integrator == "IE"
JuMP.@constraint(model, [j in 1:V, i in 1:(N-1)], xs[j,i+1] == xs[j,i] + tstep*dx[j](xs[:,i+1]..., ps...))
else
error("Available integrators: EE, IE")
end
return
end

"""
Expand Down
10 changes: 7 additions & 3 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,17 @@ end
pL = [10.0, 10.0, 0.001]
pU = [1200.0, 1200.0, 40.0]
JuMP.@variable(model, pL[i] <= p[i=1:3] <= pU[i])

@test_throws ErrorException("Available integrators: EE, IE") EOptInterface.register_odesystem(model, system, tspan, tstep, "RK4")

EOptInterface.register_odesystem(model, system, tspan, tstep, "EE")

JuMP.@objective(model, Min, sum((intensity(z[5,i], z[4,i], z[3,i]) - data[i-1])^2 for i in 2:N))
JuMP.optimize!(model)

Test.@test JuMP.termination_status(model) == JuMP.LOCALLY_SOLVED
Test.@test JuMP.primal_status(model) == JuMP.FEASIBLE_POINT
Test.@test isapprox(JuMP.objective_value(model), 9622.762852574022, atol=1e-3)
@test JuMP.termination_status(model) == JuMP.LOCALLY_SOLVED
@test JuMP.primal_status(model) == JuMP.FEASIBLE_POINT
@test isapprox(JuMP.objective_value(model), 9622.762852574022, atol=1e-3)

model = JuMP.Model(Ipopt.Optimizer)
V = length(unknowns(system))
Expand Down
Loading