# How to get StreamPlot to draw many hundreds of streamlines?

For artistic reasons, I want to draw an extremely dense StreamPlot with something like a thousand streamlines. I tried setting StreamPoints -> {Automatic, d} where $d$ is a small value specifying the minimum distance between streamlines, but after a point reducing the value of $d$ stops having an effect.

GraphicsColumn[
StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3},
StreamPoints -> {Automatic, #}, ImageSize -> Medium] & /@ {1, 0.3,
0.1, 0.03, 0.01}]


(click for image)

The same thing happens when setting StreamPoints -> n for increasing values of $n$, or when manually seeding hundreds of seed points; Mathematica silently refuses to plot any more streamlines.

How can I get around this? Is it possible to plot arbitrarily closely spaced streamlines using StreamPlot?

Update: To clarify, I want to keep the style of the fully-automatic default StreamPlot, which attempts to maintain a uniform spacing between streamlines, and just make it denser. So I don't want to get rid of the minimum distance entirely; I just want to lower it. To save everyone some time, here is what I find unsatisfactory about all the documented settings for StreamPoints.

• None: Obviously no good.
• $n$: Stops having an effect somewhere between 50 and 100.
• Automatic, Coarse, and Fine: Not dense enough.
• {p1, p2, ...} and {{p1, g1}, ...}: See n.
• {spec, d}: d stops having an effect somewhere between 0.2 and 0.1.
• {spec, {dStart, dEnd}}: Strangely, increasing dEnd plots more streamlines. Compare {Automatic, {0.5, 10}} with {Automatic, 0.5} and {Automatic, {0.5, 0.5}}. I don't understand this setting at all.
• {spec, d, len}: When spec is Automatic, len has no effect as far as I can tell. On the other hand, when spec is {p1, p2, ...}, len causes d to be ignored completely.
-
Are you sure? Your 3rd & 4th images above are different. Please check again but using ImageSize->(eg) 700 so you can see differences. –  dwa Dec 7 '12 at 6:09
@dwa: They are slightly different, but the fourth image is certainly not 3 times denser. I've updated with a hopefully more convincing example. –  Rahul Narain Dec 7 '12 at 6:24
Great question. Now I have reason to explore the inner workings of StreamPlot, which I've never really considered before. –  Mr.Wizard Dec 7 '12 at 11:19
Actually, the uniform spacing between streamlines that you like so much isn't really that useful. In many applications, one wants the streamline density to vary with the field strength. The automatic minimum distance actually prevents that! So I find it necessary to choose my own seed points to make sure that the function is represented faithfully. When you ask for longer streamlines, it becomes harder on average to enforce a minimum separation, and spacings that look even in one region may not in another region. –  Jens Dec 7 '12 at 16:52

Maybe this isn't what you need, but for aesthetic reasons I would suggest for such a high streamline density to use a different plot altogether:

LineIntegralConvolutionPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3,
3}, {y, -3, 3}, LineIntegralConvolutionScale -> 2,
ColorFunction -> GrayLevel, RasterSize -> 300]


LineIntegralConvolutionPlot[{{-1 - x^2 + y, 1 + x - y^2},
Image[Table[((-1)^i (-1)^j + 1)/2, {i, 45}, {j, 45}]]}, {x, -3,
3}, {y, -3, 3}, LineIntegralConvolutionScale -> 2,
ColorFunction -> GrayLevel, RasterSize -> 300]


There are many additional options for LineIntegralConvolutionPlot, but I like its smoothed, continuous representation of the streamlines.

Edit

Here is a simple way to create arbitrary many streamlines by circumventing the ceiling that StreamPlot appears to impose on us:

t = Map[StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3,
3}, StreamStyle -> "Line",
StreamPoints -> RandomReal[{-3, 3}, {#, 2}], ImageSize -> 500] &,
ConstantArray[50, 20]];

Show[t]


The trick I used is to generate a whole list of StreamPlots, all with different seed points (here chosen randomly, but you could tweak that at will). Each single plot is given a fixed number of seed points that doesn't have to be very large (here 50).

But then I superimpose all these plots using Show, and the result is an arbitrarily dense array of stream lines because the individual plots don't know anything about how close stream lines in the other plots are.

Edit 2

For fun, I made this stream plot with nominally 5000 seed points, and gave it random gray scales to see how similar it looks to the LineIntegralConvolutionPlot above. Here is the result:

t = Map[StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3,
3}, StreamStyle -> "Line",
StreamPoints -> RandomReal[{-3, 3}, {#, 2}],
StreamColorFunction -> (GrayLevel[RandomReal[]] &),
ImageSize -> 500] &, ConstantArray[50, 100]];

Show[t]


-
Thanks, I'm aware of line integral convolution, but I really do want a streamline plot. I'll be rendering it with StreamStyle -> "Line" and ImageSize -> Large if that helps convince you of the aesthetic I'm going for. –  Rahul Narain Dec 7 '12 at 6:41
@RahulNarain OK, this really is a different problem then. I'll edit my answer to address this shortcoming. –  Jens Dec 7 '12 at 7:13
Clever! +1. However, what makes the output of StreamPlot nice is that it attempts to keep the streamlines uniformly spaced, which is no longer the case with this approach. –  Rahul Narain Dec 7 '12 at 9:07
The spacing depends only on your choice of seed points. –  Jens Dec 7 '12 at 15:03
@Jens: Very cool and informative approach. –  JohnD Dec 7 '12 at 15:49

It seems to help to include a maximum length in the StreamPoints setting:

StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3},
StreamPoints -> {Tuples[Range[-3, 3, 0.2], 2], Automatic, 10},
ImageSize -> Medium, StreamStyle -> "Line"]


Count[%, _Line, -1]
(* 960 *)

-
Interesting observation (+1). –  Jens Dec 7 '12 at 15:02
Interesting. However, it seems this only works by overriding the minimum distance between streamlines. Now the streamlines are nonuniformly dense (e.g. lower right), even after replacing Automatic with a fixed value. Also, this doesn't work when using automatic seed points instead of Tuples[...]. –  Rahul Narain Dec 7 '12 at 16:08
I've updated the question; sorry about the confusion. –  Rahul Narain Dec 7 '12 at 16:43
This inhomogeneity seems to me quite unavoidable as a result of the fact that you can't predict that the spacing will remain uniform everywhere if you set it to be approximately uniform in some subregion of the plot. Maybe the reason this answer works in the first place is that Mathematica knows about this uncertainty and stops obsessing about minimum separation when you ask for long stream lines where it becomes too hard to predict the separation over long "times" on the streamline. –  Jens Dec 7 '12 at 16:57
@Jens, Mathematica normally deals with the non-uniform density by terminating some of the streamlines as their spacing decreases. It's not clear to me why this stops happening when you specify a maximum length for the streamlines. –  Simon Woods Dec 7 '12 at 19:19