Ways to speed up user implemented RK4Speed up Numerical IntegrationHow to choose MaxStepFraction for optimal speed of NDSolveNIntegrate: how to speed up code?Compiling FoldList implementation for RK4How to speed up this code?Solving an unstable BVP numerically, accurately and efficientlyHow to speed up integral of results of PDE modelSolve BVP involving user defined functionWays to speed up PickSpeed up ParametricNDSolve

How do I go from 300 unfinished/half written blog posts, to published posts?

How to run a prison with the smallest amount of guards?

Are student evaluations of teaching assistants read by others in the faculty?

How to safely derail a train during transit?

How to be diplomatic in refusing to write code that breaches the privacy of our users

Trouble understanding the speech of overseas colleagues

What is paid subscription needed for in Mortal Kombat 11?

Large drywall patch supports

Tiptoe or tiphoof? Adjusting words to better fit fantasy races

Is expanding the research of a group into machine learning as a PhD student risky?

Is HostGator storing my password in plaintext?

How does the UK government determine the size of a mandate?

Is there a good way to store credentials outside of a password manager?

How do scammers retract money, while you can’t?

I'm in charge of equipment buying but no one's ever happy with what I choose. How to fix this?

Method to test if a number is a perfect power?

Applicability of Single Responsibility Principle

What Brexit proposals are on the table in the indicative votes on the 27th of March 2019?

Pole-zeros of a real-valued causal FIR system

How to Reset Passwords on Multiple Websites Easily?

What is the difference between "behavior" and "behaviour"?

Anatomically Correct Strange Women In Ponds Distributing Swords

Opposite of a diet

What can we do to stop prior company from asking us questions?



Ways to speed up user implemented RK4


Speed up Numerical IntegrationHow to choose MaxStepFraction for optimal speed of NDSolveNIntegrate: how to speed up code?Compiling FoldList implementation for RK4How to speed up this code?Solving an unstable BVP numerically, accurately and efficientlyHow to speed up integral of results of PDE modelSolve BVP involving user defined functionWays to speed up PickSpeed up ParametricNDSolve













8












$begingroup$


So, I've implemented RK4, and I'm wondering what I can do to make it more efficient? What I've got so far is below. I wish to still record all steps. I think AppendTo is doing the most damage to the time, is there a faster alternative?



rk4[f_, variables_, valtinit_, tinit_, tfinal_, nsteps_] := 
Module[table, xlist, ylist, step, k1, k2, k3, k4,
xlist = tinit;
step = N[(tfinal - tinit)/(nsteps)];
ylist = valtinit;
table = xlist, ylist;
Table[
k1 = step* f /. MapThread[Rule, variables, ylist]; (*
Equivalent to step* f/.Thread[Rule[variables,ylist]]*)
k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist];
k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist];
k4 = step*f /. MapThread[Rule, variables, k3 + ylist];
ylist += 1/6 (k1 + 2 (k2 + k3) + k4);
xlist += step;
AppendTo[table, xlist, ylist];
xlist, ylist, nsteps];
table
];


Example Input:



funclist = -x + y, x - y;
initials = 1, 2;
variables = x, y;
init = 0;
final = 200;
nstep = 20000;
approx = rk4[funclist, variables, initials, init, final, nstep]//AbsoluteTiming;



3.59932,...




I'd love some suggestions!










share|improve this question











$endgroup$







  • 3




    $begingroup$
    AppendTo is quadratic time complexity. Might be better to preallocate and set by index. Also it'll be much faster to not use Rule and instead code stuff up a little bit more explicitly. As a general rule, too, use vectorized operators. Those can be very fast. And if everything can be totally functional over "packed arrays" (look them up here) it'll be very quick too.
    $endgroup$
    – b3m2a1
    yesterday










  • $begingroup$
    I'll work on implementing it more explicity, this is what came to find first though. It'll require some changes to the inputs, I'll have to ponder this. And preallocating the list is a quick change that won't be an issue to do, I can't believe I forgot that's faster :(. Thanks though!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    Shinaoloard, using Join[ xlist, ylist, Table[ k1 = step*f /. MapThread[Rule, variables, ylist]; k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist]; k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist]; k4 = step*f /. MapThread[Rule, variables, k3 + ylist]; ylist += 1/6 (k1 + 2 (k2 + k3) + k4); xlist += step; xlist, ylist, nsteps ] ] as return value is already a first step. There is no point in appending if you use a Table anyways.
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 3




    $begingroup$
    Why not just get NDSolve[] to use fourth-order Runge-Kutta to begin with?
    $endgroup$
    – J. M. is slightly pensive
    23 hours ago






  • 1




    $begingroup$
    @J.M.isslightlypensive I know it can, I just wanted to make sure I could actually code it myself, instead of just using options to get Mathematica to do it for me (:. Thanks for trying to help though!!
    $endgroup$
    – Shinaolord
    13 hours ago















8












$begingroup$


So, I've implemented RK4, and I'm wondering what I can do to make it more efficient? What I've got so far is below. I wish to still record all steps. I think AppendTo is doing the most damage to the time, is there a faster alternative?



rk4[f_, variables_, valtinit_, tinit_, tfinal_, nsteps_] := 
Module[table, xlist, ylist, step, k1, k2, k3, k4,
xlist = tinit;
step = N[(tfinal - tinit)/(nsteps)];
ylist = valtinit;
table = xlist, ylist;
Table[
k1 = step* f /. MapThread[Rule, variables, ylist]; (*
Equivalent to step* f/.Thread[Rule[variables,ylist]]*)
k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist];
k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist];
k4 = step*f /. MapThread[Rule, variables, k3 + ylist];
ylist += 1/6 (k1 + 2 (k2 + k3) + k4);
xlist += step;
AppendTo[table, xlist, ylist];
xlist, ylist, nsteps];
table
];


