TransWikia.com

Speed up a differential equation solution + parameter integration + parameter maximization

Mathematica Asked by Nicola on January 23, 2021

The problem I am trying to solve can be described as a maximization of an integral of the solution of a differential equation. A MWE is

ClearAll["Global`*"]
$Assumptions =  a > 0 && n > 1;
sol[a_, n_] := NDSolve[{X'[u] == a^2/2 ((1 + n) (1 - 2 X[u]) + Sqrt[4 n + (1 - n)^2 (1 - 2 X[u])^2]), X[0] == 1/2}, X[u], {u, 0, 1}];
P[a_, n_?NumericQ, t_] := (X[u] /. sol[a, n] /. {u -> t})[[1]];
Pmax[a0_, n0_] := Module[{a = a0, n = n0}, 
   f[m_?NumericQ] := NIntegrate[P[a, n - m, 1] E^-(m  a^2 + b^2) 2 b BesselI[0, 2 Sqrt[m] a b], {b, 0, ∞}]; 
   maxIntegral = NMaximize[f[m], {m} ∈ Interval[{0., n}]]; {maxIntegral[[1]], maxIntegral[[2, 1, 2]]}];
Pmax[1.5, 2] // Timing (* gives me {420.376, {0.998829, 4.47458*10^-12}} *)

How can I speed up the evaluation? I am interested in Pmax ranging 0<a<2 and 1<n<20, I suspect there will be numerical issues as n increases.

In addition, is there a better practice to formulate the problem in Mathematica?

EDIT: As suggested in an answer, in this particular MWE the term P[a, n - m, 1] can be left out of NIntegrate, leading to a simplification of the evaluation (the integral gives 1). In the original problem, P also depends on b, so I am looking to more computationally-efficient ways to perform the nested sequence of NDSolve, NIntegrate and NMaximize.

2 Answers

Here my solution attempt

In the definition f[m_]:=… one can leave out P[a, n - m, 1] because it doesn't depend on b. The remaining Integral

Integrate[E^-(m a^2 + b^2) 2 b BesselI[0, 2 Sqrt[m] a b], {b, 0, [Infinity]},Assumptions -> Element[m, Reals]]
(*ConditionalExpression[1, m != 0]*)

equals 1 for real m(m!=0)!

Modified definition Pmax

Pmax[a0_, n0_] :=Module[{a = a0, n = n0}, f[m_?NumericQ] := P[a, n - m, 1] ;
maxIntegral =NMaximize[
f[m], {m} [Element] Interval[{0., n}]]; {maxIntegral[[1]],maxIntegral[[2, 1, 2]]}]     

now is evaluated

Pmax[1.5, 2] // Timing
(*{32.8125, {0.998829, -6.705*10^-26}}*)

in 32seconds! (<< 420s)

Answered by Ulrich Neumann on January 23, 2021

Use a detour with Plot , Reap the plotted points and generate an interpolating function for f[m] to get maximum in half a second.

See Edit at end

Xsol[a_?NumericQ, n_?NumericQ] := 
    X /. First@
NDSolve[{Derivative[1][X][u] == 
  a^2/2 ((1 + n) (1 - 2 X[u]) + 
     Sqrt[4 n + (1 - n)^2 (1 - 2 X[u])^2]), X[0] == 1/2}, 
X, {u, 0, 1}]

Xsol[3, 2][.3]

nint[m_, a_, n_] := 
  NIntegrate[
Xsol[a, n - m][1] E^-(m a^2 + b^2) 2 b BesselI[0, 
2 Sqrt[(m)] a b], {b, 0, [Infinity]}]

Get maximum with Plot and see what is going on.

Manipulate[{pl2 = 
   Plot[nint[m, a, n], {m, 0, n}, PlotRange -> {.45, 1.05}, 
ImageSize -> 400], {"Max=", 
Max[pl2[[1, 1, 3, 2, 1]][[All, 2]]]}}, {{a, 1}, 0, 2, 
Appearance -> "Labeled"}, {{n, 3}, 1, 20, Appearance -> "Labeled"}, 
ContinuousAction -> False]

rp[a_, n_] := 
  Reap[Plot[fr = nint[m, a, n], {m, 0, n}, PlotPoints -> 30, 
 MaxRecursion -> 1, EvaluationMonitor :> Sow[{m, fr}]]][[2, 1]] //
Sort

f[a_?NumericQ, n_?NumericQ] := Interpolation[rp[a, n]]

f[1, 3][1]

Plot[Evaluate[f[1, 3][m]], {m, 0, 3}, PlotRange -> All]

max[a_, n_] := Maximize[{f[a, n][m], 0 <= m <= n}, m]

nmax[a_, n_] := NMaximize[{f[a, n][m], 0 <= m <= n}, m]

{max[2, 2] // AbsoluteTiming, nmax[2, 2] // AbsoluteTiming}


(*   {{0.4843818, {0.999989, {m -> 0.}}}, {0.5312506, {0.999989, {m -> 
 0.}}}}   *)

Maximize and NMaximize need the same time. You gain a lot of speed due to MaxRecursion -> 1 in Plot, but accuracy seems not to suffer.

Edit I just see, for high n the interpolation generates artificial peaks for f[m] at m near n, which give maxima above 1.0. Have no more time to play with InterpolationOrder or else to correct it. (As rp[a,n] shows,you can set it to 1 this case.) Leave it to you.

Answered by Akku14 on January 23, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP