Overview
This tutorial explains how to use the generalized adaptive CFD–POD–LSTM pipeline developed at ETSIAE–UPM. The pipeline couples an OpenFOAM CFD solver with a data-driven surrogate model (Proper Orthogonal Decomposition + Long Short-Term Memory network) in a closed loop. At each iteration, OpenFOAM generates a block of flow snapshots, the LSTM is trained on them and predicts the next block, and the solver restarts — keeping prediction accuracy controlled over arbitrarily long horizons.
The generalization introduced in this work replaces all scattered shell and Python configuration files from the original implementation (Zou 2025) with a single config.yaml file and a single Python orchestrator (directorpython.py), making the pipeline portable to any OpenFOAM case.
Code
Comming soon…
What This Tutorial Covers
- What CFD adaptive prediction is and why it is needed.
- How the CFD–POD–LSTM loop works (adaptive framework).
- How POD via truncated SVD reduces the problem dimensionality.
- How the LSTM is trained and used for auto-regressive prediction.
- How to install the required Python environment.
- How to copy the pipeline into any OpenFOAM case.
- How to configure every parameter in
config.yaml. - How to run in offline mode (
SOLO_PYTHON=true) on pre-computed snapshots. - How to run the full adaptive loop (
SOLO_PYTHON=false) with a live OpenFOAM simulation. - How to read the output logs and visualise results in ParaView.
Full Tutorial Content
Table of Contents
- Introduction
- The adaptive framework
- Methodology: POD + LSTM
- File structure
- Environment setup
- config.yaml — all parameters
- Run the pipeline
- Summary / Checklist
1. Introduction
The challenge of high-fidelity simulations
Computational Fluid Dynamics (CFD) solvers — such as OpenFOAM — numerically solve the Navier–Stokes equations to predict how a fluid (air, water, etc.) moves through a geometry. To get accurate results, the solver must resolve all relevant spatial and temporal scales of the flow, which translates directly into very fine meshes and very small time steps.
This accuracy comes at a steep computational price:
- A single simulation of a realistic case can take hours or days on a cluster.
- Engineering tasks like parameter optimisation or uncertainty quantification require thousands of such evaluations.
- Running all of them with a full CFD solver is often completely infeasible.
Why machine learning?
Data-driven surrogate models can learn the dynamics of a flow from a set of precomputed snapshots and then predict future states in a fraction of the time. The idea is to let the CFD solver run for a while, collect its output, train a neural network, and then let the network take over prediction — bypassing the expensive solver.
The key challenge is prediction drift: purely data-driven models are trained once and their accuracy degrades over time as the flow evolves and the model encounters conditions not seen during training.
Adaptive prediction: the solution
Adaptive prediction solves the drift problem by coupling the ML model with the live CFD solver in a closed loop. Instead of training once and predicting forever, the pipeline alternates between:
- CFD solver — generates new, accurate snapshots for a window of time.
- ML model (POD-DL) — trains on those snapshots and predicts the next window.
- Repeat — the solver restarts from near the end of the ML prediction, corrects any drift, and the cycle continues.
This way, accuracy remains controlled over arbitrarily long prediction horizons and the model stays robust to shifts in the flow regime.
The only file you need to edit is
config.yaml. The only command you need to run ispython pyPseudo_Adaptive_parallel/directorpython.py.
2. The adaptive framework
How the loop works
The pipeline alternates between blocks of CFD simulation and blocks of ML prediction:

At each iteration:
- OpenFOAM runs from T₀ to T₁, saving a snapshot of the flow field every
TIME_STEP_WRITE_OFseconds. - POD-DL reads those snapshots, applies truncated SVD to reduce them to a low-dimensional representation, and trains an LSTM on the resulting temporal coefficients.
- LSTM predicts the coefficients from T₁ to T₂ in an auto-regressive loop; the full flow field is reconstructed from those coefficients.
- OpenFOAM restarts from T₂ −
TIME_AHEAD(a small overlap ensures continuity between the CFD and ML blocks). - Steps 1–4 repeat
NUM_ITERATIONStimes.
Key design choices
| Concept | What it means |
|---|---|
TIME_AHEAD |
A small temporal overlap (typically 5 snapshots × dt) so that OpenFOAM does not start from a discontinuity when it picks up after the ML block. |
| Transfer learning | The LSTM is not retrained from scratch every iteration. If a checkpoint exists from the previous round, the model is loaded and fine-tuned on the new data — each successive round trains faster. |
SOLO_PYTHON=true |
Skips OpenFOAM entirely. All snapshots must already exist in CFD_DIR. Useful for offline experiments, first validation, or debugging the ML module without running a full simulation. |
3. Methodology: POD + LSTM
The big picture
The full pipeline goes from raw CFD snapshots to predicted flow fields in five steps:

