2016-01-21 2 views
2

У меня возникли проблемы с решателем complex_ode python.python complex_ode передают матричные параметры

Я пытаюсь решить следующее уравнение:

д/дт = -iAy - ICOS (Omegat) B у

, где А и В NxN массивы и неизвестное у есть Nx1, i - мнимая единица, а Omega - параметр.

Вот мой код:

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) 

Если вместо этого я использую решатель = ода (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__' 

, где я понял, что поплавок относится к параметру Omega [пробуя целое]. Опять же, «ода» в одиночку работает в этом случае.

Последних , Я пробовал одно и то же комплекснозначное уравнение, но теперь A и B являются просто числами. Я попытался передать их как параметры, т. Е. Params = [Omega, A, B], как хорошо l как сделать их глобальными переменными, в этом случае params = [Omega]. Ошибка:

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

ошибка - полная ошибка такая же, как указано выше. И снова эта проблема не возникает для вещественной «оды».

Я знаю, что zvode является альтернативой, но он кажется довольно медленным для больших N. В реальной задаче у меня есть A - диагональная матрица, но B - не разреженная полная матрица.

Любые идеи очень ценятся! Меня интересуют как (i) альтернативные способы решения этого комплекснозначного ОДУ с параметрами массива, так и (ii) как запускать complex_ode :)

Спасибо!

+0

Можете ли вы показать нам полную трассу, пожалуйста? «TypeError» похоже на [здесь] (https://stackoverflow.com/questions/34577870/using-scipy-integrate-complex-ode-instead-of-scipy-integrate-ode). Короче говоря, не используйте 'set_f_params()' с 'complex_ode()'. Для решения сложных ОДУ вы также можете использовать 'zvode()'. Это позаботится о проблеме номер 2. – Reti43

+0

Я обновил сообщение, отображающее полное сообщение об ошибке в обоих случаях. Я знаю zvode, но это медленный процесс, когда размер матрицы становится большим. Или вы имеете в виду, что есть способ комбинировать complex_ode() и zvode только для передачи параметров? –

+0

Это ошибка, хорошо.Если вы напечатаете значения, переданные в '_wrap()', вы увидите, что все они искалечены, если вы использовали 'set_f_params()' или модифицировали 'solver.params' самостоятельно (это то, что' set_f_params () 'делает внутренне). Итак, где вы должны быть режущими массивами в '_wrap()', вы получаете float, следовательно, 'TypeError'. Нет, нет объединения двух интеграторов, вы просто используете 'zvode' от get go. Почему интегратор не должен замедляться, когда матрица становится больше? Если матрицы должны содержать неизвестные параметры, их число увеличивается на 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()'. Если вы ответите на мой вопрос, являются ли 'Omega',' A' и 'B' постоянными параметрами, мы можем разрешить это как дубликат. Связываясь с другим вопросом, будущие читатели смогут увидеть решение, не размещая здесь дубликат. – Reti43

+0

Да, Omega, A и B a t-independent. Я думаю, что это дубликат, поэтому его можно удалить. –

+0

Не удаляйте вопрос. Дубликаты полезны, потому что они эффективно вводят больше ключевых слов, которые люди могут использовать в своем поиске, чтобы наткнуться на исходный вопрос/ответ. – Reti43

Смежные вопросы