简体   繁体   English

了解Matlab中的DEL2函数以便在C ++中进行编码

[英]Understanding DEL2 function in Matlab in order to code it in C++

in order to code the DEL2 matlab function in c++ I need to understand the algorithm. 为了用C ++编写DEL2 matlab函数的代码,我需要了解算法。 I've managed to code the function for elements of the matrix that are not on the borders or the edges. 我设法为不在边界或边缘上的矩阵元素编码函数。 I've seen several topics about it and read the MATLAB code by typing "edit del2" or "type del2" but I don't understand the calculations that are made to obtain the borders and the edges. 我已经看过几个相关的主题,并通过键入“ edit del2”或“ type del2”来阅读MATLAB代码,但我不理解为获得边界和边缘而进行的计算。

Any help would be appreciated, thanks. 任何帮助,将不胜感激,谢谢。

You want to approximate u'' knowing only the value of u on the right (or the left) of a point. 您想只知道点右侧(或左侧)的u值来近似u''。 In order to have a second order approximation, you need 3 equations (basic taylor expansion): 为了获得二阶近似,您需要3个方程式(基本泰勒展开式):

u(i+1) = u(i) + hu' + (1/2) h^2 u'' + (1/6) h^3 u''' + O(h^4) u(i + 1)= u(i)+ hu'+(1/2)h ^ 2 u''+(1/6)h ^ 3 u'''+ O(h ^ 4)

u(i+2) = u(i) + 2 hu' + (4/2) h^2 u'' + (8/6) h^3 u''' + O(h^4) u(i + 2)= u(i)+ 2 hu'+(4/2)h ^ 2 u''+(8/6)h ^ 3 u'''+ O(h ^ 4)

u(i+3) = u(i) + 3 hu' + (9/2) h^2 u'' + (27/6) h^3 u''' + O(h^4) u(i + 3)= u(i)+ 3 hu'+(9/2)h ^ 2 u''+(27/6)h ^ 3 u'''+ O(h ^ 4)

Solving for u'' gives (1) : 解决u''得到(1)

h^2 u'' = -5 u(i+1) + 4 u(i+2) - u(i+3) + 2 u(i) +O(h^4) h ^ 2 u''= -5 u(i + 1)+ 4 u(i + 2)-u(i + 3)+ 2 u(i)+ O(h ^ 4)

To get the laplacian you need to replace the traditional formula with this one on the borders. 要获得拉普拉斯算式,您需要在边界上用此公式代替传统公式。

For example where "i = 0" you'll have: 例如,在“ i = 0”的情况下,您将拥有:

del2(u) (i=0,j) = [-5 u(i+1,j) + 4 u(i+2,j) - u(i+3,j) + 2 u(i,j) + u(i,j+1) + u(i,j-1) - 2u(i,j) ]/h^2 del2(u)(i = 0,j)= [-5 u(i + 1,j)+ 4 u(i + 2,j)-u(i + 3,j)+ 2 u(i,j) + u(i,j + 1)+ u(i,j-1)-2u(i,j)] / h ^ 2

EDIT clarifications: 编辑说明:

The laplacian is the sum of the 2nd derivatives in the x and in the y directions. 拉普拉斯算子是x和y方向上的二阶导数之和。 You can calculate the second derivative with the formula (2) 您可以使用公式(2)计算二阶导数

u'' = (u(i+1) + u(i-1) - 2u(i))/h^2 u''=(u(i + 1)+ u(i-1)-2u(i))/ h ^ 2

if you have both u(i+1) and u(i-1). 如果您同时拥有u(i + 1)和u(i-1)。 If i=0 or i=imax you can use the first formula I wrote to compute the derivatives (notice that due to the simmetry of the 2nd derivative, if i = imax you can just replace "i+k" with "ik"). 如果i = 0或i = imax,则可以使用我编写的第一个公式来计算导数(请注意,由于二阶导数的模拟,如果i = imax,则可以将“ i + k”替换为“ ik”) 。 The same applies for the y (j) direction: y(j)方向也是如此:

On the edges you can mix up the formulas (1) and (2) : 在边缘,您可以混合公式(1)(2)

del2(u) (i=imax,j) = [-5 u(i-1,j) + 4 u(i-2,j) - u(i-3,j) + 2 u(i,j) + u(i,j+1) + u(i,j-1) - 2u(i,j) ]/h^2 del2(u)(i = imax,j)= [-5 u(i-1,j)+ 4 u(i-2,j)-u(i-3,j)+ 2 u(i,j) + u(i,j + 1)+ u(i,j-1)-2u(i,j)] / h ^ 2

