optimization of CountourPlot with NIntegrate

I have to use ContourPlot with a complicated function depending on 2 parametrs (that I cannot report here) that contains numerical integrations.

Here is a simple example to clarify my problem:

f[a_?NumberQ, b_?NumberQ] := NIntegrate[a*x + b, {x, 0, 1}];
ContourPlot[{f[a, b] == 3, f[a, b] == 6, f[a, b] == 10}, {a, 0,
10}, {b, 0, 10}] // Timing As you can see, since Nintegrate is evaluated in every point, the computation is very slow (over 3 seconds on my laptop, even for this simple case): how can I optimize this?

• ContourPlot[f[a, b], {a, 0, 10}, {b, 0, 10}, Contours -> {3, 6, 10}] // Timing isn't probably the best solution, but it shaves the time by 40% – Dr. belisarius Feb 10 '15 at 17:00
• Maybe also play with the number of PlotPoints. – Jens Feb 10 '15 at 17:34
• this is redundantly computing the Integral at some points, saving values ( f[a_?NumberQ, b_?NumberQ] := f[a,b]= NIntegrate.. ) cuts the time in half for this example. – george2079 Feb 10 '15 at 20:51

Update: Using the memoization trick suggested by @george2079 in the comments combined with MeshFunctions we get the same picture in 0.015625 seconds:

fa[a_?NumericQ, b_?NumericQ] := fa[a, b] = NIntegrate[a*x + b, {x, 0, 1}];
First@Timing[ContourPlot[fa[a, b], {a, 0, 10}, {b, 0, 10}, Contours -> {},
ContourShading -> None, MeshFunctions -> {#3 &},
Mesh -> {{{3, Red}, {6, Green}, {10, Blue}}},
MeshStyle -> Thick] /. Polygon[__] -> Sequence[]]
(* 0.015625 *)

Original post:

Using MeshFunctions with no contours

First@Timing[cp1 = ContourPlot[f[a, b], {a, 0, 10}, {b, 0, 10},
Contours -> {}, ContourShading -> None,
MeshFunctions -> {#3 &}, Mesh -> {{{3, Red}, {6, Green}, {10, Blue}}},
MeshStyle -> Thick]/. Polygon[__] -> Sequence[]]
(* 0.578125 *)

makes it faster

cp1 versus

First@Timing[ContourPlot[f[a, b], {a, 0, 10}, {b, 0, 10}, Contours -> {3, 6, 10}]]
(* 1.625000 *)
• I cannot avoid numerical integrations – mattiav27 Feb 10 '15 at 17:18
• @belisarius, mattiav27, sorry i missed the key requirement of the question:) – kglr Feb 10 '15 at 17:20
• Much better now. +1 cp1 /. GrayLevel[_] :> GrayLevel – Dr. belisarius Feb 10 '15 at 17:46
• It is important to see why this is fast: here the function value is computed on a regular grid and the contours are based on simple interpolation. In the approach in the question ContourPlot uses a root finding algorithm to accurately find the locus of the contours. – george2079 Feb 10 '15 at 21:19
• @george, good point, thank you. Actually, MeshFunctions combined with your memoization suggestion cuts the timing to almost zero. – kglr Feb 10 '15 at 21:35

Here is another alternative for how to speed up the plotting if you want to retain all the functionality and options of ContourPlot: use ParallelTable:

f[a_?NumericQ, b_?NumericQ] := NIntegrate[a*x + b, {x, 0, 1}];

Timing[Show[
ParallelTable[
ContourPlot[f[a, b], {a, 0, 10}, {b, 0, 10}, Contours -> {i},