簡體   English   中英

將代碼從Matlab轉換為python,出現問題

[英]Convert code from matlab to python, problems occurred

我發現了用matlab編寫的向后Euler的實現, 這里計算步長的方程為:

function [t,y]=beul(f,df,y0,t0,tf,n)
h=(tf-t0)/n;
t=linspace(t0,tf,n+1);
y=zeros(n+1,length(y0));
y(1,:)=y0;
for i=1:n
    x0=y(i,:)’;
    x1=x0-inv(eye(length(y0))-h*feval(df,t(i),x0))*(x0-h*feval(f,t(i),x0)’-y(i,:)’);
    while (norm(x1-x0)>0.0001)
      x0=x1;
      x1=x0-inv(eye(length(y0))-h*feval(df,t(i),x0))*(x0-h*feval(f,t(i),x0)’-y(i,:)’);
    end
    y(i+1,:)=x1’;
end
end

然后將此函數稱為函數和jacobian的定義系統:

function yp=volt(t,y)
a=4;
c=1;
yp(1)=a*(y(1)-y(1)*y(2));
yp(2)=-c*(y(2)-y(1)*y(2));
end

function y=dvol(t,x)
a=4;
c=1;
y(1,1)=a*(1-x(2));
y(1,2)=-a*x(1);
y(2,1)=c*x(2);
y(2,2)=-c*(1-x(1));

后向歐拉稱為:

[t,y]=beul(’volt’,’dvol’,[2,1],0,10,1000);

我已經翻譯了python中的代碼:

class Backward(Euler):
    def solve(self):
        for i in range(len(self.time)-1):
          u0 = self.u[i].T 

          u1 = u0 - np.linalg.inv(np.eye(len(self.dydt.u0)) - self.dt * self.dydt.df(self.time[i+1],u0)) * (u0 - self.dt * self.dydt.f(self.time[i+1], u0).T - self.u[i].T )

          error = np.array([1.0])
          iters = 0
          while True:
              try:  
                 u0 = u1.T
                 u1 = u0 - np.linalg.inv(np.eye(len(self.dydt.u0)) - self.dt * self.dydt.df(self.time[i+1],u0)) * (u0 - self.dt * self.dydt.f(self.time[i+1], u0).T - self.u[i].T )

                 iters += 1
                 error = np.abs(u1-u0)

                 if np.sum(np.abs(error)) <= toll:
                     break
             except ValueError as ex:
             print('Error occurred in Implicit-NR Euler Solvers: %s' %ex.args)
             return None , None
      self.u[i+1] = u1.T

然后我將jacobian矩陣定義如下:

   def f(self,ti,ui):
       return  np.array([function(ti,ui) for function in self.func])     
   def df(self, t, u, **params):

      eps = 1e-12
      J = np.zeros([len(u), len(u)], dtype = np.float)

      for i in range(len(u)):
          u1 = u.copy()
          u2 = u.copy()

          u1[i] += eps
          u2[i] -= eps

          f1 = self.f(t, u1, **params)
          f2 = self.f(t, u2, **params)

          J[ : , i] = (f1 - f2) / (2 * eps)

      return J

如果我嘗試運行單個方程式問題,則方法效果很好(我已與其他求解器進行了比較)

但是問題是matlab產品的行為有所不同! 所以我不知道如何在python中將產品固定為相同的,因為當我為系統運行代碼時(例如,由matlab解決的相同)

eq1 = lambda t,u : a*(u[0]-u[0]*u[1]);
eq2 = lambda t,u : -c*(u[1]-u[0]*u[1]);

func1 = np.array([eq1,eq2])

y0      = np.array([2.,1.])

我收到此錯誤:

Running Newton-Rapson Backward Euler ....
Error occurred in Implicit-NR Euler Solvers: could not broadcast input array from shape (2,2) into shape (2)

所以我該如何定義與matlab計算相同的產品(它的df也是2x2矩陣)以修復python的方法?

解決了使用numpy.dot產品:

u1 = u0 - np.linalg.inv(np.eye(len(self.dydt.u0)) - self.dt * self.dydt.df(self.time[i+1],u0)).dot(u0 - self.dt * self.dydt.f(self.time[i+1], u0).T - self.u[i].T )

暫無
暫無

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

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