Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6946312
Merge pull request #68 from wcwitt/main
wcwitt Jan 23, 2026
4e47715
adding sycl headers
Feb 23, 2026
e024c39
adding sycl macro
Feb 23, 2026
ea77614
update namespace sycl
Feb 23, 2026
cf1bcfe
Fixed issue with mixed devices being used when extracting MACE models
G-Seaford Apr 10, 2026
d5367e1
Change device to CPU for model loading
G-Seaford Apr 10, 2026
b5ac8ec
better error checking, including float issues, for spline bounds
bernstei May 8, 2026
a825dc2
fix bug in clamp arg type, and spline upper bound check
bernstei May 8, 2026
e012645
missing ;
bernstei May 8, 2026
40942d1
update tests for new cubic spline out of bounds exception message
bernstei May 8, 2026
635dc31
Merge branch 'main' into develop
wcwitt Jul 23, 2026
571debc
tidy.
wcwitt Jul 23, 2026
f4a3ba3
spaces for consistency.
wcwitt Jul 23, 2026
9b1cdd6
bump sphericart to v2.0.3.
wcwitt Jul 23, 2026
577b635
Merge pull request #76 from G-Seaford/main
wcwitt Jul 23, 2026
dc14489
tweak for correct name in error message.
wcwitt Jul 23, 2026
ebfb8b1
fix outdated syntax.
wcwitt Jul 23, 2026
ac934aa
check for nan.
wcwitt Jul 23, 2026
b247612
sanity check constructor.
wcwitt Jul 23, 2026
2aca216
special check for deriv_divided.
wcwitt Jul 23, 2026
c6283c9
harden splines for kokkos.
wcwitt Jul 23, 2026
047936f
improve constructor in cubic_spline_kokkos.
wcwitt Jul 23, 2026
4fe7eb3
drop tests that trigger with fast-math.
wcwitt Jul 24, 2026
1590cfa
Merge pull request #79 from wcwitt/spline_bounds
wcwitt Jul 24, 2026
ad12d2d
Merge branch 'develop' into alvaro
wcwitt Jul 24, 2026
865b6ce
Merge pull request #72 from alvarovm/main
wcwitt Jul 24, 2026
d53eace
bump kokkos to 5.1.1.
wcwitt Jul 27, 2026
6b9b831
finalize kokkos correctly when testing.
wcwitt Jul 27, 2026
c34aa9a
Merge pull request #84 from wcwitt/update-kokkos
wcwitt Jul 27, 2026
9bf6e33
modernize python packaging and ci.
chiang-yuan Jul 27, 2026
34d72ce
restore ruff workflow and python formatting
chiang-yuan Jul 27, 2026
847dd7f
targeted safe_globals.
wcwitt Jul 27, 2026
18f2430
prevent ruff from removing.
wcwitt Jul 27, 2026
8bf1144
fix typo.
wcwitt Jul 27, 2026
1f4b223
require torch 2.5 for targeted safe_globals.
wcwitt Jul 27, 2026
27b2d06
restore whitespace checker.
wcwitt Jul 27, 2026
952e56e
Merge pull request #75 from chiang-yuan/patch/readability
wcwitt Jul 28, 2026
e762729
Merge branch 'main' into develop
wcwitt Aug 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 47 additions & 46 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,40 @@ name: CI
on: [pull_request, workflow_dispatch]

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v8.3.2
- name: Run pre-commit
run: uvx pre-commit run --all-files

symmetrix:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get install -y build-essential cmake git libblas-dev liblapack-dev
- name: Set up python
uses: actions/setup-python@v5
sudo apt-get update
sudo apt-get install -y build-essential cmake git libblas-dev liblapack-dev ninja-build
- name: Set up uv
uses: astral-sh/setup-uv@v8.3.2
with:
python-version: '3.12'
- name: Create python venv
- name: Create python venv and install
run: |
python -m venv venv
source venv/bin/activate
pip install ase cmake-build-extension[all] numpy pytest setuptools scipy wheel cmake-build-extension[all]
deactivate
- name: Build and package symmetrix
run: |
source venv/bin/activate
cd symmetrix
pip install .
cd ..
uv venv --clear
source .venv/bin/activate
uv pip install ./symmetrix[test]
deactivate
- name: Run tests
run: |
source venv/bin/activate
source .venv/bin/activate
python -c "import symmetrix; print(symmetrix.__version__)"
cd symmetrix/test
pytest
Expand All @@ -44,25 +47,26 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake git libfftw3-dev libopenmpi-dev mpi-default-bin mpi-default-dev libblas-dev liblapack-dev
- name: Set up python
uses: actions/setup-python@v5
- name: Set up uv
uses: astral-sh/setup-uv@v8.3.2
with:
python-version: '3.12'
- name: Create python venv
- name: Create python venv and install
run: |
python -m venv venv
source venv/bin/activate
pip install numpy pytest
uv venv --clear
source .venv/bin/activate
uv pip install pip numpy pytest
deactivate
- name: Clone and build LAMMPS
run: |
source venv/bin/activate
source .venv/bin/activate
git clone -b release --depth 1 https://github.com/lammps/lammps.git
cd pair_symmetrix
chmod +x install.sh
Expand All @@ -82,13 +86,13 @@ jobs:
-D Kokkos_ENABLE_AGGRESSIVE_VECTORIZATION=ON \
-D SYMMETRIX_KOKKOS=ON \
cmake
cmake --build build -j 2
cmake --build build -j 4
cd build
make install-python
cd ../../..
- name: Run tests
run: |
source venv/bin/activate
source .venv/bin/activate
cd pair_symmetrix/test/
python -m pytest

Expand All @@ -97,42 +101,39 @@ jobs:
strategy:
fail-fast: false
matrix:
mace-torch: ["mace-torch==0.3.10", "mace-torch"]
include:
- mace-torch: "mace-torch==0.3.10"
torch: "torch==2.5.*"
- mace-torch: "mace-torch"
torch: "torch"
steps:
- name: Clone repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get install -y build-essential cmake git libblas-dev liblapack-dev
- name: Set up python
uses: actions/setup-python@v5
sudo apt-get update
sudo apt-get install -y build-essential cmake git libblas-dev liblapack-dev ninja-build
- name: Set up uv
uses: astral-sh/setup-uv@v8.3.2
with:
python-version: '3.12'
- name: Create python venv
run: |
python -m venv venv
source venv/bin/activate
pip install ${{ matrix.mace-torch }}
deactivate
- name: Build and package symmetrix
- name: Create python venv and install
run: |
source venv/bin/activate
cd symmetrix
pip install .
cd ..
uv venv --clear
source .venv/bin/activate
uv pip install "${{ matrix.torch }}" "${{ matrix.mace-torch }}" "./symmetrix[mace]"
deactivate
- name: Test model extraction
run: |
source venv/bin/activate
pip install mace-torch
source .venv/bin/activate
# check for valid symmetrix json from atomic numbers and default filename
wget https://github.com/ACEsuit/mace-off/raw/refs/heads/main/mace_off23/MACE-OFF23_small.model
wget https://github.com/ACEsuit/mace-off/raw/refs/heads/main/mace_off23/MACE-OFF23_small.model
symmetrix_extract_mace --model MACE-OFF23_small.model --atomic-numbers 1 8
python3 -c "from symmetrix import Symmetrix; calc = Symmetrix('MACE-OFF23_small-1-8.json', species=[1, 8])"
# check for valid symmetrix json from checmical symbols and specified filename
wget https://github.com/ACEsuit/mace-off/raw/refs/heads/main/mace_off23/MACE-OFF23_medium.model
wget https://github.com/ACEsuit/mace-off/raw/refs/heads/main/mace_off23/MACE-OFF23_medium.model
symmetrix_extract_mace --model MACE-OFF23_medium.model --chemical-symbols H O -o extract_test.json
python3 -c "from symmetrix import Symmetrix; calc = Symmetrix('extract_test.json', species=[1, 8])"
deactivate
15 changes: 15 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ See the `symmetrix` [README](symmetrix/README.md) to build and use the Python pa

See the `pair_symmetrix` [README](pair_symmetrix/README.md) for use from LAMMPS.

### Development Setup

Use `uv` to create a virtual environment and install the package with its test dependencies:

```bash
uv venv
source .venv/bin/activate
uv pip install -e "./symmetrix[test]"
```

Run Python formatting and lint checks with `uvx pre-commit run --all-files`.

### Citing Symmetrix

The earliest `symmetrix` results are reported in:
Expand Down
6 changes: 5 additions & 1 deletion libsymmetrix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ if (SYMMETRIX_SPHERICART_CUDA)
message(STATUS "Symmetrix: Will use CUDA version of sphericart.")
target_compile_definitions(symmetrix PRIVATE SYMMETRIX_SPHERICART_CUDA)
endif()

option(SYMMETRIX_SPHERICART_SYCL OFF)
if (SYMMETRIX_SPHERICART_SYCL)
message(STATUS "Symmetrix: Will use SYCL version of sphericart.")
target_compile_definitions(symmetrix PRIVATE SYMMETRIX_SPHERICART_SYCL)
endif()
2 changes: 1 addition & 1 deletion libsymmetrix/external/kokkos
Submodule kokkos updated 486 files
2 changes: 1 addition & 1 deletion libsymmetrix/external/kokkos-kernels
Submodule kokkos-kernels updated 346 files
2 changes: 1 addition & 1 deletion libsymmetrix/external/sphericart
Submodule sphericart updated 116 files
29 changes: 17 additions & 12 deletions libsymmetrix/source/cubic_spline.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <stdexcept>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>

#include "cubic_spline.hpp"

Expand All @@ -14,10 +17,9 @@ CubicSpline::CubicSpline(

double CubicSpline::evaluate(double r)
{
const int i = static_cast<int>(r / h);
// TODO: something better with this bounds checking
if (i<0 or i>=c.size()/4)
throw std::invalid_argument("Out of bounds in CubicSpline::evaluate.");
if (r<0 or r>h*c.size()/4 or std::isnan(r))
throw std::invalid_argument("Out of bounds in CubicSpline::evaluate. r=" + std::to_string(r));
const int i = std::clamp(static_cast<int>(r / h), 0, static_cast<int>(c.size()/4 - 1));
const double x = r - h*i;
const double xx = x*x;
const double xxx = xx*x;
Expand All @@ -28,10 +30,9 @@ double CubicSpline::evaluate(double r)

std::tuple<double,double> CubicSpline::evaluate_deriv(double r)
{
const int i = static_cast<int>(r / h);
// TODO: something better with this bounds checking
if (i<0 or i>=c.size()/4)
throw std::invalid_argument("Out of bounds in CubicSpline::evaluate_deriv.");
if (r<0 or r>h*c.size()/4 or std::isnan(r))
throw std::invalid_argument("Out of bounds in CubicSpline::evaluate_deriv. r=" + std::to_string(r));
const int i = std::clamp(static_cast<int>(r / h), 0, static_cast<int>(c.size()/4 - 1));
const double x = r - h*i;
const double xx = x*x;
const double xxx = xx*x;
Expand All @@ -42,10 +43,9 @@ std::tuple<double,double> CubicSpline::evaluate_deriv(double r)

std::tuple<double,double> CubicSpline::evaluate_deriv_divided(double r)
{
const int i = static_cast<int>(r / h);
// TODO: something better with this bounds checking
if (i<0 or i>=c.size()/4)
throw std::invalid_argument("Out of bounds in CubicSpline::evaluate_deriv.");
if (r<=0 or r>h*c.size()/4 or std::isnan(r))
throw std::invalid_argument("Out of bounds in CubicSpline::evaluate_deriv_divided. r=" + std::to_string(r));
const int i = std::clamp(static_cast<int>(r / h), 0, static_cast<int>(c.size()/4 - 1));
const double x = r - h*i;
const double xx = x*x;
const double xxx = xx*x;
Expand All @@ -60,6 +60,11 @@ auto CubicSpline::generate_coefficients(
std::vector<double> nodal_derivs)
-> std::vector<double>
{
if (h<=0 or not std::isfinite(h))
throw std::invalid_argument("CubicSpline requires positive finite spacing.");
if (nodal_values.size()<2 or nodal_values.size()!=nodal_derivs.size())
throw std::invalid_argument("CubicSpline requires at least two values and matching derivatives.");

auto c = std::vector<double>(4*(nodal_values.size()-1), 0.0);
for (int i=0; i<nodal_values.size()-1; ++i) {
c[4*i] = nodal_values[i];
Expand Down
43 changes: 26 additions & 17 deletions libsymmetrix/source/cubic_spline_kokkos.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
#include <stdexcept>
#include<iostream>
#include<cmath>
#include<string>
#include<algorithm>
#include "cubic_spline_kokkos.hpp"

CubicSplineKokkos::CubicSplineKokkos(
double h,
std::vector<double> nodal_values,
std::vector<double> nodal_derivs)
: h(h), num_coeffs(4*(nodal_values.size() - 1))
: h(h)
{
if (h<=0 or not std::isfinite(h))
throw std::invalid_argument("CubicSplineKokkos requires positive finite spacing.");
if (nodal_values.size()<2 or nodal_values.size()!=nodal_derivs.size())
throw std::invalid_argument("CubicSplineKokkos requires at least two values and matching derivatives.");
num_coeffs = 4*(nodal_values.size() - 1);
c = Kokkos::View<double*>("coeffs",num_coeffs);
generate_coefficients(h, nodal_values, nodal_derivs);
}
Expand All @@ -17,26 +24,30 @@ CubicSplineKokkos::CubicSplineKokkos(
double h,
Kokkos::View<double*> nodal_values,
Kokkos::View<double*> nodal_derivs)
: h(h), num_coeffs(4*(nodal_values.size() - 1))
: h(h)
{
if (h<=0 or not std::isfinite(h))
throw std::invalid_argument("CubicSplineKokkos requires positive finite spacing.");
if (nodal_values.size()<2 or nodal_values.size()!=nodal_derivs.size())
throw std::invalid_argument("CubicSplineKokkos requires at least two values and matching derivatives.");
num_coeffs = 4*(nodal_values.size() - 1);
c = Kokkos::View<double*>("coeffs",num_coeffs);
generate_coefficients(h, nodal_values, nodal_derivs);
}

double CubicSplineKokkos::evaluate(double r)
{
const int i = static_cast<int>(r / h);
// TODO: something better with this bounds checking
if (i < 0 || i >= num_coeffs / 4)
throw std::invalid_argument("Out of bounds in CubicSplineKokkos::evaluate.");

if (r<0 or r>h*num_coeffs/4 or std::isnan(r))
throw std::invalid_argument("Out of bounds in CubicSplineKokkos::evaluate. r=" + std::to_string(r));
const int i = std::clamp(static_cast<int>(r / h), 0, static_cast<int>(num_coeffs/4 - 1));

const double x = r - h * i;
const double xx = x * x;
const double xxx = xx * x;
const int i4 = 4 * i;

auto h_c = Kokkos::create_mirror_view(c);

double ret = 0;
const double c0 = h_c(i4);
const double c1 = h_c(i4 + 1);
Expand All @@ -49,10 +60,9 @@ double CubicSplineKokkos::evaluate(double r)

std::tuple<double, double> CubicSplineKokkos::evaluate_deriv(double r)
{
const int i = static_cast<int>(r / h);
// TODO: something better with this bounds checking
if (i < 0 || i > num_coeffs / 4)
throw std::invalid_argument("Out of bounds in CubicSplineKokkos::evaluate_deriv.");
if (r<0 or r>h*num_coeffs/4 or std::isnan(r))
throw std::invalid_argument("Out of bounds in CubicSplineKokkos::evaluate_deriv. r=" + std::to_string(r));
const int i = std::clamp(static_cast<int>(r / h), 0, static_cast<int>(num_coeffs/4 - 1));

const double x = r - h * i;
const double xx = x * x;
Expand All @@ -74,10 +84,9 @@ std::tuple<double, double> CubicSplineKokkos::evaluate_deriv(double r)

std::tuple<double,double> CubicSplineKokkos::evaluate_deriv_divided(double r)
{
const int i = static_cast<int>(r / h);
// TODO: something better with this bounds checking
if (i<0 or i> num_coeffs)
throw std::invalid_argument("Out of bounds in CubicSplineKokkos::evaluate_deriv.");
if (r<=0 or r>h*num_coeffs/4 or std::isnan(r))
throw std::invalid_argument("Out of bounds in CubicSplineKokkos::evaluate_deriv_divided. r=" + std::to_string(r));
const int i = std::clamp(static_cast<int>(r / h), 0, static_cast<int>(num_coeffs/4 - 1));

const double x = r - h*i;
const double xx = x*x;
Expand All @@ -90,7 +99,7 @@ std::tuple<double,double> CubicSplineKokkos::evaluate_deriv_divided(double r)
const double c1 = h_c(i4+1);
const double c2=h_c(i4+2);
const double c3=h_c(i4+3);

return {c0 + c1*x + c2*xx + c3*xxx, (c1 + 2*c2*x + 3*c3*xx) / r};
}

Expand Down
2 changes: 1 addition & 1 deletion libsymmetrix/source/cubic_spline_kokkos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ CubicSplineKokkos(double h,
CubicSplineKokkos(double h,
Kokkos::View<double*> nodal_values,
Kokkos::View<double*> nodal_derivs);

double evaluate(double r);
std::tuple<double,double> evaluate_deriv(double r);
std::tuple<double,double> evaluate_deriv_divided(double r);
Expand Down
Loading
Loading