Skip to content

Commit 6f6d9bb

Browse files
liam-o-marshLuthaf
authored andcommitted
Fixed double-counting of periopdic image pairs
1 parent 6703672 commit 6f6d9bb

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

rascaline/src/systems/neighbors.rs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl CellList {
174174
let n_cells = self.cells.shape();
175175
let n_cells = [n_cells[0], n_cells[1], n_cells[2]];
176176

177-
// find the cell in which this atom should go
177+
// find the subcell in which this atom 'should go'
178178
let cell_index = [
179179
f64::floor(fractional[0] * n_cells[0] as f64) as i32,
180180
f64::floor(fractional[1] * n_cells[1] as f64) as i32,
@@ -250,10 +250,28 @@ impl CellList {
250250
let shift = CellShift(cell_shift) + atom_i.shift - atom_j.shift;
251251
let shift_is_zero = shift[0] == 0 && shift[1] == 0 && shift[2] == 0;
252252

253-
if atom_i.index == atom_j.index && shift_is_zero {
254-
// only create pair with the same atom twice
255-
// if the pair spans more than one unit cell
256-
continue;
253+
if atom_i.index == atom_j.index {
254+
if shift_is_zero {
255+
// only create pair with the same atom twice
256+
// if the pair spans more than one unit cell
257+
continue;
258+
}
259+
260+
if (shift[0] + shift[1] + shift[2] < 0) ||
261+
(
262+
(shift[0] + shift[1] + shift[2] == 0) &&
263+
(shift[2] < 0 || (shift[2] == 0 && shift[1] < 0))
264+
)
265+
{
266+
// When creating pairs between an atom
267+
// and one of its periodic images, the
268+
// code generate multiple redundant
269+
// pairs (e.g. with shifts 0 1 1 and 0
270+
// -1 -1); and we want to only keep one
271+
// of these. We keep the pair in the
272+
// positive half plane of shifts.
273+
continue;
274+
}
257275
}
258276

259277
if self.unit_cell.is_infinite() && !shift_is_zero {
@@ -426,21 +444,15 @@ mod tests {
426444
let neighbors = NeighborsList::new(&positions, cell, 3.0);
427445

428446
let expected = [
429-
(Vector3D::new(0.0, -1.0, -1.0), [-1, 0, 0]),
430447
(Vector3D::new(1.0, 0.0, -1.0), [-1, 0, 1]),
431448
(Vector3D::new(1.0, -1.0, 0.0), [-1, 1, 0]),
432-
(Vector3D::new(-1.0, 0.0, -1.0), [0, -1, 0]),
433449
(Vector3D::new(0.0, 1.0, -1.0), [0, -1, 1]),
434-
(Vector3D::new(-1.0, -1.0, 0.0), [0, 0, -1]),
435450
(Vector3D::new(1.0, 1.0, 0.0), [0, 0, 1]),
436-
(Vector3D::new(0.0, -1.0, 1.0), [0, 1, -1]),
437451
(Vector3D::new(1.0, 0.0, 1.0), [0, 1, 0]),
438-
(Vector3D::new(-1.0, 1.0, 0.0), [1, -1, 0]),
439-
(Vector3D::new(-1.0, 0.0, 1.0), [1, 0, -1]),
440452
(Vector3D::new(0.0, 1.0, 1.0), [1, 0, 0]),
441453
];
442454

443-
assert_eq!(neighbors.pairs.len(), 12);
455+
assert_eq!(neighbors.pairs.len(), 6);
444456
for (pair, (vector, shifts)) in neighbors.pairs.iter().zip(&expected) {
445457
assert_eq!(pair.first, 0);
446458
assert_eq!(pair.second, 0);
@@ -480,4 +492,26 @@ mod tests {
480492
assert_ulps_eq!(pair.distance, 2.0);
481493
}
482494
}
495+
496+
#[test]
497+
fn small_cell_large_cutoffs() {
498+
let cell = UnitCell::cubic(0.5);
499+
let positions = [Vector3D::new(0.0, 0.0, 0.0)];
500+
let neighbors = NeighborsList::new(&positions, cell, 0.6);
501+
502+
let expected = [
503+
(Vector3D::new(0.0, 0.0, 0.5), [0, 0, 1]),
504+
(Vector3D::new(0.0, 0.5, 0.0), [0, 1, 0]),
505+
(Vector3D::new(0.5, 0.0, 0.0), [1, 0, 0]),
506+
];
507+
508+
assert_eq!(neighbors.pairs.len(), 3);
509+
for (pair, (vector, shifts)) in neighbors.pairs.iter().zip(&expected) {
510+
assert_eq!(pair.first, 0);
511+
assert_eq!(pair.second, 0);
512+
assert_ulps_eq!(pair.distance, 0.5);
513+
assert_ulps_eq!(pair.vector, vector);
514+
assert_eq!(&pair.cell_shift_indices, shifts);
515+
}
516+
}
483517
}

0 commit comments

Comments
 (0)