Example Input:



funclist = -x + y, x - y;
initials = 1, 2;
variables = x, y;
init = 0;
final = 200;
nstep = 20000;
approx = rk4[funclist, variables, initials, init, final, nstep]//AbsoluteTiming;



3.59932,...




I'd love some suggestions!










share|improve this question











$endgroup$







  • 3




    $begingroup$
    AppendTo is quadratic time complexity. Might be better to preallocate and set by index. Also it'll be much faster to not use Rule and instead code stuff up a little bit more explicitly. As a general rule, too, use vectorized operators. Those can be very fast. And if everything can be totally functional over "packed arrays" (look them up here) it'll be very quick too.
    $endgroup$
    – b3m2a1
    yesterday










  • $begingroup$
    I'll work on implementing it more explicity, this is what came to find first though. It'll require some changes to the inputs, I'll have to ponder this. And preallocating the list is a quick change that won't be an issue to do, I can't believe I forgot that's faster :(. Thanks though!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    Shinaoloard, using Join[ xlist, ylist, Table[ k1 = step*f /. MapThread[Rule, variables, ylist]; k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist]; k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist]; k4 = step*f /. MapThread[Rule, variables, k3 + ylist]; ylist += 1/6 (k1 + 2 (k2 + k3) + k4); xlist += step; xlist, ylist, nsteps ] ] as return value is already a first step. There is no point in appending if you use a Table anyways.
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 3




    $begingroup$
    Why not just get NDSolve[] to use fourth-order Runge-Kutta to begin with?
    $endgroup$
    – J. M. is slightly pensive
    23 hours ago






  • 1




    $begingroup$
    @J.M.isslightlypensive I know it can, I just wanted to make sure I could actually code it myself, instead of just using options to get Mathematica to do it for me (:. Thanks for trying to help though!!
    $endgroup$
    – Shinaolord
    13 hours ago













8












8








8


1



$begingroup$


So, I've implemented RK4, and I'm wondering what I can do to make it more efficient? What I've got so far is below. I wish to still record all steps. I think AppendTo is doing the most damage to the time, is there a faster alternative?



rk4[f_, variables_, valtinit_, tinit_, tfinal_, nsteps_] := 
Module[table, xlist, ylist, step, k1, k2, k3, k4,
xlist = tinit;
step = N[(tfinal - tinit)/(nsteps)];
ylist = valtinit;
table = xlist, ylist;
Table[
k1 = step* f /. MapThread[Rule, variables, ylist]; (*
Equivalent to step* f/.Thread[Rule[variables,ylist]]*)
k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist];
k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist];
k4 = step*f /. MapThread[Rule, variables, k3 + ylist];
ylist += 1/6 (k1 + 2 (k2 + k3) + k4);
xlist += step;
AppendTo[table, xlist, ylist];
xlist, ylist, nsteps];
table
];


Example Input:



funclist = -x + y, x - y;
initials = 1, 2;
variables = x, y;
init = 0;
final = 200;
nstep = 20000;
approx = rk4[funclist, variables, initials, init, final, nstep]//AbsoluteTiming;



3.59932,...




I'd love some suggestions!










share|improve this question











$endgroup$




So, I've implemented RK4, and I'm wondering what I can do to make it more efficient? What I've got so far is below. I wish to still record all steps. I think AppendTo is doing the most damage to the time, is there a faster alternative?



rk4[f_, variables_, valtinit_, tinit_, tfinal_, nsteps_] := 
Module[table, xlist, ylist, step, k1, k2, k3, k4,
xlist = tinit;
step = N[(tfinal - tinit)/(nsteps)];
ylist = valtinit;
table = xlist, ylist;
Table[
k1 = step* f /. MapThread[Rule, variables, ylist]; (*
Equivalent to step* f/.Thread[Rule[variables,ylist]]*)
k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist];
k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist];
k4 = step*f /. MapThread[Rule, variables, k3 + ylist];
ylist += 1/6 (k1 + 2 (k2 + k3) + k4);
xlist += step;
AppendTo[table, xlist, ylist];
xlist, ylist, nsteps];
table
];


Example Input:



funclist = -x + y, x - y;
initials = 1, 2;
variables = x, y;
init = 0;
final = 200;
nstep = 20000;
approx = rk4[funclist, variables, initials, init, final, nstep]//AbsoluteTiming;



3.59932,...




I'd love some suggestions!







differential-equations numerical-integration performance-tuning






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









xzczd

27.4k573255




27.4k573255










asked yesterday









ShinaolordShinaolord

1088




1088







  • 3




    $begingroup$
    AppendTo is quadratic time complexity. Might be better to preallocate and set by index. Also it'll be much faster to not use Rule and instead code stuff up a little bit more explicitly. As a general rule, too, use vectorized operators. Those can be very fast. And if everything can be totally functional over "packed arrays" (look them up here) it'll be very quick too.
    $endgroup$
    – b3m2a1
    yesterday










  • $begingroup$
    I'll work on implementing it more explicity, this is what came to find first though. It'll require some changes to the inputs, I'll have to ponder this. And preallocating the list is a quick change that won't be an issue to do, I can't believe I forgot that's faster :(. Thanks though!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    Shinaoloard, using Join[ xlist, ylist, Table[ k1 = step*f /. MapThread[Rule, variables, ylist]; k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist]; k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist]; k4 = step*f /. MapThread[Rule, variables, k3 + ylist]; ylist += 1/6 (k1 + 2 (k2 + k3) + k4); xlist += step; xlist, ylist, nsteps ] ] as return value is already a first step. There is no point in appending if you use a Table anyways.
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 3




    $begingroup$
    Why not just get NDSolve[] to use fourth-order Runge-Kutta to begin with?
    $endgroup$
    – J. M. is slightly pensive
    23 hours ago






  • 1




    $begingroup$
    @J.M.isslightlypensive I know it can, I just wanted to make sure I could actually code it myself, instead of just using options to get Mathematica to do it for me (:. Thanks for trying to help though!!
    $endgroup$
    – Shinaolord
    13 hours ago












  • 3




    $begingroup$
    AppendTo is quadratic time complexity. Might be better to preallocate and set by index. Also it'll be much faster to not use Rule and instead code stuff up a little bit more explicitly. As a general rule, too, use vectorized operators. Those can be very fast. And if everything can be totally functional over "packed arrays" (look them up here) it'll be very quick too.
    $endgroup$
    – b3m2a1
    yesterday










  • $begingroup$
    I'll work on implementing it more explicity, this is what came to find first though. It'll require some changes to the inputs, I'll have to ponder this. And preallocating the list is a quick change that won't be an issue to do, I can't believe I forgot that's faster :(. Thanks though!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    Shinaoloard, using Join[ xlist, ylist, Table[ k1 = step*f /. MapThread[Rule, variables, ylist]; k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist]; k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist]; k4 = step*f /. MapThread[Rule, variables, k3 + ylist]; ylist += 1/6 (k1 + 2 (k2 + k3) + k4); xlist += step; xlist, ylist, nsteps ] ] as return value is already a first step. There is no point in appending if you use a Table anyways.
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 3




    $begingroup$
    Why not just get NDSolve[] to use fourth-order Runge-Kutta to begin with?
    $endgroup$
    – J. M. is slightly pensive
    23 hours ago






  • 1




    $begingroup$
    @J.M.isslightlypensive I know it can, I just wanted to make sure I could actually code it myself, instead of just using options to get Mathematica to do it for me (:. Thanks for trying to help though!!
    $endgroup$
    – Shinaolord
    13 hours ago







3




3




$begingroup$
AppendTo is quadratic time complexity. Might be better to preallocate and set by index. Also it'll be much faster to not use Rule and instead code stuff up a little bit more explicitly. As a general rule, too, use vectorized operators. Those can be very fast. And if everything can be totally functional over "packed arrays" (look them up here) it'll be very quick too.
$endgroup$
– b3m2a1
yesterday




$begingroup$
AppendTo is quadratic time complexity. Might be better to preallocate and set by index. Also it'll be much faster to not use Rule and instead code stuff up a little bit more explicitly. As a general rule, too, use vectorized operators. Those can be very fast. And if everything can be totally functional over "packed arrays" (look them up here) it'll be very quick too.
$endgroup$
– b3m2a1
yesterday












$begingroup$
I'll work on implementing it more explicity, this is what came to find first though. It'll require some changes to the inputs, I'll have to ponder this. And preallocating the list is a quick change that won't be an issue to do, I can't believe I forgot that's faster :(. Thanks though!
$endgroup$
– Shinaolord
yesterday




$begingroup$
I'll work on implementing it more explicity, this is what came to find first though. It'll require some changes to the inputs, I'll have to ponder this. And preallocating the list is a quick change that won't be an issue to do, I can't believe I forgot that's faster :(. Thanks though!
$endgroup$
– Shinaolord
yesterday












$begingroup$
Shinaoloard, using Join[ xlist, ylist, Table[ k1 = step*f /. MapThread[Rule, variables, ylist]; k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist]; k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist]; k4 = step*f /. MapThread[Rule, variables, k3 + ylist]; ylist += 1/6 (k1 + 2 (k2 + k3) + k4); xlist += step; xlist, ylist, nsteps ] ] as return value is already a first step. There is no point in appending if you use a Table anyways.
$endgroup$
– Henrik Schumacher
yesterday




$begingroup$
Shinaoloard, using Join[ xlist, ylist, Table[ k1 = step*f /. MapThread[Rule, variables, ylist]; k2 = step*f /. MapThread[Rule, variables, k1/2 + ylist]; k3 = step*f /. MapThread[Rule, variables, k2/2 + ylist]; k4 = step*f /. MapThread[Rule, variables, k3 + ylist]; ylist += 1/6 (k1 + 2 (k2 + k3) + k4); xlist += step; xlist, ylist, nsteps ] ] as return value is already a first step. There is no point in appending if you use a Table anyways.
$endgroup$
– Henrik Schumacher
yesterday




3




3




$begingroup$
Why not just get NDSolve[] to use fourth-order Runge-Kutta to begin with?
$endgroup$
– J. M. is slightly pensive
23 hours ago




$begingroup$
Why not just get NDSolve[] to use fourth-order Runge-Kutta to begin with?
$endgroup$
– J. M. is slightly pensive
23 hours ago




1




1




$begingroup$
@J.M.isslightlypensive I know it can, I just wanted to make sure I could actually code it myself, instead of just using options to get Mathematica to do it for me (:. Thanks for trying to help though!!
$endgroup$
– Shinaolord
13 hours ago




$begingroup$
@J.M.isslightlypensive I know it can, I just wanted to make sure I could actually code it myself, instead of just using options to get Mathematica to do it for me (:. Thanks for trying to help though!!
$endgroup$
– Shinaolord
13 hours ago










1 Answer
1






active

oldest

votes


















15












$begingroup$

Just to give you an impression how fast things may get when you use the right tools.



For given stepsize τ and given vector field F, this creates a CompiledFunction cStep that computes a single Runge-Kutta step



F = X [Function] -Indexed[X, 2], Indexed[X, 1];

τ = 0.01;
Block[YY, Y, k1, k2, k3, k4,

YY = Table[Compile`GetElement[Y, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];

cStep = With[code = YY + (k1 + 2. (k2 + k3) + k4)/6. ,
Compile[Y, _Real, 1,
code,
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
]
];


Now we can apply it 20 million times with NestList and it stills takes only about 2 seconds.



nsteps = 20000000;
xlist = Range[0., τ nsteps, τ];
Ylist = NestList[cStep, 1., 0., nsteps]; // AbsoluteTiming // First



2.08678




Edit



This can be sped up even more my avoiding NestList (the loop behind it can also be compiled which saves several calls to libraries) and by utilizing that the dimension of the ODE is known at compile time. For low dimensional systems, it may be also beneficial to avoid tensor operations altogether and to perform computations in scalar registers as done below.



τ = 0.01;
cFlow = Block[YY, Y, k1, k2, k3, k4, τ, Ylist, j,
YY = Table[Compile`GetElement[Ylist, j, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];
With[
code1 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[1]],
code2 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[2]]
,
Compile[Y0, _Real, 1, τ, _Real, n, _Integer,
Block[Ylist,
Ylist = Table[0., n + 1, Length[Y0]];
Ylist[[1]] = Y0;
Do[
Ylist[[j + 1, 1]] = code1;
Ylist[[j + 1, 2]] = code2;
,
j, 1, n];
Ylist
],
CompilationTarget -> "C", RuntimeOptions -> "Speed"
]
]
];
Ylist2 = cFlow[1., 0., τ, nsteps]; // AbsoluteTiming // First



1.06549




Don't be too upset by parts of the code being highlighted in red; this is on purpose.






share|improve this answer











$endgroup$








  • 1




    $begingroup$
    Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    You're welcome.
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
    $endgroup$
    – Shinaolord
    yesterday






  • 1




    $begingroup$
    This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
    $endgroup$
    – b3m2a1
    18 hours ago











  • $begingroup$
    @b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
    $endgroup$
    – Henrik Schumacher
    18 hours ago










Your Answer





StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
);
);
, "mathjax-editing");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "387"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f194002%2fways-to-speed-up-user-implemented-rk4%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