Why dimensionality reduction?
A typical CFD mesh has millions of cells and each field (velocity, pressure) is a vector at every cell. Feeding raw snapshots directly into a neural network would be computationally prohibitive. Proper Orthogonal Decomposition (POD) compresses the data: instead of predicting millions of numbers, the LSTM only needs to predict a handful of temporal coefficients.
POD via truncated SVD
The snapshot matrix X (one column per time step, one row per mesh cell) is factorised via Singular Value Decomposition (SVD). We then keep only the r₀ most energetic modes — this is the “truncation” step. The result is a small set of temporal coefficients that capture the essential dynamics of the flow:

- U_r — spatial POD modes (basis vectors): the “shapes” of the flow patterns
- Σ_r — singular values: how much energy each mode carries
- C — temporal coefficients: how much each mode contributes at each time step
The reconstruction error (RRMSE) tells you how much information is lost by keeping only r₀ modes. A good choice of NUM_MODES (r₀) keeps this below ~5 %.
LSTM prediction
The LSTM receives a sliding window of past temporal coefficients and predicts the next one. This prediction is then fed back as input to predict the following step — and so on, auto-regressively, for NUM_PREDS steps:

Once the LSTM has predicted all the future temporal coefficients, the full flow field is reconstructed by multiplying back with the spatial modes (U_r · Σ_r · Ĉ).
Training
The LSTM is trained to minimise the Mean Squared Error (MSE) between its predicted coefficients and the true ones from the CFD data. Two key features make training efficient:
- Transfer learning: if a model checkpoint exists from the previous adaptive iteration, it is loaded and fine-tuned instead of training from scratch. This makes each successive round converge much faster.
- Early stopping: training halts automatically when loss drops below
LOSS_THRESHOLD.

The two hyperparameters with the greatest impact on prediction quality are
NUM_MODES(r₀) andINP_SEQ(L). Start withNUM_MODES=5andINP_SEQ=8and tune from there.
Divergence monitoring: CE and TE
As the LSTM predicts further into the future, its error grows. The pipeline monitors this error in real time using two metrics:
- Consistency Estimate (CE) — how far the LSTM prediction has drifted from the POD-reconstructed reference.
- Truncation Estimate (TE) — how much information is lost by retaining only r₀ modes.
When either metric exceeds its threshold (CE_THRESHOLD or TE_THRESHOLD in config.yaml), the CFD solver is automatically restarted to correct the drift:

In fixed-interval mode both thresholds are set to 10⁹ (effectively disabled) and the solver restarts after a fixed number of predicted snapshots.
Divergence monitoring: Mahalanobis distance and ensemble UQ
Two additional, more sophisticated criteria are available:
Mahalanobis distance — measures how far a predicted coefficient vector has strayed from the training distribution. If the prediction lands in a region of the coefficient space that the model has never seen during training, the solver is recalled. This is controlled by the mahalanobis_thr parameter in config.yaml.
Ensemble uncertainty quantification (UQ) — instead of training a single LSTM, an ensemble of M models is trained. At each prediction step, each member produces a slightly different output. The spread (standard deviation) across ensemble members is a direct measure of prediction uncertainty:

