@@ -39,7 +39,7 @@ pub struct NeighborList {
39
39
pub full_neighbor_list : bool ,
40
40
/// Should individual atoms be considered their own neighbor? Setting this
41
41
/// to `true` will add "self pairs", i.e. pairs between an atom and itself,
42
- /// with the distance 0. The `pair_id` of such pairs is set to -1.
42
+ /// with the distance 0.
43
43
pub self_pairs : bool ,
44
44
}
45
45
@@ -423,7 +423,8 @@ impl FullNeighborList {
423
423
let cell_c = pair. cell_shift_indices [ 2 ] ;
424
424
425
425
if species_first == species_second {
426
- // same species for both atoms in the pair
426
+ // same species for both atoms in the pair, add the pair
427
+ // twice in both directions.
427
428
if species[ pair. first ] == species_first. i32 ( ) && species[ pair. second ] == species_second. i32 ( ) {
428
429
builder. add ( & [
429
430
LabelValue :: from ( system_i) ,
@@ -434,18 +435,14 @@ impl FullNeighborList {
434
435
LabelValue :: from ( cell_c) ,
435
436
] ) ;
436
437
437
- if pair. first != pair. second {
438
- // if the pair is between two different atoms,
439
- // also add the reversed (second -> first) pair.
440
- builder. add ( & [
441
- LabelValue :: from ( system_i) ,
442
- LabelValue :: from ( pair. second ) ,
443
- LabelValue :: from ( pair. first ) ,
444
- LabelValue :: from ( -cell_a) ,
445
- LabelValue :: from ( -cell_b) ,
446
- LabelValue :: from ( -cell_c) ,
447
- ] ) ;
448
- }
438
+ builder. add ( & [
439
+ LabelValue :: from ( system_i) ,
440
+ LabelValue :: from ( pair. second ) ,
441
+ LabelValue :: from ( pair. first ) ,
442
+ LabelValue :: from ( -cell_a) ,
443
+ LabelValue :: from ( -cell_b) ,
444
+ LabelValue :: from ( -cell_c) ,
445
+ ] ) ;
449
446
}
450
447
} else {
451
448
// different species, find the right order for the pair
@@ -501,6 +498,11 @@ impl FullNeighborList {
501
498
let species = system. species ( ) ?;
502
499
503
500
for pair in system. pairs ( ) ? {
501
+ if pair. first == pair. second {
502
+ // self pairs should not be part of the neighbors list
503
+ assert_ne ! ( pair. cell_shift_indices, [ 0 , 0 , 0 ] ) ;
504
+ }
505
+
504
506
let first_block_i = descriptor. keys ( ) . position ( & [
505
507
species[ pair. first ] . into ( ) , species[ pair. second ] . into ( )
506
508
] ) ;
@@ -565,11 +567,6 @@ impl FullNeighborList {
565
567
}
566
568
}
567
569
568
- if pair. first == pair. second {
569
- // do not duplicate self pairs
570
- continue ;
571
- }
572
-
573
570
// then the pair second -> first
574
571
if let Some ( second_block_i) = second_block_i {
575
572
let mut block = descriptor. block_mut_by_id ( second_block_i) ;
@@ -764,6 +761,75 @@ mod tests {
764
761
assert_relative_eq ! ( array, expected, max_relative=1e-6 ) ;
765
762
}
766
763
764
+ #[ test]
765
+ fn periodic_neighbor_list ( ) {
766
+ let mut calculator = Calculator :: from ( Box :: new ( NeighborList {
767
+ cutoff : 12.0 ,
768
+ full_neighbor_list : false ,
769
+ self_pairs : false ,
770
+ } ) as Box < dyn CalculatorBase > ) ;
771
+
772
+ let mut systems = test_systems ( & [ "CH" ] ) ;
773
+
774
+ let descriptor = calculator. compute ( & mut systems, Default :: default ( ) ) . unwrap ( ) ;
775
+ assert_eq ! ( * descriptor. keys( ) , Labels :: new(
776
+ [ "species_first_atom" , "species_second_atom" ] ,
777
+ & [ [ 1 , 1 ] , [ 1 , 6 ] , [ 6 , 6 ] ]
778
+ ) ) ;
779
+
780
+ // H-H block
781
+ let block = descriptor. block_by_id ( 0 ) ;
782
+ assert_eq ! ( block. samples( ) , Labels :: new(
783
+ [ "structure" , "first_atom" , "second_atom" , "cell_shift_a" , "cell_shift_b" , "cell_shift_c" ] ,
784
+ // the pairs only differ in cell shifts
785
+ & [ [ 0 , 1 , 1 , 0 , 0 , 1 ] , [ 0 , 1 , 1 , 0 , 1 , 0 ] , [ 0 , 1 , 1 , 1 , 0 , 0 ] ]
786
+ ) ) ;
787
+
788
+ let array = block. values ( ) . to_array ( ) ;
789
+ let expected = & ndarray:: arr3 ( & [
790
+ [ [ 0.0 ] , [ 0.0 ] , [ 10.0 ] ] ,
791
+ [ [ 0.0 ] , [ 10.0 ] , [ 0.0 ] ] ,
792
+ [ [ 10.0 ] , [ 0.0 ] , [ 0.0 ] ] ,
793
+ ] ) . into_dyn ( ) ;
794
+ assert_relative_eq ! ( array, expected, max_relative=1e-6 ) ;
795
+
796
+ // now a full NL
797
+ let mut calculator = Calculator :: from ( Box :: new ( NeighborList {
798
+ cutoff : 12.0 ,
799
+ full_neighbor_list : true ,
800
+ self_pairs : false ,
801
+ } ) as Box < dyn CalculatorBase > ) ;
802
+
803
+ let descriptor = calculator. compute ( & mut systems, Default :: default ( ) ) . unwrap ( ) ;
804
+ assert_eq ! ( * descriptor. keys( ) , Labels :: new(
805
+ [ "species_first_atom" , "species_second_atom" ] ,
806
+ & [ [ 1 , 1 ] , [ 1 , 6 ] , [ 6 , 1 ] , [ 6 , 6 ] ]
807
+ ) ) ;
808
+
809
+ // H-H block
810
+ let block = descriptor. block_by_id ( 0 ) ;
811
+ assert_eq ! ( block. samples( ) , Labels :: new(
812
+ [ "structure" , "first_atom" , "second_atom" , "cell_shift_a" , "cell_shift_b" , "cell_shift_c" ] ,
813
+ // twice as many pairs
814
+ & [
815
+ [ 0 , 1 , 1 , 0 , 0 , 1 ] , [ 0 , 1 , 1 , 0 , 0 , -1 ] ,
816
+ [ 0 , 1 , 1 , 0 , 1 , 0 ] , [ 0 , 1 , 1 , 0 , -1 , 0 ] ,
817
+ [ 0 , 1 , 1 , 1 , 0 , 0 ] , [ 0 , 1 , 1 , -1 , 0 , 0 ] ,
818
+ ]
819
+ ) ) ;
820
+
821
+ let array = block. values ( ) . to_array ( ) ;
822
+ let expected = & ndarray:: arr3 ( & [
823
+ [ [ 0.0 ] , [ 0.0 ] , [ 10.0 ] ] ,
824
+ [ [ 0.0 ] , [ 0.0 ] , [ -10.0 ] ] ,
825
+ [ [ 0.0 ] , [ 10.0 ] , [ 0.0 ] ] ,
826
+ [ [ 0.0 ] , [ -10.0 ] , [ 0.0 ] ] ,
827
+ [ [ 10.0 ] , [ 0.0 ] , [ 0.0 ] ] ,
828
+ [ [ -10.0 ] , [ 0.0 ] , [ 0.0 ] ] ,
829
+ ] ) . into_dyn ( ) ;
830
+ assert_relative_eq ! ( array, expected, max_relative=1e-6 ) ;
831
+ }
832
+
767
833
#[ test]
768
834
fn finite_differences_positions ( ) {
769
835
// half neighbor list
0 commit comments