I'm trying to run a simple particle trajectory simulation, in which I propagate ~10,000 particles through a potential energy surface. In other programs like Matlab, I of course get a huge speedup when I vectorize my code such that all particles take time steps together, and I apply Newton's laws to entire vectors holding the positions/ velocities. In Mathematica, I'm trying to use this same method but see that the simulation time scales exactly linearly with the number of particles I put in. Is this typical, or should Mathematica also benefit from vectorized code?
singlestep[rv_, dt_, dUx_, dUy_, dUz_, nf_] :=
Module[{fx, fy, fz, xx, yy, zz, xnew, ynew, znew, vx, vy, vz, vxnew,
vynew, vznew},
xx = rv[[;; , 1]]; yy = rv[[;; , 2]]; zz = rv[[;; , 3]];
vx = rv[[;; , 4]]; vy = rv[[;; , 5]]; vz = rv[[;; , 6]];
Do[
fx = -dUx /@ Transpose@{xx, yy, zz};
fy = -dUy /@ Transpose@{xx, yy, zz};
fz = -dUz /@ Transpose@{xx, yy, zz};
xx += vx* dt + 1/2*fx/M*dt^2;
yy += vy *dt + 1/2*fy/M*dt^2;
zz += vz* dt + 1/2*fz/M*dt^2;
vx += fx/M*dt;
vy += fy/M*dt;
vz += fz/M*dt,
{nn, 1, nf}];
xnew = xx; ynew = yy; znew = zz;
vxnew = vx; vynew = vy; vznew = vz;
{xnew, ynew, znew, vxnew, vynew, vznew}]
nf is a variable referring to how many "fine" steps are taken (but for this test I am setting it to 1). dUx/y/z are interpolating functions that contain the force components as a function of position. rv is an array that contains the 3 positions and 3 velocity components from the previous steps, so for each particle is size 1x6. As I add more particles by increasing the size of rv from 1x6 to nx6, I see the code slow down exactly proportional to n.
Listable
is not exactly the same as vectorization. Many, but not all, mathematical functions have internal vectorized versions that are automatically called if you set up your code and data properly. $\endgroup$InterpolatingFunction
is one of the functions not vectorized; however it is listable, anddUx @ Transpose@{xx, yy, zz}
should save a some time. Also, your're transposing{xx, yy, zz}
three times each loop-step. You should be able to do it once outside the loop and use the transposed array (probably would need to transpose{vx, vy, vz}
too); or not even transpose. Isn'trv[[ ;; , 1;;3]]
== Transpose@{xx, yy, zz}`? $\endgroup$M
in your code? You can probably get good enough speed without improving your algorithm simply viaCompile
(assuming thedU
s are compileable) $\endgroup$