This is the HTML version of a Mathematica 8/9 notebook. You can copy and paste the following into a notebook as literal plain text. For the motivation and further discussion of this notebook, see "Mathematica density and contour Plots with rasterized image representation"
The function gradientFieldPlot
takes a scalar potential with two independent variables as its first argument: φ(x, y)
. The second and third arguments are the name and range of the independent variables, e.g., {x, xmin, xmax}
and {y, ymin, ymax}
.
The plot contains three elements:
φ
, ∇φ
,∇φ
(they are everywhere perpendicular to the contour lines of the potential).gradientFieldPlot[f_, rx_, ry_, opts : OptionsPattern[]] := Module[ { img, cont, densityOptions, contourOptions, frameOptions, gradField, field, fieldL, plotRangeRule, rangeCoords }, densityOptions = Join[ FilterRules[{opts}, FilterRules[Options[DensityPlot], Except[{Prolog, Epilog, FrameTicks, PlotLabel, ImagePadding, GridLines, Mesh, AspectRatio, PlotRangePadding, Frame, Axes}]]], {PlotRangePadding -> None, Frame -> None, Axes -> None, AspectRatio -> Automatic} ]; contourOptions = Join[ FilterRules[{opts}, FilterRules[Options[ContourPlot], Except[{Prolog, Epilog, FrameTicks, PlotLabel, Background, ContourShading, PlotRangePadding, Frame, Axes, ExclusionsStyle}]]], {PlotRangePadding -> None, Frame -> None, Axes -> None, ContourShading -> False} ]; gradField = ComplexExpand[{D[f, rx[[1]]], D[f, ry[[1]]]}]; fieldL = DensityPlot[Norm[gradField], rx, ry, Evaluate@Apply[Sequence, densityOptions]]; field=First@Cases[{fieldL},Graphics[__],\[Infinity]]; img = Rasterize[field, "Image"]; plotRangeRule = FilterRules[Quiet@AbsoluteOptions[field], PlotRange]; cont = If[ MemberQ[{0, None}, (Contours /. FilterRules[{opts}, Contours])], {}, ContourPlot[f, rx, ry, Evaluate@Apply[Sequence, contourOptions]] ]; frameOptions = Join[ FilterRules[{opts}, FilterRules[Options[Graphics], Except[{PlotRangeClipping, PlotRange}]]], {plotRangeRule, Frame -> True, PlotRangeClipping -> True} ]; rangeCoords = Transpose[PlotRange /. plotRangeRule]; If[Head[fieldL]===Legended,Legended[#,fieldL[[2]]],#]&@ Apply[Show[ Graphics[ { Inset[ Show[SetAlphaChannel[img, "ShadingOpacity" /. {opts} /. {"ShadingOpacity" -> 1}], AspectRatio -> Full], rangeCoords[[1]], {0, 0}, rangeCoords[[2]] - rangeCoords[[1]]] }], cont, StreamPlot[gradField, rx, ry, Evaluate@FilterRules[{opts}, StreamStyle], Evaluate@FilterRules[{opts}, StreamColorFunction], Evaluate@FilterRules[{opts}, StreamColorFunctionScaling], Evaluate@FilterRules[{opts}, StreamPoints], Evaluate@FilterRules[{opts}, StreamScale]], ## ] &, frameOptions] ]
Here is an example of how to use the function. The contour lines of the potential are shown in white, and the streamlines of the gradient field are orange.
gradientFieldPlot[ (y^2 + (x - 2)^2)^(-1/2) - (y^2 + (x - 1/2)^2)^(-1/2)/2, {x, -1.5, 2.5}, {y, -1.5, 1.5}, PlotPoints -> 50, ColorFunction -> "BlueGreenYellow", Contours -> 10, ContourStyle -> White, Frame -> True, FrameLabel -> {"x", "y"}, ClippingStyle -> Automatic, Axes -> True, StreamStyle -> Orange]
But perhaps you would like to emphasize the horizontal axis by making it really thick. Now you can achieve this without obscuring the plot:
gradientFieldPlot[(y^2 + (x - 2)^2)^(-1/ 2) - (y^2 + (x - 1/2)^2)^(-1/2)/2, {x, -1.5, 3.5}, {y, -1.5, 1.5}, PlotPoints -> 50, ColorFunction -> "BlueGreenYellow", Contours -> 16, ContourStyle -> White, Frame -> True, FrameLabel -> {"x", "y"}, ClippingStyle -> Automatic, StreamStyle -> Orange, ImageSize -> 500, GridLinesStyle -> Directive[Thick, Black], "ShadingOpacity" -> .8, Axes -> {True, False}, AxesStyle -> Directive[Thickness[.03], Black], Method -> {"AxesInFront" -> False}]