Cutoff neighbour lists¶
Build the cutoff list, choose the thread count, and read the pinned session that compared it with vesin, freud, matscipy, mdapy, and OVITO. The calls are on the API map. The drivers are on Benchmarks.
Box¶
nneigh::orthoFullCsr reads PointCloud.box.
A length of 3 is orthorhombic. box[0..2] are Lx, Ly, Lz.
The minimum image on each axis is dr - L * floor(dr / L + 0.5).
A length of at least 6 is a restricted triclinic LAMMPS dump.
box[0..2] are the bound spans xhi_bound - xlo_bound and so on.
box[3..5] are the tilt factors xy, xz, yz in the same length unit.
boxLow is the bound origin.
gen::makeFracBox recovers the edge lengths
lx = xspan - max(0, xy, xz, xy+xz) + min(0, xy, xz, xy+xz)ly = yspan - max(0, yz) + min(0, yz)lz = zspan
and the perpendicular widths wx, wy, wz.
The cartesian image of a fractional shift (sx, sy, sz) is
x = lx * sx + xy * sy + xz * szy = ly * sy + yz * szz = lz * sz
Cells are sized from those perpendicular widths. When every axis has reach 1 and at least four cells, both boxes fill the 27 image shifts once and walk that stencil. A wider cell uses the fractional minimum image. The pair is kept when the squared length is strictly below the cutoff squared.
nneigh::setBoxFromLammpsEdges stores edge lengths plus tilt as that
dump box. A zero tilt stays three spans, so the orthorhombic loop is
unchanged. seams read prints the spans and, when the box has six
entries, xy xz yz. There is no tilt flag.
CSR¶
offsets has length nop + 1.
cols[offsets[i] .. offsets[i + 1]] is sorted by cloud index and has
no self entry.
A null subset is every atom.
half keeps the pair only on the lower cloud index.
The pair set does not depend on the thread count.
The call returns false when the box is not usable.
Scratch stays allocated and is refilled on the next call.
idRowsFromCsr and indexRowsFromCsr put the atom itself first and
then the CSR partners, as atom ids or as cloud indices.
halfIdRowsFromCsr keeps the pair on the lower index.
neighListO, halfNeighList, and getNewNeighbourListByIndex build
this CSR and then those rows.
CutoffSkin builds candidates at cutoff + skin.
update calls moved. That is true when the atom count, the box, the
origin, or any minimum-image displacement exceeds skin / 2.
Otherwise lastReused is true.
filter then copies the wide CSR down to pairs still inside cutoff.
moved and filter are private. offsets and cols are the filtered
list.
chill::classifyBondsCsr labels the bonds of that CSR.
chill::chillPlusFromCsr keeps the four nearest of each row, accumulates
the real spherical harmonics at l = 3, and returns the cubic count.
symm::diamondFromCsr reads the twelve second-shell vectors from the
same rows: a clean cubic shell is 1, a clean hexagonal shell is 0, and
an undecided shell is -1.
chill::steinhardtQlCutoff builds the CSR for one atom type and returns
q_l. The Lechner-Dellago average is filled only when average is true.
Degrees other than 3, 4, 6, 8, and 12 return zeros. l = 12 runs on the
host.
Threads¶
The list, the skin filter, and the row converters use OpenMP.
Each call sets omp_set_dynamic(0) and sizes its scratch for
omp_get_max_threads.
The thread count is OMP_NUM_THREADS.
There is no setter and no thread argument on these functions.
A call made from inside an OpenMP region does not fork a second team.
The pinned session also sets OMP_PROC_BIND=close, OMP_PLACES=cores,
OMP_DYNAMIC=FALSE, and OMP_WAIT_POLICY=PASSIVE, and pins the process
with taskset to cores 0 .. T-1.
Orthorhombic session¶
Ice Ic, lattice constant 6.35 Å, cutoff 3.5 Å.
Each conventional cell holds 8 molecules, so the three frames are
10648, 110592, and 884736 molecules.
The full list has four neighbours per molecule, 4N directed pairs.
Rows are sorted by cloud index.
The same checksum is produced at 1, 2, 4, and 8 threads.
The host is a KVM guest, kernel 6.12.113+, one socket, Intel Xeon
family 6 model 207 stepping 2, 8 cores, one thread per core, 2.4 GHz.
Caches are L1d 384 KiB, L1i 256 KiB, L2 16 MiB, L3 320 MiB, with 47 GiB
of RAM. The compiler is GCC 15.2.0, release -O3.
The guest does not expose hardware performance counters.
The comparison columns used eight timed calls after one warmup.
The median is the 5th of the 8 sorted samples. Times are milliseconds.
The d-SEAMS columns are the later session recorded under the table.
vesin is 0.6.2, freud is 3.6.1, matscipy is 1.3.1 with ASE 3.29.0.
Every code returned 4N pairs.
molecules |
threads |
d-SEAMS CSR |
d-SEAMS rows |
vesin |
freud |
matscipy |
|---|---|---|---|---|---|---|
10648 |
1 |
3.709 |
4.160 |
5.674 |
9.508 |
8.458 |
10648 |
8 |
0.968 |
1.241 |
2.375 |
9.575 |
9.215 |
110592 |
1 |
25.080 |
29.510 |
52.801 |
104.725 |
76.528 |
110592 |
8 |
4.554 |
6.077 |
18.159 |
37.994 |
79.412 |
884736 |
1 |
244.517 |
291.817 |
1073.681 |
1067.929 |
585.680 |
884736 |
8 |
35.618 |
49.400 |
176.231 |
1068.058 |
590.335 |
The 2-thread and 4-thread rows are in markdown/neighbours.md.
The d-SEAMS columns in this table, and the triclinic and orthorhombic
columns of the shared-stencil table, were measured in one session on
8 cores. Eight timed calls after one warmup. The process is pinned to
cores 0 .. T-1, with OMP_NUM_THREADS=T, OMP_DYNAMIC=FALSE,
OMP_PROC_BIND=close, OMP_PLACES=cores, and OMP_WAIT_POLICY=PASSIVE.
bench_cutoff_list times this orthorhombic CSR and the atom-ID rows.
bench_v2 tilt and ortho time the shared-stencil CSR. The median
is the 5th of the 8 sorted samples. The interquartile range (IQR) is
the linear 75th percentile minus the linear 25th, with rank (n-1)p.
No host name is part of the record. The vesin, freud, and matscipy
columns are the earlier comparison, not this session.
Orthorhombic CSR median (IQR) in milliseconds, 1 thread then 8: 10648 is 3.709 (0.280) and 0.968 (0.040); 110592 is 25.080 (0.222) and 4.554 (0.322); 884736 is 244.517 (4.625) and 35.618 (1.582). The row medians (IQR) are 4.160 (0.179) and 1.241 (0.104); 29.510 (0.500) and 6.077 (0.959); 291.817 (12.147) and 49.400 (2.016).
meson setup build-release --buildtype=release -Dwith_tests=true \
-Dwith_cli=true -Dwith_mpi=disabled -Dwith_openmp_offload=disabled
ninja -C build-release tests/bench_cutoff_list
NEIGH_BENCH=$PWD/build-release/tests/bench_cutoff_list \
python3 scripts/bench_neighbours_threads.py
bench_cutoff_list is the d-SEAMS side of that driver.
The comparison environment is vesin 0.6.2, freud-analysis, matscipy,
and ASE. NEIGH_PYTHON selects that interpreter. Do not install the
unrelated PyPI package named freud.