# Flow Induced Oscillation on Cylinder Half Submerged in Water Simulation **Repository Path**: seaoftranquility/FIV ## Basic Information - **Project Name**: Flow Induced Oscillation on Cylinder Half Submerged in Water Simulation - **Description**: Flow Induced Oscillation on Cylinder Half Submerged in Water Simulation was first matlab based, however moved to octave on ubuntu os with gpu abilities - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-09 - **Last Updated**: 2026-10-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Flow-Induced Vibration (FIV) Simulator A self-contained simulator for two-dimensional incompressible flow past movable bluff bodies, available in **two parallel tracks** that share the same physics and benchmark targets: | Track | Language | Backend | Status | Notes | |---|---|---|---|---| | **Track-1** | MATLAB / Octave | CPU (MATLAB R2025b golden; GNU Octave ≥ 8 drop-in) | Complete | Original, fully validated solver. Numerics unchanged on Octave via a shim layer. | | **Track-2** | Python | NumPy / CuPy (real GPU) | Functional | Faithful port; ~3× faster than MATLAB on CPU, 5–20× on GPU via CuPy. | The solver produces time-resolved velocity/pressure fields, vorticity and turbulence diagnostics, hydrodynamic forces, and rigid-body motion for fixed, prescribed-motion, or tethered/spring-mounted bodies in cylinder, square, delta, and NACA0012/aileron geometries. - **Track-1 manual:** [`docs/track1-manual.md`](docs/track1-manual.md) - **Track-2 manual:** [`docs/track2-manual.md`](docs/track2-manual.md) - **Video feature tracker (`vtrack`) manual:** [`vtrack/README.md`](vtrack/README.md) - **Validation record:** [`VALIDATION.md`](VALIDATION.md) - **Study notes (physics / equations / numerics):** [`docs/`](docs/README.md) --- ## Two-track repository layout The repo is organised so each track is self-contained and its *main programs* are cleanly separated from *utility/library* code: ``` fluid-dynamics/ ├── README.md # this file ├── MANUAL.md # cross-track operations overview ├── VALIDATION.md # benchmark numbers vs literature ├── .gitignore │ ├── track1-matlab/ # ── TRACK 1: MATLAB / Octave ── │ ├── main/ # MAIN PROGRAMS (run directly) │ │ ├── runFIV.m runFIVEnhanced.m runBenchmark.m │ │ ├── runConvergence.m sweepFIV.m testEnhancedFIV.m │ │ ├── analyzeFIV.m plotFIV.m animateFIV.m octaveProbe.m │ ├── lib/ # UTILITY / LIBRARY (called by mains) │ │ ├── defaultFIVConfig.m validateFIVConfig.m buildFIVGeometry.m │ │ ├── gpuFIVOps.m gapCorrectionsFIV.m storageGuard.m │ │ ├── diagFIV.m diagProjection.m debug_pressure.m │ │ ├── probeSchemeDissipation.m isOctaveCompat.m │ │ └── mall.m momit.m somit.m vomit.m (Octave reduction shims) │ ├── shims/ # UTILITY — Octave graphics/interp/detrend shims │ │ └── shimCaxis.m … shimVecnorm.m (12 files) │ ├── tests/ # TESTS │ │ ├── testFIVSmoke.m diagBodyCoupling.m testHelpers.m testSolverStability.m │ ├── scripts/ # SUPPORT SCRIPTS │ │ └── baselineTiming.m │ ├── scratch/ # THROWAWAY debug scripts (do not ship) │ │ └── *_tmp.m (5 files) │ └── experiments/ # DEV solvers (not production) │ └── stagTest.m psiOmegaTest.m lbmTest.m │ ├── track2-python/ # ── TRACK 2: Python ── │ ├── run_fiv.py # MAIN: single simulation │ ├── run_convergence.py # MAIN: convergence ladder │ ├── run_benchmark.py # MAIN: benchmark │ └── fiv/ # PACKAGE (imported, never run directly) │ ├── __init__.py backend.py config.py geometry.py │ ├── operators.py pressure.py solver.py analyze.py │ ├── vtrack/ # ── STANDALONE: video feature tracker ── │ ├── run_track.py # MAIN: video feature tracker (mp4 → orbit) │ ├── run_selftest.py # self-test against synthetic ground truth │ ├── run_centerbench.py # compares the three centre-finding modes │ ├── run_centrefigure.py # renders the three-mode comparison figure │ ├── run_synth.py # synthetic footage generator │ └── vtrack/ # PACKAGE (video tracking: detect/track/body) │ ├── docs/ # study notes 01–05 + the two track manuals ├── data/ # .mat result/reference dumps (never loaded by code) └── logs/ # generated run logs (git-ignored) ``` **Main programs vs. utility scripts** - *Track-1:* `main/` = everything you run (solvers, post-processing, probe); `lib/` + `shims/` = everything those mains call (config, geometry, diagnostics, Octave shims). The `tests/`, `scripts/`, `scratch/`, `experiments/` folders are support/dev/throwaway. - *Track-2:* `run_*.py` = the three CLI entry scripts; `fiv/` = the library package they import. --- ## Quick start ### Track-1 (MATLAB, from the project root) ```matlab addpath(genpath('track1-matlab')); % Default: fixed cylinder, Re=100, 20×10 domain cfg = defaultFIVConfig(); cfg = validateFIVConfig(cfg); sim = runFIV(cfg); report = analyzeFIV(sim); % forces, spectra, frequencies, lock-in, energy plotFIV(sim); % field, history, spectrum plots animateFIV(sim); % optional animation % Enhanced solver (GPU + gap corrections + storage guard): sim2 = runFIVEnhanced(cfg); % drop-in replacement; same output + corrections ``` ### Track-1 (GNU Octave, from the project root) ```bash octave --no-gui -q --eval "addpath(genpath('track1-matlab')); testFIVSmoke" octave --no-gui -q --eval "addpath(genpath('track1-matlab')); runConvergence" ``` ### Track-2 (Python) ```bash cd track2-python python run_fiv.py --smoke # fast sanity check python run_convergence.py # 3-grid ladder python run_benchmark.py # benchmark + target check ``` --- ## Project status | Component | Track | Status | Notes | |---|---|---|---| | `defaultFIVConfig` / `validateFIVConfig` | 1 | Complete (v2) | Full SI-unit config with validation; version 2 | | `buildFIVGeometry` | 1 | Complete | SDF, markers, mass properties for all shapes | | `runFIV` | 1 | Repaired & upgraded | Exact projection; sub-iterated coupling fixed; spring support; convective outflow; `pcg` pressure option | | `runFIVEnhanced` | 1 | Complete (Oct 2026) | Drop-in GPU acceleration, gap-closure corrections (G2–G7), storage throttling; 100% compatible with existing config/analysis/plotting | | `gpuFIVOps` | 1 | Complete (Oct 2026) | GPU-accelerated field operators (advection, laplacian, Smagorinsky, Brinkman) with transparent CPU fallback | | `gapCorrectionsFIV` | 1 | Complete (Oct 2026) | Six multiplicative correction factors (Re/viscosity, free-surface image, aspect ratio, turbulence, blockage, shear) | | `storageGuard` | 1 | Complete (Oct 2026) | Three-tier disk-space monitor: ok → warning (3× interval) → critical (snapshots disabled) | | `analyzeFIV` | 1 | Complete | Forces, spectra (Hann + interpolation), frequencies, lock-in, energy, spring metrics | | `plotFIV` / `animateFIV` | 1 | Complete | Field, history, spectrum plots + animation; honors `cfg.visualization` | | `sweepFIV` | 1 | Complete | Serial parameter sweep with summary table | | `runBenchmark` | 1 | Complete | Preset benchmark cases vs literature targets | | `runConvergence` / `probeSchemeDissipation` | 1 | Complete | Grid-convergence ladder and scheme-dissipation verification probes | | Smoke test | 1 | Passing | Fixed + tether + **spring** cases with physical assertions | | `fiv` package + `run_*.py` | 2 | Functional | Faithful NumPy/CuPy port; GPU-accelerated via `FIV_USE_GPU` | **Solver architecture:** The flow solver uses a collocated Cartesian grid with a fractional-step projection method. The immersed body is represented by Brinkman volume penalization (smooth, implicit) applied before the pressure projection. Forward-difference divergence and backward-difference pressure gradient ensure `div(grad(p)) = Lap(p)` exactly, eliminating the pressure-velocity decoupling on the collocated grid. First-order upwind advection provides stability at high cell Reynolds numbers; a slope-limited (`limited`) second-order scheme is available for fine grids. **October 2026 realism upgrade (cfg v2):** the coupling loop advanced the fluid once per coupling *iteration* — every pre-upgrade benchmark silently ran at half the intended Reynolds number. That and eight further defects (body double-advance, committed under-relaxation, Newmark predictor, damping-force consistency, inert turbulence models, simplified SST, turning-point dt spike, unwired knobs) are fixed; see `VALIDATION.md` for the probes and measured before/after numbers. **Known limitation (validated honestly):** at 10 cells/diameter with first-order upwind, CD is 10–30% and St ~40% below the literature bands — the scheme's numerical viscosity (~5× physical at this resolution) dominates. CLrms is inside the band at every tested grid. The `limited` scheme reaches CD 1.22 at 320×160 but is unstable at coarser grids for long runs. --- ## Benchmark cases (Track-1) ```matlab addpath(genpath('track1-matlab')); b = runBenchmark('cylinder_Re150', 'Nx', 200, 'Ny', 100, 'tEnd', 40); % Springer target Cd≈1.32, St≈0.189 b = runBenchmark('cylinder_Re100', 'Nx', 160, 'Ny', 80, 'tEnd', 40); b = runBenchmark('inline_Re100', 'fExc', 0.16, 'tEnd', 30); % OpenFOAM benchmark, A=0.14D b = runBenchmark('transverse_Re150', 'fExc', 0.18, 'tEnd', 30); % Springer lock-in, A=0.3D b = runBenchmark('tether_noflow', 'tEnd', 5); % no-flow tether test ``` For Track-2 equivalents, see `docs/track2-manual.md` §3. --- ## Configuration All settings are ordinary MATLAB structs (Track-1) or a dataclass (Track-2). See `track1-matlab/lib/defaultFIVConfig.m` / `track2-python/fiv/config.py` for the full list, and the track manuals for the configuration reference. Key fields: ```matlab cfg = defaultFIVConfig(); cfg.domain.Nx = 200; % grid resolution cfg.flow.nu = 1/150; % Re = U*D/nu cfg.flow.tEnd = 40; % simulation duration cfg.body.shape = 'cylinder'; % cylinder|square|delta|naca0012|polygon cfg.body.D = 1.0; % diameter (cylinder) cfg.body.support = 'fixed'; % fixed|tether|forced|spring cfg.body.center = [5 5]; % body position cfg.body.mass = 2.0; % mass per unit span cfg.solver.penaltyTime = 0.02; % Brinkman penalty parameter (eta) cfg.solver.advection = 'upwind1'; % upwind1|limited|upwind2 cfg.solver.pressureSolver = 'lu'; % lu|pcg|auto cfg.solver.forceMethod = 'markers'; % markers|penalization cfg.domain.outflow = 'convective'; % convective|zeroGradient cfg.solver.dt = []; % empty = adaptive, or fixed dt cfg.output.saveEvery = 10; % snapshot cadence cfg.output.saveFile = ''; % optional .mat archive of the result ``` --- ## File manifest (segmented) **Track-1 — `track1-matlab/`** | Folder | Role | Files | |---|---|---| | `main/` | Main programs | `runFIV`, `runBenchmark`, `runConvergence`, `sweepFIV`, `analyzeFIV`, `plotFIV`, `animateFIV`, `octaveProbe` | | `lib/` | Utilities | `defaultFIVConfig`, `validateFIVConfig`, `buildFIVGeometry`, `diagFIV`, `diagProjection`, `debug_pressure`, `probeSchemeDissipation`, `isOctaveCompat`, `mall`/`momit`/`somit`/`vomit` | | `shims/` | Utilities (Octave) | `shimCaxis` … `shimVecnorm` (12) | | `tests/` | Tests | `testFIVSmoke`, `diagBodyCoupling`, `testHelpers`, `testSolverStability` | | `scripts/` | Support | `baselineTiming` | | `scratch/` | Throwaway | `debugSmokeSpring_tmp`, `debugSmokeSpring2_tmp`, `maskStudy_tmp`, `verifyP2_tmp`, `stabCheck_tmp` | | `experiments/` | Dev solvers | `stagTest`, `psiOmegaTest`, `lbmTest` | **Track-2 — `track2-python/`** | Folder | Role | Files | |---|---|---| | root | Main entry scripts | `run_fiv.py`, `run_convergence.py`, `run_benchmark.py` | | `fiv/` | Package (library) | `__init__`, `backend`, `config`, `geometry`, `operators`, `pressure`, `solver`, `analyze` | **Video feature tracker — `vtrack/` (standalone)** | Folder | Role | Files | |---|---|---| | root | Main entry scripts | `run_track.py`, `run_selftest.py`, `run_centerbench.py`, `run_centrefigure.py`, `run_synth.py` | | `vtrack/` | Package (video tracking) | `__init__`, `video`, `detect`, `track`, `body`, `metrics`, `plot`, `view`, `synth`, `export` | **Video feature tracker (`vtrack`)** — turns an mp4 of a cylinder carrying a coloured sticker into an animated orbit, displacement plots and a calculation table. Full documentation, including a measured comparison of the three ways to recover the base centre (two-sticker midpoint / cylinder end-face outline / raw sticker) and the recommendation to use **two stickers**: [`vtrack/README.md`](vtrack/README.md). **Root-level:** `README.md`, `MANUAL.md`, `VALIDATION.md`, `docs/`, `data/` (`.mat` outputs — never loaded by code), `logs/` (generated, git-ignored). --- ## Validation targets | Case | Source | Re | Key metrics | This solver (see `VALIDATION.md`) | |---|---|---|---|---| | Stationary cylinder | Springer (2024) | 150 | Cd_mean≈1.29, CL_rms≈0.40, St≈0.189 | Re=100 tested: CLrms in band; CD −11…−37%, St −27…−60% (grid-limited) | | Stationary cylinder | — | 100 | Cd_mean≈1.33, St≈0.165 | 0.79 / 1.00 / 1.10 at 6/10/16 cells per D | | Forced transverse | Springer (2024) | 150 | Lock-in 0.75≤f/f_s≤1.05, A=0.3D | not yet re-run post-upgrade | | Forced inline | OpenFOAM wiki | 100 | f=0,0.16,0.33 Hz, A=0.14D | not yet re-run post-upgrade | | Square cylinder | AIP PoF (2025) | 2.2e4 | SST, peak Cd near f/f_s=1 | not yet attempted (expected near-miss, 2-D IB limits) | --- ## References 1. Wu, Liu & Zhang, "Numerical simulation of flow around a transversely oscillating square cylinder at different frequencies," *Physics of Fluids* 37 (2025), DOI [10.1063/5.0256326](https://doi.org/10.1063/5.0256326). 2. Roy & Peter, "Numerical Investigations of Forced Oscillating Circular Cylinder in Uniform Flow," *Fluid Mechanics and Fluid Power* (2024), DOI [10.1007/978-981-99-5752-1_55](https://doi.org/10.1007/978-981-99-5752-1_55). 3. Alletto, "Inline oscillating cylinder," OpenFOAM Wiki, [wiki.openfoam.com](https://wiki.openfoam.com/Inline_oscillating_cylinder_by_Michael_Alletto). --- ## Smoke test ```matlab addpath(genpath('track1-matlab')); testFIVSmoke ``` Runs two small cases (fixed cylinder + no-flow tether) and verifies the public API returns finite fields, histories, and scalar metrics. For the Python equivalent: `python track2-python/run_fiv.py --smoke`.