@@ -4,23 +4,26 @@ using Pyomo
44using DiffEqBase
55using UnPack
66using NaNMath
7+ using Setfield
78const MTK = ModelingToolkit
89
910struct PyomoDynamicOptModel
1011 model:: ConcreteModel
1112 U:: PyomoVar
1213 V:: PyomoVar
13- tₛ:: Union{Int, PyomoVar}
14+ tₛ:: PyomoVar
1415 is_free_final:: Bool
16+ solver_model:: Union{Nothing, ConcreteModel}
1517 dU:: PyomoVar
1618 model_sym:: Union{Num, Symbolics.BasicSymbolic}
1719 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}
1922
2023 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
2225 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 )
2427 end
2528end
2629
@@ -39,6 +42,9 @@ struct PyomoDynamicOptProblem{uType, tType, isinplace, P, F, K} <:
3942 end
4043end
4144
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+
4248function MTK. PyomoDynamicOptProblem (sys:: ODESystem , u0map, tspan, pmap;
4349 dt = nothing , steps = nothing ,
4450 guesses = Dict (), kwargs... )
@@ -68,24 +74,22 @@ function MTK.generate_input_variable!(m::ConcreteModel, c0, nc, ts)
6874end
6975
7076function 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 ))
7278end
7379
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
7782 expr = if cons isa Equation
7883 cons. lhs - cons. rhs == 0
7984 elseif cons. relational_op === Symbolics. geq
8085 cons. lhs - cons. rhs ≥ 0
8186 else
8287 cons. lhs - cons. rhs ≤ 0
8388 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)))
8993end
9094
9195function MTK. set_objective! (m:: PyomoDynamicOptModel , expr)
@@ -107,12 +111,12 @@ end
107111MTK. process_integral_bounds (model, integral_span, tspan) = integral_span
108112
109113function 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 ))
111115 Symbolics. unwrap (mdU[i, m. t_sym])
112116end
113117
114118function 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))
116120 var = t isa Union{Num, Symbolics. Symbolic} ? X[i, m. t_sym] : X[i, t]
117121 Symbolics. unwrap (var)
118122end
@@ -125,21 +129,21 @@ end
125129MTK. PyomoCollocation (solver, derivative_method = LagrangeRadau (5 )) = PyomoCollocation (solver, derivative_method)
126130
127131function MTK. prepare_and_optimize! (prob:: PyomoDynamicOptProblem , collocation; verbose, kwargs... )
128- m = prob. wrapped_model. model
132+ solver_m = prob. wrapped_model. model. clone ()
129133 dm = collocation. derivative_method
130134 discretizer = TransformationFactory (dm)
131135 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))
133137 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
136140end
137141
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]
141145
142- function MTK. successful_solve (m:: PyomoDynamicOptModel )
146+ function MTK. successful_solve (m:: ConcreteModel )
143147 ss = m. solver. status
144148 tc = m. solver. termination_condition
145149 if ss == opt. SolverStatus. ok && (tc == opt. TerminationStatus. optimal || tc == opt. TerminationStatus. locallyOptimal)
0 commit comments