@@ -4,23 +4,26 @@ using Pyomo
4
4
using DiffEqBase
5
5
using UnPack
6
6
using NaNMath
7
+ using Setfield
7
8
const MTK = ModelingToolkit
8
9
9
10
struct PyomoDynamicOptModel
10
11
model:: ConcreteModel
11
12
U:: PyomoVar
12
13
V:: PyomoVar
13
- tₛ:: Union{Int, PyomoVar}
14
+ tₛ:: PyomoVar
14
15
is_free_final:: Bool
16
+ solver_model:: Union{Nothing, ConcreteModel}
15
17
dU:: PyomoVar
16
18
model_sym:: Union{Num, Symbolics.BasicSymbolic}
17
19
t_sym:: Union{Num, Symbolics.BasicSymbolic}
18
- idx_sym:: Union{Num, Symbolics.BasicSymbolic}
20
+ uidx_sym:: Union{Num, Symbolics.BasicSymbolic}
21
+ vidx_sym:: Union{Num, Symbolics.BasicSymbolic}
19
22
20
23
function PyomoDynamicOptModel (model, U, V, tₛ, is_free_final)
21
- @variables MODEL_SYM:: Symbolics.symstruct (PyomoDynamicOptModel) IDX_SYM :: Int T_SYM
24
+ @variables MODEL_SYM:: Symbolics.symstruct (ConcreteModel) U_IDX_SYM :: Int V_IDX_SYM :: Int T_SYM
22
25
model. dU = dae. DerivativeVar (U, wrt = model. t, initialize = 0 )
23
- new (model, U, V, tₛ, is_free_final, PyomoVar (model. dU), MODEL_SYM, T_SYM, IDX_SYM )
26
+ new (model, U, V, tₛ, is_free_final, nothing , PyomoVar (model. dU), MODEL_SYM, T_SYM, U_IDX_SYM, V_IDX_SYM )
24
27
end
25
28
end
26
29
@@ -39,6 +42,9 @@ struct PyomoDynamicOptProblem{uType, tType, isinplace, P, F, K} <:
39
42
end
40
43
end
41
44
45
+ pysym_getproperty (s, name:: Symbol ) = Symbolics. wrap (SymbolicUtils. term (_getproperty, s, Val {name} (), type = Symbolics. Struct{PyomoVar}))
46
+ _getproperty (s, name:: Val{fieldname} ) where fieldname = getproperty (s, fieldname)
47
+
42
48
function MTK. PyomoDynamicOptProblem (sys:: ODESystem , u0map, tspan, pmap;
43
49
dt = nothing , steps = nothing ,
44
50
guesses = Dict (), kwargs... )
@@ -68,24 +74,22 @@ function MTK.generate_input_variable!(m::ConcreteModel, c0, nc, ts)
68
74
end
69
75
70
76
function MTK. generate_timescale! (m:: ConcreteModel , guess, is_free_t)
71
- m. tₛ = is_free_t ? PyomoVar (pyomo. Var (initialize = guess, bounds = (0 , Inf ))) : 1
77
+ m. tₛ = is_free_t ? PyomoVar (pyomo. Var (initialize = guess, bounds = (0 , Inf ))) : PyomoVar (Pyomo . Py ( 1 ))
72
78
end
73
79
74
- function MTK. add_constraint! (pmodel:: PyomoDynamicOptModel , cons)
75
- @unpack model, model_sym, idx_sym, t_sym = pmodel
76
- @show model. dU
80
+ function MTK. add_constraint! (pmodel:: PyomoDynamicOptModel , cons; n_idxs = 1 )
81
+ @unpack model, model_sym, t_sym = pmodel
77
82
expr = if cons isa Equation
78
83
cons. lhs - cons. rhs == 0
79
84
elseif cons. relational_op === Symbolics. geq
80
85
cons. lhs - cons. rhs ≥ 0
81
86
else
82
87
cons. lhs - cons. rhs ≤ 0
83
88
end
84
- constraint_f = Symbolics. build_function (expr, model_sym, idx_sym, t_sym, expression = Val{false })
85
- @show typeof (constraint_f)
86
- @show typeof (Pyomo. pyfunc (constraint_f))
87
- cons_sym = gensym ()
88
- setproperty! (model, cons_sym, pyomo. Constraint (model. u_idxs, model. t, rule = Pyomo. pyfunc (constraint_f)))
89
+ f_expr = Symbolics. build_function (expr, model_sym, t_sym)
90
+ cons_sym = Symbol (" cons" , hash (cons))
91
+ constraint_f = eval (:(cons_sym = $ f_expr))
92
+ setproperty! (model, cons_sym, pyomo. Constraint (model. t, rule = Pyomo. pyfunc (constraint_f)))
89
93
end
90
94
91
95
function MTK. set_objective! (m:: PyomoDynamicOptModel , expr)
@@ -107,12 +111,12 @@ end
107
111
MTK. process_integral_bounds (model, integral_span, tspan) = integral_span
108
112
109
113
function MTK. lowered_derivative (m:: PyomoDynamicOptModel , i)
110
- mdU = Symbolics. symbolic_getproperty ( m. model_sym, :dU ). val
114
+ mdU = Symbolics. value ( pysym_getproperty ( m. model_sym, :dU ))
111
115
Symbolics. unwrap (mdU[i, m. t_sym])
112
116
end
113
117
114
118
function MTK. lowered_var (m:: PyomoDynamicOptModel , uv, i, t)
115
- X = Symbolics. symbolic_getproperty ( m. model_sym, uv). val
119
+ X = Symbolics. value ( pysym_getproperty ( m. model_sym, uv))
116
120
var = t isa Union{Num, Symbolics. Symbolic} ? X[i, m. t_sym] : X[i, t]
117
121
Symbolics. unwrap (var)
118
122
end
@@ -125,21 +129,21 @@ end
125
129
MTK. PyomoCollocation (solver, derivative_method = LagrangeRadau (5 )) = PyomoCollocation (solver, derivative_method)
126
130
127
131
function MTK. prepare_and_optimize! (prob:: PyomoDynamicOptProblem , collocation; verbose, kwargs... )
128
- m = prob. wrapped_model. model
132
+ solver_m = prob. wrapped_model. model. clone ()
129
133
dm = collocation. derivative_method
130
134
discretizer = TransformationFactory (dm)
131
135
ncp = Pyomo. is_finite_difference (dm) ? 1 : dm. np
132
- discretizer. apply_to (m , wrt = m . t, nfe = m . steps, scheme = Pyomo. scheme_string (dm))
136
+ discretizer. apply_to (solver_m , wrt = solver_m . t, nfe = solver_m . steps, scheme = Pyomo. scheme_string (dm))
133
137
solver = SolverFactory (string (collocation. solver))
134
- solver. solve (m , tee = true )
135
- Main . xx[] = solver
138
+ solver. solve (solver_m , tee = true )
139
+ solver_m
136
140
end
137
141
138
- MTK. get_U_values (m:: PyomoDynamicOptModel ) = [pyomo. value (m. model . U[i]) for i in m. model . U . index_set () ]
139
- MTK. get_V_values (m:: PyomoDynamicOptModel ) = [pyomo. value (m. model . V[i]) for i in m. model . V . index_set () ]
140
- MTK. get_t_values (m:: PyomoDynamicOptModel ) = Pyomo . get_results (m . model, :t )
142
+ MTK. get_U_values (m:: ConcreteModel ) = [[ pyomo. value (m. U[i, t ]) for i in m. u_idxs] for t in m . t ]
143
+ MTK. get_V_values (m:: ConcreteModel ) = [[ pyomo. value (m. V[i, t ]) for i in m. v_idxs] for t in m . t ]
144
+ MTK. get_t_values (m:: ConcreteModel ) = [t for t in m . t]
141
145
142
- function MTK. successful_solve (m:: PyomoDynamicOptModel )
146
+ function MTK. successful_solve (m:: ConcreteModel )
143
147
ss = m. solver. status
144
148
tc = m. solver. termination_condition
145
149
if ss == opt. SolverStatus. ok && (tc == opt. TerminationStatus. optimal || tc == opt. TerminationStatus. locallyOptimal)
0 commit comments