0

I want to set up a two dimensional box with length L and periodic boundary conditions in Python. One way to proceed is to fix the reference frame at bottom left corner, then I have:

L = 5 # box length
x, y = 2, 3 # initial values

# step in my algorithm
x = (x + 4) % L
y = (y - 4) % L

And the output is, obviously, x, y = (1, 4). We can assure that for every step the positions of the particles will remain inside the box of length L.

Okay, but what if I want to set the reference frame in the center of the box? The following code, of course, doesn't work:

x = (x + 4) % L/2
y = (y - 4) % L/2

What I want to happen is that if a particle escapes from the x=+L/2 side then it appears by x=-L/2 (same for y), but the module operator cannot deal with this in the same way as in the previous case.

martineau
  • 119,623
  • 25
  • 170
  • 301
Dani
  • 473
  • 3
  • 21
  • 1
    The modulo operator "wraps" a value around the `0` point on the axis, proportionally, so it may not be able to do what you need — which means you may need to actually write code to handle each possible scenario separately. – martineau Mar 23 '20 at 22:32
  • Keep your definitions, but subtract L/2 from them after you mod-them. `x=((x-4) % L) - L/2` etc. The inner operation ensures your coordinates are between 0 and L, and then you transform it to your box-centered coordinates by subtracting L/2. The bounds for your new x are `(0-L/2, L-L/2)` -> `(-L/2, L/2)`. – SyntaxVoid Mar 23 '20 at 22:45
  • @SyntaxVoidsupportsMonica but that doesn't work because, for example, if my box has length L=6, and I have a particle initially at x=2, then by subtracting 2 it should later be at x=-2 (since it has not reached any edge), nevertheless, it returns 1 – Dani Mar 23 '20 at 23:41

1 Answers1

0

For L odd, the range of centered values is symmetric [(1-L)/2, (L+1)/2]. For L even, the ranged of centered values will have either an extra positive or extra negative term.

First two examples:

L = 5, Centered Range [-2, 2]

the value x : ... -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7 ...
x % L       : ...  4  0  1  2  3  4  0  1  2  3  4  0  1  2 ...
centered    : ... -1  0  1  2 -2 -1  0  1  2 -2 -1  0  1  2 ...

L = 6, Centered Range [-3, 2]

the value x : ... -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8 ...
x % L       : ...  5  0  1  2  3  4  5  0  1  2  3  4  5  0  1  2 ...
centered    : ... -1  0  1  2 -3 -2 -1  0  1  2 -3 -2 -1  0  1  2 ...

One way to compute this using only binary operations is

center_mod = lambda x: (x % L) - L*((x % L) // ((L + 1)//2))

The idea is to conditionally subtract L if the value (x % L) is beyond the end of the center range.