del2(u) (i,j=0) = [-5 u(i,j+1) + 4 u(i,j+2) - u(i,j+3) + 2 u(i,j) + u(i+1,j) + u(i-1,j) - 2u(i,j) ]/h^2 del2(u)(i,j = 0)= [-5 u(i,j + 1)+ 4 u(i,j + 2)-u(i,j + 3)+ 2 u(i,j) + u(i + 1,j)+ u(i-1,j)-2u(i,j)] / h ^ 2

del2(u) (i,j=jmax) = [-5 u(i,j-1) + 4 u(i,j-2) - u(i,j-3) + 2 u(i,j) + u(i+1,j) + u(i-1,j) - 2u(i,j) ]/h^2 del2(u)(i,j = jmax)= [-5 u(i,j-1)+ 4 u(i,j-2)-u(i,j-3)+ 2 u(i,j) + u(i + 1,j)+ u(i-1,j)-2u(i,j)] / h ^ 2

And on the corners you'll just use (1) two times for both directions. 而且在拐角处,您只需在两个方向上两次使用(1)

del2(u) (i=0,j=0) = [-5 u(i,j+1) + 4 u(i,j+2) - u(i,j+3) + 2 u(i,j) + -5 u(i,j+1) + 4 u(i+2,j) - u(i+3,j) + 2 u(i,j)]/h^2 del2(u)(i = 0,j = 0)= [-5 u(i,j + 1)+ 4 u(i,j + 2)-u(i,j + 3)+ 2 u(i, j)+ -5 u(i,j + 1)+ 4 u(i + 2,j)-u(i + 3,j)+ 2 u(i,j)] / h ^ 2

Del2 is the 2nd order discrete laplacian, ie it permits to approximate the laplacian of a real continuous function given its values on a square cartesian grid NxN where the distance between two adjacent nodes is h . DEL2是第二阶离散拉普拉斯,即,它允许以接近在正方形笛卡尔网格的N×N,其中的两个相邻节点之间的距离为h给定其值的真实连续函数的拉普拉斯算子。

h^2 is just a constant dimensional-factor, you can get the matlab implementation from these formulas by setting h^2 = 4. h ^ 2只是一个恒定的尺寸因数,您可以通过设置h ^ 2 = 4从这些公式中获得matlab实现。

For example, if you want to compute the real laplacian of u(x,y) on the (0,L) x (0,L) square, what you do is writing down the values of this function on an NxN cartesian grid, ie you calculate u(0,0), u(L/(N-1),0), u(2L/(N-1),0) ... u( (N-1)L/(N-1) =L,0) ... u(0,L/(N-1)), u(L/(N-1),L/(N-1)) etc. and you put down these N^2 values in a matrix A. 例如,如果您要在(0,L)x(0,L)平方上计算u(x,y)的真实拉普拉斯算子,您要做的就是在NxN笛卡尔网格上写下该函数的值,即您计算u(0,0),u(L /(N-1),0),u(2L /(N-1),0)... u((N-1)L /(N- 1)= L,0)... u(0,L /(N-1)),u(L /(N-1),L /(N-1))等,然后放下这些N ^矩阵A中的2个值。

Then you'll have ans = 4*del2(A)/h^2, where h = L/(N-1). 那么您将获得ans = 4 * del2(A)/ h ^ 2,其中h = L /(N-1)。

del2 will return the exact value of the continuous laplacian if your starting function is linear or quadratic (x^2+y^2 fine, x^3 + y^3 not fine). 如果您的起始函数是线性或二次函数(x ^ 2 + y ^ 2很好,x ^ 3 + y ^ 3不好),则del2将返回连续拉普拉斯算术值。 If the function is not linear nor quadratic, the result will be more accurate the more points you use (ie in the limit h -> 0) 如果该函数既不是线性函数也不是二次函数,则使用的点数越多,结果将越准确(即在h-> 0的范围内)

I hope this is more clear, notice that i used 0-based indices for accessing matrix (C/C++ array style), while matlab uses 1-based. 我希望这更加清楚,请注意,我使用基于0的索引来访问矩阵(C / C ++数组样式),而matlab使用基于1的索引。

DEL2 in MatLab represents Discrete Laplace operator, you can find some information about it here . MatLab中的DEL2代表离散Laplace运算符,您可以在此处找到有关它的一些信息。

The main thing about the edges is that elements in the interior of the matrix have four neighbors, while elements on the edges and corners have three or two neighbors respectfully. 关于边缘的主要问题是矩阵内部的元素具有四个相邻元素,而边缘和角上的元素则分别具有三个或两个相邻元素。 So you calculate the corners and edges the same way, but using less elements. 因此,您可以用相同的方式计算拐角和边,但使用的元素更少。

