2014-11-16 58 views
0

好的,我是新來的swig。我終於用swig和numpy.i成功地包裝了我的python程序中最昂貴的部分。該程序是2D波PDE的有限差分格式。我的問題是我現在如何使用它?在IPython中導入後我可以看到它。如何使用我在Python中使用swig生成的包裝函數?

In [1]: import wave2 

In [2]: wave2.wave_prop 
Out[2]: <function _wave2.wave_prop> 

但是,當我去使用它,我得到一個錯誤說:

TypeError: in method 'wave_prop', argument 1 of type 'float **' 

我怎樣才能改變我的2D numpy的陣列,以某種形式,使我用這個。還有另一個非常相似的stackoverflow,雖然我在這個過程中發現了很多關於這個問題的幫助。

這裏是標題:

void wave_prop(float** u_prev ,int Lx, int Ly,float** u ,int Lx2, int Ly2,float** u_next,int Lx3,int Ly3 ); 

這裏是C代碼:

#include<string.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<math.h> 

#define n 100 



void wave_prop(float** u_prev ,int Lx,int Ly,float** u ,int Lx2,int Ly2,float** u_next,int Lx3,int Ly3){ 

int dx=1; 
int dy=1; 
float c=1; 
float dt =1; 
int t_old=0;int t=0;int t_end=150; 
int x[Lx]; 
int y[Ly]; 

for(int i=0;i<=99;i++){ 
     x[i]=i; 
     y[i]=i; 
    } 


while(t<t_end){ 
    t_old=t; t +=dt; 
    //the wave steps through time 
    for (int i=1;i<99;i++){ 
     for (int j=1;j<99;j++){ 
       u_next[i][j] = - u_prev[i][j] + 2*u[i][j] + \ 
         (c*dt/dx)*(c*dt/dx)*u[i-1][j] - 2*u[i][j] + u[i+1][j] + \ 
       (c*dt/dx)*(c*dt/dx)*u[i][j-1] - 2*u[i][j] + u[i][j+1]; 
       } 
      } 

    //set boundary conditions to 0 

    for (int j=0;j<=99;j++){ u_next[0][j] = 0;} 
    for (int i=0;i<=99;i++){ u_next[i][0] = 0;} 
    for (int j=0;j<=99;j++){ u_next[Lx-1][j] = 0;} 
    for (int i=0;i<=99;i++){ u_next[i][Ly-1] = 0;} 

    //memcpy(dest, src, sizeof (mytype) * rows * coloumns); 
    memcpy(u_prev, u, sizeof (float) * Lx * Ly); 
    memcpy(u, u_next, sizeof (float) * Lx * Ly); 

    } 
} 

這裏是我的接口:

%module wave2 
%{ 
    #define SWIG_FILE_WITH_INIT 
    #include "wave2.h" 

%} 

%include "numpy.i" 

%init %{ 
    import_array(); 
%} 

%include "wave2.h" 
%apply (float** INPLACE_ARRAY2, int DIM1, int DIM2) { (float** u_prev,int Lx,int Ly),(float** u,int Lx2,int Ly2),(float* u_next,int Lx3,int Ly3)} 

這是我用來編譯命令和鏈接:

$ swig -python wave2.i 
$ gcc -c -fpic wave2.c wave2_wrap.c -I/usr/include/python2.7 -std=c99 
$ gcc -shared wave2.o wave2_wrap.o -o _wave2.so 

沒有任何錯誤或警告。在互聯網上缺乏像這樣的中間例子,相信我我已經搜遍了!,所以如果我們能夠得到這個工作,它可以作爲一個很好的教程。請不要標記我的問題,然後離開到夜晚。如果你覺得我的一些編碼需要改進,請讓我知道,我想現在基本上教我的一切......非常感謝你們的幫助

哦,也就是在這裏,我試圖用一個腳本它在我也曾嘗試使用內IPython的其他方面的功能...

'''George Lees Jr. 
2D Wave pde ''' 

from numpy import * 
import numpy as np 
import matplotlib.pyplot as plt 
from wave2 import * 
import wave2 

#declare variables 
#need 3 arrays u_prev is for previous time step due to d/dt 

Lx=Ly = (100) 
n=100 
dx=dy = 1 
x=y = np.array(xrange(Lx)) 
u_prev = np.array(zeros((Lx,Ly),float)) 
u = np.array(zeros((Lx,Ly),float)) 
u_next = np.array(zeros((Lx,Ly),float)) 
c = 1 #constant velocity 
dt = (1/float(c))*(1/sqrt(1/dx**2 + 1/dy**2)) 
t_old=0;t=0;t_end=150 

#set Initial Conditions and Boundary Points 
#I(x) is initial shape of the wave 
#f(x,t) is outside force that creates waves set =0 

def I(x,y): return exp(-(x-Lx/2.0)**2/2.0 -(y-Ly/2.0)**2/2.0) 
def f(x,t,y): return 0 

#set up initial wave shape 

for i in xrange(100): 
    for j in xrange(100): 
     u[i,j] = I(x[i],y[j]) 

#copy initial wave shape for printing later 

u1=u.copy() 

#set up previous time step array 

for i in xrange(1,99): 
    for j in xrange(1,99): 
      u_prev[i,j] = u[i,j] + 0.5*((c*dt/dx)**2)*(u[i-1,j] - 2*u[i,j] + u[i+1,j]) + \ 
      0.5*((c*dt/dy)**2)*(u[i,j-1] - 2*u[i,j] + u[i,j+1]) + \ 
      dt*dt*f(x[i], y[j], t) 

#set boundary conditions to 0 

for j in xrange(100): u_prev[0,j] = 0 
for i in xrange(100): u_prev[i,0] = 0 
for j in xrange(100): u_prev[Lx-1,j] = 0 
for i in xrange(100): u_prev[i,Ly-1] = 0 

wave2.wave_prop(u_prev ,Lx ,Ly , u , Lx, Ly, u_next,Lx,Ly) 

#while t<t_end: 
# t_old=t; t +=dt 
    #the wave steps through time 
# for i in xrange(1,99): 
#  for j in xrange(1,99): 
#    u_next[i,j] = - u_prev[i,j] + 2*u[i,j] + \ 
#      ((c*dt/dx)**2)*(u[i-1,j] - 2*u[i,j] + u[i+1,j]) + \ 
#    ((c*dt/dx)**2)*(u[i,j-1] - 2*u[i,j] + u[i,j+1]) + \ 
#      dt*dt*f(x[i], y[j], t_old) 
# 
# #set boundary conditions to 0 
# 
# for j in xrange(100): u_next[0,j] = 0 
# for i in xrange(100): u_next[i,0] = 0 
# for j in xrange(100): u_next[Lx-1,j] = 0 
# for i in xrange(100): u_next[i,Ly-1] = 0 

    #set prev time step equal to current one 
# u_prev = u.copy(); u = u_next.copy(); 

fig = plt.figure() 
plt.imshow(u,cmap=plt.cm.ocean) 
plt.colorbar() 
plt.show() 
print u_next 

而且是的,我檢查,以確保該陣列都numpy的第二數組類型

回答

0

好了,所以我是能夠在Cython中完成我想要的,感謝上帝。在這個過程中,我發現Cython更強大的工具!

所以結果是使用有限差分求解的2D波PDE。主計算已導出爲Cythonized函數。該函數需要三個2D np.ndarrays並返回一個。使用numpy和其他數據類型也更容易。

這裏是Cythonized功能:

from numpy import * 
cimport numpy as np 