15












$begingroup$

Just to give you an impression how fast things may get when you use the right tools.



For given stepsize τ and given vector field F, this creates a CompiledFunction cStep that computes a single Runge-Kutta step



F = X [Function] -Indexed[X, 2], Indexed[X, 1];

τ = 0.01;
Block[YY, Y, k1, k2, k3, k4,

YY = Table[Compile`GetElement[Y, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];

cStep = With[code = YY + (k1 + 2. (k2 + k3) + k4)/6. ,
Compile[Y, _Real, 1,
code,
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
]
];


Now we can apply it 20 million times with NestList and it stills takes only about 2 seconds.



nsteps = 20000000;
xlist = Range[0., τ nsteps, τ];
Ylist = NestList[cStep, 1., 0., nsteps]; // AbsoluteTiming // First



2.08678




Edit



This can be sped up even more my avoiding NestList (the loop behind it can also be compiled which saves several calls to libraries) and by utilizing that the dimension of the ODE is known at compile time. For low dimensional systems, it may be also beneficial to avoid tensor operations altogether and to perform computations in scalar registers as done below.



τ = 0.01;
cFlow = Block[YY, Y, k1, k2, k3, k4, τ, Ylist, j,
YY = Table[Compile`GetElement[Ylist, j, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];
With[
code1 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[1]],
code2 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[2]]
,
Compile[Y0, _Real, 1, τ, _Real, n, _Integer,
Block[Ylist,
Ylist = Table[0., n + 1, Length[Y0]];
Ylist[[1]] = Y0;
Do[
Ylist[[j + 1, 1]] = code1;
Ylist[[j + 1, 2]] = code2;
,
j, 1, n];
Ylist
],
CompilationTarget -> "C", RuntimeOptions -> "Speed"
]
]
];
Ylist2 = cFlow[1., 0., τ, nsteps]; // AbsoluteTiming // First



1.06549




Don't be too upset by parts of the code being highlighted in red; this is on purpose.






share|improve this answer











$endgroup$








  • 1




    $begingroup$
    Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    You're welcome.
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
    $endgroup$
    – Shinaolord
    yesterday






  • 1




    $begingroup$
    This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
    $endgroup$
    – b3m2a1
    18 hours ago











  • $begingroup$
    @b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
    $endgroup$
    – Henrik Schumacher
    18 hours ago















15












$begingroup$

Just to give you an impression how fast things may get when you use the right tools.



For given stepsize τ and given vector field F, this creates a CompiledFunction cStep that computes a single Runge-Kutta step



F = X [Function] -Indexed[X, 2], Indexed[X, 1];

τ = 0.01;
Block[YY, Y, k1, k2, k3, k4,

YY = Table[Compile`GetElement[Y, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];

cStep = With[code = YY + (k1 + 2. (k2 + k3) + k4)/6. ,
Compile[Y, _Real, 1,
code,
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
]
];


Now we can apply it 20 million times with NestList and it stills takes only about 2 seconds.



nsteps = 20000000;
xlist = Range[0., τ nsteps, τ];
Ylist = NestList[cStep, 1., 0., nsteps]; // AbsoluteTiming // First



2.08678




Edit



This can be sped up even more my avoiding NestList (the loop behind it can also be compiled which saves several calls to libraries) and by utilizing that the dimension of the ODE is known at compile time. For low dimensional systems, it may be also beneficial to avoid tensor operations altogether and to perform computations in scalar registers as done below.



τ = 0.01;
cFlow = Block[YY, Y, k1, k2, k3, k4, τ, Ylist, j,
YY = Table[Compile`GetElement[Ylist, j, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];
With[
code1 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[1]],
code2 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[2]]
,
Compile[Y0, _Real, 1, τ, _Real, n, _Integer,
Block[Ylist,
Ylist = Table[0., n + 1, Length[Y0]];
Ylist[[1]] = Y0;
Do[
Ylist[[j + 1, 1]] = code1;
Ylist[[j + 1, 2]] = code2;
,
j, 1, n];
Ylist
],
CompilationTarget -> "C", RuntimeOptions -> "Speed"
]
]
];
Ylist2 = cFlow[1., 0., τ, nsteps]; // AbsoluteTiming // First



1.06549




Don't be too upset by parts of the code being highlighted in red; this is on purpose.






share|improve this answer











$endgroup$








  • 1




    $begingroup$
    Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    You're welcome.
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
    $endgroup$
    – Shinaolord
    yesterday






  • 1




    $begingroup$
    This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
    $endgroup$
    – b3m2a1
    18 hours ago











  • $begingroup$
    @b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
    $endgroup$
    – Henrik Schumacher
    18 hours ago













15












15








15





$begingroup$

Just to give you an impression how fast things may get when you use the right tools.



For given stepsize τ and given vector field F, this creates a CompiledFunction cStep that computes a single Runge-Kutta step



F = X [Function] -Indexed[X, 2], Indexed[X, 1];

