# How to speed up the plot of NIntegrate?

Here is a toy example:

f[t_] := NIntegrate[Sin[x], {x, 0, t}];
Plot[f[t], {t, 0, 10}] // Timing


Even such a simple example will take 2.8 seconds on my computer.

Since many of the plot family functions have the attribute HoldAll, Mathematica evaluates f[t] only after assigning specific numerical values to t, thus causing a lot of repeated evaluations of NIntegrate. The integration to a smaller upper-limit is forgotten when integrating to a bigger upper-limit. On the other hand, I can’t benefit from wrapping the function in Evaluate, because of the numerical nature of NIntegrate. Something stuck here. So the questions are:

• Can NIntegrate remember or make full use of the result of a smaller upper-limit integral? Or generally, how to speed up the plot involving NIntegrate or is there any principle to do it?

• Is it possible to realize ParametricNIntegrate just as ParametricNDSolve in version 9?

Edit

Following the way of changing the integral to NDSolve (Thanks to Mark McClure) ,I’ve come up with one possible way to realize ParametricNIntegrate. Here is the code for a more general way compared to the toy model:

sol=ParametricNDSolveValue[{f'[x] == Sin[a x], f[0] == 0},f,{x,0,10},{a}];
Manipulate[Plot[{sol[a][t], 1/a (1 - Cos[a t])}, {t, 0, 10}], {a, 1, 5}]


Now I can change the parameter and plot the integral in real-time.Any better ideas?

-

You can express your integral in terms of a differential equation and use NDSolve. Since NDSolve builds up the solution as it goes, this is typically much faster.

Clear[y];
y[x_] = y[x] /. First[
NDSolve[{y'[x] == Sin[x], y[0] == 0}, y[x], {x, 0, 10}]
];
t = AbsoluteTime[];
Plot[y[t], {t, 0, 10}]
AbsoluteTime[] - t


-
Thank you! That's a very smart way:) I wonder if it will also work when the integrand is complicated. – luyuwuli Apr 23 '13 at 12:37
@luyuwuli It should work whenever NDSolve works. My guess is that it is not quite a broadly applicable as the integrate technique, but it should be nearly so. – Mark McClure Apr 23 '13 at 12:41
I just came up with the idea that if the function has parameters in the integrand(no just the upper-limit),following the same way, ParametricNDSolve will do the trick:) I think this may be called ParametricNIntegrate. Thank you again! – luyuwuli Apr 23 '13 at 12:55
Since NDSolve[] is also more cautious than NIntegrate[], this approach is also less likely to miss features of your integrand, like sharp peaks. – J. M. Apr 23 '13 at 13:54
@J.M. Why is NDSolve more cautious than NIntegrate? IMHO, solving the integral is easier than the PDEs. – luyuwuli Apr 23 '13 at 14:11

An alternative approach is to form an approximate interpolating function from your actual function, which is (often) cheaper to integrate. To wit,

nsin = FunctionInterpolation[Sin[x], {x, 0, 10}];
ni = Derivative[-1][nsin];

Plot[ni[t], {t, 0, 10}]


In this case, we know that the integral of sine can be expressed simply, so we can compare the exact function with the approximate one:

Plot[ni[t] - 2 Haversine[t], {t, 0, 10}, Frame -> True, PlotRange -> All]


Pretty darn good, if I do say so myself! If you need a bit more accuracy, FunctionInterpolation[] has a number of options you can tweak as needed; see the docs for details.

-
Thanks. I've added a solution to do something like ParametricNIntegrate. I'm just not sure whether it's good. – luyuwuli Apr 24 '13 at 3:44

Another possibility is to sieze control over the evaluation of f[t]. For instance:

ListLinePlot[Table[f[t], {t, 0, 10, 0.1}]]


evaluates f[t] at exactly the points you choose. In this case, it gives substantially the same plot as the original, and is about 10 times faster.

-
This is a discrete version. The drawback is that I have to manually decided how many and which points to calculate. For a complicated function, it would very difficult to do so. And in the aspect of saving calculation, I think that this method will repeat the integral 101 times. If the number of selected points is as much as the one in Plot, this will also drag down the speed. – luyuwuli Apr 23 '13 at 13:52