Vesin: we are all neighbors¶
English 🇺🇸/🇬🇧 |
French 🇫🇷 |
Spanish 🇪🇸 |
Italian 🇮🇹 |
||||
|---|---|---|---|---|---|---|---|
neighbo(u)r |
vesin |
voisin |
vesin |
visin |
veí |
vecino |
vicino |
vesin is a lightweight neighbor list calculator for molecular systems and
three-dimensional graphs. It is written in C++ and can be used as a standalone
library from C or Python. vesin is designed to be fast
and easy to use.
Installation¶
You can install the code with pip:
pip install vesin
TorchScript:
The TorchScript bindings can be installed with:
pip install vesin[torch]
If you use CMake as your build system, the simplest thing to do is to add https://github.com/Luthaf/vesin to your project.
# assuming the code is in the `vesin/` directory (for example using
# git submodule)
add_subdirectory(vesin)
target_link_libraries(your-target vesin)
Alternatively, you can use CMake’s FetchContent module to automatically download the code:
include(FetchContent)
FetchContent_Declare(
vesin
GIT_REPOSITORY https://github.com/Luthaf/vesin.git
)
FetchContent_MakeAvailable(vesin)
target_link_libraries(your-target vesin)
To make the TorchScript version of the library available to CMake as
well, you should set the VESIN_TORCH option to ON. If you are
using add_subdirectory(vesin):
set(VESIN_TORCH ON CACHE BOOL "Build the vesin_torch library")
add_subdirectory(vesin)
target_link_libraries(your-target vesin_torch)
And if you are using FetchContent:
set(VESIN_TORCH ON CACHE BOOL "Build the vesin_torch library")
# like above
FetchContent_Declare(...)
FetchContent_MakeAvailable(...)
target_link_libraries(your-target vesin_torch)
To make the fortran bindings of the library available to CMake, you
should set the VESIN_FORTRAN option to ON.
set(VESIN_FORTRAN ON CACHE BOOL "Build the vesin_fortran library")
add_subdirectory(vesin)
# or use fetch_content
FetchContent_xxx(...)
To enable the CUDA implementation, set the VESIN_ENABLE_CUDA option
to ON.
set(VESIN_ENABLE_CUDA ON CACHE BOOL "Build the CUDA backend of vesin")
add_subdirectory(vesin)
# or use fetch_content
FetchContent_xxx(...)
We support merging all files in the vesin library to a single one that can then be included in your own project and built with the same build system as the rest of your code.
You can generate this single file to build with the following commands:
git clone https://github.com/Luthaf/vesin.git
cd vesin
python create-single-cpp.py
Then you’ll need to copy both include/vesin.h and
vesin-single-build.cpp in your project and configure your build
system accordingly.
Important
Neither the TorchScript API or the CUDA implementation are supported by the single file file build. If you need these features, please use one of the CMake options instead.
You can build and install vesin in some global location (referred to as
$PREFIX below), and then use the right compiler flags to give this
location to your compiler. In this case, compilation of vesin and
your code happen separately.
git clone https://github.com/Luthaf/vesin.git
cd vesin
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=$PREFIX <other options> ..
cmake --install .
You can then compile your code, adding $PREFIX/include to the
compiler include path, $PREFIX/lib to the linker library path; and
linking to vesin (typically with -lvesin). If you are building vesin
as a shared library, you’ll also need to define VESIN_SHARED as a
preprocessor constant (-DVESIN_SHARED when compiling the code).
Some relevant cmake options you can customize:
Option |
Description |
Default |
|---|---|---|
|
Type of build: Debug or Release |
Release |
|
Prefix where the library will be installed |
|
|
Default to building and installing a shared library instead of a static one |
OFF |
|
Should CMake install vesin library and headers |
ON when building vesin directly OFF when including vesin in another project |
|
Build (and install if |
OFF |
|
Build (and install if |
OFF |
|
Build the CUDA implementation of vesin |
OFF |
Set VESIN_TORCH to ON to build and install the TorchScript
bindings.
You can then compile your code, adding $PREFIX/include to the
compiler include path, $PREFIX/lib to the linker library path; and
linking to vesin_torch (typically with -lvesin_torch).
You’ll need to also add to the include and linker path the path to the
same libtorch installation that was used to build the library.
Set VESIN_FORTRAN to ON to build and install the Fortran
bindings.
You can then compile your code, adding $PREFIX/include to the
compiler include path, $PREFIX/lib to the linker library path; and
linking to vesin_fortran (typically with -lvesin_fortran).
Set VESIN_ENABLE_CUDA to ON to build the CUDA implementation. It
will then be available from all language bindings (C, C++, Fortran,
TorchScript).
Usage example¶
There are two ways to use vesin from Python, you can use the
NeighborList class:
import numpy as np
from vesin import NeighborList
# positions can be anything compatible with numpy's ndarray
positions = [
(0, 0, 0),
(0, 1.3, 1.3),
]
box = 3.2 * np.eye(3)
calculator = NeighborList(cutoff=4.2, full_list=True)
i, j, S, d = calculator.compute(
points=points,
box=box,
periodic=True,
quantities="ijSd"
)
Alternatively, you can use the ase_neighbor_list() function,
which mimics the API of ase.neighborlist.neighbor_list():
import ase
from vesin import ase_neighbor_list
atoms = ase.Atoms(...)
i, j, S, d = ase_neighbor_list("ijSd", atoms, cutoff=4.2)
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <vesin.h>
int main() {
// points can be any pointer to `double[3]`
double points[][3] = {
{0, 0, 0},
{0, 1.3, 1.3},
};
size_t n_points = 2;
// box can be any `double[3][3]` array
double box[3][3] = {
{3.2, 0.0, 0.0},
{0.0, 3.2, 0.0},
{0.0, 0.0, 3.2},
};
bool periodic = true;
// calculation setup
VesinOptions options;
options.cutoff = 4.2;
options.full = true;
// decide what quantities should be computed
options.return_shifts = true;
options.return_distances = true;
options.return_vectors = false;
VesinNeighborList neighbors;
memset(&neighbors, 0, sizeof(VesinNeighborList));
const char* error_message = NULL;
int status = vesin_neighbors(
points, n_points, box, periodic,
VesinCPU, options,
&neighbors,
&error_message,
);
if (status != EXIT_SUCCESS) {
fprintf(stderr, "error: %s\n", error_message);
return 1;
}
// use neighbors as needed
printf("we have %d pairs\n", neighbors.length);
vesin_free(&neighbors);
return 0;
}
The fortran bindings provide a module named vesin which contains the
NeighborList type.
program main
use vesin, only: NeighborList
implicit none
real :: points(:,:)
real :: box(3,3)
integer :: i, ierr
type(NeighborList) :: neighbor_list
! define some points positions and box
points = reshape([ &
0.0_real64, 0.0_real64, 0.0_real64, &
0.0_real64, 1.3_real64, 1.3_real64 &
], [2, 3])
box = reshape([ &
3.2_real64, 0.0_real64, 0.0_real64, &
0.0_real64, 3.2_real64, 0.0_real64, &
0.0_real64, 0.0_real64, 3.2_real64 &
], [3, 3])
! initialize `neighbor_list` with some options
neighbor_list = NeighborList(cutoff=4.2, full=.true., sorted=.true.)
! run the calculation
call neighbor_list%compute(points, box, periodic=.true., status=ierr)
if (ierr /= 0) then
write(*, *) neighbor_list%errmsg
stop
end if
write(*,*) "we got ", neighbor_list%length, "pairs"
do i=1,neighbor_list%length
write(*, *) " - ", i, ":", neighbor_list%pairs(:, i)
end do
! release allocated memory
call neighbor_list%free()
deallocate(positions)
end program main
The entry point for the TorchScript API is the
vesin.torch.NeighborList class in Python, and the
corresponding vesin_torch::NeighborListHolder class in C++;
both modeled after vesin’s Python API.
In both cases, the code is integrated with PyTorch autograd framework,
meaning if the points or box argument have
requires_grad=True, then the d (distances) and D (distance
vectors) outputs will be integrated to the computational graph.
For Python, the NeighborList class is available in the
vesin.torch module.
import torch
from vesin.torch import NeighborList
positions = torch.tensor(
[[0.0, 0.0, 0.0],
[0.0, 1.3, 1.3]],
dtype=torch.float64,
requires_grad=True,
)
box = 3.2 * torch.eye(3, dtype=torch.float64)
calculator = NeighborList(cutoff=4.2, full_list=True)
i, j, S, d = calculator.compute(
points=points,
box=box,
periodic=True,
quantities="ijSd"
)
For C++, the class is available in the vesin_torch.hpp header.
#include <torch/torch.h>
#include <vesin_torch.hpp>
int main() {
auto options = torch::TensorOptions().dtype(torch::kFloat64);
auto positions = torch.tensor(
{{0.0, 0.0, 0.0},
{0.0, 1.3, 1.3}},
options
);
positions.requires_grad_(true);
auto box = 3.2 * torch.eye(3, options);
auto calculator = torch::make_intrusive<NeighborListHolder>(
/*cutoff=*/ 4.2,
/*full_list=*/ true
);
calculator.
auto outputs = calculator.compute(
/*points=*/ points,
/*box=*/ box,
/*periodic=*/ true,
/*quantities=*/ "ijSd",
/*copy=*/ true,
);
auto i = outputs[0];
auto j = outputs[1];
auto S = outputs[2];
auto d = outputs[3];
// ...
}








