Skip to content

Conversation

@balos1
Copy link
Member

@balos1 balos1 commented Nov 11, 2025

This PR adds sundials4py, which is a Python interface to SUNDIALS.

The generator code can be found here: https://github.com/sundials-codes/sundials4py-generate.

Rendered docs: https://sundials--796.org.readthedocs.build/en/796/.

Review Requests

@drreynolds:

  • doc/
  • bindings/sundials4py/arkode
  • bindings/sundials4py/idas
  • bindings/sundials4py/kinsol
  • bindings/sundials4py/sundomeigest
  • bindings/sundials4py/sunlinsol
  • bindings/sundials4py/sunmatrix
  • bindings/sundials4py/examples

@gardner48:

Everything but can skip:

  • _generated.hpp files (Steven and I will review these)
  • bindings/sundials4py/examples (Steven and Dan are both reviewing these)
  • bindings/sundials4py/arkode (Steven and Dan both reviewing these)
  • bindings/sundials4py/idas (Steven and Dan both reviewing these)

@Steven-Roberts

  • Skim _generated.hpp files in bindings/sundials4py
  • bindings/sundials4py/arkode
  • bindings/sundials4py/idas
  • bindings/sundials4py/include
  • bindings/sundials4py/sundials
  • bindings/sundials4py/nvector
  • bindings/sundials4py/sunadaptcontroller
  • bindings/sundials4py/sunadjointcheckpointscheme
  • bindings/sundials4py/sunnonlinsol
  • bindings/sundials4py/sunmemory
  • bindings/sundials4py/examples
  • https://github.com/sundials-codes/sundials4py-generate

Base automatically changed from feature/enable-python to develop November 21, 2025 00:15

This chapter covers details developers need to know about the SUNDIALS Python interfaces, distributed as the Python package sundials4py.

We use `nanobind <https://github.com/wjakob/nanobind>__` for the Python bindings. nanobind is a sleeker, faster ``pybind11``.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is nanobind a fork/version of pybind11? Is it just a completely separate package? As written, it sounds like the developers of pybind11 just cleaned things up and changed the name.

Suggested change
We use `nanobind <https://github.com/wjakob/nanobind>__` for the Python bindings. nanobind is a sleeker, faster ``pybind11``.
We use `nanobind <https://github.com/wjakob/nanobind>__` for the Python bindings. nanobind is a sleeker, faster replacement for ``pybind11``.

Copy link
Collaborator

@drreynolds drreynolds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've finished going through doc. I have a good amount of bindings/sundials4py to finish...

Copy link
Collaborator

@drreynolds drreynolds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! I have a few more questions/comments, but I believe I've finished a first pass over my "assignments"

Comment on lines +29 to +30
using namespace sundials::experimental;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated below

Suggested change
using namespace sundials::experimental;

Comment on lines +73 to +91
// m.def("MRIStepInnerStepper_GetForcingData",
// [](MRIStepInnerStepper stepper) -> std::tuple<int, sunrealtype, sunrealtype, std::vector<N_Vector>, int> {

// sunrealtype tshift = 0.0;
// sunrealtype tscale = 0.0;
// N_Vector* forcing_1d = nullptr;
// int nforcing = 0;

// int status = MRIStepInnerStepper_GetForcingData(stepper, &tshift, &tscale, &forcing_1d, &nforcing);

// std::vector<N_Vector> forcing(nforcing);
// // TODO(CJB): for some reason this causes a segfault unless you clone
// // for (int i = 0; i < nforcing; i++) {
// // // forcing[i] = N_VClone(forcing_1d[i]);
// // forcing[i] = forcing_1d[i];
// // }

// return std::make_tuple(status, tshift, tscale, forcing, nforcing);
// });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this commented-out code be removed or fixed?

assert status == ARK_SUCCESS

# PCG linear solver with no preconditioning, with up to N iterations
LS = SUNLinSol_PCG(y, 0, N, sunctx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update the C example to use the enum as well:

Suggested change
LS = SUNLinSol_PCG(y, 0, N, sunctx)
LS = SUNLinSol_PCG(y, SUN_PREC_NONE, N, sunctx)

status = ark.ARKodeSetMaxNumSteps(arkode.get(), int((tf - t0) / dt) + 1)
assert status == ark.ARK_SUCCESS

# # Enable checkpointing during the forward run
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# # Enable checkpointing during the forward run
# Enable checkpointing during the forward run

# transition, both u and v continue to evolve somewhat
# rapidly for another 1.4 time units, and finish off smoothly.
#
# This program solves the problem with the DIRK method, using a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# This program solves the problem with the DIRK method, using a
# This program solves the problem with the BDF method, using a

Comment on lines +74 to +79
# Reshape to 2D for vectorized operations
u2d = np.zeros((self.NX + 2, self.NY + 2), dtype=sunrealtype)
# Fill interior points
for i in range(1, self.NX + 1):
for j in range(1, self.NY + 1):
u2d[i, j] = u[idx(i, j)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on your comment, it looks like you were attempting to use np.reshape but couldn't get it to work, so you ended up copying u into a new 2D array, u2d. If so, it's too bad that this didn't work, since numpy's multi-dimensional arrays are incredibly attractive for structured grid calculations, but I recommend that you modify the comment:

Suggested change
# Reshape to 2D for vectorized operations
u2d = np.zeros((self.NX + 2, self.NY + 2), dtype=sunrealtype)
# Fill interior points
for i in range(1, self.NX + 1):
for j in range(1, self.NY + 1):
u2d[i, j] = u[idx(i, j)]
# Copy state to 2D for vectorized operations
u2d = np.zeros((self.NX + 2, self.NY + 2), dtype=sunrealtype)
# Fill interior points
for i in range(1, self.NX + 1):
for j in range(1, self.NY + 1):
u2d[i, j] = u[idx(i, j)]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment was chatgpt and I missed updating it (chatgpt did a great job at the initial porting of C examples to Python). I did not try using np.reshape.

Copy link
Collaborator

@Steven-Roberts Steven-Roberts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of docs. I now realize that wasn't assigned to me, but I needed to read it anyway to install and understand sundials4py.


SUNDIALS packages and several modules/classes require user-supplied callback functions to define problem-specific behavior,
such as the right-hand side of an ODE or a nonlinear system function. In sundials4py, you can provide these as standard Python functions or lambdas.
Somethings to note:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Somethings to note:
Here are some things to note:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants