簡體   English   中英

在python中實現Euler方法求解ODE

[英]Implementing Euler's Method in python to solve ODE

我正在做一個小科學項目,用ODE(常微分方程)模擬機械系統。

機械系統的微分方程

我想使用Euler方法來執行此操作,但是我相信我正在做一些工作,因為我創建的輸出數據圖不是應該的樣子,並且我100%確信方程本身是正確的 您能看一下我的代碼並告訴我我做錯了什么嗎? 此代碼會將CSV值輸出到控制台和output.csv文件中。

測試:

class Calculus:
    def __init__(self):
        print "object created"

    @staticmethod
    def euler(f,y0,a,b,h):
        """y0 - temperatura poczatkowa, a-chwila poczatkowa czasu(warunek brzegowy) , b-chwila koncowa, h - krok"""
        t,y = a,y0
        time = [t]
        value = [y]

        while t <= b:
            print "%6.3f,%6.3f" % (t,y)

            t += h
            y += h * f(t,y, h, value)
            time.append(t)
            value.append(y)

        data = {'time' : time, 'value' : value}
        return data

class Mechanical_system:
    #Constructor
    def __init__(self, momentum1, momentum2, b1, b2, N1, N2, w1, Tau, k):
        self.system_parameters = {'momentum1': momentum1, 'momentum2': momentum2,
                                               'b1': b1, 'b2' : b2, 
                                               'N1': N1, 'N2' : N2, 
                                               'w1' : w1,
                                               'Tau' : Tau,
                                               'k' : k};

    def ODE(self, time, w, h, value):
        """ODE - ordinary differential equation describing our system"""

        #first calculation will only have one value in the list, so we can't calculate delt_value = current - last
        #thus, we need to assume that if there is no penault value (index error) let penault = 0
        try:
            penault = value[len(value) -2]
        except IndexError:
            penault = 0


        momentum1 = self.system_parameters['momentum1']
        momentum2 = self.system_parameters['momentum2']
        b1 =        self.system_parameters['b1']
        b2 =        self.system_parameters['b2']
        N1 =        self.system_parameters['N1']
        N2 =        self.system_parameters['N2']
        Tau =       self.system_parameters['Tau']
        k =         self.system_parameters['k']

        dOmega = w - penault
        dt = h
        Omega = float(dOmega) / float(dt)

        return (1.0 / (momentum1 + ((N1/N2)**2)*momentum2))*(Tau - (Omega)*(b1 + ((N1/N2)**2)*b2) - w * ((N1/N2)**2)*k)

if __name__ == "__main__":
        """reads values from input boxes and then calculates the value and plot value(time)"""
        momentum1 = 1
        momentum2 = 2
        b1 =        0.5
        b2 =        0.6
        N1 =        10
        N2 =        20
        a =         0
        b =         100
        h =         0.1
        w1 =        0
        Tau =       100
        k =         0.5

        system1 = Mechanical_system(momentum1, momentum2, b1, b2, N1, N2, w1, Tau, k)
        data = Calculus.euler(system1.ODE, w1, a, b, h)

        ##writing output to CSV file
        f = open('output.csv', 'w')
        for index in range(len(data['time'])):
            f.write("%s,%s\n" % (data['time'][index], data['value'][index]))

        f.close()

        del system1
        del data

在機械系統中使用Euler通常是個壞主意。 探索該陳述最簡單的測試案例是簡單的振盪器x''+x=0 ,您會發現系統的能量迅速增長。

對於一般的機械系統,您有一個運動方程m*x'' = F(t,x,x') 這為您提供了矢量值系統

def f(t,y):
    x,v = y
    return [ v; 1/m*F(t,x,v) ]

請注意,系統功能中沒有hdt 這對於ODE及其數值處理至關重要。 軌跡遵循的方向場不取決於數值解法的細節。

因此,請在相空間中將您的方程式重構為二階方程式或一階系統。


我認為您的方程式旨在

F(x,v) = Tau - (b1 + ((N1/N2)**2)*b2) * v -  ((N1/N2)**2)*k * x

有質量

m = momentum1 + ((N1/N2)**2)*momentum2

或其某些縮放版本。 所以某種彈簧在重力和摩擦力作用下。 如果是這樣,那么您就將物理系統的加速度視為數值實現中的速度。 這只能給出毫無意義的結果。


剝離這些類,可以像這樣反映系統的第二順序:

def euler(f,y0,v0,a,b,h):
    t,y,v = a,y0,v0
    time = [t]
    value = [y]

    while t <= b:
        print "%6.3f,%6.3f" % (t,y)
        accel =  f(t,y,v)
        t += h
        y += h * v
        v += h*accel
        time.append(t)
        value.append(y)

    data = {'time' : time, 'value' : value}
    return data

def ODE(t,y,v,param):
    momentum1, momentum2, b1, b2, N1, N2, Tau, k = param
    mass = momentum1 + ((N1/N2)**2)*momentum2
    force = Tau - v*(b1 + ((N1/N2)**2)*b2) - y * ((N1/N2)**2)*k
    return force/mass


momentum1 = 1
momentum2 = 2
b1 =        0.5
b2 =        0.6
N1 =        10.
N2 =        20.
Tau =       100
k =         0.5    
a =         0
b =         100
h =         0.1
y0 =        0
v0 =        0

params = [momentum1, momentum2, b1, b2, N1, N2, Tau, k]
data = euler(lambda t,y,v: ODE(t,y,v,params),y0,v0,a,b,h)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM