Forcing NDSolve not to store full solution, in order to save memory
Inspired from Nasser's answer:
It's possible to return only the last (or some other specific values) value from NDSolve
.
Try
sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 5, y[0] == 1, y'[0] ==0},y[5], {x, 4.5, 5}]
ByteCount[sol3](*16*)
Is there a way to save memory by forcing NIntegrate to only return the final values of the dependent variables?
One way could be to just give it the small end range of interest, this way the interpolation function will have much smaller size. You can still give initial conditions at say x=0
but tell it to given solution starting at much larger x
value, and it will still work. The x_start
in {x,x_start,x_end}
does not have to be the same as the initial value of x
.
For example, instead of
sol = NDSolveValue[{y''[x] + Sin[x]*x == 5, y[0] == 1, y'[0] == 0}, y, {x, 0, 5}]
Plot[sol[x], {x, 0, 5}]
sol2 = NDSolveValue[{y''[x]+Sin[x]*x==5,y[0]==1,y'[0]==0},y,{x,4.5,5}]
Plot[sol2[x],{x,4.5,5},AxesOrigin->{0,0}]
If you compare sol
and sol2
, you'll see sol2
has less data in it.
ByteCount[sol]
(*3984*)
ByteCount[sol2]
(*1936*)
I feel some clarification is needed to the answers by @Nasser and @UlrichNeumann. There's not really much difference in the memory used by either. @UlrichNewmann's sol3 = NDSolveValue[..., y[5],...]
seems basically to be syntactic sugar for sol3 = NDSolveValue[..., y,...]; sol3 = sol3[5]
. The main memory saving comes from @Nasser's {x, 4.5, 5}
, instead of which {x, 5, 5}
would give even more memory savings.
Examples: I've extended the domain so that the differences would be more noticeable.
@UlrichNeumann's method:
Quit[]
$HistoryLength = 0;
MaxMemoryUsed[]
(* 65508912 -- baseline *)
sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 1/1000, y[0] == 1,
y'[0] == 0}, y[200000], {x, 100000, 200000}];
ByteCount[sol3]
MaxMemoryUsed[]
(*
16
235687584
*)
MemoryInUse[]
(* 82906632 *)
Quit[]
@Nasser's method. Note that the max memory usage and the memory in use after sol3 = sol3[200000]
are similar.
$HistoryLength = 0;
MaxMemoryUsed[]
(* 65508848 -- baseline *)
sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 1/20, y[0] == 1,
y'[0] == 0}, y, {x, 100000, 200000}];
ByteCount[sol3]
MaxMemoryUsed[]
(*
59626536
238685400
*)
MemoryInUse[]
(* 142533152 *)
sol3 = sol3[200000];
ByteCount[sol3]
(* 16 *)
MemoryInUse[]
(* 82906320 *)
The equivalent of using {x, 5, 5}
with @UlrichNeumann's method. Note that the max memory used is just a little above the memory in use.
Quit[]
$HistoryLength = 0;
MaxMemoryUsed[]
(* 65508848 -- baseline *)
sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 1/20, y[0] == 1,
y'[0] == 0}, y[200000], {x, 200000, 200000}];
ByteCount[sol3]
MaxMemoryUsed[]
(*
16
85011648
*)
MemoryInUse[]
(* 82640112 *)