# ContourPlot does not show correct ratio of two functions

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}]}


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}]


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.

• 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. Apr 14 '20 at 4:43
• @LouisB thank you, sir. It works, however, how can I convert the legends to the actual values instead of their logarithm? Apr 14 '20 at 7:45

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]


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]


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]


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

• 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? Apr 17 '20 at 4:17
• @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. Apr 17 '20 at 5:00
• @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. Apr 17 '20 at 5:10