Plotting the branches of a complex function

纵然是瞬间 提交于 2021-01-21 11:22:17

问题


I'm trying to plot a kind of Riemann's surface of a function (I'm not sure if it's the right name for the thing), as shown below:

Here's what I tried:

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

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)';

Which gives me the following:

My questions are:

  1. I thought I would plot what is on the first image, but I got something else. What did I plot if it isn't a Riemann's surface?

  2. How can I change my code to get the top plot?

  3. Would it be possible have a scale in radians on the first graph?


回答1:


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.

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)';

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)';

Here's the result:

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.

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.



来源:https://stackoverflow.com/questions/53234466/plotting-the-branches-of-a-complex-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!