# quiver plot on hyperboloid surface

Using pgfplots, I'm trying to create a quiver plot on a hyperboloid surface something like this.

I was able to generate the hyperboloid surface using parametric equations. I could'nt find out how to generate the quiver plot tangent to the surface. Any help would be greatly appreciated.

I'm okay with using any other package like asymptote etc if I can get this working.

The MWE is here

\documentclass[12pt]{book}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
\begin{axis}[view={110}{20}, %
scale = 1.2, y post scale = 1.5,
xlabel = $x$, ylabel = $y$, zlabel = $z$]
\addplot3[surf, samples=25, variable = \u, variable y = \v, z buffer = sort,
y domain = 0:2*pi]({sqrt(1+u^2)*cos(deg(v))}, {u}, {sqrt(1+u^2)*sin(deg(v))});
\end{axis}
\end{tikzpicture}
\end{document}


Surface of revolution of y=1/x. quiver plot code.

 \addplot3[surf,domain=1:2, y domain = 0:2*pi, z buffer=sort, samples = 10, quiver = {
u = {(x+0.01)*cos(deg(y)) - x},
v = {(x+0.01)*sin(deg(y)) - y},
w = {1/(x+0.01) - z},
}
]
({x*cos(deg(y))}, {x*sin(deg(y))}, {1/x});

-

Asymptote is probably better for this, since it allows for hiding the arrows behind the hyperboloid surface, but here's how you can draw the arrows using PGFPlots.

To calculate the tangent vector, you can simply evaluate the y and z values at a location a small distance along the x axis.

\documentclass[12pt]{book}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
\begin{axis}[view={110}{20}, %
scale = 1.2, y post scale = 1.5,
xlabel = $x$, ylabel = $y$, zlabel = $z$]
\addplot3[surf, samples=8, variable = \u, variable y = \v, z buffer = sort,
y domain = 0:2*pi,
quiver={
u={(sqrt(1+(u+0.01)^2)*cos(deg(v)))-x},
v={0.01},
w={(sqrt(1+(u+0.01)^2)*sin(deg(v)))-z},
scale arrows=75
},
-stealth, thick]
({sqrt(1+u^2)*cos(deg(v))},
{u},
{sqrt(1+u^2)*sin(deg(v))});
\end{axis}
\end{tikzpicture}
\end{document}


This approach works for other functions as well. You need to make sure to explicitly assign the independent variables of your parametric plot variable names other than x and y, however, otherwise it's not clear whether x refers to the independent variable or to the x coordinate:

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
\begin{axis}[view={110}{20}, %
scale = 1.2, y post scale = 1.5,
xlabel = $x$, ylabel = $y$, zlabel = $z$]
\addplot3[surf,domain=1:2, y domain = 0:2*pi, z buffer=sort, samples = 5, samples y=10,
variable = \s, variable y=\t,
quiver = {
u = {(s+0.01)*cos(deg(t)) - x},
v = {(s+0.01)*sin(deg(t)) - y},
w = {1/(s+0.01) - z},
scale arrows=15
},
-stealth, thick
]
({s*cos(deg(t))}, {s*sin(deg(t))}, {1/s});
\end{axis}
\end{tikzpicture}
\end{document}

-
Worked like charm. –  Surya Nov 25 '13 at 12:38
Is this general method of creating quiver plots ? I tried the same logic (u+0.01) with surface of revolution of 1/x and I got some pretty weird lines. I've updated my original question with the new input. –  Surya Nov 26 '13 at 7:29
@Surya: Yes, that's a general method. You need to make sure to assign variable names for your independent variables that aren't x and y. I've edited my answer. –  Jake Nov 26 '13 at 7:49
Okay. That was the mistake then. Thanks. –  Surya Nov 26 '13 at 8:11

The code:

\documentclass[margin=10pt]{standalone}
\usepackage{asymptote}
\begin{document}
\begin{asy}
settings.render=4;
settings.prc=false;

size3(8cm);
defaultpen(fontsize(10pt));

import graph3;
currentprojection=orthographic(5,2,3);

real ymax = 3;
real ymin = -ymax;
real h(real y) {
return sqrt(1 + (y/2)^2);
}
path hyperbola = graph(h, ymin, ymax, operator ..);
path3 hyperbola3 = path3(hyperbola, plane=YZplane);
surface hyperboloid = surface(hyperbola3, c=O, axis=Y);

real umax = hyperboloid.index.length - .001;
real vmax = hyperboloid.index[0].length - .001;

/* Parametrize by the square [0,2pi] x [ymin,ymax] */
triple point(real theta, real y) {
return hyperboloid.point(theta/(2pi) * umax, (y-ymin)/(ymax-ymin) * vmax);
}
triple normal(real theta, real y) {
return hyperboloid.normal(theta/(2pi) * umax, (y-ymin)/(ymax-ymin) * vmax);
}

int n = 10;
int m = 10;
real shrinkfactor=0.8;
for (int i = 0; i < n; ++i) {
real theta = i/n*2pi;
triple f(real t) {
return point(theta, t);
}
for (int j = 0; j < m; ++j) {
real ylow = j/m*(ymax-ymin) + ymin;
real yhigh = ylow + shrinkfactor*(ymax-ymin)/m;
path3 arrowpath = graph(f, ylow, yhigh, n=10, operator..);
}
}

draw(hyperboloid, surfacepen=emissive(white));

pen extraspen = linewidth(0.2);
draw(Circle(c=ymax*Y, r=h(ymax), normal=Y), extraspen);
draw(Circle(c=ymin*Y, r=h(ymin), normal=-Y), extraspen);

scale(true);

xaxis3("$x$", Bounds, InTicks, p=extraspen);
yaxis3("$y$", Bounds, InTicks, p=extraspen);
zaxis3("$z$", Bounds, InTicks, p=extraspen);
\end{asy}
\end{document}

-
Wow.. the image looks very nice. I've to read asymptote docs to understand the code. Nice to have another option. Thx –  Surya Dec 5 '13 at 15:38