τ = 0.01;
Block[YY, Y, k1, k2, k3, k4,

YY = Table[Compile`GetElement[Y, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];

cStep = With[code = YY + (k1 + 2. (k2 + k3) + k4)/6. ,
Compile[Y, _Real, 1,
code,
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
]
];


Now we can apply it 20 million times with NestList and it stills takes only about 2 seconds.



nsteps = 20000000;
xlist = Range[0., τ nsteps, τ];
Ylist = NestList[cStep, 1., 0., nsteps]; // AbsoluteTiming // First



2.08678




Edit



This can be sped up even more my avoiding NestList (the loop behind it can also be compiled which saves several calls to libraries) and by utilizing that the dimension of the ODE is known at compile time. For low dimensional systems, it may be also beneficial to avoid tensor operations altogether and to perform computations in scalar registers as done below.



τ = 0.01;
cFlow = Block[YY, Y, k1, k2, k3, k4, τ, Ylist, j,
YY = Table[Compile`GetElement[Ylist, j, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];
With[
code1 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[1]],
code2 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[2]]
,
Compile[Y0, _Real, 1, τ, _Real, n, _Integer,
Block[Ylist,
Ylist = Table[0., n + 1, Length[Y0]];
Ylist[[1]] = Y0;
Do[
Ylist[[j + 1, 1]] = code1;
Ylist[[j + 1, 2]] = code2;
,
j, 1, n];
Ylist
],
CompilationTarget -> "C", RuntimeOptions -> "Speed"
]
]
];
Ylist2 = cFlow[1., 0., τ, nsteps]; // AbsoluteTiming // First



1.06549




Don't be too upset by parts of the code being highlighted in red; this is on purpose.






share|improve this answer











$endgroup$



Just to give you an impression how fast things may get when you use the right tools.



For given stepsize τ and given vector field F, this creates a CompiledFunction cStep that computes a single Runge-Kutta step



F = X [Function] -Indexed[X, 2], Indexed[X, 1];

τ = 0.01;
Block[YY, Y, k1, k2, k3, k4,

YY = Table[Compile`GetElement[Y, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];

cStep = With[code = YY + (k1 + 2. (k2 + k3) + k4)/6. ,
Compile[Y, _Real, 1,
code,
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
]
];


Now we can apply it 20 million times with NestList and it stills takes only about 2 seconds.



nsteps = 20000000;
xlist = Range[0., τ nsteps, τ];
Ylist = NestList[cStep, 1., 0., nsteps]; // AbsoluteTiming // First



2.08678




Edit



This can be sped up even more my avoiding NestList (the loop behind it can also be compiled which saves several calls to libraries) and by utilizing that the dimension of the ODE is known at compile time. For low dimensional systems, it may be also beneficial to avoid tensor operations altogether and to perform computations in scalar registers as done below.



τ = 0.01;
cFlow = Block[YY, Y, k1, k2, k3, k4, τ, Ylist, j,
YY = Table[Compile`GetElement[Ylist, j, i], i, 1, 2];
k1 = τ F[YY];
k2 = τ F[0.5 k1 + YY];
k3 = τ F[0.5 k2 + YY];
k4 = τ F[k3 + YY];
With[
code1 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[1]],
code2 = (YY + (k1 + 2. (k2 + k3) + k4)/6)[[2]]
,
Compile[Y0, _Real, 1, τ, _Real, n, _Integer,
Block[Ylist,
Ylist = Table[0., n + 1, Length[Y0]];
Ylist[[1]] = Y0;
Do[
Ylist[[j + 1, 1]] = code1;
Ylist[[j + 1, 2]] = code2;
,
j, 1, n];
Ylist
],
CompilationTarget -> "C", RuntimeOptions -> "Speed"
]
]
];
Ylist2 = cFlow[1., 0., τ, nsteps]; // AbsoluteTiming // First



1.06549




Don't be too upset by parts of the code being highlighted in red; this is on purpose.







share|improve this answer














share|improve this answer



share|improve this answer








edited 12 hours ago

























answered yesterday









Henrik SchumacherHenrik Schumacher

58.1k580160




58.1k580160







  • 1




    $begingroup$
    Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    You're welcome.
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
    $endgroup$
    – Shinaolord
    yesterday






  • 1




    $begingroup$
    This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
    $endgroup$
    – b3m2a1
    18 hours ago











  • $begingroup$
    @b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
    $endgroup$
    – Henrik Schumacher
    18 hours ago












  • 1




    $begingroup$
    Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
    $endgroup$
    – Shinaolord
    yesterday










  • $begingroup$
    You're welcome.
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
    $endgroup$
    – Shinaolord
    yesterday






  • 1




    $begingroup$
    This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
    $endgroup$
    – b3m2a1
    18 hours ago











  • $begingroup$
    @b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
    $endgroup$
    – Henrik Schumacher
    18 hours ago







1




1




$begingroup$
Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
$endgroup$
– Shinaolord
yesterday




$begingroup$
Damn, you definitely know how to use Mathematica A LOT more efficiently than I do. Thanks!
$endgroup$
– Shinaolord
yesterday












$begingroup$
You're welcome.
$endgroup$
– Henrik Schumacher
yesterday




$begingroup$
You're welcome.
$endgroup$
– Henrik Schumacher
yesterday












$begingroup$
I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
$endgroup$
– Shinaolord
yesterday




