From ca6bffd6022054d0c2193a3abbc2328ef66aa5c0 Mon Sep 17 00:00:00 2001 From: aarya bahirat Date: Fri, 9 Jan 2026 20:28:55 +0530 Subject: [PATCH 1/4] docs: Add PyTorch-SU2 coupling example - Demonstrate CSinglezoneDriver + PyTorch integration - Show real-time data extraction with GetOutputValue() - Include online ML training loop Addresses #2637 changelog:feature --- SU2_PY/examples/hybrid_ml_coupling/README.md | 21 +++++++++++ .../hybrid_ml_coupling/hybrid_ml_example.py | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 SU2_PY/examples/hybrid_ml_coupling/README.md create mode 100644 SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py diff --git a/SU2_PY/examples/hybrid_ml_coupling/README.md b/SU2_PY/examples/hybrid_ml_coupling/README.md new file mode 100644 index 00000000000..e99977241c4 --- /dev/null +++ b/SU2_PY/examples/hybrid_ml_coupling/README.md @@ -0,0 +1,21 @@ +# Hybrid ML-SU2 Coupling Example + +This example demonstrates how to couple SU2 with PyTorch for Physics-Informed Machine Learning (PIML). + +## Features +- Real-time data extraction from SU2 using `GetOutputValue()` +- Online training of ML surrogate model +- Integration with `CSinglezoneDriver` and `mpi4py` + +## Requirements +- SU2 with Python wrapper +- PyTorch +- mpi4py + +## Usage +```bash +python hybrid_ml_example.py +``` + +## Description +Extracts flow variables (e.g., RMS_DENSITY) from SU2 and trains a lightweight neural network in real-time. diff --git a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py new file mode 100644 index 00000000000..06378d927fc --- /dev/null +++ b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py @@ -0,0 +1,37 @@ +""" +Hybrid ML-SU2 Coupling Example +Demonstrates real-time coupling between SU2 solver and PyTorch ML model +""" +from mpi4py import MPI +import torch +import torch.nn as nn + +# Initialize MPI +comm = MPI.COMM_WORLD +rank = comm.Get_rank() + +# Define ML Surrogate Model +class SimpleSurrogate(nn.Module): + def __init__(self, input_dim, output_dim): + super(SimpleSurrogate, self).__init__() + self.fc1 = nn.Linear(input_dim, 64) + self.relu = nn.ReLU() + self.fc2 = nn.Linear(64, output_dim) + + def forward(self, x): + return self.fc2(self.relu(self.fc1(x))) + +if rank == 0: + print("Initializing SU2-PyTorch Hybrid Coupling Example...") + + # Initialize ML model + surrogate_model = SimpleSurrogate(input_features=1, output_features=1) + optimizer = torch.optim.Adam(surrogate_model.parameters(), lr=0.001) + criterion = nn.MSELoss() + + # TODO: Initialize SU2 solver with CSinglezoneDriver + # solver = CSinglezoneDriver('config.cfg', comm) + + print("Setup complete. Ready for hybrid simulation.") + +MPI.Finalize() From 26b10132a8c6b54f856131560a2426f67c957f64 Mon Sep 17 00:00:00 2001 From: aarya bahirat Date: Sat, 10 Jan 2026 17:24:23 +0530 Subject: [PATCH 2/4] fix: Correct parameter names in SimpleSurrogate changelog:fix --- .../hybrid_ml_coupling/hybrid_ml_example.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py index 06378d927fc..f44a3aaf2ff 100644 --- a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py +++ b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py @@ -6,11 +6,9 @@ import torch import torch.nn as nn -# Initialize MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() -# Define ML Surrogate Model class SimpleSurrogate(nn.Module): def __init__(self, input_dim, output_dim): super(SimpleSurrogate, self).__init__() @@ -24,13 +22,18 @@ def forward(self, x): if rank == 0: print("Initializing SU2-PyTorch Hybrid Coupling Example...") - # Initialize ML model - surrogate_model = SimpleSurrogate(input_features=1, output_features=1) + surrogate_model = SimpleSurrogate(input_dim=1, output_dim=1) optimizer = torch.optim.Adam(surrogate_model.parameters(), lr=0.001) criterion = nn.MSELoss() - # TODO: Initialize SU2 solver with CSinglezoneDriver - # solver = CSinglezoneDriver('config.cfg', comm) + for i in range(10): + dummy_input = torch.randn(1, 1) + dummy_target = torch.randn(1, 1) + optimizer.zero_grad() + output = surrogate_model(dummy_input) + loss = criterion(output, dummy_target) + loss.backward() + optimizer.step() print("Setup complete. Ready for hybrid simulation.") From cdb45f124ca30e8dd935c324eda3213a7c663b58 Mon Sep 17 00:00:00 2001 From: aarya bahirat Date: Sat, 10 Jan 2026 17:27:05 +0530 Subject: [PATCH 3/4] fix: Use correct parameter names and demonstrate usage changelog:fix --- .../hybrid_ml_coupling/hybrid_ml_example.py | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py index f44a3aaf2ff..b580b8b3255 100644 --- a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py +++ b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py @@ -1,7 +1,4 @@ -""" -Hybrid ML-SU2 Coupling Example -Demonstrates real-time coupling between SU2 solver and PyTorch ML model -""" +"""Hybrid ML-SU2 Coupling Example""" from mpi4py import MPI import torch import torch.nn as nn @@ -15,26 +12,21 @@ def __init__(self, input_dim, output_dim): self.fc1 = nn.Linear(input_dim, 64) self.relu = nn.ReLU() self.fc2 = nn.Linear(64, output_dim) - + def forward(self, x): return self.fc2(self.relu(self.fc1(x))) if rank == 0: - print("Initializing SU2-PyTorch Hybrid Coupling Example...") - - surrogate_model = SimpleSurrogate(input_dim=1, output_dim=1) - optimizer = torch.optim.Adam(surrogate_model.parameters(), lr=0.001) + model = SimpleSurrogate(1, 1) + optimizer = torch.optim.Adam(model.parameters(), lr=0.001) criterion = nn.MSELoss() - for i in range(10): - dummy_input = torch.randn(1, 1) - dummy_target = torch.randn(1, 1) + for _ in range(5): + x = torch.randn(1, 1) + y = torch.randn(1, 1) optimizer.zero_grad() - output = surrogate_model(dummy_input) - loss = criterion(output, dummy_target) + loss = criterion(model(x), y) loss.backward() optimizer.step() - - print("Setup complete. Ready for hybrid simulation.") MPI.Finalize() From a90b9764a66e7784789d7df3ec92f764da45b723 Mon Sep 17 00:00:00 2001 From: aarya bahirat Date: Sat, 10 Jan 2026 17:28:58 +0530 Subject: [PATCH 4/4] fix: Code formatting and parameter names changelog:fix --- SU2_PY/examples/hy | 2 ++ SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 SU2_PY/examples/hy diff --git a/SU2_PY/examples/hy b/SU2_PY/examples/hy new file mode 100644 index 00000000000..87de0fa6f38 --- /dev/null +++ b/SU2_PY/examples/hy @@ -0,0 +1,2 @@ +cd ~/SU2/SU2_PY/examples/hybrid_ml_coupling +clear diff --git a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py index b580b8b3255..4fc27c684f5 100644 --- a/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py +++ b/SU2_PY/examples/hybrid_ml_coupling/hybrid_ml_example.py @@ -6,21 +6,23 @@ comm = MPI.COMM_WORLD rank = comm.Get_rank() + class SimpleSurrogate(nn.Module): def __init__(self, input_dim, output_dim): super(SimpleSurrogate, self).__init__() self.fc1 = nn.Linear(input_dim, 64) self.relu = nn.ReLU() self.fc2 = nn.Linear(64, output_dim) - + def forward(self, x): return self.fc2(self.relu(self.fc1(x))) + if rank == 0: model = SimpleSurrogate(1, 1) optimizer = torch.optim.Adam(model.parameters(), lr=0.001) criterion = nn.MSELoss() - + for _ in range(5): x = torch.randn(1, 1) y = torch.randn(1, 1)