Python 尝试在PyOpenCL中实现三维波动方程时遇到困难

Python 尝试在PyOpenCL中实现三维波动方程时遇到困难,python,opencl,physics,pyopencl,Python,Opencl,Physics,Pyopencl,我试图在OpenCL中实现离散时间波动方程。我想我已经很接近了,但是结果看起来和我从热方程中所期望的一样。我知道它们非常相似,但当我不使用OpenCL实现2D波动方程时,我得到了不同的波前和反射。在OpenCL内核的下面,所有东西都会扩散,直到被清洗 __kernel void wave_calc( __global float* height, __global float* height_old, const unsigned int len_x, cons

我试图在OpenCL中实现离散时间波动方程。我想我已经很接近了,但是结果看起来和我从热方程中所期望的一样。我知道它们非常相似,但当我不使用OpenCL实现2D波动方程时,我得到了不同的波前和反射。在OpenCL内核的下面,所有东西都会扩散,直到被清洗

 __kernel void wave_calc(
    __global float* height,
    __global float* height_old,
    const unsigned int len_x,
    const unsigned int len_y,
    const unsigned int len_z,
    const float dtxc_term)
{

    unsigned int x = get_global_id(0);
    unsigned int y = get_global_id(1);
    unsigned int z = get_global_id(2);
    int this_cell = x + len_y * (y + len_x * z);
    float laplacian;

    if (x==0 || x==(len_x-1) || y==0 || y==(len_y-1) || z==0 || z==(len_z-1)) {
       laplacian = 0;
       height_old[this_cell]  = height[this_cell];
       height[this_cell] = 0;
    }

    else if ( x < len_x-1 && y < len_y-1 && z < len_z-1 ){
        int n1 = x - 1 + len_y * (y + len_x * z);
        int n2 = x + 1 + len_y * (y + len_x * z);
        int n3 = x + len_y * (y - 1 + len_x * z);
        int n4 = x + len_y * (y + 1 + len_x * z);
        int n5 = x + len_y * (y + len_x * (z -1));
        int n6 = x + len_y * (y + len_x * (z + 1));

        laplacian = -6 * height[this_cell] +
                                    height[n1] +
                                    height[n2] +
                                    height[n3] +
                                    height[n4] +
                                    height[n5] +
                                    height[n6];

        height_old[this_cell]  = height[this_cell];
        height[this_cell] = (dtxc_term*laplacian+2*height[this_cell]) - height_old[this_cell];

    }  
}
有什么想法/建议/居高临下的评论吗?如蒙惠顾,不胜感激

以下是回答Joel问题的更新:

当我谈到微积分时,我并不是很好,但是我在2D中采用了一个工作C++实现,并试图使它适应3D。下面是C++。我所做的唯一修改是循环,因为3D中有6个相邻单元,而不是4个。在这两种情况下,平面/立方体的外墙都设置为0:

for(int x=1; x<field.xRes()-1;x++) {
            for (int y=1; y<field.yRes()-1; y++) {

                    laplacian(x,y) = -4 * height(x,y) +
                    height(x-1,y) +
                    height(x+1,y) +
                    height(x,y-1) +
                    height(x,y+1);

            }
        }

const float dt = 0.001;
const float xLen = 1.0;
const float C = 1.0;
const float dx = xLen/xRes;

backup = height;
height = ((dt*dt)/(dx*dx))*C*laplacian+2*height;
height = height - heightOld;
heightOld = backup;

您尝试使用的数值方法是什么?您能否明确给出您尝试求解的方程是什么?在我看来,您的代码有很多数据竞争-您正在更新height[],而其他线程可能需要它。相反,您应该将新值计算到一个新数组中,然后在最后执行切换或复制。感谢Hristo的建议,我将实现它。嗨,Joel,我用更多信息更新了问题。方程是波动方程,在2D中有一个简单的实现,就像上面的C++示例中那样。在3D中,我开始意识到除了邻居的数量之外,可能还有更多的变化:哦,具体的模拟方法是FDTD:
for(int x=1; x<field.xRes()-1;x++) {
            for (int y=1; y<field.yRes()-1; y++) {

                    laplacian(x,y) = -4 * height(x,y) +
                    height(x-1,y) +
                    height(x+1,y) +
                    height(x,y-1) +
                    height(x,y+1);

            }
        }

const float dt = 0.001;
const float xLen = 1.0;
const float C = 1.0;
const float dx = xLen/xRes;

backup = height;
height = ((dt*dt)/(dx*dx))*C*laplacian+2*height;
height = height - heightOld;
heightOld = backup;