$begingroup$
I'll have to play around with Compile, it definitely seems like a massive speed up if used correctly.
$endgroup$
– Shinaolord
yesterday




1




1




$begingroup$
This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
$endgroup$
– b3m2a1
18 hours ago





$begingroup$
This is exactly the kind of thing I like to show people when they complain about the slowness of Mathematica. Of course with some cleverness in vectorized operations Compile could probably be avoided altogether if one so desired.
$endgroup$
– b3m2a1
18 hours ago













$begingroup$
@b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
$endgroup$
– Henrik Schumacher
18 hours ago




$begingroup$
@b3m2a1 Yeah, right. However, with ODE systems of this small dimension (dim = 2) I am not sure how to utilize vectorization since the ODE has to be solved in serial and because the vector field F may be very nonlinear.
$endgroup$
– Henrik Schumacher
18 hours ago

















draft saved

draft discarded
















































Thanks for contributing an answer to Mathematica Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f194002%2fways-to-speed-up-user-implemented-rk4%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Triangular numbers and gcdProving sum of a set is $0 pmod n$ if $n$ is odd, or $fracn2 pmod n$ if $n$ is even?Is greatest common divisor of two numbers really their smallest linear combination?GCD, LCM RelationshipProve a set of nonnegative integers with greatest common divisor 1 and closed under addition has all but finite many nonnegative integers.all pairs of a and b in an equation containing gcdTriangular Numbers Modulo $k$ - Hit All Values?Understanding the Existence and Uniqueness of the GCDGCD and LCM with logical symbolsThe greatest common divisor of two positive integers less than 100 is equal to 3. Their least common multiple is twelve times one of the integers.Suppose that for all integers $x$, $x|a$ and $x|b$ if and only if $x|c$. Then $c = gcd(a,b)$Which is the gcd of 2 numbers which are multiplied and the result is 600000?

