Shape optimization of the inner (stagnation) boundary for 2D axisymmetric swirling flow using parallel FEM solver with multiple optimizers and spline interpolation methods.
This code is designed for analyzing and optimizing draft tube geometries to minimize vortex rope formation in hydraulic turbines operating at part-load conditions.
- Features
- Problem Description
- Requirements
- Quick Start
- Building
- Optimizers
- Spline Interpolation Methods
- Benchmark Script
- Command-Line Reference
- Examples
- Output Files
- Code Structure
- Troubleshooting
- Physics
- Acknowledgements
- Third-Party Libraries
- License
- Citing This Work
- Contributing
- Parallel FEM Solver: MPI-parallelized finite element solver using PETSc
- Multiple Optimizers: DONLP2 SQP (recommended), PETSc TAO, Python SciPy
- 11 Spline Methods: GSL, PCHIP, FITPACK, and ALGLIB with various interpolation types
- Configurable Boundary Conditions: Independent left/right BC control for ALGLIB cubic splines
- Automated Benchmarking: Compare all optimizer/spline combinations automatically
- Multiple Output Formats: Tecplot, VTK (ParaView), PNG plots, GAMBIT journal
This code solves an optimal shape design problem for swirling flow in a pipe with:
- Inlet: z=0, r=[0.132, 1.0] (hub to shroud)
- Outlet: z=4, r=[0.55, 1.1] (stagnant boundary to wall)
- Inner boundary: Optimized shape connecting inlet hub (r=0.132) to outlet stagnant region (r=0.55)
- Outer boundary: Conical expansion from r=1.0 to r=1.1
The objective is to minimize the flow force functional by finding the optimal shape of the inner (stagnation) boundary, parameterized by control points interpolated with splines.
| Requirement | Purpose | Notes |
|---|---|---|
| PETSc 3.x | Parallel FEM solver, TAO optimizer | Must be configured with --download-triangle |
| GSL | Spline interpolation | GNU Scientific Library |
| MPI | Parallel computing | OpenMPI, MPICH, or Intel MPI |
| gfortran | FITPACK compilation | Any Fortran compiler |
| C++11 compiler | ALGLIB compilation | gcc 4.8+, clang 3.3+ |
| CMake 3.14+ | Build system (optional) | Alternative to Make |
For benchmarking and plotting scripts:
pip install numpy scipy matplotlib
# Or use the provided requirements file:
pip install -r requirements.txtPETSc must be installed with Triangle mesh library:
cd petsc
./configure --download-triangle [other options...]
make allAfter building PETSc, set environment variables (add to ~/.bashrc):
export PETSC_DIR=/path/to/petsc
export PETSC_ARCH=arch-linux-c-debug # Your configuration name# Using CMake (recommended)
mkdir build && cd build
cmake ..
make -j4
cd ..
./build/generate_rpsi_data
mpirun -np 4 ./build/swirl2d_ipopt -nparam 2 -spline_type pchip
# Or using Make
make full
./generate_rpsi_data
mpirun -np 4 ./swirl2d_ipopt -nparam 2 -spline_type pchip
# Run comprehensive benchmark
python3 benchmark_all.py --quickThree build systems are available: CMake (recommended), Autoconf, and Make.
CMake automatically downloads ALGLIB and FITPACK if not present.
# Basic build
mkdir build && cd build
cmake ..
make -j4
# With custom PETSc location
cmake -DPETSC_DIR=/path/to/petsc -DPETSC_ARCH=arch-linux-c-opt ..
make -j4CMake Options:
| Option | Default | Description |
|---|---|---|
PETSC_DIR |
$PETSC_DIR env |
Path to PETSc installation |
PETSC_ARCH |
$PETSC_ARCH env |
PETSc configuration name |
DOWNLOAD_ALGLIB |
ON | Download ALGLIB if not present |
DOWNLOAD_FITPACK |
ON | Download FITPACK if not present |
ALGLIB_VERSION |
4.04.0 | ALGLIB version to download |
CMake Targets:
make # Build all executables
make swirl2d_ipopt # Build optimizer only
make generate_rpsi_data # Build data generator only
make run # Generate data and run optimizer
make run4 # Run with 4 MPI processes
make benchmark # Run quick benchmark (requires Python)
make benchmark_full # Run full benchmark
make python-deps # Install Python dependencies via pipStandard GNU autoconf build with ./configure.
# Generate configure script (only needed once, or after changing configure.ac)
autoconf
# Configure (uses PETSC_DIR and PETSC_ARCH from environment)
./configure
# Or specify PETSc location explicitly
./configure --with-petsc-dir=/path/to/petsc --with-petsc-arch=arch-linux-c-opt
# Build
makeConfigure Options:
| Option | Description |
|---|---|
--with-petsc-dir=DIR |
PETSc installation directory |
--with-petsc-arch=ARCH |
PETSc architecture name |
--with-alglib=DIR |
ALGLIB source directory (default: alglib-cpp) |
--with-alglib-version=VER |
ALGLIB version to download (default: 4.04.0) |
--with-fitpack=DIR |
FITPACK source directory (default: fitpack) |
--enable-download-alglib |
Download ALGLIB if not present (default: yes) |
--enable-download-fitpack |
Download FITPACK if not present (default: yes) |
--prefix=DIR |
Installation prefix (default: /usr/local) |
Autoconf Targets:
make # Build all executables
make deps # Download/build dependencies only
make run # Generate data and run optimizer
make run4 # Run with 4 MPI processes
make benchmark # Run quick benchmark
make install # Install to prefix
make clean # Remove build files
make distclean # Remove all generated files
make help # Show all targetsTraditional Makefile build that also downloads dependencies.
make all # Build optimizer and data generator
make full # Build all including FITPACK and ALGLIB
make fitpack # Download and build FITPACK library
make alglib # Build ALGLIB C++ wrapper
make donlp2 # Build DONLP2 SQP library
make clean # Remove object files
make distclean # Remove all generated files (including downloads)
make print # Show build configuration
make help # Show all targetsBoth build systems will download ALGLIB and FITPACK automatically:
# CMake - clean build
rm -rf build alglib-cpp fitpack
mkdir build && cd build
cmake .. # Downloads ALGLIB and FITPACK
make -j4
# Make - clean build
make distclean # Removes alglib-cpp and fitpack directories
make full # Downloads and builds everythingAfter running ./configure, the original Makefile is backed up. To switch between systems:
# Use autoconf-generated Makefile (after ./configure)
make # Uses ./Makefile (generated by configure)
# Use original direct Makefile
make -f Makefile.direct # Uses the original Makefile without configure
# Restore original Makefile
cp Makefile.orig MakefileThree optimization backends are available:
Sequential Quadratic Programming optimizer. Fast and reliable for this problem.
# Sequential
./swirl2d_ipopt -nparam 2
# Parallel (4 MPI ranks for FEM)
mpirun -np 4 ./swirl2d_ipopt -nparam 2
# With options
mpirun -np 4 ./swirl2d_ipopt -nparam 5 -donlp2_maxiter 100DONLP2 Options:
| Option | Description |
|---|---|
-donlp2_maxiter N |
Maximum iterations (default: 100) |
PETSc's optimization solvers. Good for comparison but may be slower.
# TAO BLMVM (bounded L-BFGS)
mpirun -np 4 ./swirl2d_ipopt -nparam 2 -tao -tao_type blmvm
# TAO with monitoring
mpirun -np 4 ./swirl2d_ipopt -tao -tao_type blmvm -tao_monitor -tao_viewTAO Options:
| Option | Description |
|---|---|
-tao |
Enable TAO optimizer (disables DONLP2) |
-tao_type TYPE |
blmvm, bqnls, bnls, nm (default: blmvm) |
-tao_max_it N |
Maximum iterations |
-tao_monitor |
Print iteration progress |
-tao_view |
Print solver summary |
Uses scipy.optimize for optimization, calls FEM solver via subprocess.
python3 swirl2d_sqp.py --nparam 2 --mpi 4
python3 swirl2d_sqp.py --nparam 5 --mpi 4 --method L-BFGS-BThe inner boundary shape is defined by control points interpolated with splines. Eleven different spline methods are available:
-spline_type gsl -gsl_type cubic # Classic cubic spline (default)
-spline_type gsl -gsl_type akima # Akima spline (local, needs 5+ points)
-spline_type gsl -gsl_type steffen # Steffen spline (monotonic)Piecewise Cubic Hermite Interpolating Polynomial. Shape-preserving, monotonicity-maintaining.
-spline_type pchipB-spline library from netlib. Supports smoothing and constrained fitting.
-spline_type fitpack -fitpack_type curfit # Standard B-spline
-spline_type fitpack -fitpack_type concon # Constrained spline (needs 4+ points)
-fitpack_smooth 0.001 # Smoothing factor (0=interpolating)
-fitpack_order 3 # Spline order (1-5, default: 3=cubic)C++ spline library with multiple algorithms and configurable boundary conditions.
-spline_type alglib -alglib_type cubic # Cubic spline with configurable BC
-spline_type alglib -alglib_type akima # Akima spline (needs 5+ points)
-spline_type alglib -alglib_type monotone # Monotone spline (shape-preserving)
-spline_type alglib -alglib_type hermite # Hermite spline (auto-derivatives)
-spline_type alglib -alglib_type catmullrom # Catmull-Rom (smooth through all points)Boundary conditions for cubic spline:
# Set both endpoints to same BC type
-alglib_bc_type 0 # Parabolically-terminated (parabolic runout)
-alglib_bc_type 1 # First derivative specified
-alglib_bc_type 2 # Second derivative specified (default: natural spline)
# Set left/right BC types independently
-alglib_bc_type_left 0 # Left: parabolic
-alglib_bc_type_right 1 # Right: first derivative
# Boundary values (for bc_type 1 or 2)
-alglib_bc_left 0.0 # Left boundary value
-alglib_bc_right 0.0 # Right boundary value| Method | Min Points | Monotonic | Best For |
|---|---|---|---|
| GSL-cubic | 3 | No | General purpose |
| GSL-akima | 5 | No | Avoiding overshoot |
| GSL-steffen | 3 | Yes | Few control points |
| PCHIP | 3 | Yes | Best overall results |
| FITPACK-curfit | 3 | No | Configurable smoothing |
| FITPACK-concon | 4 | Constrained | Convexity control |
| ALGLIB-cubic | 3 | No | Configurable BC |
| ALGLIB-akima | 5 | No | Avoiding overshoot |
| ALGLIB-monotone | 3 | Yes | Shape-preserving |
| ALGLIB-hermite | 3 | No | Auto-estimated derivatives |
| ALGLIB-catmullrom | 3 | No | Smooth through all points |
Recommendation: Use PCHIP (-spline_type pchip) for best (sometimes) optimization results.
Automatically test all combinations of methods:
# Quick test (subset of methods, nparam 1-5)
python3 benchmark_all.py --quick
# Full benchmark (all methods, nparam 1-10)
python3 benchmark_all.py --nparam-max 10 -o results.csv
# Custom settings
python3 benchmark_all.py --nparam-max 8 --timeout 300Benchmark output includes:
- Best FFeval for each (spline, optimizer) combination
- Best FFeval by number of parameters
- Success rate for each method
- Detailed CSV results file
| Method | Optimizer | FFeval |
|---|---|---|
| PCHIP | DONLP2 | -0.130732 |
| PCHIP | TAO-blmvm | -0.130731 |
| FITPACK-concon | DONLP2 | -0.130719 |
| GSL-steffen | DONLP2 | -0.130637 |
./swirl2d_ipopt [options]
General Options:
-nparam N Number of control points (default: 2)
-seq_fem Use sequential FEM (disable parallel)
Optimizer Selection:
(default) Use DONLP2 SQP
-tao Use PETSc TAO optimizer
DONLP2 Options:
-donlp2_maxiter N Maximum iterations (default: 100)
TAO Options:
-tao_type TYPE blmvm, bqnls, bnls, nm
-tao_max_it N Maximum iterations
-tao_monitor Print progress
-tao_view Print summary
Spline Options:
-spline_type TYPE gsl, pchip, fitpack, alglib (default: gsl)
-gsl_type TYPE cubic, akima, steffen (default: cubic)
-fitpack_type TYPE curfit, concon (default: curfit)
-fitpack_smooth S Smoothing factor (default: 0.001)
-fitpack_order K Spline order 1-5 (default: 3)
-alglib_type TYPE cubic, akima, monotone, hermite, catmullrom
-alglib_bc_type N BC type for both ends: 0=parabolic, 1=1st deriv, 2=2nd deriv
-alglib_bc_type_left N Left BC type (overrides -alglib_bc_type)
-alglib_bc_type_right N Right BC type (overrides -alglib_bc_type)
-alglib_bc_left V Left boundary value (for bc_type 1 or 2)
-alglib_bc_right V Right boundary value (for bc_type 1 or 2)# Basic optimization
mpirun -np 4 ./swirl2d_ipopt
# PCHIP spline with 5 control points
mpirun -np 4 ./swirl2d_ipopt -nparam 5 -spline_type pchip
# FITPACK with smoothing
mpirun -np 4 ./swirl2d_ipopt -spline_type fitpack -fitpack_smooth 0.01
# TAO optimizer with monitoring
mpirun -np 4 ./swirl2d_ipopt -tao -tao_type blmvm -tao_monitor
# GSL Steffen (monotonic) spline
mpirun -np 4 ./swirl2d_ipopt -spline_type gsl -gsl_type steffen
# ALGLIB monotone spline
mpirun -np 4 ./swirl2d_ipopt -spline_type alglib -alglib_type monotone
# ALGLIB Hermite spline
mpirun -np 4 ./swirl2d_ipopt -spline_type alglib -alglib_type hermite
# ALGLIB cubic with parabolic boundary conditions
mpirun -np 4 ./swirl2d_ipopt -spline_type alglib -alglib_type cubic -alglib_bc_type 0
# ALGLIB cubic with different left/right BC types
mpirun -np 4 ./swirl2d_ipopt -spline_type alglib -alglib_type cubic \
-alglib_bc_type_left 0 -alglib_bc_type_right 1 -alglib_bc_right 0.1
# Run benchmark
python3 benchmark_all.py --quick -o results.csv| File | Description |
|---|---|
meshoutSQP.dat |
Tecplot mesh with PSI solution (DONLP2, Python SQP) |
meshout.dat |
Tecplot mesh with PSI solution (TAO) |
params.dat |
Optimization log with all function evaluations |
gambit.jou |
GAMBIT journal with optimized boundary vertices |
solutionSQP.vtk |
VTK format for ParaView visualization |
solutionSQP.png |
PSI contour plot (generated by plot_psi.py) |
inlet-r-psi.dat |
Inlet boundary conditions |
outlet-r-psi.dat |
Outlet boundary conditions |
inner_flux.dat |
Boundary flux on inner (stagnation) boundary |
outer_flux.dat |
Boundary flux on outer (wall) boundary |
benchmark_results.csv |
Benchmark results (from benchmark_all.py) |
Note: DONLP2 and Python SQP write to meshoutSQP.dat, while TAO writes to meshout.dat.
.
├── CMakeLists.txt # CMake build system (recommended)
├── configure.ac # Autoconf input file
├── Makefile.ac.in # Autoconf Makefile template
├── configure # Generated configure script (run autoconf)
├── Makefile.orig # Original Make build system
├── Makefile # Active Makefile (from configure or original)
├── README.md # This documentation
├── requirements.txt # Python dependencies
├── install-sh # Autoconf helper script
│
├── swirl2d_ipopt.c # Main: Parallel FEM solver with DONLP2/TAO optimizers
├── generate_rpsi_data.c # Analytical boundary condition generator
├── alglib_wrapper.cpp # C++ wrapper for ALGLIB spline interpolation
│
├── benchmark_all.py # Automated benchmarking of all method combinations
├── swirl2d_sqp.py # Python SQP optimizer wrapper (uses scipy.optimize)
├── plot_psi.py # PSI contour visualization
│
├── build/ # CMake build directory (created by user)
│ ├── swirl2d_ipopt # Built executable
│ └── generate_rpsi_data # Built data generator
│
├── fitpack/ # FITPACK B-spline library (auto-downloaded)
├── donlp2c/ # DONLP2 SQP optimizer library
│ ├── donlp2.c # DONLP2 core algorithm
│ └── donlp2_compat.h # Compatibility header
├── alglib-cpp/ # ALGLIB C++ spline library (auto-downloaded)
│ └── src/ # ALGLIB source files
└── ../src/ # Shared sources
└── dnconf_wrapper.c # DONLP2 configuration wrapper
| File | Description |
|---|---|
swirl2d_ipopt.c |
Main program: mesh generation, FEM assembly, optimization loop |
generate_rpsi_data.c |
Generates inlet/outlet BCs from abc-swirl analytical solution |
alglib_wrapper.cpp |
Exposes ALGLIB splines to C code via extern "C" interface |
benchmark_all.py |
Tests all spline/optimizer combinations, generates CSV reports |
swirl2d_sqp.py |
Alternative optimizer using Python scipy.optimize.minimize |
If you see "Internal error in finddirection()" with FITPACK, this is a numerical precision issue in the Triangle library. The code includes a workaround (tiny perturbation) but some parameter combinations may still trigger it. Use PCHIP or GSL-steffen instead.
GSL and ALGLIB Akima splines require at least 5 data points (nparam >= 3). The code automatically falls back to Steffen if fewer points are provided.
FITPACK concon (constrained spline) requires m > 3, meaning nparam >= 2.
The code solves the Bragg-Hawthorne equation for axisymmetric swirling flow:
-d/dz(1/r * dpsi/dz) - d/dr(1/r * dpsi/dr) = r*H'(psi) - K(psi)*K'(psi)/r
where:
- psi: stream function (constant on streamlines)
- H(psi): total head distribution (Bernoulli function)
- K(psi): circulation distribution (r * v_theta)
Boundary conditions are derived from the abc-swirl analytical solution:
- Inlet (z=0): Prescribed psi profile from hub to shroud
- Outlet (z=4): Prescribed psi profile from stagnation region to wall
- Inner boundary: Stagnation streamline (psi=0)
- Outer boundary: Wall streamline (psi=psi_wall)
The optimization minimizes the flow force functional (FFeval), which represents the integrated pressure and momentum flux on the inner boundary. Lower values indicate better flow conditions with reduced recirculation and vortex rope formation.
- PETSc team for the parallel linear algebra framework
- Jonathan Shewchuk for the Triangle mesh generator
- P. Spellucci for the original DONLP2 optimizer (Fortran)
- S. Schoeffert (ASB, Bourges, France) for the DONLP2 C translation
- Diethelm Wuertz and Ryuichi Tamura for the Rdonlp2 R package
- Paul Dierckx for the FITPACK library
- ALGLIB project for the spline interpolation library
This project uses the following external libraries:
| Library | Purpose | License |
|---|---|---|
| PETSc | Parallel linear algebra, TAO optimizer | BSD-2-Clause |
| Triangle | Mesh generation | Non-commercial use |
| GSL | Spline interpolation | GPL-3.0 |
| FITPACK | B-spline fitting | Public domain (Netlib) |
| ALGLIB | Spline interpolation | GPL-2.0+ |
| DONLP2 | SQP optimizer (C code extracted from R package Rdonlp2) | Non-commercial use |
Note: DONLP2 and Triangle have non-commercial use restrictions. For commercial applications, contact the respective authors for licensing terms.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
If you use SWIRL2D in your research, you MUST cite the following paper:
Anton, A., Muntean, S., & Susan-Resiga, R. (2016). SWIRL2D: An interface tracking algorithm for computing the two-dimensional swirling flows with stagnant region. Proceedings of the Romanian Academy, Series A, 17(4), 379-386. PDF
@article{Anton2016swirl2d,
author = {Anton, Alin and Muntean, Sebastian and Susan-Resiga, Romeo},
title = {{SWIRL2D}: An interface tracking algorithm for computing the
two-dimensional swirling flows with stagnant region},
journal = {Proceedings of the Romanian Academy, Series A - Mathematics,
Physics, Technical Sciences, Information Science},
volume = {17},
number = {4},
pages = {379--386},
year = {2016},
url = {https://acad.ro/sectii2002/proceedings/doc2016-4/12ProcRoAcad-4-2016.pdf}
}Theoretical background (IAHR Working Group presentation, included in repository):
@inproceedings{SusanResiga2013IAHRWG,
author = {Susan-Resiga, Romeo and Muntean, Sebastian and Anton, Alin},
title = {Swirling Flow Analysis in a Francis Turbine Draft Tube},
booktitle = {6th IAHR International Meeting of the Workgroup on
Cavitation and Dynamic Problems in Hydraulic Machinery and Systems},
year = {2013},
address = {Ljubljana, Slovenia},
note = {PDF included: Resiga2013IAHRWG.pdf}
}Theoretical background (variational model):
@article{SusanResiga2016variational,
author = {Susan-Resiga, R.F. and Muntean, S. and Stuparu, A. and
Bosioc, A.I. and Tanasa, C. and Ighisan, C.},
title = {A variational model for swirling flow states with stagnant region},
journal = {European Journal of Mechanics - B/Fluids},
volume = {55}, pages = {104--115}, year = {2016},
doi = {10.1016/j.euromechflu.2015.09.002}
}PETSc (parallel solver and TAO optimizer):
@techreport{PETSc2024,
author = {Balay, S. and Abhyankar, S. and Adams, M.F. and others},
title = {{PETSc/TAO} Users Manual},
institution = {Argonne National Laboratory},
number = {ANL-21/39 - Revision 3.22}, year = {2024},
url = {https://petsc.org/}
}Triangle (mesh generation):
@inproceedings{Shewchuk1996triangle,
author = {Shewchuk, Jonathan Richard},
title = {Triangle: Engineering a {2D} quality mesh generator and
{Delaunay} triangulator},
booktitle = {Applied Computational Geometry: Towards Geometric Engineering},
series = {LNCS}, volume = {1148}, pages = {203--222},
year = {1996}, publisher = {Springer-Verlag}
}FITPACK (B-spline fitting):
@book{Dierckx1993fitpack,
author = {Dierckx, Paul},
title = {Curve and Surface Fitting with Splines},
publisher = {Oxford University Press}, year = {1993},
note = {FITPACK library: https://www.netlib.org/dierckx/}
}DONLP2 (SQP optimizer):
@techreport{Spellucci1998donlp2,
author = {Spellucci, Peter},
title = {{DONLP2} -- Dynamic constrained nonlinear optimization},
institution = {TU Darmstadt}, year = {1998},
note = {C code from Rdonlp2 R package}
}GSL (spline interpolation):
@book{Galassi2009gsl,
author = {Galassi, M. and Davies, J. and Theiler, J. and others},
title = {{GNU} Scientific Library Reference Manual},
publisher = {Network Theory Ltd.}, edition = {3rd}, year = {2009},
url = {https://www.gnu.org/software/gsl/}
}ALGLIB (spline interpolation):
@misc{ALGLIB,
author = {Bochkanov, Sergey},
title = {{ALGLIB} -- Numerical analysis library},
year = {2024}, url = {https://www.alglib.net/}
}A complete BibTeX file is available in references.bib.
Contributions are welcome! Please feel free to submit issues and pull requests.