Distances between points in periodic cube

I'm assuming here that x is a list of points between which you want to calculate the distance. If so, then I think your code can be condensed to something like

PeriodicDistance[x_, size_: 1] := Outer[Norm@Mod[#2 - #1, size, -size/2] &, x, x, 1]

Edit

A faster version of the code above is something like

PeriodicDistance3[x_, size_: 1] := 
   Map[Norm, Mod[Outer[Subtract, x, x, 1], size, -size/2], {-2}]

On my system this is about as efficient as the code in the original question, whereas the previous version is a factor 2 to 3 slower.


Very late to the party, but I'll show a method that's faster than anything posted so far and will be hard to beat.

First let's define our PeriodicDistance:

PeriodicDistance = Compile[{{x, _Real, 1}, {y, _Real, 2}, {size, _Real}}, 
   Sqrt@Total[((x - y) - size*Round[(x - y)/size])^2], 
   CompilationTarget :> "C", RuntimeOptions -> "Speed"];

Now our distance matrix:

PeriodicDistanceMatrix[dat_?MatrixQ, size_Real:1.0] := 
 With[{tr = Transpose[dat]}, Map[PeriodicDistance[dat[[#]], tr, size] &, Range@Length@dat]]

Some Timings:

data = RandomReal[1, {2000, 3}];

(* This answer *)

PeriodicDistanceMatrix[data]; // AbsoluteTiming

(* 0.265632 *)

(* Heike's faster version *)

PeriodicDistanceB[data]; //AbsoluteTiming

(* 2.599099 *)

(* J.M.'s answer *)

PeriodicDistance[data]; // AbsoluteTiming

(* 6.246279 *)

(* O.P.'s version *)

PeriodicDistance2[data]; // AbsoluteTiming

(* 10.026386 *)

And yes, all the outputs are identical.

Edit

Needs["GeneralUtilities`"] (* for v10 *)

BenchmarkPlot[{RunnyKine, Heike, JM}, RandomReal[1, {#, 3}] &, 2^Range[6, 14]]

Mathematica graphics


You want something like

PeriodicDistance[pts_, size_: 1] := 
 Outer[EuclideanDistance, size*FractionalPart[pts/size], 
  size*FractionalPart[pts/size], 1]

But what you did is a bit different in terms of how you wrap things periodically. If it is really as you intended, replace size everywhere by 2*size.

PeriodicDistanceB[pts_, size_: 1] := 
 Outer[EuclideanDistance, 2*size*FractionalPart[pts/(2*size)], 
  2*size*FractionalPart[pts/(2*size)], 1]