Let me first show what I'm trying to do, and then I will ask the question.

I defined three function

BumpFunction[x_] := Exp[-x^2/(1-x^2)]

IntegrateBumpFunction[x_] := NIntegrate[BumpFunction[t] , {t, 0, x}]

IntegrateBumpFunctionNormalized[x_] := NIntegrate[BumpFunction[t] , {t, 0, x}]/NIntegrate[BumpFunction[t] , {t, 0, 1}]

Then, I will use Timing to measure the time spend to plot the functions IntegrateBumpFunction and IntegrateBumpFunctionNormalized.

Timing[Plot[IntegrateBumpFunction[x], {x,-1,1}]]
Timing[Plot[IntegrateBumpFunctionNormalized[x], {x,-1,1}]]

You will see that there is a runtime difference. The cause of this discrepancy is in the denominator NIntegrate[BumpFunction[t] , {t, 0, 1}] in the function IntegrateBumpFunctionNormalized. In my opinion this happen because the Plot function calls the IntegrateBumpFunctionNormalized function several times during its execution and you always have to evaluate the integral NIntegrate[BumpFunction[t] , {t, 0, 1}]. This causes an increase in time to plot.bvd

My question is: Is it possible to avoid this problem by telling the plot function evaluate the term NIntegrate[BumpFunction[t] , {t, 0, 1}] only once?


  • 3
    $\begingroup$ Any function that uses a numeric technique (e.g., NIntegrate) should have its argument(s) restricted to numeric values (NumericQ), e.g., IntegrateBumpFunction[x_?NumericQ] := ... $\endgroup$
    – Bob Hanlon
    Oct 24 at 18:08
  • 2
    $\begingroup$ AbsoluteTiming is preferable to Timing in modern multi-threaded CPUs. $\endgroup$
    – Michael E2
    Oct 24 at 19:39

Change definition of normalized function

nor = NIntegrate[BumpFunction[t], {t, 0, 1}]; 
IntegrateBumpFunctionNormalized[x_] := 
    NIntegrate[BumpFunction[t], {t, 0, x}]/nor

Or, ultrafast, integrate with NDSolve , so you don't have to integrate as many times as you have plotPoints, but only once generate an interpolating fucntion.

BumpFunction[x_] = Exp[-x^2/(1 - x^2)];

bfsol = bf /. 
  First@NDSolve[{bf'[x] == BumpFunction[x], bf[0] == 0}, 
bf, {x, -1, 1}]

Timing[Plot[bfsol[x], {x, -1, 1}]]
Timing[Plot[bfsol[x]/bfsol[1], {x, -1, 1}]]
  • 3
    $\begingroup$ Shorter, if plotting only: NDSolveValue[{bf'[x] == BumpFunction[x], bf[0] == 0}, bf, {x, -1, 1}] // ListLinePlot, though normalized is not quite as slick: NDSolveValue[{bf'[x] == BumpFunction[x], bf[0] == 0}, {Indexed[bf@"Coordinates", 1], bf@"ValuesOnGrid"/bf[1]}, {x, -1, 1}] // Transpose // ListLinePlot (+1) $\endgroup$
    – Michael E2
    Oct 24 at 19:40
  • $\begingroup$ Hi @Akku14. Your answer really works. However, I was trying to keep all the computation within a single function and not separate parts. Anyway, thanks for the reply. $\endgroup$
    – jon jones
    Oct 24 at 22:12
  • $\begingroup$ Hi @jonjones, "trying to keep all the computation within a single function" is a new request, not something you specified in your original question. I think that moving the goalpost after receiving a good answer is not nice. Probably you can ask a new question with all the new requirements spelt out explicitly from the beginning. $\endgroup$
    – rhermans
    Oct 25 at 9:28
  • $\begingroup$ @MichaelE2 , thanks for the tips from a real expert. $\endgroup$
    – Akku14
    Oct 25 at 10:25
  • $\begingroup$ Hello @rhermans, . I think you are right. The answer was really good and I had no intention of belittling the answer gave by Michael E2. $\endgroup$
    – jon jones
    Oct 25 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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