2016-01-21 126 views
2

我遇到一些麻煩python的complex_ode求解。蟒蛇complex_ode通矩陣值參數

我試圖解決以下等式:

DY/DT = -iAy - ICOS(Omegat)ý

其中A和B是N×N個陣列和未知y是Nx1陣列,i是虛數單位,Ω是參數。

這裏是我的代碼:

import numpy as np 
from scipy.integrate import ode,complex_ode 


N = 3 #linear matrix dim 
Omega = 1.0 #parameter 

# define symmetric matrices A and B 
A = np.random.ranf((N,N)) 
A = (A + A.T)/2.0 

B = np.random.ranf((N,N)) 
B = (B + B.T)/2.0 

# define RHS of ODE 
def f(t,y,Omega,A,B): 
    return -1j*A.dot(y)-1j*np.cos(Omega*t)*B.dot(y) 

# define list of parameter 
params=[Omega,A,B] 

# choose solver: need complex_ode for this ODE 
#solver = ode(f) 
solver = complex_ode(f) 
solver.set_f_params(*params) 
solver.set_integrator("dop853") 
# set initial value 
v0 = np.zeros((N,),dtype=np.float64) 
v0[0] = 1.0 

# check that the function f works properly 
print f(0,v0,Omega,A,B) 

# solve-check the ODE 
solver.set_initial_value(v0) 
solver.integrate(10.0) 

print solver.successful() 

運行此腳本將產生錯誤

capi_return is NULL 
Call-back cb_fcn_in___user__routines failed. 
Traceback (most recent call last): 
File "ode_test.py", line 37, in <module> 
    solver.integrate(10.0) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 515, in integrate 
y = ode.integrate(self, t, step, relax) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 388, in integrate 
self.f_params, self.jac_params) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 946, in run 
tuple(self.call_args) + (f_params,))) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 472, in _wrap 
f = self.cf(*((t, y[::2] + 1j * y[1::2]) + f_args)) 
TypeError: f() takes exactly 5 arguments (2 given) 

相反,如果我用求解= ODE(F),即。實值解算器,它運行良好。除了它不解決ODE我想要哪個是複數值:(

然後我嘗試通過使矩陣A和B全局變量來減少參數的數量。這樣,函數f接受的唯一參數是歐米茄,錯誤修改

capi_return is NULL 
Call-back cb_fcn_in___user__routines failed. 
Traceback (most recent call last): 
File "ode_test.py", line 37, in <module> 
solver.integrate(10.0) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 515, in integrate 
y = ode.integrate(self, t, step, relax) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 388, in integrate 
self.f_params, self.jac_params) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 946, in run 
tuple(self.call_args) + (f_params,))) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 472, in _wrap 
f = self.cf(*((t, y[::2] + 1j * y[1::2]) + f_args)) 
TypeError: 'float' object has no attribute '__getitem__' 

,我想通了,浮指參數歐米茄[試圖通過一個整數。同樣,在這種情況下,「頌」單獨的作品也是如此。

末,我試圖值方程相同的配合物,但現在A和B僅僅是數字。我試圖他們兩個作爲參數傳遞,即PARAMS =ω,A,B]爲WEL l使它們成爲全局變量,在這種情況下,params =Ω。錯誤是

TypeError: 'float' object has no attribute '__getitem__' 

錯誤 - 完整的錯誤是與上面相同。再次,這個問題對於實值「頌歌」不會發生。

我知道zvode是一種選擇,但它似乎成爲大N.在真正的問題我已經很慢,A是對角矩陣,但B是一個非稀疏全矩陣。

任何見解都非常感謝!我在(我)的替代方法來解決與數組值參數此復值ODE都感興趣,並且(ii)如何獲得complex_ode運行:)

謝謝!

+0

,你能否告訴我們完整的追蹤嗎? TypeError似乎和[here]一樣(https://stackoverflow.com/questions/34577870/using-scipy-integrate-complex-ode-instead-of-scipy-integrate-ode)。簡而言之,不要在'complex_ode()'中使用'set_f_params()'。爲了解決複雜的ODE,你也可以使用'zvode()'。這照顧到問題編號2. – Reti43

+0

我更新了顯示完整錯誤消息的帖子。我知道zvode,但是當矩陣大小變大時它有點慢。或者你是否意味着有一種方法可以結合complex_ode()和zvode來傳遞參數? –

+0

這就是bug,沒關係。如果你打印在'_wrap()'中傳遞的值,你會發現如果你自己使用了'set_f_params()'或者修改了'solver.params',那麼它們都會被損壞(這就是'set_f_params )'在內部)。所以你應該在'_wrap()'中切分數組,所以你最終得到了浮點數,因此是'TypeError'。不,沒有兩個集成商結合在一起,你只需從頭開始使用'zvode'。爲什麼矩陣變大時積分器不能變慢?如果矩陣應該保持未知參數,則它們的數量增加N ** 2。 – Reti43

回答

0

這似乎是鏈接Reti43發佈包含了答案,所以讓我把它放在這裏爲未來用戶的利益:

from scipy.integrate import complex_ode 
import numpy as np 

N = 3 
Omega = 1.0; 

class myfuncs(object): 
    def __init__(self, f, fargs=[]): 
     self._f = f 
     self.fargs=fargs 

    def f(self, t, y): 
     return self._f(t, y, *self.fargs) 

def f(t, y, Omega,A,B): 
    return -1j*(A+np.cos(Omega*t)*B).dot(y)  


A = np.random.ranf((N,N)) 
A = (A + A.T)/2.0 

B = np.random.ranf((N,N)) 
B = (B + B.T)/2.0 

v0 = np.zeros((N,),dtype=np.float64) 
v0[0] = 1.0 

t0 = 0 

case = myfuncs(f, fargs=[Omega, A, B]) 
solver = complex_ode(case.f) 
solver.set_initial_value(v0, t0) 

solver.integrate([10.0]) 

print solver.successful() 

""" 
t1 = 10 
dt = 1 
while solver.successful() and solver.t < t1: 
    solver.integrate(solver.t+dt) 
    print(solver.t, solver.y) 

""" 

莫非爲什麼這招沒有工作也許有人對此有何評論?

+0

請參閱我上面關於僅將't'和'y'的函數傳遞給'complex_ode()'的註釋。如果您回答我的問題,「歐米茄」,「A」和「B」是否爲常數參數,那麼我們可以將其作爲重複來解決。通過鏈接到另一個問題,未來的讀者將能夠看到解決方案,而無需在此重複發佈。 – Reti43

+0

是的,Omega,A和B是一個t獨立的。我認爲這是重複的,所以可以刪除。 –

+0

不要刪除問題。重複是很有用的,因爲它們有效地引入了更多的關鍵字,人們可以在搜索中使用它們來偶然發現原始問題/答案。 – Reti43