# StreamPlot in Polar Coordinates

I want to use StreamPlot to map out the field lines of an electric field $\mathbf{E}$ given by $$\mathbf{E} = \frac{3D}{4r^{4}}(3\cos(\theta)^{2}-1)\mathbf{\hat{r}} +\frac{3D}{4r^{4}}\sin(2\theta)\boldsymbol{\hat{\theta}}$$ I could convert it to Cartesian coordinates, but I have quite a few more fields to plot, so I would rather leave it in polar coordinates. How can I get StreamPlot to accept polar coordinates?

-
Just use the function! You will get the stream lines in the $r-\theta$ space! – Spawn1701D Apr 9 '13 at 22:10
possible duplicate with no answers : mathematica.stackexchange.com/questions/18550/… – andre Apr 9 '13 at 22:11
Thanks Andre, although the other one was posted first, I've marked it as the duplicate and this one as the canonical version. – Verbeia Apr 9 '13 at 23:05

One way to do it is to write our own wrapper function which does the conversion and feeds it to StreamPlot. Thereby we have the convenience of a selfcontained function without the hassle of having to do the conversion manually every time. We can convert our field

field =  3/(4r^4) (3Cos[\[Theta]]^2-1) Overscript[r, ^]
+ 3/(4r^4) Sin[2\[Theta]] Overscript[\[Theta], ^]


to cartesian form by preparing a set of conversion rules from polar to cartesian coordinates

tocartesian = {Overscript[r, ^] -> x/r Overscript[x, ^] + y/r Overscript[y, ^],
Overscript[\[Theta], ^] -> -(y/Sqrt[x^2+y^2]) Overscript[x, ^]+x/Sqrt[x^2+y^2] Overscript[y, ^],
r -> Sqrt[x^2+y^2],
\[Theta] -> ArcTan[x,y] };


and a rule to make this into a list afterwards

cartesianlist = (a_ Overscript[x, ^] + b_ Overscript[y, ^]) -> {a, b};