When the uncertainty exceeds a user-defined threshold (sigma_thr in config.yaml), the solver is recalled.
4. File structure
What you need inside your OpenFOAM case directory
my_openfoam_case/
│
├── 0/ ← OpenFOAM initial conditions (U, p, …)
├── constant/ ← mesh + fluid properties (unchanged)
├── system/
│ ├── controlDict ← auto-modified by directorpython.py — do not set startTime/endTime manually
│ └── decomposeParDict ← numberOfSubdomains and n-tuple auto-updated from config.yaml
│ └── ...
│
├── pyPseudo_Adaptive_parallel/ ← copy this folder from the repository
│ ├── directorpython.py ← Python orchestrator: reads config.yaml and drives the full loop
│ ├── field_read_write.py ← reads and writes OpenFOAM binary and ASCII fields
│ ├── load_data.py ← snapshot loading and preprocessing
│ ├── forecasting_and_uq.py ← SVD, LSTM training, prediction, and UQ metrics
│ ├── Forecasting/
│ │ ├── nn_lstm.py ← LSTM architecture definition (PyTorch)
│ │ └── model_trainer.py ← training loop and checkpointing logic
│ └── training_inference_module.py ← top-level training / inference interface
│
└── config.yaml ← the only file you need to edit
How directorpython.py drives the loop:
For each iteration it automatically:
- Reads
config.yaml - Auto-detects OpenFOAM (or uses
ENV_OFif set) - Updates
system/controlDict(startTime,endTime,writeInterval,writeFormat) viafoamDictionary - Runs
mpirun -np N <solver> -paralleland writes the log tolog_OF_<start>_<end>.txt - Runs
reconstructParand deletesprocessor*/folders - Calls the ML module with the parameters from
config.yaml - Goes back to step 3 for the next iteration
You never need to touch any of these files.
5. Environment setup
5.1 Create a Python virtual environment
You need Python 3.10 (or 3.9+). Choose either venv or conda:
# Option A — venv (recommended, no extra install needed)
python3 -m venv ~/envs/cfd_ml
source ~/envs/cfd_ml/bin/activate
# Option B — conda
conda create -n cfd_ml python=3.10 -y
conda activate cfd_ml
5.2 Install dependencies
pip install torch numpy scipy matplotlib pyyaml psutil
Verify that everything installed correctly:
python -c "import torch, yaml, psutil; print('OK')"
# Expected output: OK
5.3 Point config.yaml to your environment
In config.yaml, under parametros_entorno, set ENV_CONDA to the full path of your Python binary:
parametros_entorno:
ENV_CONDA: "/home/youruser/envs/cfd_ml/bin/python" # venv
# ENV_CONDA: "/home/w460/youruser/.conda/envs/cfd_ml/bin/python" # Magerit conda
# ENV_CONDA: "NULL" # use system python3
directorpython.py auto-detects OpenFOAM by searching /opt/openfoam*/etc/bashrc. If your installation is elsewhere, set the full path:
ENV_OF: "/media/apps/avx512-2021/software/OpenFOAM/12-foss-2023a/OpenFOAM-12/etc/bashrc"
# ENV_OF: "NULL" # auto-detect
6. config.yaml — all parameters
The entire experiment is controlled from a single YAML file. Below is every section and every parameter.
Overview
| Section | What it controls |
|---|---|
parametros_entorno |
OpenFOAM path, Python path, CPU cores, SOLO_PYTHON mode |
parametros_flujo |
Timing: T₀, OF window, ML window, overlap, number of iterations |
parametros_caso |
Case name, variables to predict |
parametros_svd |
SVD/lcSVD model, number of modes, sensors |
parametros_lstm |
LSTM architecture, training hyperparameters |
parametros_umbrales |
CE/TE thresholds to trigger early OF restart |
parametros_rutas |
Paths to CFD data, saved models, sensors |
All parameters live here. You never need to open any
.pyfile.
6.1 parametros_entorno — Environment
parametros_entorno:
ENV_OF: "NULL" # OpenFOAM bashrc path; NULL = auto-detect
ENV_CONDA: "/home/user/envs/cfd_ml/bin/python" # path to your Python binary
N_PROCESOS: 4 # MPI cores for OpenFOAM
DECOMP_N: [2, 2, 1] # domain decomposition: n1×n2×n3 must equal N_PROCESOS
SOLO_PYTHON: false # true = ML only; false = full OF + ML loop
| Parameter | Description |
|---|---|
ENV_OF |
Full path to OpenFOAM’s etc/bashrc. "NULL" auto-detects from /opt/openfoam*. |
ENV_CONDA |
Full path to the Python interpreter in your virtual environment. "NULL" uses system python3. |
N_PROCESOS |
Number of MPI subdomains for mpirun. directorpython.py writes this to numberOfSubdomains in system/decomposeParDict automatically. |
DECOMP_N |
Spatial decomposition tuple [n1, n2, n3] where n1 × n2 × n3 = N_PROCESOS. Written to {method}Coeffs/n in decomposeParDict. Example: 48 cores → [6, 4, 2]. |
SOLO_PYTHON |
true skips OpenFOAM and only runs ML on pre-existing snapshots. false runs the full loop. |
6.2 parametros_flujo — Timing
parametros_flujo:
INITIAL_TIME: 100 # start time of the first CFD block
TIME_PERIOD_OF: 100 # duration of each OpenFOAM window (seconds)
TIME_PERIOD_PY: 100 # duration of each ML prediction window (seconds)
TIME_STEP_WRITE_OF: 1 # OpenFOAM writeInterval (seconds)
TIME_STEP_WRITE_PY: 1 # time resolution of ML predictions (seconds)
TIME_AHEAD: 5 # OF–ML overlap (seconds); typically 5 × TIME_STEP_WRITE_OF
NUM_ITERATIONS: 2 # number of OF + ML rounds
# Only used when SOLO_PYTHON: true
START_TIME_SP: -- # first available snapshot
MID_TIME_SP: -- # end of training data
END_TIME_SP: -- # end of prediction
| Parameter | Description |
|---|---|
INITIAL_TIME |
Physical time at which the first OpenFOAM block starts. |
TIME_PERIOD_OF |
How long (in simulated seconds) OpenFOAM runs per round before handing off to ML. |
TIME_PERIOD_PY |
How far ahead (in simulated seconds) the LSTM predicts per round. |
TIME_STEP_WRITE_OF |
OpenFOAM writeInterval. Sets the temporal resolution of the training snapshots. |
TIME_STEP_WRITE_PY |
Time step between consecutive ML prediction outputs. Can be coarser than TIME_STEP_WRITE_OF. |
TIME_AHEAD |
Overlap between the end of the ML block and the OF restart point. Prevents discontinuities at the handoff. Typically 5 × TIME_STEP_WRITE_OF. |
NUM_ITERATIONS |
Total number of OF→ML cycles. |
START_TIME_SP |
(SOLO_PYTHON only) First time folder present in CFD_DIR. |
MID_TIME_SP |
(SOLO_PYTHON only) Boundary between training data and prediction data. |
END_TIME_SP |
(SOLO_PYTHON only) Last time instant to predict. |
6.3 parametros_caso — Case
parametros_caso:
CASE_NAME: "cylinder" # used to name saved model files
VARIABLES:
- "U"
- "p"
| Parameter | Description |
|---|---|
CASE_NAME |
Short label for your experiment. Appears in the names of saved model files (e.g., cylinder_0.003_1000_10_18_saved_models/). |
VARIABLES |
List of OpenFOAM field names to predict. U is a vector field (3 components); p is a scalar. Add as many as your case has. |
6.4 parametros_svd — Dimensionality reduction
parametros_svd:
SVD_MODEL: "SVD" # "SVD" (standard) or "lcSVD" (low-cost, sensor-based)
NUM_MODES: 5 # number of POD modes r₀ to retain
NUM_SENSORS: -- # sensor points (lcSVD only)
RRMSE_CRITI: -- # acceptable RRMSE % for sensor selection (lcSVD only)
OVERLAP_POINTS: -- # spatial overlap between parallel processing chunks
| Parameter | Description |
|---|---|
SVD_MODEL |
"SVD" for standard truncated SVD (recommended). "lcSVD" for the low-cost sensor-based variant suited to very large meshes. |
NUM_MODES |
Number of POD modes to keep. Start with 5 and tune. Increase if reconstruction RRMSE is too high; decrease if training is slow. This is the most influential hyperparameter. |
NUM_SENSORS |
(lcSVD only) Number of sensor measurement points. |
RRMSE_CRITI |
(lcSVD only) Target RRMSE (%) when optimising sensor placement. |
OVERLAP_POINTS |
Spatial overlap between domain chunks when processing in parallel, to avoid boundary artefacts. |
6.5 parametros_lstm — LSTM architecture and training
parametros_lstm:
MODEL_NAME: "lstm"
HIDDEN_SIZE: 100 # hidden units in the LSTM cell
NUM_LAYERS: 1 # stacked LSTM layers
INP_SEQ: 8 # input window length (past time steps fed to the model)
OUT_SEQ: 1 # steps predicted at once (always keep at 1)
STRIDE: 0
STEP: 1
VAL_SIZE: 0
EPOCHS: 1000 # maximum training epochs
LOSS_THRESHOLD: 1.0e-8 # stop early if loss drops below this value
BATCH_SIZE: 4
OPTIMIZER_NAME: "Adam"
OPTIMIZER_HPARAMS:
lr: 1.0e-3
weight_decay: 1.0e-4
VERSION: 0 # checkpoint version index
SNAP_STEP: 1.0
NUM_PREDS: 100 # number of auto-regressive predictions per ML round
| Parameter | Description |
|---|---|
HIDDEN_SIZE |
Width of the LSTM hidden state. Start with 100. Larger values are more expressive but slower. |
NUM_LAYERS |
Number of stacked LSTM layers. 1 is usually enough. |
INP_SEQ |
Length of the sliding input window (in time steps). Start with 8 and tune. This is the second most influential hyperparameter. |
OUT_SEQ |
Always keep at 1. The model predicts one step at a time in auto-regressive mode. |
EPOCHS |
Maximum training epochs. Training stops early when LOSS_THRESHOLD is reached. |
LOSS_THRESHOLD |
MSE stopping criterion. Relax to 1e-6 if training takes too long. |
BATCH_SIZE |
Number of (input, output) sequence pairs per gradient update. |
OPTIMIZER_HPARAMS.lr |
Adam learning rate. 1e-3 is a good default. |
VERSION |
Used to distinguish checkpoint files across experiments. |
NUM_PREDS |
Number of auto-regressive prediction steps per ML round. |
6.6 parametros_umbrales — Thresholds (CE / TE)
parametros_umbrales:
CE_THRESHOLD: 1.0e+9 # consistency estimate threshold
TE_THRESHOLD: 1.0e+9 # truncation estimate threshold
When set to 1e9 (the default), both thresholds are effectively disabled and the pipeline uses fixed time windows (TIME_PERIOD_PY). To enable automatic early restart of OpenFOAM when prediction quality degrades, set these to meaningful values based on your flow (consult Zou 2025 for derivation).
6.7 parametros_rutas — Paths
parametros_rutas:
CFD_DIR: "/path/to/my_openfoam_case"
SAVED_MODELS_DIR: "./pyPseudo_Adaptive_parallel"
SENSORS_DIR: "./pyPseudo_Adaptive_parallel/sensors"
| Parameter | Description |
|---|---|
CFD_DIR |
Absolute path to the OpenFOAM case directory (contains 0/, constant/, system/). |
SAVED_MODELS_DIR |
Where LSTM checkpoint .pt files are saved. Relative paths are resolved from CFD_DIR. |
SENSORS_DIR |
Sensor location files (only needed for lcSVD mode). |
7. Run the pipeline
Two modes are available. Choose based on whether you already have CFD snapshots.
7.1 SOLO_PYTHON mode — offline prediction on pre-computed snapshots
Use this when you already have all the OpenFOAM time folders and want to test the ML module without running the solver.
Step 1 — Enable SOLO_PYTHON and define the time split
parametros_entorno:
SOLO_PYTHON: false
parametros_flujo:
START_TIME_SP: 100 # first available time folder
MID_TIME_SP: 200 # training uses [START → MID]
END_TIME_SP: 300 # ML predicts [MID → END]
Step 2 — Point to the data
parametros_rutas:
CFD_DIR: "/path/to/my_case_snapshots" # must contain 100/, 101/, 102/, …
Step 3 — Run
cd /path/to/my_openfoam_case/
python pyPseudo_Adaptive_parallel/directorpython.py
Log created automatically:
log_py_100_200.txt ← epoch / loss per iteration + RRMSE of reconstruction
7.2 Full adaptive loop — OpenFOAM + ML
Use this for a live simulation where the CFD solver and the ML model alternate.
Step 1 — Configure the timing
parametros_entorno:
SOLO_PYTHON: false
N_PROCESOS: 48 # directorpython.py updates numberOfSubdomains automatically
DECOMP_N: [6, 4, 2] # 6×4×2 = 48 — updates hierarchicalCoeffs/n automatically
parametros_flujo:
INITIAL_TIME: 100
TIME_PERIOD_OF: 100 # OF runs for 100 s = 100 snaps at dt=1
TIME_PERIOD_PY: 100 # ML predicts 100 s = 100 snaps
TIME_STEP_WRITE_OF: 1
TIME_AHEAD: 5 # 5-snapshot overlap
NUM_ITERATIONS: 2
Step 2 — Run
cd /path/to/my_openfoam_case/
python pyPseudo_Adaptive_parallel/directorpython.py
Expected log files (for NUM_ITERATIONS=2):
log_OF_100_200.txt ← OpenFOAM round 1
log_py_200_300.txt ← ML round 1
log_OF_295_400.txt ← OpenFOAM round 2 (restarts from T₁ − TIME_AHEAD)
log_py_400_500.txt ← ML round 2
7.3 Output files and how to interpret them
After a successful run:
my_openfoam_case/
├── 100/, 101/, …, 200/ ← CFD snapshots (OpenFOAM format)
├── 200/, 201/, …, 300/ ← ML predictions (same OpenFOAM format)
├── log_OF_100_200.txt ← OpenFOAM residuals log
├── log_py_200_300.txt ← ML training + prediction log
└── pyPseudo_Adaptive_parallel/
└── cylinder_1_100_100_5_saved_models/
├── best_model_z_0.pt ← LSTM weights for field U
└── best_model_p_0.pt ← LSTM weights for field p
Reading the logs:
log_OF_*.txt— standard OpenFOAM log: PISO residuals, continuity errors, same as any standalone OpenFOAM run.log_py_*.txt— ML log: epoch number, MSE loss, and SVD reconstruction RRMSE for each variable. A healthy run shows steadily decreasing loss and RRMSE below ~5%.- Success: last line reads
"All iterations completed successfully!"— everything worked. - ERROR: check
ENV_OF(OpenFOAM not found) orENV_CONDA(Python not found), and confirm your OpenFOAM case runs correctly on its own before using the pipeline.
Visualising results in ParaView:
The ML prediction folders are standard OpenFOAM time folders. Open them alongside the CFD folders:
ParaView → File > Open → select your .foam file
→ Apply → scrub through time → select field (U, p, …)
Both CFD and ML time steps appear in the same timeline, letting you compare them directly.
8. Summary / Checklist
Use this checklist every time you set up a new experiment from scratch.
Step 1 — Install the environment (once per machine)
python3 -m venv ~/envs/cfd_ml
source ~/envs/cfd_ml/bin/activate
pip install torch numpy scipy matplotlib pyyaml psutil
python -c "import torch, yaml, psutil; print('OK')"
Step 2 — Copy the code into your OpenFOAM case
cp -r /path/to/repo/pyPseudo_Adaptive_parallel/ /path/to/my_openfoam_case/
cp /path/to/repo/config.yaml /path/to/my_openfoam_case/
Step 3 — Edit config.yaml
These are the fields you must set before running:
| Field | Section | What to put |
|---|---|---|
ENV_CONDA |
parametros_entorno |
Full path to your Python binary |
ENV_OF |
parametros_entorno |
OpenFOAM bashrc path, or "NULL" |
N_PROCESOS |
parametros_entorno |
MPI cores (auto-written to decomposeParDict) |
DECOMP_N |
parametros_entorno |
[n1, n2, n3] with n1×n2×n3 = N_PROCESOS (auto-written to decomposeParDict) |
SOLO_PYTHON |
parametros_entorno |
true (offline) or false (full loop) |
VARIABLES |
parametros_caso |
Fields to predict, e.g. ["U", "p"] |
CASE_NAME |
parametros_caso |
Short name for your experiment |
CFD_DIR |
parametros_rutas |
Absolute path to your OpenFOAM case |
NUM_MODES |
parametros_svd |
Start with 10, tune up/down |
INP_SEQ |
parametros_lstm |
Start with 8, tune up/down |
INITIAL_TIME / TIME_PERIOD_OF / TIME_PERIOD_PY |
parametros_flujo |
(full loop) your simulation timing |
START_TIME_SP / MID_TIME_SP / END_TIME_SP |
parametros_flujo |
(SOLO_PYTHON) your data split |
Step 4 — Run
cd /path/to/my_openfoam_case/
python pyPseudo_Adaptive_parallel/directorpython.py
Step 5 — Verify
tail -1 log_py_*.txt
# Expected: "All iterations completed successfully!"
Then open ParaView, load your .foam file, and compare predicted vs CFD fields across the time timeline.
Summary: a single
config.yamland a singlepythoncommand replace all the scattered shell scripts and Python files of the original implementation. The pipeline works with any OpenFOAM case — pointCFD_DIRto your case, set your variables, and run.
Contributors
- Xiangrui Zou
- Carlos Sainz García
- Mikel Navarro Huarte
ModelFLOWs-UPM · Adaptive CFD-LSTM · POD/SVD + Deep Learning
pyPseudo_Adaptive_parallel/ + config.yaml
Based on:
- Abadía-Heredia, R., Zou., X., López-Martín, M., Le Clainche, S., An Adaptive Framework for Autoregressive Forecasting in CFD Using Hybrid Modal Decomposition and Deep Learning, arXiv:2505.01531, 2025
- Zou, X., Zhao, Z., Barragán, G., Le Clainche, S., Divergence-aware adaptive prediction framework for accelerating CFD simulations of unsteady flows, arXiv:2605.24150 , 2026.