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?
-
$\begingroup$ Just use the function! You will get the stream lines in the $r-\theta$ space! $\endgroup$– Spawn1701DApr 9, 2013 at 22:10
-
$\begingroup$ possible duplicate with no answers : mathematica.stackexchange.com/questions/18550/… $\endgroup$– andre314Apr 9, 2013 at 22:11
-
$\begingroup$ Thanks Andre, although the other one was posted first, I've marked it as the duplicate and this one as the canonical version. $\endgroup$– VerbeiaApr 9, 2013 at 23:05
5 Answers
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}
]
-
9$\begingroup$
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 θ]}
. $\endgroup$ Apr 10, 2013 at 1:00 -
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.
-
$\begingroup$ 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. $\endgroup$ Apr 10, 2013 at 4:32
-
$\begingroup$ 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!! $\endgroup$ Apr 10, 2013 at 4:34
-
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.
-
$\begingroup$ It works (+1), but I had to correct a small syntax error in
StreamScale
where a}
is missing. $\endgroup$– JensApr 10, 2013 at 5: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!
-
$\begingroup$ You can consider using
Block
to localizer
andt
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. $\endgroup$– SzabolcsFeb 10, 2014 at 19:53 -
$\begingroup$ To force a single evaluation of
rMax
, use an additional Module variable, sayrMax2
and assignrMax2 = rMax
. Then userMax2
in StreamPlot. $\endgroup$– SzabolcsFeb 10, 2014 at 19:58 -
$\begingroup$ @Szabolcs With regard to putting
r
andt
in aBlock
, isn't this already happening since they're arguments of the function? (Sorry, I'm a CS guy - not so used to Mathematica) $\endgroup$ Feb 10, 2014 at 21:36 -
$\begingroup$ There's the line starting with
Fns = ...
. It has{r,t}
. This will effectively evaluate the symbols that were passed toPolarStreamPlot
as $r$ and $t$. If they have values, it will cause an error inTransformedField
. Try settingr=1
then 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. $\endgroup$– SzabolcsFeb 10, 2014 at 21:47 -
$\begingroup$ Another potential localization failure is not using
:=
in the definition ofmArcTan
. However, for reasons that I don't understand, Mathematica does renamevars
to localize it, so having a globally definedvars=1
does not actually break things. $\endgroup$– SzabolcsFeb 10, 2014 at 21:51