Solving an ode y'=f (x) with numerical values of f (x) but without analitical expresion

时间:2019-04-08 13:41:34

标签: python ode

I want to solve an ODE numerically in python, like y'=f(x) (with boundary condition y(0)=0). The point is that I don't know what is the analitical expresion of this function f(x), instead I have a set of points (data) of this function for the domain where I want to solve the differential equation.

I have tried with (odeint) https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html. But this method works when you know the explicit analitical expresion for f(x), which is not my case. In particular, I have the following code, with the function f(x) in an array (FOR SIMPLICITY I CONSIDER AN KNOWN f(x), BUT IN MY REAL PROBLEM THIS ARRAY f(x) COMES FROM A NUMERICAL SIMULATION WITHOUT KNOKN ANALITICAL EXPRESION).

I Show you the code that I did, but doesn't work, since odeint thinks that I have y'=x, and not my values f(x).

from scipy.integrate import odeint
import numpy as np

def dy_dx(y, f):
    return f #it doesn't work!!


xs = np.linspace(0,10,100)

f = np.sin(xs)*np.exp(-0.1*xs) #data of the function f, but in my real problem I DON'T KNOW THE ANALITICAL SOLUTION! JUST ONLY the points

ys = odeint(dy_dx, 0.0, xs)

Someone has any idea how to solve this problem? I think that must exist something in python to solve this, because basically you are solving the ode numericaly and you know already what are the values of f(x) in the domain of the ode. But I don't see the way.

Thanks in advantge!!

1 个答案:

答案 0 :(得分:2)

您应该能够使用scipy.integrate的正交例程来解决此问题。如果您确实想使用复杂的形式,则必须使用插值,例如

from scipy.integrate import odeint
from scipy.interpolate import interp1d
import numpy as np

xs = np.linspace(0,10,100+1);
fs = np.sin(xs)*np.exp(-0.1*xs) # = Imag( exp((1j-0.1)*x) )
# the exact anti-derivative of f is 
# F = Imag( (exp((1j-0.1)*x)-1)/(1j-0.1) )
#   = Imag( -(1j+0.1)*(exp((1j-0.1)*x)-1)/(1.01) )
#   = 1/1.01 - exp(-0.1*x)/1.01 * ( cos(x) + 0.1*sin(x) )

def IntF(x): return (1-np.exp(-0.1*x)*(np.cos(x)+0.1*np.sin(x)))/1.01 

f = interp1d(xs, fs, kind="quadratic", fill_value="extrapolate")

def dy_dx(y, x):
    return f(x) 

ys = odeint(dy_dx, 0.0, xs)

for x,y in zip(xs, ys): print "%8.4f %20.15f %20.15f"%(x,y,IntF(x))

前10行

    x          interpolated           exact
 --------------------------------------------------
  0.0000    0.000000000000000    0.000000000000000
  0.1000    0.004965420470493    0.004962659238991
  0.2000    0.019671988500299    0.019669801188631
  0.3000    0.043783730081358    0.043781529336000
  0.4000    0.076872788780423    0.076870713937278
  0.5000    0.118430993242631    0.118428986914274
  0.6000    0.167875357240100    0.167873429717074
  0.7000    0.224555718642310    0.224553873611032
  0.8000    0.287762489870417    0.287760727322230
  0.9000    0.356734939606963    0.356733243391002
  1.0000    0.430669760236151    0.430668131955269