Skip to content

[Docs] Missing examples for direct Python-ML coupling (PyTorch/TensorFlow) #2637

Closed as not planned

Description

@ayush4874

Problem Description

The current Python Wrapper examples primarily focus on shape optimization (FADO) or basic fluid driver execution. However, with the growing interest in Physics-Informed Machine Learning (PIML) and the integration of MLPCpp, there are no clear examples demonstrating how to couple the SU2 solver with external ML libraries (like PyTorch) in a single process.

Users currently have to guess how to extract field variables (e.g., RMS_DENSITY) from memory and pass them to a training loop in real-time.

Proposed Solution

I propose adding a dedicated example directory SU2_PY/examples/hybrid_ml_coupling/ containing a script that demonstrates:

  1. Initializing the CSinglezoneDriver with mpi4py.
  2. Running a time-stepping loop where the solver runs alongside a lightweight surrogate model.
  3. Extracting flow data from memory (using GetOutputValue) to train the model online.

I have prototyped a working script using PyTorch and would like to submit a PR to add this to the documentation/examples.

Activity

  1. ayush4874 commented on Dec 10, 2025

    @ayush4874
    ContributorAuthor

    I have migrated the example code to the Tutorials repository as requested by @bigfooted.

    The new PR is here: su2code/Tutorials#71

    I will leave this issue open until that PR is merged to track the resolution.

  2. ayush4874 commented on Dec 10, 2025

    @ayush4874
    ContributorAuthor

    Update: I have also submitted the corresponding documentation page as requested.

    Documentation PR: su2code/su2code.github.io#189

  3. pcarruscag commented on Dec 10, 2025

    @pcarruscag
    Member

    @EvertBunschoten you are the resident ML expert, please review these PRs

  4. ayush4874 commented on Dec 11, 2025

    @ayush4874
    ContributorAuthor

    Hi @EvertBunschoten, thanks for taking a look!

    While working on the documentation, I've also been digging into MLPCpp/include/CLookUp_ANN.hpp to architect the next step (Dynamic Weight Injection).

    It seems NeuralNetworks is strictly private and GenerateANN only supports file-based I/O. This effectively locks the model to "Read-Only" status after initialization.

    I have prototyped a patch locally that breaks this encapsulation (adding a SetWeights interface), and I successfully updated the network parameters mid-simulation from the Python driver.

    I plan to formalize this refactoring for my GSoC 2026 proposal. Before I do:
    Does the team have concerns about thread safety when updating these weights during an MPI run?
    (My current prototype assumes the Python driver handles the synchronization before pushing the weights, but I'd like to align with the core philosophy).

  5. aryab08 commented on Jan 2, 2026

    @aryab08
    Contributor

    Thanks for the detailed example and discussion.
    I’m following this thread to learn more about SU2–ML coupling.

  6. EvertBunschoten commented on Jan 9, 2026

    @EvertBunschoten
    Member

    Hello Ayush,
    Thank you for your interest in this topic. Could you give some more details about what you have in mind regarding the use of physics-informed methods in SU2?

  7. EvertBunschoten commented on Jan 9, 2026

    @EvertBunschoten
    Member

    Hi @EvertBunschoten, thanks for taking a look!

    While working on the documentation, I've also been digging into MLPCpp/include/CLookUp_ANN.hpp to architect the next step (Dynamic Weight Injection).

    It seems NeuralNetworks is strictly private and GenerateANN only supports file-based I/O. This effectively locks the model to "Read-Only" status after initialization.

    I have prototyped a patch locally that breaks this encapsulation (adding a SetWeights interface), and I successfully updated the network parameters mid-simulation from the Python driver.

    I plan to formalize this refactoring for my GSoC 2026 proposal. Before I do: Does the team have concerns about thread safety when updating these weights during an MPI run? (My current prototype assumes the Python driver handles the synchronization before pushing the weights, but I'd like to align with the core philosophy).

    It is true that in its current form the CNeuralNetwork class is indeed strictly private. The MLPCpp module currently only works for the inference of deep, dense multilayer perceptrons, not the training of them. It would be better to add this functionality through a PR on the MLPCpp repository.

  8. ayush4874 commented on Jan 9, 2026

    @ayush4874
    ContributorAuthor

    Hi @EvertBunschoten, thanks for the guidance. I'll definitely move the implementation to a PR on the MLPCpp repository then.

    To answer your question about the physics-informed side:
    The main idea is to enable online learning or hybrid loops where the solver and the network interact in real-time.

    Right now, since the weights are static, we can only do inference. If we expose SetWeights, we can have a Python driver (using PyTorch/JAX) that:

    1. Takes the flow state from SU2.
    2. Calculates a physics-based loss (like residual minimization).
    3. Updates the network weights and injects them back into SU2 mid-simulation.

    This closes the loop, allowing the model to adapt to the physics as the simulation evolves, rather than just being a fixed pre-trained block.

    I'll get started on the MLPCpp PR. Thanks!

  9. EvertBunschoten commented on Jan 9, 2026

    @EvertBunschoten
    Member

    Hi @EvertBunschoten, thanks for the guidance. I'll definitely move the implementation to a PR on the MLPCpp repository then.

    To answer your question about the physics-informed side: The main idea is to enable online learning or hybrid loops where the solver and the network interact in real-time.

    Right now, since the weights are static, we can only do inference. If we expose SetWeights, we can have a Python driver (using PyTorch/JAX) that:

    1. Takes the flow state from SU2.
    2. Calculates a physics-based loss (like residual minimization).
    3. Updates the network weights and injects them back into SU2 mid-simulation.

    This closes the loop, allowing the model to adapt to the physics as the simulation evolves, rather than just being a fixed pre-trained block.

    I'll get started on the MLPCpp PR. Thanks!

    Well the loop is not really closed, because currently the pytorch model is currently not controlling anything in SU2. In the tutorial example you share, the model uses the iteration number as input and the density residual as output. Is your goal to train an MLP to approximate the solution of the Navier-Stokes equations? Or something like a machine-learning based turbulence model? Physics-informed machine learning is quite a broad topic and the complexity of the feature you want to implement depends a lot on the problem you're trying to solve.

  10. ayush4874 commented on Jan 10, 2026

    @ayush4874
    ContributorAuthor

    You're absolutely right, the iteration-to-residual example was basically just a "connectivity test." I mostly wanted to prove I could inject weights mid-simulation without crashing the MPI synchronization or causing memory issues.

    My actual goal for the GSoC project is Data-Driven Turbulence Modeling (closure modeling). The plan is to use an ANN to predict closure terms, like eddy viscosity, based on input flow features.

    The reason I need the SetWeights interface is to enable Inverse Modeling or Data Assimilation loops. The idea is that SU2 runs the forward pass using the ANN, the Python driver calculates the error against experimental data (like Cp distribution), and then we update the network weights on the fly to "learn" the physics. This PR is just laying the C++ foundation to make that update step possible.

  11. added a commit that references this issue on Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions