且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

绘制复杂函数的分支

更新时间:1970-01-01 07:56:48

您的第一个图显示了多值函数"的多个分支.从通常意义上讲,它实际上不是一个函数,因为对于给定的 z ,您具有多个函数值.您只能通过多次绕原点进行复制,即角度变量中的 2 * pi 个以上.您所绘制的是该函数的主要分支,即与从 -pi pi 的复杂阶段相对应的工作表.

Your first plot shows multiple branches of a multiple-valued "function". It's not really a function in the usual sense, since for a given z you have more than one function value. You can only reproduce this by going around more than once around the origin, i.e. more than 2*pi in your angular variable. What you plot is the principal branch of that function, i.e. the sheet that corresponds to complex phases ranging from -pi to pi.

此外,还有一个更基本的问题.一旦切换到表示为双精度的复数,您将丢失有关原点周围其他相位的任何信息(表示为实数+虚数部分的复数只会导致其复数的本金,即介于 -pi之间 pi ).因此,您需要根据复数的三角形式手动"计算平方根:

Furthermore, there's a more fundamental issue. Once you switch to complex numbers represented as doubles, you lose any information about additional phase around the origin (complex numbers represented as a real + imaginary part will only result in the principal value of their complex phase, which falls between -pi and pi). So you need to compute the square root "manually", from the trigonometric form of the complex number:

r = (0:1:15)';                           % create a matrix of complex inputs
theta = pi*(-2:0.05:2);
z = r*exp(1i*theta);
%w = z.^(1/2)  ;                          % calculate the complex outputs
w = sqrt(r)*exp(1i*theta/2);

figure('Name','Graphique complexe','units','normalized','outerposition',[ 0.08 0.1 0.8 0.55]);
subplot(121)

surf(real(z),imag(z),real(w),imag(w))    % visualize the complex function using surf
xlabel('Real(z)')
ylabel('Imag(z)')
zlabel('Real(u)')
cb = colorbar;
colormap jet;                            % gradient from blue to red
cb.Label.String = 'Imag(v)';

subplot(122)
surf(real(z),imag(z),imag(w),real(w))    % visualize the complex function using surf
xlabel('Real(z)')
ylabel('Imag(z)')
zlabel('Imag(v)')
cb = colorbar;
colormap jet;                            % gradient from blue to red
cb.Label.String = 'Real(u)';

如您所见,该函数按其应有的方式工作.请注意,图中没有弧度的比例"是没有意义的.您绘制的所有内容均具有线性"尺寸:实部和虚部.弧度仅对 angles (即类似 theta 的量)有意义.

As you can see, the function acts as it should. Note that it doesn't make sense to have "the scale in radians" in the figure. Everything you plot has "linear" dimensions: real parts and imaginary parts. Radians would only make sense for angles, i.e. theta-like quantities.

此外,由于我们使用极坐标进行绘制,因此您可能会注意到上图具有圆边.可以创建一个矩形图,但需要做很多工作.这是部分解决方案.想法是将相同的网格缝合两次,以绘制函数的两个分支:

Also, you may note that the above figure has round edges, since we're plotting using polar coordinates. It's possible to create a rectangular plot but it takes a lot more work. Here's a partial solution. The idea is to sew together the same mesh twice in order to plot the two branches of the function:

r0 = 15;
re = linspace(-r0, r0, 31).';                           % create a matrix of complex inputs
im = linspace(-r0, r0, 31);
z = re + 1j*im;
theta = angle(z);  % atan2(imag(z), real(z));
r = abs(z);

% concatenate the same mesh twice (plotting trick) back to back, insert nan in between
w1 = sqrt(r).*exp(1i*theta/2); % first branch
w2 = sqrt(r).*exp(1i*(theta+2*pi)/2); % second branch

z = [z, nan(size(w1,1),1), z(:,end:-1:1)];
w = [w1, nan(size(w1,1),1), w2(:,end:-1:1)];

figure('Name','Graphique complexe','units','normalized','outerposition',[ 0.08 0.1 0.8 0.55]);
subplot(121)
surf(real(z),imag(z),real(w),imag(w))    % visualize the complex function using surf
xlabel('Real(z)')
ylabel('Imag(z)')
zlabel('Real(u)')
cb = colorbar;
colormap jet;                            % gradient from blue to red
cb.Label.String = 'Imag(v)';

subplot(122)
surf(real(z),imag(z),imag(w),real(w))    % visualize the complex function using surf
xlabel('Real(z)')
ylabel('Imag(z)')
zlabel('Imag(v)')
cb = colorbar;
colormap jet;                            % gradient from blue to red
cb.Label.String = 'Real(u)';

结果如下:

如您所见,复杂的部分看起来很奇怪.这是因为复数的相位沿负实半轴跳跃.该可以补救,但需要做很多工作,这留给读者练习.我将一列 nan s注入数据的原因是为了防止在第一幅图中出现类似的跳跃伪像.另一种选择是分别绘制函数的两个分支,并在它们之间保持 ,但是随后还必须进行额外的工作才能对图形上的颜色图进行标准化.

As you can see the complex part looks weird. This is because the phase of complex numbers jumps along the negative real half axis. This could be remedied but takes a lot more work, this is left as an exercise to the reader. The reason I injected a column of nans into the data is to prevent a similar jump artifact to be present in the first plot. The other option is to plot the two branches of the function separately, with hold on in between, but then extra work would have to be done to normalize the colormap on the figures.

最后,请考虑不要使用 jet ,而是使用默认的 parula 颜色图.对于视力受损的人来说,喷射非常有害,而 parula 几乎在感知上是统一的.对于该问题的简短介绍,我建议您观看scipy团队的这个精彩的演讲.

Finally, do consider not using jet but the default parula colormap instead. Jet is very bad for people with impaired colour vision, and parula is close to perceptually uniform. For a short introduction to the problem I suggest watching this great talk from the scipy guys.