Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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 @@ -115,6 +115,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 @@ -146,5 +151,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 @@ -129,6 +132,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
35 changes: 35 additions & 0 deletions bindings/sundials4py/sunlinsol/sunlinsol_klu_generated.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
m.attr("SUNKLU_ORDERING_DEFAULT") = SUNKLU_ORDERING_DEFAULT;

m.attr("SUNKLU_REINIT_FULL") = SUNKLU_REINIT_FULL;

m.attr("SUNKLU_REINIT_PARTIAL") = SUNKLU_REINIT_PARTIAL;

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>());

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"));
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
Loading