0

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)
2
  • The analytic "solution" doesn't look at all right to me. Differentiate it wrt t and you get dx/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. Commented Nov 15, 2024 at 15:09
  • Hey Martin, thanks for your comment. Actually, by replacing exp(5t) by (0.6 - x(t))/0.4, you end up with the ode equation. Thank you. Commented Nov 15, 2024 at 16:21

1 Answer 1

0

I was able to solve the issue by switching to glpk solver. The solution now matches the analytical solution.

Sign up to request clarification or add additional context in comments.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.