I am trying to solve an ode within the pyomo framework, using the forward euler method. I wrote down the discretization scheme explicitly but the result is not as expected. From the pyomo model the vector sol (where the solution is stored) is the following:
array([0.2, 0.5823949246629659, 0.6041743993067193, 0.5990101939788192, 0.6002346962730635, 0.5999443503682427, 0.6000131952735094, 0.5999968712238071, 0.6000007418747674, 0.59999982409155, 0.6000000417102511, 0.5999999901099405, 0.6000000023450657, 0.5999999994439535, 0.6000000001318461, 0.5999999999687375, 0.6000000000074127, 0.5999999999982424, 0.6000000000004168, 0.5999999999999012, 0.6000000000000234, 0.5999999999999944, 0.6000000000000013, 0.5999999999999996, 0.6000000000000001])
while the vector containing the values from the analytical solution is the following:
array([ 2.00000000e-01, -5.87652636e+01, -8.80998632e+03, -1.30760635e+06,
-1.94066078e+08, -2.88019597e+10, -4.27458983e+12, -6.34405381e+14,
-9.41541067e+16, -1.39737084e+19, -2.07388221e+21, -3.07791411e+23,
-4.56802956e+25, -6.77955698e+27, -1.00617547e+30, -1.49329680e+32,
-2.21624895e+34, -3.28920509e+36, -4.88161318e+38, -7.24495633e+40,
-1.07524686e+43, -1.59580783e+45, -2.36838881e+47, -3.51500065e+49,
-5.21672351e+51])
ode: dx/dt = 5*x - 3
Analytical solution with initial condition x(0) = 0.2: x(t) = -0.4*exp(5*t) + 0.6
Please, could anyone help me figure out where I made a mistake ? Thanks in advance.
from pyomo.environ import *
from pyomo.dae import *
m = ConcreteModel()
m.tf = Param(initialize=24)
m.t = RangeSet(0, value(m.tf))
m.ht = Param(initialize=(value(m.tf))/(value(m.tf)), mutable=False) # TimeStep
m.x = Var(m.t)
m.dxdt = Var(m.t)
#Define the ode
def _ode(m, k):
return m.dxdt[k]==5*m.x[k] - 3
#Discretization scheme
def _ode_discr(m, k):
if k==0:
return Constraint.Skip
return m.x[k] == m.x[k-1] + m.ht*m.dxdt[k-1]
#Initial condition
def _initial_cond(m):
return m.x[0]==0.2
m.initial_cond = Constraint(rule=_initial_cond)
m.obj = Objective(expr=1)
sol=[]
for t in m.t:
if 'ode' and 'ode_discr' in m.component_map(): # this line helps to get rid of the previous warning
m.del_component(m.ode) # this line helps to get rid of the previous warning
m.del_component(m.ode_discr) # this line helps to get rid of the previous warning
m.ode = Constraint(m.t, rule=_ode)
m.ode_discr = Constraint(m.t, rule=_ode_discr)
solver = SolverFactory("ipopt")
results=solver.solve(m, tee=False)
print("at", t, "", "value=", value(m.x[t]))
sol.append(value(m.x[t]))
print(sol)
tand you getdx/dt = -2exp(5t)whereas the problem states `dx/dt = 5x-3'. I think PYOMO may have found the right solution (give or take a sign error) but that the timestep is too large so there is a huge jump away from the initial starting point.exp(5t)by(0.6 - x(t))/0.4, you end up with the ode equation. Thank you.