MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Vector Runge-Kutta ODE solver with compilation?

  • To: mathgroup at smc.vnet.net
  • Subject: [mg116805] Re: Vector Runge-Kutta ODE solver with compilation?
  • From: Oliver Ruebenkoenig <ruebenko at wolfram.com>
  • Date: Tue, 1 Mar 2011 05:20:29 -0500 (EST)

On Mon, 28 Feb 2011, DmitryG wrote:

> On 27 Feb., 04:43, Oliver Ruebenkoenig <ruebe... at wolfram.com> wrote:
>
>> You could use CompilePrint to see that for NN=11 this generates a some 900
>> line so code - quite a lot of which are Part[]. Make sure you understand
>> what you are doing here - you in-line this sum into the code.
>>
>>
> ......................
>>
>> Weird code? - No, not really.
>> ...
>>

Hi Dmitry,

>
> Hi Oliver,
>
> In this short program I mimick my real-life program that solves a

Why do you not send the example that you classify as real-life?

> system of NN ODE's with the maximal coupling: the RHS of each of NN
> equations contains all NN variables. Any molecular dynamics (MD)
> simulation is of this kind: Acceleration of any particle depends on
> positions of all particles.
>

One method I have seen for MD programs is to use a cut-off range that 
mimics for example the Lennard-Jones potential - which reduces the 
complexity of the alg.

> This application of Mathematica's compilation is crucial but there are
> two problems that I have encountered:
>
> 1) Compilation in C is prohibitively slow above NN=50 or so. In this
> case Mathematica's own compiler is still doing a good job.
>

I think the in-lining of the sum is not what you want to do here. You 
should either use vectorized code or another compiled function, as shown 
in a previous post.

> 2) For NN=1000 or above Mathematica's compiler consumes all RAM (my
> laptop has 3 GB RAM) and quits. This is very disappointing because
> generating the list of RHS does not take much memory and the RK 4
> routine does not consume much memory as well. Thus it would be only a
> matter of computer time to solve a problem for any NN. However,
> compiler generates a blown-up code (component by component, with the
> vector structure abandoned) that does not fit into memory.
>

No it is not that compiler that generated this - you told it to in-line that 
into the code and that's what happened. - A compiler is optimized to 
optimize hand written code - it can not do logical simplifications.

Would you copy and past your sum function in a C file? No, you'd write a 
function and call it. In Mathematica you additionally have the option to 
use vectorized code. What is wrong with a vector approach?

> Thank you for suggestion to look into the compiled code with
> CompilePrint. Yes, the code is very long, and its structure is the
> same for the initial problem we considered, the problem with
>
> RHS=Quiet[{x[[2]],1-x[[1]]+4/x[[1]]^3}]
>

Just the slight difference that in the initial problem NN=2.

> Also in this case the compiled code contains Part[].
>
> Is there any way to optimize this calculation or we have an intrinsic
> limitation of Mathematica here? Below is the code again:
>

The limitation is in the code you inline. It is not that you inline, but 
what you inline.

> *******************************************************************************
> (* Definition *)
> makeCompRK[fIn_]:=With[{f=fIn},Compile[{{x0,_Real,1},{t0,_Real},
> {tMax,_Real},{n,_Integer}},Module[{h,K1,K2,K3,K4,SolList,x=x0,t},
> h=(tMax-t0)/n;
> SolList=Table[x0,{n+1}];
> Do[t=t0+k h;
> K1=h f[t,x];
> K2=h f[t+(1/2) h,x+(1/2) K1];
> K3=h f[t+(1/2) h,x+(1/2) K2];
> K4=h f[t+h,x+K3];
> x=x+(1/6) K1+(1/3) K2+(1/3) K3+(1/6) K4;
> SolList[[k+1]]=x
>
> ,{k,1,n}];
> SolList](*,CompilationTarget->"C"*)]];
>
> (* Calculation *)
> NN=15;
> Timing[RHS=Quiet[Table[-x[[i]]/(1+300Sum[x[[j]],{j,1,NN}]^2/NN^2),{i,
> 1,NN}]];] (* Quiet to suppress complaints *)
> F=Function[{t,x},Evaluate[RHS]];  (* Evaluate to use actual form of
> RHS *)
> Print[]
>
> tt0=AbsoluteTime[];
> Timing[RK4Comp=makeCompRK[F];]
> AbsoluteTime[]-tt0
> Print[];
>
> x0=Table[RandomReal[{0,1}],{i,1,NN}];   t0=0;    tMax=50;   n=500;
> tt0=AbsoluteTime[];
> Sol=RK4Comp[x0,t0,tMax,n];
> AbsoluteTime[]-tt0
>
> Print["Compilation: ",Developer`PackedArrayQ@Sol]
>
> (* Plotting time dependences *)
>
> x1List=Table[{1.t0+(tMax-t0)k/n,Sol[[k+1,1]]},{k,0,n}];
> x2List=Table[{1.t0+(tMax-t0)k/n,Sol[[k+1,2]]},{k,0,n}];
> x3List=Table[{1.t0+(tMax-t0)k/n,Sol[[k+1,3]]},{k,0,n}];
> ListLinePlot[{x1List,x2List,x3List},PlotMarkers->Automatic,PlotStyle-
>> {Blue,Green,Red},PlotRange->{0,1}]
>
>
> *********************************
>
> Thank you for your help,
>
> Dmitry
>
>

Here is the code for NN=1000, tMax0 and n = 50000

makeCompRK[fIn_] :=
   With[{f = fIn},
    Compile[{{x0, _Real,
       1}, {t0, _Real}, {tMax, _Real}, {n, _Integer}},
     Module[{h, K1, K2, K3, K4, SolList, x = x0, t},
      h = (tMax - t0)/n;
      SolList = Table[x0, {n + 1}];
      Do[t = t0 + k h;
       K1 = h f[t, x];
       K2 = h f[t + (1/2) h, x + (1/2) K1];
       K3 = h f[t + (1/2) h, x + (1/2) K2];
       K4 = h f[t + h, x + K3];
       x = x + (1/6) K1 + (1/3) K2 + (1/3) K3 + (1/6) K4;
       SolList[[k + 1]] = x, {k, 1, n}];
      SolList], CompilationTarget -> "C"]];

NN = 1000;
RHS = Quiet[-x/(1 + 300*Total[x]^2/NN^2)]
F = Function[{t, x}, Evaluate[RHS]]

tt0 = AbsoluteTime[];
Timing[RK4Comp = makeCompRK[F];]
AbsoluteTime[] - tt0

x0 = RandomReal[{0, 1}, {NN}]; t0 = 0; tMax = 200; n = 50000;
tt0 = AbsoluteTime[];
Sol = RK4Comp[x0, t0, tMax, n];
AbsoluteTime[] - tt0

runs in about 3.7 sec on my laptop.

Oliver


  • Prev by Date: Re: NIntegrate and speed
  • Next by Date: Re: Vector Runge-Kutta ODE solver with compilation?
  • Previous by thread: Re: Vector Runge-Kutta ODE solver with compilation?
  • Next by thread: Re: Vector Runge-Kutta ODE solver with compilation?