1
$\begingroup$

I am using ContourPlot to compare the norm of the two vector fields, $||\boldsymbol{f}||/||\boldsymbol{g}||$, which should be contour on $(x,y)$ plane.

Consider the following PDEs about $u(x,y,t)$ and $v(x,y,t)$,

L = 4;
solu = NDSolveValue[{D[u[t, x, y], t, t] == 
D[u[t, x, y], x, x] + D[u[t, x, y], y, y] + Sin[u[t, x, y]], 
u[t, -L, y] == u[t, L, y], u[t, x, -L] == u[t, x, L], u[0, x, y] == Exp[-(x^2 + y^2)], 
Derivative[1, 0, 0][u][0, x, y] == 0}, u, {t, 0, 4}, {x, -L, L}, {y, -L, L}]

solv = NDSolveValue[{D[v[t, x, y], t, t] == 
D[v[t, x, y], x, x] + D[v[t, x, y], y, y]/2 + (1 - v[t, x, y]^2) (1 + 2 v[t, x, y]), 
v[0, x, y] == E^-(x^2 + y^2), v[t, -L, y] == v[t, L, y], 
v[t, x, -L] == v[t, x, L], Derivative[1, 0, 0][v][0, x, y] == 0}, 
v, {t, 0, 4}, {x, -L, L}, {y, -L, L}]

and these two vector fields

f[x_, y_, t_] = solu[t, x, y]*Grad[solv[t, x, y], {x, y}] + Grad[solu[t, x, y], {x, y}];

g[x_, y_, t_] = Grad[solu[t, x, y], {x, y}]*solu[t, x, y];

I can plot the respective contours with

{ContourPlot[Norm[f[x, y, 1]], {x, 0, L}, {y, 0, L}, PlotRange -> All, ColorFunction -> "Rainbow", Contours -> 10, PlotLegends -> BarLegend[Automatic, All], FrameLabel -> {x, y}],
ContourPlot[Norm[g[x, y, 1]], {x, 0, L}, {y, 0, L}, PlotRange -> All, ColorFunction -> "Rainbow", Contours -> 10, PlotLegends -> BarLegend[Automatic, All], FrameLabel -> {x, y}]}

enter image description here

But if I plot their ratio, i.e. the ratio of the norms of the two vector fields, ContourPlot produces a strange result, which looks not correct.

ContourPlot[Norm[f[x, y, 1]]/Norm[g[x, y, 1]], {x, 0, L}, {y, 0, L}, PlotRange -> All,
ColorFunction -> "Rainbow", Contours -> 10, PlotLegends -> BarLegend[Automatic, All], FrameLabel -> {x,y}]

enter image description here

A quick check:

Norm[f[1.6, 0.5, 1]]/Norm[g[1.6, 0.5, 1]]
(*4.72938*)

This is not consistent with the last contour plot. What am I doing wrong? Thank you in advance.

$\endgroup$
2
  • $\begingroup$ Maybe plot the contours of Log[ Norm[ f[x, y, 1] ] / Norm[ g[x, y, 1] ] ] and use Log[ Norm[ f[1.6, 0.5, 1] ] / Norm[ g[1.6, 0.5, 1] ] ] for the sanity check. $\endgroup$
    – LouisB
    Commented Apr 14, 2020 at 4:43
  • $\begingroup$ @LouisB thank you, sir. It works, however, how can I convert the legends to the actual values instead of their logarithm? $\endgroup$
    – user55777
    Commented Apr 14, 2020 at 7:45

1 Answer 1

1
$\begingroup$

Your contour plot is actually showing the ratio correctly, but the scale is inappropriate. Here are three methods that can be used to improve the visualization.

Method 1: Logarithmic Scale

We can change to a logarithmic scale with the ScalingFunctions option like this

ContourPlot[Norm[f[x, y, 1]]/Norm[g[x, y, 1]],
 {x, 0, L}, {y, 0, L},
 ScalingFunctions -> "Log10",
 ColorFunction -> ColorData["Rainbow"],
 FrameLabel -> {x, y},
 PlotLegends -> BarLegend[Automatic],
 PlotRange -> All]

enter image description here The advantage of Method 1 is that it is easy to apply.

Method 2: Legend Modifications

The legend text from Method 1 can be modified with a simple hack, if desired. First, we define rules to replace the existing legend text. Then we apply those rules in the LegendFunction option to the BarLegend function, like this

legendTextRules = {
   Text[100000, q___] :> Text[Superscript[10, 5], q],
   Text[10000, q___] :> Text[Superscript[10, 4], q],
   Text[1000, q___] :> Text[Superscript[10, 3], q]};

ContourPlot[Norm[f[x, y, 1]]/Norm[g[x, y, 1]],
 {x, 0, L}, {y, 0, L},
 ScalingFunctions -> "Log10",
 ColorFunction -> ColorData["Rainbow"],
 FrameLabel -> {x, y},
 PlotLegends -> BarLegend[Automatic,
   LegendFunction -> ((# /. legendTextRules) &)],
 PlotRange -> All]

enter image description here

The advantage of Method 2 is that legend text looks better.

Method 3: User-Defined Contours

We can also define the contours and ColorFunction to be used. This method allows us to add more detail in areas of interest. First, we define 2 parameters for our color function. These parameters are the base 10 logs of the minimum and maximum contours, roughly. Next we defined the list of contours. Finally, we plot the function with a logarithmic color functions, like this

{minLog10, maxLog10} = {-1, 6};
contours = {1/2, 1, 2, 3, 5, 10, 100, 500, 
             1000, 5000, 10^6};

ContourPlot[Norm[f[x, y, 1]]/Norm[g[x, y, 1]],
 {x, 0, L}, {y, 0, L},
 Contours -> contours,
 ColorFunctionScaling -> False,
 ColorFunction -> (ColorData[
      "Rainbow"][(Log10[#] - minLog10)/
          (maxLog10 - minLog10)] &),
 FrameLabel -> {x, y},
 PlotLegends -> BarLegend[Automatic],
 PlotRange -> All]

enter image description here

The advantage of Method 3 is more contours in the lower left corner of the plot.

$\endgroup$
3
  • $\begingroup$ thanks. Plotting Log[10, Norm[f[x, y, 1]]/Norm[g[x, y, 1]]] gives the same result, except that its legend labels are the log of base 10, for the actual values on the legend instead of their logarithm, we should use ScalingFunctions -> "Log10", right? $\endgroup$
    – user55777
    Commented Apr 17, 2020 at 4:17
  • $\begingroup$ @user55777 In this case ScalingFunctions -> "Log10" is preferred over just taking the log of the function. I take the log first for a quick look at the results to see if that's the right thing to do. If it works out and I want a plot with a nice legend, then I will switch to ScalingFunctions. $\endgroup$
    – LouisB
    Commented Apr 17, 2020 at 5:00
  • $\begingroup$ @user55777 BTW, if I was making a ContourPlot I would also look at Plot3D[Log10[Norm[f[x, y, 1]]/Norm[g[x, y, 1]]], {x, 0, L}, {y, 0, L}, BoxRatios -> {1, 1, 1}] as a sanity check and for guidance on what else I need to look at. $\endgroup$
    – LouisB
    Commented Apr 17, 2020 at 5:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.