Then we can let Mathematica repeatedly apply (//.) our tocartesian rule to eliminate all occurences of r and then let FullSimplify help us to eliminate the trigonometric functions. At last we use cartesianlist to switch to list form:

cartesianfield = FullSimplify[field //. tocartesian] /. cartesianlist


For convenient usage we define our own PolarStreamPlot function

PolarStreamPlot[{rfield_,thetafield_}, opts___] := Module[
{tocartesian,cartesianlist,field,cartesianfield},
tocartesian={Overscript[r, ^]->x/r Overscript[x, ^]+y/r Overscript[y, ^],
Overscript[\[Theta], ^]->-(y/Sqrt[x^2+y^2])Overscript[x, ^]
+ x/Sqrt[x^2+y^2] Overscript[y, ^],
r->Sqrt[x^2+y^2], \[Theta]->ArcTan[x,y]};
cartesianlist=(a_ Overscript[x, ^] + b_ Overscript[y, ^])->{a,b};
field = rfield Overscript[r, ^] + thetafield Overscript[\[Theta], ^];
cartesianfield = FullSimplify[field//.tocartesian]/.cartesianlist;
StreamPlot[cartesianfield, opts]
]


and now we can feed it our original $r$-$\theta$ field definition directly

PolarStreamPlot[
{3/(4r^4) (3Cos[\[Theta]]^2-1),
3/(4r^4) Sin[2\[Theta]]},
{x, -3, 3}, {y, -3, 3}
]


-
TransformedField["Polar" -> "Cartesian", field, {r, θ} -> {x, y}] will also do the conversion for you, if field = {3/(4 r^4) (3 Cos[θ]^2 - 1), 3/(4 r^4) Sin[2 θ]}. – Michael E2 Apr 10 '13 at 1:00
@MichaelE2 one up for v9!!!! – Spawn1701D Apr 10 '13 at 4:42

If you have version 9, the TransformedField as mentioned by MichaelE2 is the way to go. In version 8, the analogous thing (which can also still be used in version 9), is this:

Needs["VectorAnalysis"]
Clear[field, r, θ, ϕ];
m = Transpose[
Transpose[JacobianMatrix[#, Spherical @@ #]]/
ScaleFactors[Spherical @@ #]] &@{r, θ, ϕ};
field[r_, θ_, ϕ_] =
Simplify[m.{3/(4 r^4) (3 Cos[θ]^2 - 1),
3/(4 r^4) Sin[2 θ], 0}];

StreamPlot[
Delete[
field @@ CoordinatesFromCartesian[{x, 0, z}, Spherical], 2],
{x, -3, 3}, {z, -3, 3}]


It uses the VectorAnalysis package like Spawn's answer, but I didn't see any reason why you would first plot the function in polar coordinates, so I inserted the coordinate transformation directly in the StreamPlot. This works for any field defined as a function (field) of the three spherical coordinates, as shown above. All you need is to replace field by field @@ CoordinatesFromCartesian[{x, y, z}, Spherical]. In the plot here, I just set y=0 to get the field lines in the x-z plane.

Edit

The field in the question was given in spherical coordinates, but I copied it from a comment and assumed it was cartesian components. So to correct that, in the definition of field, I added the transformation to the spherical unit vectors. I did this in the most general way I could think of, so that the field can be changed easily. All that you need is the transformation matrix m. If you desire any other coordinate system, just replace Spherical above.

The definition of field also is kept three-dimensional for generality, so that in the StreamPlot I have to Delete one of the three components. Since I'm plotting the x-z plane, I drop the y component which is zero there.

-
The field is given in polar space ($\hat r, \hat\theta$), so first of all you have to change the base of the tangent space. Then you have to consider the transformations involved. For spherical coordinates the change is$$r=\sqrt(x^2+y^2+z^2),\\ \theta=\arccos(z/r),\\ \phi=\arctan(y/x),$$ for cylindrical $$r=\sqrt(x^2+y^2),\\ \theta=\arctan(y/x),\\ z=z$$ To coincide you have to set z=0 and use the first and the third argument. Cylindrical coordinates are better because they are just the cartesian product of polar space with the Real line. – Spawn1701D Apr 10 '13 at 4:32
What i did was to first create the stream plot in polar space and then transform the whole plot in cartesian ones. It is evident from your plot that something is wrong though ... Nevertheless v9 comes to the rescue!! – Spawn1701D Apr 10 '13 at 4:34
Oh yes, I overlooked that part. I'll edit my answer to fix it usng the same method I used here. – Jens Apr 10 '13 at 5:28

Update - A straightforward alternative

Just to put my comment into code in at least one answer: For V9+,

field = {3/(4 r^4) (3 Cos[θ]^2 - 1), 3/(4 r^4) Sin[2 θ]};
StreamPlot[Evaluate@TransformedField["Polar" -> "Cartesian",
field, {r, θ} -> {x, y}], {x, -3, 3}, {y, -3, 3}]
(*  image as above  *)


Original approach

Here is an approach I have been taking with my differential equations class. It shows some of the versatility of the Dt operator and we can break the process down into elementary mathematical steps, instead of using TransformedField as a black box, although using Dt to handle the calculus. We can represent $\mathbf{\hat{r}}$ and $\boldsymbol{\hat{\theta}}$ by Dt[r] and r Dt[θ]. Then straight substitutions may be used. In the end we can convert to a vector field by replacing Dt[x], Dt[y] by {1, 0}, {0, 1} respectively.

polarToCartesian = {r -> Sqrt[x^2 + y^2], θ -> ArcTan[x, y]};
differentialTofield = {Dt[x] -> {1, 0}, Dt[y] -> {0, 1}};

field = (3/(4 r^4) (3 Cos[θ]^2 - 1)) Dt[r] + (3/(4 r^4) Sin[2 θ]) r Dt[θ];

cartesianField =
field /. polarToCartesian /. differentialTofield // Simplify
(*
{ (3 x ( 2 x^2 - 3 y^2)) / (4 (x^2 + y^2)^(7/2)),
-(3 y (-4 x^2 +   y^2)) / (4 (x^2 + y^2)^(7/2))}
*)

StreamPlot[
cartesianField,
{x, -3, 3}, {y, -3, 3}
]


-

Ok the stream plot on the polar space is given by say

With[{D=1},plot=StreamPlot[{3*D/(4r^4)(3Cos[θ]^2-1),3*D/(4r^4) Sin[2θ]},{r,0,1},{θ,0,2*π},
StreamScale -> {Automatic, Automatic, Automatic, Function[{x, y, vx, vy, n}, x]}]]


Now, IF you want this stream plot embedded on cartesian space you can either transform the vector field to cartesian space as you correctly say or do the following:

Needs["VectorAnalysis"]
Show[plot/.
Arrow[v:{__?VectorQ}]:>Arrow[(Most[CoordinatesToCartesian[Append[#, 0], Cylindrical]]&/@v)],
PlotRange -> Automatic]


I suppose your question is if there is a function like PolarPlot for StreamPlot or other plot functions. The short answer is no. You can either change before hand the function or the field or embed the field afterward. Which method is best depends on the specific trasformation involved and if you want to exploit Mathematica's routines in giving you the best presentation of the field.

-
It works (+1), but I had to correct a small syntax error in StreamScale where a } is missing. – Jens Apr 10 '13 at 5:43
@Jens thanx! I am correcting it now! – Spawn1701D Apr 10 '13 at 5:51

For those using Mathematica 9, I have created the following function to produce polar plots. It takes all options that can be given to StreamPlot, but also masks any results outside of the provided domain (which is provided in polar coordinates).

SetAttributes[PolarStreamPlot, HoldAll];
PolarStreamPlot[
fns_, {r_Symbol, rMin_, rMax_}, {t_Symbol, tMin_, tMax_}, opts___] :=
Module[{Fns, x, y, RF, TMin, TMax, mArcTan, RMax},
If[rMin >= rMax,
Throw["Invalid range for r!"]
];
If[tMin >= tMax || tMax - tMin > 2 Pi,
Throw["Invalid range for \[Theta]!"]
];
TMin = Mod[tMin, 2 Pi, tMin];
TMax = Mod[tMax, 2 Pi, tMin];
If[TMax == TMin, TMax += 2 Pi];
mArcTan[vars__] = Mod[ArcTan[vars], 2 Pi, TMin];
Fns = TransformedField["Polar" -> "Cartesian",
fns, {r, t} -> {x, y}] /. ArcTan -> mArcTan;
RMax = rMax;
StreamPlot[Fns, {x, -RMax, RMax}, {y, -RMax, RMax},
RegionFunction ->
Function[{x, y},
Evaluate[
mArcTan[x, y] <= TMax && rMin <= Sqrt[x^2 + y^2] <= rMax]], opts]
]


Hope this helps!

-
You can consider using Block to localize r and t so the function will still work when these have a value. Also, you can use Message and Return instead of Throw. An uncaught Throw is technically a runtime error. Finally, Evaluate only works when it's at level 1 within a held function. I'm not sure it's necessary here. – Szabolcs Feb 10 '14 at 19:53
To force a single evaluation of rMax, use an additional Module variable, say rMax2 and assign rMax2 = rMax. Then use rMax2 in StreamPlot. – Szabolcs Feb 10 '14 at 19:58
@Szabolcs With regard to putting r and t in a Block, isn't this already happening since they're arguments of the function? (Sorry, I'm a CS guy - not so used to Mathematica) – s.pledger Feb 10 '14 at 21:36
There's the line starting with Fns = .... It has {r,t}. This will effectively evaluate the symbols that were passed to PolarStreamPlot as $r$ and $t$. If they have values, it will cause an error in TransformedField. Try setting r=1 then calling PolarStreamPlot[..., {r, ...}, ...]. It will show errors. However, if you wrap the whole thing in Block[{r,t}, ...] then it'll work. Do not mind about the red colouring you see, it's just a warning. But doing this here is justified. – Szabolcs Feb 10 '14 at 21:47
Another potential localization failure is not using := in the definition of mArcTan. However, for reasons that I don't understand, Mathematica does rename vars to localize it, so having a globally defined vars=1 does not actually break things. – Szabolcs Feb 10 '14 at 21:51