Skip to main content

plotting - How do I plot a proper streamline plot, including spacings and line endings?


Mathematica includes two nice built-in tools to visualize vector fields, VectorPlot and StreamPlot. The latter is a useful tool, and it plots the streamlines of the given 2D vector field.


enter image description here


A streamline is an integral curve of the vector field: that is, a curve $\vec\alpha(s)$ whose derivative $\frac{d\vec\alpha}{ds}$ is proportional at every point to the vector field $\vec F(\vec\alpha(s)$ at that point. These are very useful tools for understanding the qualitative behaviour of many types of vector fields.


However, in certain cases, these diagrams require a bit more structure. In situations where the divergence $\nabla\cdot\vec F$ of the field matters, and in particular for





  • streamlines of a fluid flow, and




  • field lines of an electric or magnetic field,




there are two constraints which are followed, by convention, very strictly, and which make available quantitative information about the field from the diagram, by encoding the field strength in the local density of streamlines. (For more on how and why they work, see this physics.SE thread). Specifically:





  • Streamlines should never end or begin in any region in which $\nabla\cdot\vec F$ is zero; they should start at point sources or regions where $\nabla\cdot\vec F>0$, and end at point sinks or regions where $\nabla\cdot\vec F<0$.




  • The vector field flow between adjacent streamlines, i.e. the integral $$\int_L\vec F\cdot d\vec s^\perp$$ where $L$ joins the two streamlines, should be constant. (There is some interplay when the field is in 3D, where it's the flow across unit "cell" surfaces that join three or more streamlines, or when one is displaying a 2D cross-section of a 3D field, but the principle remains.)




Unfortunately, the built-in StreamPlot function does nothing of the sort, at least out of the box, and I can find no built-in options that will enforce this type of behaviour.


For an example, consider the vector fields $\hat{\mathbf{r}}/r^n$, for $n=1$ and $n=2$. These are the electric fields produced in 3D by a line of charge and a point charge, respectively. When seen as a 2D field, the former has no divergence, and the corresponding streamlines should start at the origin and end at infinity; the latter, on the other hand, has negative divergence as a 2D field and its intensity thins out faster than the first, so the local density of field lines should thin out as $1/r$ away from the origin. If you try to plot them with Mathematica, though, the opposite happens:


enter image description here



Table[
StreamPlot[{x, y}/(x^2 + y^2)^n, {x, -2, 2}, {y, -2, 2}
, ImageSize -> 400, PlotLabel -> "(x,y)/r^{n+1}, n="<>ToString[2 n - 1]
]
, {n, {1, 3/2}}] // GraphicsRow

The field from the line charge, on the left, has approximately constant spacing after a while, but here are streamlines that are created almost at $r=1$. The field on the right is from a point charge, and it shows the opposite of what it should:



  • streamlines are created away from the origin, instead of destroyed,

  • more streamlines are created than for a line charge,


  • and to top it off, the field is not even rotationally symmetric.


Is there a way to overcome these shortcomings and make StreamPlot, with appropriate options, produce correct versions of these plots? Is there some other way to produce such a diagram properly?




Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...