[Rust / Python] Periodic boundary conditions

Consider imposing a periodic boundary condition on the real number $ \ mathbb {R} $ with a period of $ b> 0 $ ($ \ mathbb {R} / b \ mathbb {R} $), that is, two numbers $ x $. And $ x + b $ are equated. Then, as a unique representation of the coordinates corresponding to any number $ x \ in \ mathbb {R} $.

Rust implementation

Click here for the entire code and operation check: [PlayGround](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=extern%20crate%20rand%3B%20%2F%2F%200.7.3 % 0Ause% 20rand% 3A% 3A% 7BRng% 2C% 20thread_rng% 7D% 3B% 0A% 0Afn% 20main ()% 20% 7B% 0A% 20% 20% 20% 20let% 20mut% 20rng% 20% 3D% 20thread_rng ()% 3B% 0A% 20% 20% 20% 20let% 20b% 20% 3D% 201.57% 3B% 0A% 20% 20% 20% 20% 0A% 20% 20% 20% 20for% 20_% 20in% 200 .. 128% 20% 7B% 0A% 20% 20% 20% 20% 20% 20% 20% 20let% 20x% 20% 3D% 20rng.gen_range (-6.% 2C% 206.)% 3B% 0A% 20% 20% 20% 20% 20% 20% 20% 20if% 20! Check1 (x% 2C% 20b)% 20% 7B% 20println! (% 221% 3A% 20pbc (% 7B% 3A.03% 7D)) % 20% 3D% 20% 7B% 7D% 22% 2C% 20x% 2C% 20pbc1 (x% 2C% 20b))% 3B% 20% 7D% 3B% 0A% 20% 20% 20% 20% 20% 20 % 20% 20if% 20! check2 (x% 2C% 20b)% 20% 7B% 20println! (% 222% 3A% 20pbc (% 7B% 3A.03% 7D)% 20% 3D% 20% 7B% 7D% 22% 2C% 20x% 2C% 20pbc2 (x% 2C% 20b))% 3B% 20% 7D% 3B% 0A% 20% 20% 20% 20% 7D% 0A% 7D% 0A% 0A% 0A% 23% 5Binline% 5D% 0Afn% 20pbc1 (x% 3A% 20f64% 2C% 20b% 3A% 20f64)% 20-% 3E% 20f64% 20% 7B% 0A% 20% 20% 20% 20let% 20dx% 20% 3D% 20x% 25b% 3B% 0A% 20% 20% 20% 20if% 20dx% 20% 3E% 3D% 200.% 20% 7B% 20dx% 20% 7D% 20else% 20% 7B% 20dx% 20% 2B% 20b % 20% 7D% 0A% 7D% 0A% 0A% 23% 5Binline% 5D% 0 Afn% 20pbc2 (x% 3A% 20f64% 2C% 20b% 3A% 20f64)% 20-% 3E% 20f64% 20% 7B% 0A% 20% 20% 20% 20x% 20-% 20 (x% 2Fb% 20) % 2B% 200.5) .floor () * b% 0A% 7D% 0A% 0A% 0A% 23% 5Binline% 5D% 0Afn% 20check1 (x% 3A% 20f64% 2C% 20b% 3A% 20f64)% 20-% 3E% 20bool% 20% 7B% 0A% 20% 20% 20% 20let% 20x% 20% 3D% 20pbc1 (x% 2C% 20b)% 3B% 0A% 20% 20% 20% 20% 0A% 20% 20 % 20% 20 (% 20x% 20% 3E% 3D% 200.% 20)% 26 (% 20x% 20% 3C% 20b% 20)% 0A% 7D% 0A% 0A% 23% 5Binline% 5D% 0Afn% 20check2 (x% 3A% 20f64% 2C% 20b% 3A% 20f64)% 20-% 3E% 20bool% 20% 7B% 0A% 20% 20% 20% 20let% 20x% 20% 3D% 20pbc2 (x% 2C%) 20b)% 3B% 0A% 20% 20% 20% 20% 0A% 20% 20% 20% 20 (% 20x% 20% 3E% 3D% 20-b% 2F2.% 20)% 26 (% 20x% 20) % 3C% 20b% 2F2.% 20)% 0A% 7D% 0A% 0A)

0 ≦ x < b

In Rust, the remainder x% b has the same sign as x, so if x is positive, then x% b is fine, otherwise you need to add b. ..

#[inline]
fn pbc1(x: f64, b: f64) -> f64 {
    let dx = x%b;
    if dx >= 0. { dx } else { dx + b }
}

At first I was using f64 :: is_sign_negative, but after having trouble handling -0.0, I came to the conclusion that I should use the inequality sign.

-b/2 ≦ x < b/2

In this case, calculating (x / b + 0.5) .floor () will tell you how many times b should be used to move x to the desired interval.

#[inline]
fn pbc2(x: f64, b: f64) -> f64 {
    x - (x/b + 0.5).floor()*b
}

Python implementation

The following code can be used with either the input x is float or np.ndarray. Check the operation here: Paiza

0 ≦ x < b

In Python, the remainder is set to satisfy $ 0 \ leq x % b <b $ (now $ b> 0 $), so it's a one-shot.

def pbc1(x, b):
    return x%b

-b/2 ≦ x < b/2

This just rewrites the above Rust implementation into Python.

def pbc2(x, b):
    return x - np.floor(x/b + 0.5)*b

Recommended Posts

[Rust / Python] Periodic boundary conditions
Python basics: conditions and iterations
[Python] Sort iterable by multiple conditions