Here is a module I wrote in Fortran 90 that replicates the "del2()" operator in MATLAB implementing the above ideas. 这是我在Fortran 90中编写的模块,该模块复制了实现上述思想的MATLAB中的“ del2()”运算符。 It only works for arrays that that are atleast 4x4 or larger. 它仅适用于至少4x4或更大的阵列。 It works successfully when I run it so I thought I would post it so that other people dont have to waste time making their own. 当我运行它时,它可以成功运行,所以我认为我可以发布它,这样其他人就不必浪费时间自己制作。

module del2_mod
implicit none
real, private                       :: pi
integer, private                    :: nr, nc, i, j, k
contains
! nr is number of rows in array, while nc is the number of columns in the array.
!!---------------------------------------------------------- 

subroutine del2(in, out)
real, dimension(:,:)            :: in, out
real, dimension(nr,nc)          :: interior, left, right, top, bottom, ul_corner, br_corner, disp
integer                         :: i, j
real                            :: h, ul, ur, bl, br
! Zero out internal arrays
out = 0.0; interior=0.0; left = 0.0;  right = 0.0;  top = 0.0;  bottom = 0.0;  ul_corner = 0.0; br_corner = 0.0;
h=2.0

! Interior Points
do j=1,nc
    do i=1,nr
    ! Interior Point Calculations
    if( j>1 .and. j<nc .and. i>1 .and. i<nr )then
        interior(i,j) = ((in(i-1,j) + in(i+1,j) + in(i,j-1) + in(i,j+1)) - 4*in(i,j) )/(h**2)
    end if
    ! Boundary Conditions for Left and Right edges
    left(i,1) = (-5.0*in(i,2) + 4.0*in(i,3) - in(i,4) + 2.0*in(i,1) + in(i+1,1) + in(i-1,1) - 2.0*in(i,1) )/(h**2)
    right(i,nc) = (-5.0*in(i,nc-1) + 4.0*in(i,nc-2) - in(i,nc-3) + 2.0*in(i,nc) + in(i+1,nc) + in(i-1,nc) - 2.0*in(i,nc) )/(h**2)
    end do
! Boundary Conditions for Top and Bottom edges
top(1,j) = (-5.0*in(2,j) + 4.0*in(3,j) - in(4,j) + 2.0*in(1,j) + in(1,j+1) + in(1,j-1) - 2.0*in(1,j) )/(h**2)
bottom(nr,j) = (-5.0*in(nr-1,j) + 4.0*in(nr-2,j) - in(nr-3,j) + 2.0*in(nr,j) + in(nr,j+1) + in(nr,j-1) - 2.0*in(nr,j) )/(h**2)
end do
out = interior + left + right + top + bottom 
! Calculate BC for the corners
ul = (-5.0*in(1,2) + 4.0*in(1,3) - in(1,4) + 2.0*in(1,1) - 5.0*in(2,1) + 4.0*in(3,1) - in(4,1) + 2.0*in(1,1))/(h**2)
br = (-5.0*in(nr,nc-1) + 4.0*in(nr,nc-2) - in(nr,nc-3) + 2.0*in(nr,nc) - 5.0*in(nr-1,nc) + 4.0*in(nr-2,nc) - in(nr-3,nc) + 2.0*in(nr,nc))/(h**2)
bl = (-5.0*in(nr,2) + 4.0*in(nr,3) - in(nr,4) + 2.0*in(nr,1) - 5.0*in(nr-1,1) + 4.0*in(nr-2,1) - in(nr-3,1) + 2.0*in(nr,1))/(h**2)
ur = (-5.0*in(1,nc-1) + 4.0*in(1,nc-2) - in(1,nc-3) + 2.0*in(1,nc) - 5.0*in(2,nc) + 4.0*in(3,nc) - in(4,nc) + 2.0*in(1,nc))/(h**2)
! Apply BC for the corners
out(1,1)=ul
out(1,nc)=ur
out(nr,1)=bl
out(nr,nc)=br
end subroutine

end module

It's so hard! 它是如此艰苦! I wasted a few hours to understand and implement it in Java. 我浪费了几个小时来理解和实现Java。

Here is: https://gist.github.com/emersonmoretto/dec8f7125c032775da0d 这是: https : //gist.github.com/emersonmoretto/dec8f7125c032775da0d

Tested and compared to the original function DEL2 (Matlab) 经过测试并与原始功能DEL2(Matlab)进行了比较

I've found a typo in sbabbi response: 我在sbabbi回应中发现了一个错字:

del2(u) (i=0,j=0) = [-5 u(i,j+1) + 4 u(i,j+2) - u(i,j+3) + 2 u(i,j) + -5 u(i,j+1) + 4 u(i+2,j) - u(i+3,j) + 2 u(i,j)]/h^2

is

del2(u) (i=0,j=0) = [-5 u(i,j+1) + 4 u(i,j+2) - u(i,j+3) + 2 u(i,j) + -5 u(i+1,j) + 4 u(i+2,j) - u(i+3,j) + 2 u(i,j)]/h^2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM