在 MATLAB 中数值计算复值函数的导数
Numerically compute derivative of complex-valued function in MATLAB
我想在 MATLAB 中计算复值函数(全纯函数)的导数。
我计算了复平面上网格中的函数,并尝试使用柯西-黎曼关系计算导数。
鉴于:
u = real(f), v = imag(f), x = real(point), y = imag(point)
导数应为:f' = du/dx + i dv/dx = dv/dy - i du/dy
其中 'd' 是导数运算符。
我试过以下代码:
stepx = 0.01;
stepy = 0.01;
Nx = 2/stepx +1;
Ny = 2/stepy +1;
[re,im] = meshgrid([-1:stepx:1], [-1:stepy:1]);
cplx = re + 1i*im;
z = cplx.^3;
导数应为:
f1 = diff(real(z),1,2)/stepx +1i* diff(imag(z),1,2)/stepx;
或
f2 = diff(imag(z),1,1)/stepy - 1i* diff(real(z),1,1)/stepy;
但是这两个本应相等的导数却不匹配。
我做错了什么?
让我们计算差异小于 stepx 的元素的数量(假设 stepx = stepy):
lm = min(size(f1));
A = f1(1:lm,1:lm);
B = f2(1:lm,1:lm);
sum(sum(abs(A - B) <= stepx))
并使用@A 提出的修复。东达
f1i = interp1(1 : Ny, f1, 1.5 : Ny);
f2i = interp1(1 : Nx, f2 .', 1.5 : Nx) .';
sum(sum(abs(f1i - f2i) <= stepx))
在第二种情况下,它们的差异都小于应有的 stepx,而在第一种情况下,情况并非如此。
问题是使用两个不同的表达式,在 Matlab 中离散化使用,您正在计算复平面中不同点的近似导数。假设您处于虚值 y 并计算沿实轴 x 的差异,然后第 i 个差异估计 (x(i) + x(i + 1))/2
处的导数,即两个后续 x 值之间的所有中点。另一种方法是估计给定 x 处的导数,但在两个后续 y 值之间的所有中点处。
这也会导致生成的矩阵大小不同。使用第一个公式可以得到一个大小为 201x200 的矩阵,另一个大小为 200x201。这是因为在第一个变体中,沿 x 有 200 个中点,但有 201 个 y 值,反之亦然。
所以答案是,你没有做错任何事,你只是错误地解释了结果。
您可以通过沿另一个维度(未用于导数的维度)显式插值来解决问题:
f1i = interp1(1 : Ny, f1, 1.5 : Ny);
f2i = interp1(1 : Nx, f2 .', 1.5 : Nx) .';
其中 f1
是根据您的第一个公式计算的,f2
是根据第二个公式计算的。现在,两个导数都在两个维度的中点处求值,这就是为什么两个矩阵的大小都是 200x200 的原因。
如果你现在比较它们,你会发现它们在数值误差方面是相同的(毕竟,diff
只计算近似导数,而 interp1
会产生插值误差)。对于您的步长,此误差最大为 1e-4,并且可以通过使用更小的步长进一步减小。
我想在 MATLAB 中计算复值函数(全纯函数)的导数。
我计算了复平面上网格中的函数,并尝试使用柯西-黎曼关系计算导数。
鉴于: u = real(f), v = imag(f), x = real(point), y = imag(point)
导数应为:f' = du/dx + i dv/dx = dv/dy - i du/dy
其中 'd' 是导数运算符。
我试过以下代码:
stepx = 0.01;
stepy = 0.01;
Nx = 2/stepx +1;
Ny = 2/stepy +1;
[re,im] = meshgrid([-1:stepx:1], [-1:stepy:1]);
cplx = re + 1i*im;
z = cplx.^3;
导数应为:
f1 = diff(real(z),1,2)/stepx +1i* diff(imag(z),1,2)/stepx;
或
f2 = diff(imag(z),1,1)/stepy - 1i* diff(real(z),1,1)/stepy;
但是这两个本应相等的导数却不匹配。
我做错了什么?
让我们计算差异小于 stepx 的元素的数量(假设 stepx = stepy):
lm = min(size(f1));
A = f1(1:lm,1:lm);
B = f2(1:lm,1:lm);
sum(sum(abs(A - B) <= stepx))
并使用@A 提出的修复。东达
f1i = interp1(1 : Ny, f1, 1.5 : Ny);
f2i = interp1(1 : Nx, f2 .', 1.5 : Nx) .';
sum(sum(abs(f1i - f2i) <= stepx))
在第二种情况下,它们的差异都小于应有的 stepx,而在第一种情况下,情况并非如此。
问题是使用两个不同的表达式,在 Matlab 中离散化使用,您正在计算复平面中不同点的近似导数。假设您处于虚值 y 并计算沿实轴 x 的差异,然后第 i 个差异估计 (x(i) + x(i + 1))/2
处的导数,即两个后续 x 值之间的所有中点。另一种方法是估计给定 x 处的导数,但在两个后续 y 值之间的所有中点处。
这也会导致生成的矩阵大小不同。使用第一个公式可以得到一个大小为 201x200 的矩阵,另一个大小为 200x201。这是因为在第一个变体中,沿 x 有 200 个中点,但有 201 个 y 值,反之亦然。
所以答案是,你没有做错任何事,你只是错误地解释了结果。
您可以通过沿另一个维度(未用于导数的维度)显式插值来解决问题:
f1i = interp1(1 : Ny, f1, 1.5 : Ny);
f2i = interp1(1 : Nx, f2 .', 1.5 : Nx) .';
其中 f1
是根据您的第一个公式计算的,f2
是根据第二个公式计算的。现在,两个导数都在两个维度的中点处求值,这就是为什么两个矩阵的大小都是 200x200 的原因。
如果你现在比较它们,你会发现它们在数值误差方面是相同的(毕竟,diff
只计算近似导数,而 interp1
会产生插值误差)。对于您的步长,此误差最大为 1e-4,并且可以通过使用更小的步长进一步减小。