       Re: NDSolve memory management problem

• To: mathgroup at smc.vnet.net
• Subject: [mg102358] Re: NDSolve memory management problem
• From: schochet123 <schochet123 at gmail.com>
• Date: Thu, 6 Aug 2009 06:33:38 -0400 (EDT)
• References: <h41f71\$rjo\$1@smc.vnet.net>

```On Jul 20, 1:00 pm, David Szekely <dr.szek... at gmail.com> wrote:

> I'm currently trying to run a simulation in Mathematica usingNDSolvein se=
veral >dimensions. However, it tends to chew up systemmemoryvery quickly an=
d give the >standard:
> "No morememoryavailable.
> Mathematica kernel has shut down.
> Try quitting other applications and then retry."
> message.
> Here's some code for the heat equation in 4 dimensions over relatively sm=
all >ranges to show what I mean:
> i = 0;
> sol =NDSolve[{D[u[t, x, y, z], t] ==
>     D[u[t, x, y, z], x, x] + D[u[t, x, y, z], y, y] +
>      D[u[t, x, y, z], z, z],
>    u[0, x, y, z] == 0,
>    u[t, 0, y, z] == Sin[t],
>    u[t, 40, y, z] == 0,
>    u[t, x, 0, z] == Sin[t],
>    u[t, x, 40, z] == 0,
>    u[t, x, y, 0] == Sin[t],
>    u[t, x, y, 40] == 0},
>   {u}, {t, 0, 100}, {x, 0, 40}, {y, 0, 40}, {z, 0, 40},
>   MaxSteps -> Infinity, MaxStepSize -> 1,
>
>   EvaluationMonitor :> If[t > i,
>     Print[{t, MemoryInUse[]/1024^2 // N}];
>     i += 10;]
>
>   ]
> MemoryInUse[]/1024^2 // N
>
> The only solutions I need are at t = 0, 5, 10, 15 etc.. Ideally, what i=
'd like to be >able to do is add a function in "EvaluationMonitor" which re=
moves all values of t >other than the ones that I need *as it solves the sy=
stem*. This would significantly >reduce the strain on systemmemory. I would=
greatly appreciate help on this >problem! Adding morememoryis not a good s=
olution since my actual problem kills >a system with 12 Gb ofmemory:(

There are two steps that have to be taken to get around this problem.
The first is to make NDSolve stop whenever a lot of memory is being
used. The way to do that is with the EventLocator method. The second
step is to make Mathematica give back most of the memory it is using,
while keeping the computed value of the solution. That is slightly
tricky, since if we define something like solnow[x_,y_,z_]=uu
[tnow,x,y,z] where uu is a name given to the InterpolatingFunction
returned by NDSolve  then solnow uses the same amount of memory as uu
so doing Clear[uu] won't reduce memory usage. It is therefore
necessary to extract the grid points and values from the
InterpolatingFunction at the current time and use Interpolation to
produce an InterpolatingFunction using only the values at the current
time. The modification of your example given below yields the solution
(called solnow[x,y,z]) at the final time without running out of
memory. You will need to modify it if you also want to store the
solution at particular intermediate times.

Although not strictly necessary, I replaced EvaluationMonitor with
StepMonitor to reduce the number of evaluations; for example, a fourth-
order RungaKutta  method evaluates the functions appearing in the ODE
four times for each time step.

In a more complicated problem it may also be necessary to use a 64 bit
system to avoid kernel memory limits, since the size of the steps
needed to keep memory usage down might otherwise be too small.
Presumably the OP uses such a system since he has 12GB memory.

Steve

Needs["DifferentialEquations`InterpolatingFunctionAnatomy`"]

i = 0; maxmemorytouse =  300 1024^2;
timenow = 0; maxtime = 100; solnow = (0 &);

While[timenow < maxtime,
usol = u /.
NDSolve[{D[u[t, x, y, z], t] ==
D[u[t, x, y, z], x, x] + D[u[t, x, y, z], y, y] +
D[u[t, x, y, z], z, z],
u[timenow, x, y, z] == solnow[x, y, z], u[t, 0, y, z] == Sin[=
t],
u[t, 40, y, z] == 0, u[t, x, 0, z] == Sin[t],
u[t, x, 40, z] == 0, u[t, x, y, 0] == Sin[t],
u[t, x, y, 40] == 0}, {u}, {t, timenow, 100}, {x, 0, 40}, {y, 0,
40}, {z, 0, 40},
Method -> {"EventLocator",
"Event" :> MemoryInUse[] > maxmemorytouse},
MaxSteps -> Infinity, MaxStepSize -> 1,
StepMonitor :>
If[t > i,
Print[{"StepMonitor: At time ", t, "Memory in use is",
MemoryInUse[]/1024^2 // N}];
i += 10;]][];
Print[{"At time ",
timenow =
InterpolatingFunctionDomain[First[Flatten[{usol}]]][[1, -1]],
"Memory in use was ", MemoryInUse[]/1024^2 // N}];
xyzvals = Rest /@ Flatten[Last[InterpolatingFunctionGrid[usol]], 2];
uvals = Flatten[Last[InterpolatingFunctionValuesOnGrid[usol]]];
Clear[usol]; solnow = Interpolation[Transpose[{xyzvals, uvals}]];
Print[{"Memory in use reduced to ", MemoryInUse[]/1024^2 // N}]]

```