def cwave_prop(np.ndarray[double,ndim=2] u_prev, np.ndarray[double,ndim=2] u, np.ndarray[double,ndim=2] u_next): 

    cdef double t = 0 
    cdef double t_old = 0 
    cdef double t_end = 100 
    cdef int i,j 
    cdef double c = 1 
    cdef double Lx = 100 
    cdef double Ly = 100 
    cdef double dx = 1 
    cdef double dy = 1 
    cdef double dt = (1/(c))*(1/(sqrt(1/dx**2 + 1/dy**2))) 

    while t<t_end: 
     t_old=t; t +=dt 

     #wave steps through time and space 

     for i in xrange(1,99): 
      for j in xrange(1,99): 
       u_next[i,j] = - u_prev[i,j] + 2*u[i,j] + \ 
         ((c*dt/dx)**2)*(u[i-1,j] - 2*u[i,j] + u[i+1,j]) + \ 
       ((c*dt/dx)**2)*(u[i,j-1] - 2*u[i,j] + u[i,j+1]) 

     #set boundary conditions of grid to 0 

     for j in xrange(100): u_next[0,j] = 0 
     for i in xrange(100): u_next[i,0] = 0 
     for j in xrange(100): u_next[Lx-1,j] = 0 
     for i in xrange(100): u_next[i,Ly-1] = 0 

     #set prev time step equal to current one 
     for i in xrange(100): 
      for j in xrange(100):  
       u_prev[i,j] = u[i,j]; 
       u[i,j] = u_next[i,j]; 



    print u_next 

這裏是調用了它,我的Python腳本,並使其返回然後繪製出結果。 任何關於編寫更好的代碼的建議,歡迎...

'''George Lees Jr. 
2D Wave pde ''' 

from numpy import * 
import numpy as np 
import matplotlib.pyplot as plt 
import cwave2 
np.set_printoptions(threshold=np.nan) 

#declare variables 
#need 3 arrays u_prev is for previous time step due to time derivative 

Lx=Ly = (100)      #Length of x and y dims of grid 
dx=dy = 1      #derivative of x and y respectively 
x=y = np.array(xrange(Lx))    #linspace to set the initial condition of wave 
u_prev=np.ndarray(shape=(Lx,Ly), dtype=np.double) #u_prev 2D grid for previous time step needed bc of time derivative 
u=np.ndarray(shape=(Lx,Ly), dtype=np.double)  #u 2D grid 
u_next=np.ndarray(shape=(Lx,Ly), dtype=np.double) #u_next for advancing the time step #also these are all numpy ndarrays 
c = 1       #setting constant velocity of the wave 
dt = (1/float(c))*(1/sqrt(1/dx**2 + 1/dy**2))  #we have to set dt specifically to this or numerical approx will fail! 
print dt 

#set Initial Conditions and Boundary Points 
#I(x) is initial shape of the wave 

def I(x,y): return exp(-(x-Lx/2.0)**2/2.0 -(y-Ly/2.0)**2/2.0) 

#set up initial wave shape 

for i in xrange(100): 
    for j in xrange(100): 
     u[i,j] = I(x[i],y[j]) 


#set up previous time step array 

for i in xrange(1,99): 
    for j in xrange(1,99): 
      u_prev[i,j] = u[i,j] + 0.5*((c*dt/dx)**2)*(u[i-1,j] - 2*u[i,j] + u[i+1,j]) + \ 
      0.5*((c*dt/dy)**2)*(u[i,j-1] - 2*u[i,j] + u[i,j+1]) 

#set boundary conditions to 0 

for j in xrange(100): u_prev[0,j] = 0 
for i in xrange(100): u_prev[i,0] = 0 
for j in xrange(100): u_prev[Lx-1,j] = 0 
for i in xrange(100): u_prev[i,Ly-1] = 0 

#call C function from Python 
cwave2.cwave_prop(u_prev , u , u_next) 
#returned u (2D np.ndarray) 

from tempfile import TemporaryFile 
outfile = TemporaryFile() 
np.save(outfile,u) 
fig = plt.figure() 
plt.imshow(u,cmap=plt.cm.ocean) 
plt.colorbar() 
plt.show() 
相關問題