Amit
Amit

Reputation: 65

solving differential equation with step function

I am trying to solve this differential equation as part of my assignment. I am not able to understand on how can i put the condition for u in the code. In the code shown below, i arbitrarily provided

u = 5. 


2dx(t)dt=−x(t)+u(t)

5dy(t)dt=−y(t)+x(t)

u=2S(t−5)

x(0)=0

y(0)=0

where S(t−5) is a step function that changes from zero to one at t=5. When it is multiplied by two, it changes from zero to two at that same time, t=5.

def model(x,t,u):
    dxdt = (-x+u)/2
    return dxdt

def model2(y,x,t):
    dydt = -(y+x)/5
    return dydt

x0 = 0
y0 = 0
u = 5
t = np.linspace(0,40)


x = odeint(model,x0,t,args=(u,))
y = odeint(model2,y0,t,args=(u,))
plt.plot(t,x,'r-')
plt.plot(t,y,'b*')
plt.show()

Upvotes: 3

Views: 1371

Answers (2)

Sven-Eric Krüger
Sven-Eric Krüger

Reputation: 1327

I do not know the SciPy Library very well, but regarding the example in the documentation I would try something like this:

def model(x, t, K, PT)
    """
    The model consists of the state x in R^2, the time in R and the two
    parameters K and PT regarding the input u as step function, where K
    is the infimum of u and PT is the delay of the step.
    """
    x1, x2 = x   # Split the state into two variables

    u = K if t>=PT else 0    # This is the system input

    # Here comes the differential equation in vectorized form
    dx = [(-x1 + u)/2,
          (-x2 + x1)/5]
    return dx

x0 = [0, 0]
K  = 2
PT = 5
t = np.linspace(0,40)

x = odeint(model, x0, t, args=(K, PT))
plt.plot(t, x[:, 0], 'r-')
plt.plot(t, x[:, 1], 'b*')
plt.show()

Upvotes: 3

mmdanziger
mmdanziger

Reputation: 4648

You have a couple of issues here, and the step function is only a small part of it. You can define a step function with a simple lambda and then simply capture it from the outer scope without even passing it to your function. Because sometimes that won't be the case, we'll be explicit and pass it. Your next problem is the order of arguments in the function to integrate. As per the docs (y,t,...). Ie, First the function, then the time vector, then the other args arguments. So for the first part we get:

u = lambda t : 2 if t>5 else 0

def model(x,t,u):
    dxdt = (-x+u(t))/2
    return dxdt

x0 = 0
y0 = 0
t = np.linspace(0,40)


x = odeint(model,x0,t,args=(u,))

Moving to the next part, the trouble is, you can't feed x as an arg to y because it's a vector of values for x(t) for particular times and so y+x doesn't make sense in the function as you wrote it. You can follow your intuition from math class if you pass an x function instead of the x values. Doing so requires that you interpolate the x values using the specific time values you are interested in (which scipy can handle, no problem):

from scipy.interpolate import interp1d
xfunc = interp1d(t.flatten(),x.flatten(),fill_value="extrapolate") 
#flatten cuz the shape is off , extrapolate because odeint will go out of bounds
def model2(y,t,x):
    dydt = -(y+x(t))/5
    return dydt
y = odeint(model2,y0,t,args=(xfunc,))

Then you get:

enter image description here

@Sven's answer is more idiomatic for vector programming like scipy/numpy. But I hope my answer provides a clearer path from what you know already to a working solution.

Upvotes: 1

Related Questions