Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
9 changes: 9 additions & 0 deletions bindings/sundials4py/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ set(sundials_SOURCES
sunnonlinsol/sunnonlinsol_newton.cpp
test/sundials4py_test.cpp)

# Conditionally add KLU bindings
if(SUNDIALS_ENABLE_SUNLINSOL_KLU)
list(APPEND sundials_SOURCES sunlinsol/sunlinsol_klu.cpp)
endif()

# Create the Python sundials library
nanobind_add_module(sundials4py STABLE_ABI NB_STATIC ${sundials_SOURCES})

Expand Down Expand Up @@ -150,5 +155,9 @@ target_link_libraries(
sundials_sundomeigestpower
sundials_core)

if(SUNDIALS_ENABLE_SUNLINSOL_KLU)
target_link_libraries(sundials4py PRIVATE sundials_sunlinsolklu)
endif()

# Install directive for scikit-build-core
install(TARGETS sundials4py LIBRARY DESTINATION .)
6 changes: 6 additions & 0 deletions bindings/sundials4py/sundials4py.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ void bind_sundomeigest_power(nb::module_& m);

void bind_sunlinsol_band(nb::module_& m);
void bind_sunlinsol_dense(nb::module_& m);
#if defined(SUNDIALS_KLU_ENABLED)
void bind_sunlinsol_klu(nb::module_& m);
#endif
void bind_sunlinsol_pcg(nb::module_& m);
void bind_sunlinsol_spbcgs(nb::module_& m);
void bind_sunlinsol_spfgmr(nb::module_& m);
Expand Down Expand Up @@ -130,6 +133,9 @@ NB_MODULE(sundials4py, m)

sundials4py::bind_sunlinsol_band(core_m);
sundials4py::bind_sunlinsol_dense(core_m);
#if defined(SUNDIALS_KLU_ENABLED)
sundials4py::bind_sunlinsol_klu(core_m);
#endif
sundials4py::bind_sunlinsol_pcg(core_m);
sundials4py::bind_sunlinsol_spbcgs(core_m);
sundials4py::bind_sunlinsol_spfgmr(core_m);
Expand Down
4 changes: 4 additions & 0 deletions bindings/sundials4py/sunlinsol/generate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ modules:
path: sunlinsol/sunlinsol_dense_generated.hpp
headers:
- ../../include/sunlinsol/sunlinsol_dense.h
sunlinsol_klu:
path: sunlinsol/sunlinsol_klu_generated.hpp
headers:
- ../../include/sunlinsol/sunlinsol_klu.h
sunlinsol_spbcgs:
path: sunlinsol/sunlinsol_spbcgs_generated.hpp
headers:
Expand Down
33 changes: 33 additions & 0 deletions bindings/sundials4py/sunlinsol/sunlinsol_klu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* -----------------------------------------------------------------
* Programmer(s): Cody J. Balos @ LLNL
* -----------------------------------------------------------------
* SUNDIALS Copyright Start
* Copyright (c) 2025-2026, Lawrence Livermore National Security,
* University of Maryland Baltimore County, and the SUNDIALS contributors.
* Copyright (c) 2013-2025, Lawrence Livermore National Security
* and Southern Methodist University.
* Copyright (c) 2002-2013, Lawrence Livermore National Security.
* All rights reserved.
*
* See the top-level LICENSE and NOTICE files for details.
*
* SPDX-License-Identifier: BSD-3-Clause
* SUNDIALS Copyright End
* -----------------------------------------------------------------*/

#include "sundials4py.hpp"

#include <sundials/sundials_core.hpp>
#include <sunlinsol/sunlinsol_klu.h>

namespace nb = nanobind;
using namespace sundials::experimental;

namespace sundials4py {

void bind_sunlinsol_klu(nb::module_& m)
{
#include "sunlinsol_klu_generated.hpp"
}

} // namespace sundials4py
52 changes: 52 additions & 0 deletions bindings/sundials4py/sunlinsol/sunlinsol_klu_generated.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// #ifndef _SUNLINSOL_KLU_H
//
// #ifndef _KLU_H
//
// #endif
//
// #ifdef __cplusplus
// #endif
//

auto pyClass_SUNLinearSolverContent_KLU =
nb::class_<_SUNLinearSolverContent_KLU>(m, "_SUNLinearSolverContent_KLU", "")
.def(nb::init<>()) // implicit default constructor
;

m.def(
"SUNLinSol_KLU",
[](N_Vector y, SUNMatrix A,
SUNContext sunctx) -> std::shared_ptr<std::remove_pointer_t<SUNLinearSolver>>
{
auto SUNLinSol_KLU_adapt_return_type_to_shared_ptr =
[](N_Vector y, SUNMatrix A, SUNContext sunctx)
-> std::shared_ptr<std::remove_pointer_t<SUNLinearSolver>>
{
auto lambda_result = SUNLinSol_KLU(y, A, sunctx);

return our_make_shared<std::remove_pointer_t<SUNLinearSolver>,
SUNLinearSolverDeleter>(lambda_result);
};

return SUNLinSol_KLU_adapt_return_type_to_shared_ptr(y, A, sunctx);
},
nb::arg("y"), nb::arg("A"), nb::arg("sunctx"), "nb::keep_alive<0, 3>()",
nb::keep_alive<0, 3>());

m.def("SUNLinSol_KLUReInit", SUNLinSol_KLUReInit, nb::arg("S"), nb::arg("A"),
nb::arg("nnz"), nb::arg("reinit_type"));

m.def("SUNLinSol_KLUSetOrdering", SUNLinSol_KLUSetOrdering, nb::arg("S"),
nb::arg("ordering_choice"));

m.def("SUNLinSol_KLUGetSymbolic", SUNLinSol_KLUGetSymbolic, nb::arg("S"));
Comment thread
balos1 marked this conversation as resolved.

m.def("SUNLinSol_KLUGetNumeric", SUNLinSol_KLUGetNumeric, nb::arg("S"));

m.def("SUNLinSol_KLUGetCommon", SUNLinSol_KLUGetCommon, nb::arg("S"));
Comment thread
balos1 marked this conversation as resolved.
// #ifdef __cplusplus
//
// #endif
//
// #endif
//
12 changes: 12 additions & 0 deletions bindings/sundials4py/test/test_sunlinearsolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# -----------------------------------------------------------------

import pytest
import sys
from fixtures import *
from sundials4py.core import *

Expand Down Expand Up @@ -52,6 +53,17 @@ def test_create_sptfqmr(sunctx, nvec):
assert LS is not None


def test_create_klu_if_available(sunctx, nvec):
if not hasattr(sys.modules[__name__], "SUNLinSol_KLU"):
pytest.skip("SUNLinSol_KLU is unavailable in this build")

n = N_VGetLength(nvec)
A = SUNSparseMatrix(n, n, n, SUN_CSC_MAT, sunctx)
assert A is not None
LS = SUNLinSol_KLU(nvec, A, sunctx)
assert LS is not None


def test_get_type_and_id(sunctx, nvec):
A = SUNDenseMatrix(N_VGetLength(nvec), N_VGetLength(nvec), sunctx)
LS = SUNLinSol_Dense(nvec, A, sunctx)
Expand Down
12 changes: 10 additions & 2 deletions doc/shared/Python/Usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ when running pip. For example:
Other SUNDIALS options can also be accessed in this way. Review
:numref:`Installation.Options` for more information on the available options.

To build sundials4py with KLU support enabled, pass CMake options for KLU (see :numref:`Installation.Options.KLU`) through ``CMAKE_ARGS`` when building from
source:

.. code-block:: bash

export CMAKE_ARGS="-DSUNDIALS_ENABLE_KLU=ON -DKLU_ROOT=/path/to/suitesparse/installation"
pip install sundials4py --no-binary=sundials4py

.. _Python.Usage.Modules:

Modules
Expand Down Expand Up @@ -104,7 +112,7 @@ same capabilities plus continuous forward and adjoint sensitivity analysis.
.. note::

Not all SUNDIALS features are supported by the Python interfaces. In
particular, third-party libraries are not yet supported.
particular, third-party libraries are only partially supported.

.. _Python.Usage.Example:

Expand All @@ -117,7 +125,7 @@ highlighted below similarly apply to using other SUNDIALS packages. For more
information on usage differences, continue to the :ref:`next section
<Python.Usage.Differences>`. Additional examples can be found in the
``examples/python`` directory of the :examples:`SUNDIALS GitHub repository
Comment thread
balos1 marked this conversation as resolved.
Outdated
<python>`.
.
Comment thread
balos1 marked this conversation as resolved.
Outdated

This example demonstrates how to use CVODES to solve the Lotka-Volterra
equations, a model of predator-prey dynamics in ecology, given by
Expand Down
Loading
Loading