Skip to content

Commit ac0c4f2

Browse files
Adds test suite and benchmarks (#69)
* Fix: CasADi linking to work with pip isolated build environments This commit resolves a build failure that occurred when building the package with pip/nox due to pip's use of isolated and changing build environments. Problem: - CMake was using find_library() to get the absolute path to libcasadi.dylib during configuration in one temporary pip build environment - By the time the actual build ran, pip had switched to a different temporary build environment, making the hard-coded library path invalid - This caused: "No rule to make target .../libcasadi.dylib" error Solution: - Link against CasADi by library name instead of absolute path, relying on target_link_directories() to provide the search path during build - Use relative RPATH (@loader_path on macOS, $ORIGIN on Linux) so the built module can find CasADi in the same Python environment at runtime - Set BUILD_RPATH for the build environment and INSTALL_RPATH for runtime - Remove duplicate casadi link (already added in USE_PYTHON_CASADI section) * tests: adds initial test suite w/ basic functionality * infra: adds __version__ to package, adds nox to dev dependencies w/ uv backend preference * tests: adds benchmark session, uv backend for nox, updates to unit suite, integration_tests.yml uses nox session, updates docs * benchmarks: remove icons * Fix: RPath installation bool, updates PYBAMM_ENV in noxfile, adds nox install to workflow * test: try condition RPATH * fix: precommit, integration workflow missing uv * benchmarks: update regression threshold, increase repeats, try: fix windows build * fix: integration workflow * CI: unifi package management * benchmarks: timeit implementation * test: adds casadi-based integration tests, removes simplistic unit tests (#70) * precommit additions * Suggestions from review Co-authored-by: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> * precommit additions * fix: avoid single-element vector operations for MacOS-intel * another test: separate negate from casadi symbol * infra: skip macosx_x86_x64 tests for build_wheels.yml * infra: test level skip instead of workflow level --------- Co-authored-by: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
1 parent e1da345 commit ac0c4f2

File tree

19 files changed

+1419
-53
lines changed

19 files changed

+1419
-53
lines changed

.github/workflows/benchmarks.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Benchmarks
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- "main"
7+
8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
12+
jobs:
13+
pytest:
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
os: [macos-latest]
19+
python-version: ["3.12"]
20+
21+
steps:
22+
- uses: actions/checkout@v5
23+
with:
24+
submodules: 'recursive'
25+
26+
- name: Install dependencies (macOS)
27+
if: matrix.os == 'macos-15-intel' || matrix.os == 'macos-latest'
28+
env:
29+
HOMEBREW_NO_INSTALL_CLEANUP: 1
30+
HOMEBREW_NO_AUTO_UPDATE: 1
31+
HOMEBREW_NO_COLOR: 1
32+
NONINTERACTIVE: 1
33+
run: |
34+
brew analytics off
35+
brew install libomp
36+
brew reinstall gcc
37+
38+
- name: Set up Python ${{ matrix.python-version }}
39+
uses: actions/setup-python@v6
40+
with:
41+
python-version: ${{ matrix.python-version }}
42+
43+
- name: Install uv
44+
run: |
45+
pip install uv
46+
47+
- name: Run benchmarks
48+
run: |
49+
uvx nox -s benchmarks

.github/workflows/integration_tests.yml

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,11 @@ jobs:
3939
with:
4040
python-version: ${{ matrix.python-version }}
4141

42-
- name: Clone PyBaMM repository
43-
uses: actions/checkout@v5
44-
with:
45-
repository: pybamm-team/PyBaMM
46-
path: PyBaMM
47-
fetch-depth: 0
48-
fetch-tags: true
42+
- name: Install uv
43+
run: |
44+
pip install uv
4945
5046
- name: Build and test
5147
run: |
52-
# Install PyBaMM with dependencies
53-
cd ./PyBaMM
54-
pip install -e ".[all,dev,jax]"
55-
cd ..
56-
57-
# Replace PyBaMM solvers
58-
pip uninstall pybammsolvers --yes
59-
python install_KLU_Sundials.py
60-
pip install "numpy>=2" --upgrade
61-
pip install .
62-
63-
# Run pybamm tests
64-
cd ./PyBaMM
65-
pytest tests/unit
66-
pytest tests/integration
48+
# Use PyBaMM-tests nox session
49+
uvx nox -s pybamm-tests

.github/workflows/unit_tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ jobs:
4444
with:
4545
python-version: ${{ matrix.python-version }}
4646

47-
- name: Install nox
47+
- name: Install uv
4848
run: |
49-
pip install nox
49+
pip install uv
5050
5151
- name: Build and test
5252
run: |
53-
nox
53+
uvx nox

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ build
1616
# Extra directories for local work
1717
workspace
1818
deploy
19+
PyBaMM
20+
21+
# benchmark results
22+
performance_results.json

CMakeLists.txt

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -137,25 +137,51 @@ if (${USE_PYTHON_CASADI})
137137
message("Found Python CasADi library directory: ${CASADI_LIB_DIR}")
138138
target_link_directories(idaklu PRIVATE ${CASADI_LIB_DIR})
139139

140-
set_target_properties(
141-
idaklu PROPERTIES
142-
INSTALL_RPATH "${CASADI_LIB_DIR}"
143-
INSTALL_RPATH_USE_LINK_PATH TRUE
144-
)
145-
# Attempt to link the casadi library directly if found
146-
find_library(CASADI_LIBRARY NAMES casadi PATHS ${CASADI_LIB_DIR} NO_DEFAULT_PATH)
147-
if (CASADI_LIBRARY)
148-
message("Found CasADi library: ${CASADI_LIBRARY}")
149-
target_link_libraries(idaklu PRIVATE ${CASADI_LIBRARY})
150-
else ()
151-
message(WARNING "CasADi library not found in ${CASADI_LIB_DIR}. The target will rely on transitive linkage via CMake config if available.")
152-
endif ()
140+
# Set RPATH to find libraries relative to the module location
141+
# This allows finding casadi in the same Python environment at runtime
142+
# Module is at: site-packages/pybammsolvers/idaklu.so
143+
# CasADi is at: site-packages/casadi/libcasadi.dylib
144+
# SuiteSparse/SUNDIALS are found via DYLD_LIBRARY_PATH/LD_LIBRARY_PATH
145+
# (set by noxfile or user environment) pointing to .idaklu/lib
146+
# Note: Windows uses vcpkg with static linking, no RPATH needed
147+
148+
# For CI wheel builds, use BUILD_WITH_INSTALL_RPATH=FALSE so that
149+
# wheel repair tools (delocate/auditwheel) can properly analyze dependencies.
150+
# For local development, use BUILD_WITH_INSTALL_RPATH=TRUE so the module
151+
# works immediately after pip install without wheel repair.
152+
if(DEFINED ENV{CIBUILDWHEEL})
153+
set(USE_INSTALL_RPATH_AT_BUILD FALSE)
154+
else()
155+
set(USE_INSTALL_RPATH_AT_BUILD TRUE)
156+
endif()
157+
158+
if (APPLE)
159+
set_target_properties(
160+
idaklu PROPERTIES
161+
BUILD_RPATH "${CASADI_LIB_DIR}"
162+
BUILD_RPATH_USE_LINK_PATH FALSE
163+
INSTALL_RPATH "@loader_path/../casadi"
164+
BUILD_WITH_INSTALL_RPATH ${USE_INSTALL_RPATH_AT_BUILD}
165+
)
166+
else()
167+
set_target_properties(
168+
idaklu PROPERTIES
169+
BUILD_RPATH "${CASADI_LIB_DIR}"
170+
BUILD_RPATH_USE_LINK_PATH FALSE
171+
INSTALL_RPATH "$ORIGIN/../casadi"
172+
BUILD_WITH_INSTALL_RPATH ${USE_INSTALL_RPATH_AT_BUILD}
173+
)
174+
endif()
175+
# Link against casadi by name, not absolute path, to avoid issues with
176+
# pip's isolated build environments changing paths between configure and build
177+
target_link_libraries(idaklu PRIVATE casadi)
153178
else ()
154179
message(FATAL_ERROR "Could not find CasADi library directory")
155180
endif ()
156181
else ()
157182
message("Trying to link against any casadi package apart from the Python one")
158183
find_package(casadi CONFIG REQUIRED)
184+
target_link_libraries(idaklu PRIVATE casadi)
159185
endif ()
160186

161187
# openmp
@@ -180,7 +206,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR})
180206
find_package(SUNDIALS REQUIRED)
181207
message("SUNDIALS found in ${SUNDIALS_INCLUDE_DIR}: ${SUNDIALS_LIBRARIES}")
182208
target_include_directories(idaklu PRIVATE ${SUNDIALS_INCLUDE_DIR})
183-
target_link_libraries(idaklu PRIVATE ${SUNDIALS_LIBRARIES} casadi)
209+
target_link_libraries(idaklu PRIVATE ${SUNDIALS_LIBRARIES})
184210

185211
# link suitesparse
186212
# if using vcpkg, use config mode to

README.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ pip install pybammsolvers
1313
The following solvers are available:
1414
- PyBaMM's IDAKLU solver
1515

16-
## Local builds
16+
## Development
17+
18+
### Local builds
1719

1820
For testing new solvers and unsupported architectures, local builds are possible.
1921

20-
### Nox
22+
#### Nox (Recommended)
2123

2224
Nox can be used to do a quick build:
2325
```bash
@@ -26,7 +28,7 @@ nox
2628
```
2729
This will setup an environment and attempt to build the library.
2830

29-
### MacOS
31+
#### MacOS
3032

3133
Mac dependencies can be installed using brew
3234
```bash
@@ -37,7 +39,7 @@ python install_KLU_Sundials.py
3739
pip install .
3840
```
3941

40-
### Linux
42+
#### Linux
4143

4244
Linux installs may vary based on the distribution, however, the basic build can
4345
be performed with the following commands:
@@ -48,3 +50,33 @@ pip install cmake casadi setuptools wheel "pybind11[global]"
4850
python install_KLU_Sundials.py
4951
pip install .
5052
```
53+
54+
### Testing
55+
56+
The project includes comprehensive test suites:
57+
58+
#### Unit Tests
59+
Test pybammsolvers functionality in isolation:
60+
```bash
61+
nox -s unit # Run all unit tests
62+
nox -s integration # Run all integration tests
63+
```
64+
65+
#### PyBaMM Integration Tests
66+
Verify compatibility with PyBaMM:
67+
```bash
68+
nox -s pybamm-tests # Clone/update PyBaMM and run all tests
69+
nox -s pybamm-tests -- --unit-only # Run only unit tests
70+
nox -s pybamm-tests -- --integration-only # Run only integration tests
71+
nox -s pybamm-tests -- --no-update # Skip git pull (use current version)
72+
nox -s pybamm-tests -- --pybamm-dir ./custom/path # Use existing PyBaMM clone
73+
nox -s pybamm-tests -- --branch develop # Use specific branch/tag
74+
```
75+
76+
The integration tests ensure that changes to pybammsolvers don't break PyBaMM functionality.
77+
78+
### Benchmarks
79+
Test for performance regressions against released PyBaMM:
80+
```bash
81+
nox -s benchmarks
82+
```

0 commit comments

Comments
 (0)