问题
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:
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?
How can I change my code to get the top plot?
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 nan
s 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