# How to choose MaxStepFraction for optimal speed of NDSolve

I'm trying to use NDSolve to solve a 1D Schrodinger's equation, and it seems that MaxStepFraction has huge effect on the performance.

L = 5; Et[t_] := Cos[2 t];
eqn = I D[ψ[x, t], t] == -(1/2) (D[ψ[x, t], {x, 2}]) + Et[t]*x*ψ[x, t]
init = {ψ[x, 0] == Exp[-(4 x^2)], ψ[L, t] == ψ[-L, t]}

sol = NDSolve[{eqn}~Join~init, ψ, {x, -L, L}, {t, 0, 6}, MaxStepFraction -> 1/2000]; // AbsoluteTiming


Here are the timing information I get:

MaxStepFraction |time(second)|
----------------+------------+
1/1800          |not converge|
1/2000          | 4.5        |
1/2500          | 98.5       |
1/3000          | 9.1        |


For not converge, I mean it gives warning like:

NDSolve::eerr: Warning: scaled local spatial error estimate of 640.1602231577178at t = 4.504519571558874 in the direction of independent variable x is much greater than the prescribed error tolerance. Grid spacing with 1801 points may be too large to achieve the desired accuracy or precision. A singularity may have formed or a smaller grid spacing can be specified using the MaxStepSize or MinPoints method options. >>

If we slightly change L, and let L=7.5, the performance is quit different:

MaxStepFraction |time(second)|
----------------+------------+
1/1800          |not converge|
1/2000          | 64         |
1/2500          |not converge|
1/3000          | 136        |


Questions:

1. Why the value of MaxStepFraction affect the performance so dramatically? For example, sometimes converge very fast, and sometimes doesn't converge at all.
2. Are there some guide lines for choose the the value of MaxStepFraction for optimal performance?
3. General guide lines for better performance of NDSolve for PDEs (or should I leave NDSolve and build my own solver)?

PS: I'm using version 9 on Red Hat Enterprise Linux 6, on Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz.

-
……Where's your m? – xzczd Jan 26 '14 at 4:56
@xzczd m=1. Sorry I forget to delete it when I try to post a simplified version :P – xslittlegrass Jan 26 '14 at 18:42
I just come to mention that all of your MaxStepFraction don't "converge" for L = 5 in v8.0.4. (Vista Home Basic 32bit. BTW, 2GB memory so it can't bear the L = 7.5 case 囧.) And according to my experience, warning messages of NDSolve isn't a big deal for many cases. With the method mentioned in this post your warning will disappear but in fact the result doesn't change much. – xzczd Feb 1 '14 at 10:40

This is more of an observation than an answer. I wonder if using the default Method -> Automatic is contributing to the problem. Consider the following:

AbsoluteTiming[
NDSolve[{eqn}~Join~init, ψ, {x, -L, L}, {t, 0, 6},
MaxStepFraction -> 1/2000, Method -> #];] & /@ {"Adams", "BDF",
"ExplicitRungeKutta", "ImplicitRungeKutta",
"SymplecticPartitionedRungeKutta"}


which yields these time on my computer:

{{47.162698, Null}, {7.547432, Null}, {0.200011, Null}, {53.612066,
Null}, {0.269015, Null}}

Setting MaxStepFraction to 1800 and 2500 respectively yields:

{{41.212357, Null}, {36.713100, Null}, {0.286016, Null}, {50.241874, Null}, {0.234013, Null}}
{{58.735360, Null}, {12.217699, Null}, {0.235013, Null}, {72.846166, Null}, {0.277016, Null}}

Ignoring for the moment if the method is appropriate for the problem at hand, fixing the Method to something other than Automatic yields timing values that change in an expected way:

AbsoluteTiming[NDSolve[{eqn}~Join~init, \[Psi], {x, -L, L}, {t, 0, 6},
MaxStepFraction -> 1/#, Method -> "BDF"];] & /@ {1800, 2000, 2500,3000, 3500, 4000}


{{36.713100, Null}, {7.971456, Null}, {12.506715, Null}, {17.591006, Null}, {24.079377, Null}, {32.103836, Null}}

The timing for Method->"BDF" and MaxStepFraction -> 1/1800 is an outlier because I get the same error as the OP.

At the moment, I'm not sure where to go from here, but I thought I'd toss out these ideas in case it spurs someone else's imagination.

-