Србија Садржај Етимологија Географија Историја Политички систем и уставно-правно уређење Становништво Привреда Образовање Култура Спорт Државни празници Галерија Напомене Референце Литература Спољашње везе Мени за навигацију44°48′N 20°28′E / 44.800° СГШ; 20.467° ИГД / 44.800; 20.46744°48′N 20°28′E / 44.800° СГШ; 20.467° ИГД / 44.800; 20.467ууРезултати пописа 2011. према старости и полуу„Положај, рељеф и клима”„Europe: Serbia”„Основни подаци”„Gross domestic product based on purchasing-power-parity (PPP) valuation of country GDP”„Human Development Report 2018 – "Human Development Indices and Indicators 6”„Устав Републике Србије”Правопис српскога језикаGoogle DriveComparative Hungarian Cultural StudiesCalcium and Magnesium in Groundwater: Occurrence and Significance for Human Health„UNSD — Methodology”„Процене становништва | Републички завод за статистику Србије”The Age of Nepotism: Travel Journals and Observations from the Balkans During the Depression„The Serbian Revolution and the Serbian State”„Устав Србије”„Serbia a few steps away from concluding WTO accession negotiations”„A credible enlargement perspective for and enhanced EU engagement with the Western Balkans”„Freedom in the World 2017”„Serbia: On the Way to EU Accession”„Human Development Indices and Indicators: 2018 Statistical Update”„2018 Social Progress Index”„Global Peace Index”Sabres of Two Easts: An Untold History of Muslims in Eastern Europe, Their Friends and Foes„Пројекат Растко—Лузица”„Serbia: Introduction”„Serbia”оригинала„The World Factbook: Serbia”„The World Factbook: Kosovo”„Border Police Department”„Uredba o kontroli prelaska administrativne linije prema Autonomnoj pokrajini Kosovo i Metohija”оригиналаIvana Carevic, Velimir Jovanovic, STRATIGRAPHIC-STRUCTURAL CHARACTERISTICS OF MAČVA BASIN, UDC 911.2:551.7(497.11), pp. 1Archived„About the Carpathians – Carpathian Heritage Society”оригинала„O Srbiji”оригинала„Статистички годишњак Србије, 2009: Географски прегледГеографија за осми разред основне школе„Отворена, електронска база едукационих радова”„Влада Републике Србије: Положај, рељеф и клима”„Копрен (Стара планина)”„Туристичка дестинација-Србија”„Висина водопада”„РХМЗ — Републички Хидрометеоролошки завод Србије Кнеза Вишеслава 66 Београд”„Фауна Србије”„Српске шуме на издисају”„Lepih šest odsto Srbije”„Илустрована историја Срба — Увод”„Винчанска култура - Градска општина Гроцка”„''„Винча — Праисторијска метропола”''”оригиналаЈужни Словени под византијском влашћу (600—1025)Држава маћедонских Словена„Карађорђе истина и мит, Проф. др Радош Љушић, Вечерње новости, фељтон, 18 наставака, 24. август - 10. септембар 2003.”„Политика: Како је утврђена војна неутралност, 13. јануар. 2010, приступљено децембра 2012.”„Србија и РС оживеле Дејтонски споразум”„Са српским пасошем у 104 земље”Војска Србије | О Војсци | Војска Србије — Улога, намена и задациАрхивираноВојска Србије | ОрганизацијаАрхивираноОдлука о изради Стратегије просторног развоја Републике Србије до 2020. годинеЗакон о територијалној организацији Републике СрбијеЗакон о државној управиНајчешће постављана питања.„Смањење броја статистичких региона кроз измене Закона о регионалном развоју”„2011 Human development Report”„Službena upotreba jezika i pisama”„Попис становништва, домаћинстава и станова 2011. године у Републици Србији. Књига 4: Вероисповест, матерњи језик и национална припадност”„Вероисповест, матерњи језик и национална”„Специјална известитељка УН за слободу религије и вероисповести Асма Јахангир, код Заштитника грађана Саше Јанковића”„Закон о државним и другим празницима у Републици Србији”„Веронаука у српским школама”„Serbia – Ancestral Genography Atlas”Бела књига Милошевићеве владавинеоригиналаGross domestic product based on purchasing-power-parity (PPP) per capita GDP БДП 2007—2013Актуелни показатељи — Република Србија„Попис становништва, домаћинстава и станова 2011. године у Републици Србији Књига 7: Економска активност”Zemlje kandidati za članstvo u EU„Putin drops South Stream gas pipeline to EU, courts Turkey”„„Соко — историјат””оригинала„„Рембас — историјат””оригинала„„Лубница — историјат””оригинала„„Штаваљ — Историјат””оригинала„„Боговина — историјат””оригинала„„Јасеновац — историјат””оригинала„„Вршка чука — историјат””оригинала„„Ибарски рудници — историјат””оригинала„Закон о просторном плану Републике Србије од 2010 до 2020”„Кривични законик — Недозвољена изградња нуклеарних постројења, члан 267”„Б92: Srbija uklonila obogaćeni uranijum, 25. октобар 2011”„Коришћење енергије ветра у Србији — природни услови и практична примена”„Енергија ветра”„Србија може да прави струју од сунца, биомасе, воде и ветра”„Моја електрана и друге ветрењаче”„Биомаса, струја без инвестиција”„Auto-karte Srbije”„www.srbija.gov.rs Статистике о Србији”оригинала„Статистика зе месец децембар и 2016. годину”„Turizam u Srbiji”„Univerzitet u Beogradu: Vek i po akademskog znanja”„Vojnomedicinska akademija: 165 godina tradicije i napretka”Никола Гиљен, Соња Јовићевић Јов и Јелена Мандић: Мирослављево јеванђеље; Текст је публикован у ревији „Историја” и настао је као део научно-истраживачког рада Фонда „Принцеза Оливера”„World music асоцијација Србије”оригинала„World music у Србији”оригинала„Pogledajte: Boban Marković svira u redakciji „Blica”!”„Eurovision Song Contest 2007 Final”„Projekat Rastko, Alojz Ujes: Joakim Vujic”„Унеско”„Списак локалитета Светске баштине”„Guča i Egzit zaludeli svet”оригинала„Sabor trubača GUČA”„Interesting facts about Exit”оригинала„FIFA Association Information”„Serbia women win EuroBasket title, gain first Olympics berth”„Odbojkašice ispisale istoriju – Srbija je svetski prvak!”„Сајт Ватерполо савеза Србије, Освојене медаље”„Сајт ФК Црвена звезда, Бари”„Сајт ФК Црвена звезда, Токио”„Blic:Zlatna Milica! Mandićeva donela Srbiji najsjajnije odličje u Londonu!”„Милица Мандић освојила златну медаљу („Политика”, 12. август 2012)”„Златни Давор Штефанек”„DŽUDO ŠAMPIONAT Majdov osvojio svetsko zlato”„Španovićeva trećim skokom svih vremena do zlata!”„Чудо Иване Шпановић — 7,24 м („Политика”, 5. март 2017)”The Age of Nepotism: Travel Journals and Observations from the Balkans During the DepressionCalcium and Magnesium in Groundwater: Occurrence and Significance for Human HealthComparative Hungarian Cultural StudiesБела књига Милошевићеве владавинеоригиналаComparative Hungarian Cultural StudiesSabres of Two Easts: An Untold History of Muslims in Eastern Europe, Their Friends and FoesГеографија за осми разред основне школеSerbia: the country, people, life, customsМедијиВодичПодациВлада Републике СрбијеНародна скупштина Републике СрбијеНародна канцеларија председника Републике СрбијеНародна банка СрбијеТуристичка организација СрбијеПортал еУправе Републике СрбијеРепубличко јавно правобранилаштвоууууууWorldCat151202876n851959190000 0000 9526 67094054598-24101000570825ge130919

Barbados Ynhâld Skiednis | Geografy | Demografy | Navigaasjemenu