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 09 '13 at 22:10
-
possible duplicate with no answers : http://mathematica.stackexchange.com/questions/18550/plot-in-cylindrical-coordinates – andre314 Apr 09 '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 09 '13 at 23:05
5 Answers
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.
- 97,245
- 7
- 213
- 499
-
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 04: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 04: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 05:28
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) OverHat[r]
+ 3/(4r^4) Sin[2\[Theta]] OverHat[\[Theta]]

to cartesian form by preparing a set of conversion rules from polar to cartesian coordinates
tocartesian = {OverHat[r] -> x/r OverHat[x] + y/r OverHat[y],
OverHat[\[Theta]] -> -(y/Sqrt[x^2+y^2]) OverHat[x]+x/Sqrt[x^2+y^2] OverHat[y],
r -> Sqrt[x^2+y^2],
\[Theta] -> ArcTan[x,y] };
and a rule to make this into a list afterwards
cartesianlist = (a_ OverHat[x] + b_ OverHat[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={OverHat[r]->x/r OverHat[x]+y/r OverHat[y],
OverHat[\[Theta]]->-(y/Sqrt[x^2+y^2])OverHat[x]
+ x/Sqrt[x^2+y^2] OverHat[y],
r->Sqrt[x^2+y^2], \[Theta]->ArcTan[x,y]};
cartesianlist=(a_ OverHat[x] + b_ OverHat[y])->{a,b};
field = rfield OverHat[r] + thetafield OverHat[\[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}
]

- 8,814
- 34
- 44
-
9
TransformedField["Polar" -> "Cartesian", field, {r, θ} -> {x, y}]will also do the conversion for you, iffield = {3/(4 r^4) (3 Cos[θ]^2 - 1), 3/(4 r^4) Sin[2 θ]}. – Michael E2 Apr 10 '13 at 01:00 -
-
1The
Overscript[r, ^]in the code needs to be changed toOverHat[r], otherwise it will result in an error. – lotus2019 Mar 25 '24 at 13:39
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}
]

- 124,525
- 11
- 401
- 574
- 235,386
- 17
- 334
- 747
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.
- 1,871
- 13
- 14
-
It works (+1), but I had to correct a small syntax error in
StreamScalewhere a}is missing. – Jens Apr 10 '13 at 05:43 -
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!
- 41
- 2
-
You can consider using
Blockto localizerandtso 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,Evaluateonly 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, sayrMax2and assignrMax2 = rMax. Then userMax2in StreamPlot. – Szabolcs Feb 10 '14 at 19:58 -
@Szabolcs With regard to putting
randtin aBlock, 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 toPolarStreamPlotas $r$ and $t$. If they have values, it will cause an error inTransformedField. Try settingr=1then callingPolarStreamPlot[..., {r, ...}, ...]. It will show errors. However, if you wrap the whole thing inBlock[{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 ofmArcTan. However, for reasons that I don't understand, Mathematica does renamevarsto localize it, so having a globally definedvars=1does not actually break things. – Szabolcs Feb 10 '14 at 21:51 -
How about some more improvement like this? I'm also uneasy about the
EvaluateinFunctionwhich should break ifxhas a value, but it doesn't break and I don't understand why ... – Szabolcs Feb 10 '14 at 22:03 -
Let me illustrate:
x = 1; Module[{z}, Function[x, Evaluate[x < y]] ]. Here things go wrong because the value of the (global)xis substituted in. It makes no difference ifxis localized in theModule, it won't affectFunction. If this is what happens in your function too, it would break ifxoryhave a global value. But yours is slightly different. Consider nowx = 1; Module[{z}, Function[x, Evaluate[x < z]] ]. For some reason Mma decides to renamexwhen it occurs together with theModulevariable, which accidentally protects it here ... – Szabolcs Feb 10 '14 at 22:12 -
For this reason I'd remove that
Evaluateand give up some performance for the piece of mind that this'll work even in future or past versions where renaming might act differently. – Szabolcs Feb 10 '14 at 22:13