简体   繁体   English

在固定网格上求解常微分方程(最好在python中)

[英]Solving an ordinary differential equation on a fixed grid (preferably in python)

I have a differential equation of the form 我有一个形式的微分方程

dy(x)/dx = f(y,x)

that I would like to solve for y . 我想解决y

I have an array xs containing all of the values of x for which I need ys . 我有一个数组xs其中包含需要ysx所有值。

For only those values of x , I can evaluate f(y,x) for any y . 仅对于x那些值,我可以对任何yf(y,x)

How can I solve for ys , preferably in python? 如何解决ys ,最好在python中解决?

MWE MWE

import numpy as np

# these are the only x values that are legal
xs = np.array([0.15, 0.383, 0.99, 1.0001])

# some made up function --- I don't actually have an analytic form like this
def f(y, x):
    if not np.any(np.isclose(x, xs)):
        return np.nan
    return np.sin(y + x**2) 

# now I want to know which array of ys satisfies dy(x)/dx = f(y,x)

Assuming you can use something simple like Forward Euler... 假设您可以使用简单的东西,例如Forward Euler ...

Numerical solutions will rely on approximate solutions at previous times. 数值解将依赖以前的近似解。 So if you want a solution at t = 1 it is likely you will need the approximate solution at t<1 . 因此,如果您想要在t = 1处有一个解,则可能需要在t<1处有一个近似解。

My advice is to figure out what step size will allow you to hit the times you need, and then find the approximate solution on an interval containing those times. 我的建议是找出允许您达到所需时间的步长,然后在包含这些时间的时间间隔内找到大概的解决方案。

import numpy as np

#from your example, smallest step size required to hit all would be 0.0001.

a = 0 #start point
b = 1.5 #possible end point
h = 0.0001
N = float(b-a)/h

y = np.zeros(n)
t = np.linspace(a,b,n)
y[0] = 0.1 #initial condition here

for i in range(1,n):
   y[i] = y[i-1] + h*f(t[i-1],y[i-1])

Alternatively, you could use an adaptive step method (which I am not prepared to explain right now) to take larger steps between the times you need. 另外,您可以使用自适应步进方法(我现在不准备解释)在需要的时间之间采取更大的步骤。

Or, you could find an approximate solution over an interval using a coarser mesh and interpolate the solution. 或者,您可以使用较粗的网格在一定间隔内找到一个近似解,然后对该解进行插值。

Any of these should work. 这些都应该起作用。

I think you should first solve ODE on a regular grid, and then interpolate solution on your fixed grid. 我认为您应该首先在常规网格上求解ODE,然后在固定网格上插值解决方案。 The approximate code for your problem 您问题的大概代码

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

xs = np.array([0.15, 0.383, 0.99, 1.0001])

# dy/dx = f(x,y)
def dy_dx(y, x):
    return np.sin(y + x ** 2)

y0 = 0.0 # init condition
x = np.linspace(0, 10, 200)# here you can control an accuracy
sol = odeint(dy_dx, y0, x)
f = interpolate.interp1d(x, np.ravel(sol))
ys = f(xs)

But dy_dx(y, x) should always return something reasonable (not np.none). 但是dy_dx(y,x)应该总是返回合理的值(而不是np.none)。 Here is the drawing for this case 这是这种情况的图 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM