|
| 1 | +--- |
| 2 | +title: Partitioned Pipe — Geometric Axial Multiscale |
| 3 | +keywords: OpenFOAM, Nutils, preCICE, geometric multiscale, fluid |
| 4 | +summary: The Partitioned Pipe — Geometric Axial Multiscale tutorial couples a 1D pipe model with a 3D CFD pipe using preCICE. |
| 5 | +--- |
| 6 | + |
| 7 | +{% note %} |
| 8 | +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/develop/partitioned-pipe-multiscale), as continuously rendered here, or see the [latest released version](https://github.com/precice/tutorials/tree/master/partitioned-pipe-multiscale) (if there is already one). Read how in the [tutorials introduction](https://precice.org/tutorials.html). |
| 9 | +{% endnote %} |
| 10 | + |
| 11 | +## Setup |
| 12 | + |
| 13 | +We solve a simple **partitioned pipe problem** using a 1D–3D coupling approach. |
| 14 | +In this tutorial, the computational domain is split into two coupled regions: a 1D pipe section and a 3D pipe section. |
| 15 | +The coupling is performed using **preCICE**. |
| 16 | + |
| 17 | +In addition to the 1D–3D setup, this tutorial also includes configurations for **1D–1D** and **3D–3D** coupling. |
| 18 | +These variants can be beneficial for validation studies, solver comparisons, or for investigating the influence of model dimensionality. |
| 19 | + |
| 20 | +In the following, $\mathrm{1D}$ denotes the reduced-order domain (e.g., a Nutils solver) and $\mathrm{3D}$ denotes the full 3D CFD domain (e.g., OpenFOAM). |
| 21 | + |
| 22 | +The problem consists of a straight pipe of length $L = 40 \mathrm{m}$ and diameter $D = 10 \mathrm{m}$. We partition the domain at $z_c = 20 \mathrm{m}$, where the coupling interface is located. The pipe axis is aligned with the z-axis. |
| 23 | +The **1D domain** solves the flow equations using Nutils, while the **3D domain** is solved using OpenFOAM. |
| 24 | +Both solvers are coupled via preCICE by exchanging the **pressure** and **axial velocity** at the interface. |
| 25 | + |
| 26 | +Two coupling directions are possible: |
| 27 | + |
| 28 | +- **1D → 3D**: The 1D solver provides the interface velocity to the 3D solver, which responds with pressure. |
| 29 | +- **3D → 1D**: The 3D solver provides the velocity, and the 1D solver returns the pressure. |
| 30 | + |
| 31 | +The global outlet (end of the rightmost domain) is set to $p_{\mathrm{out}} = 0 \mathrm{Pa}$. |
| 32 | + |
| 33 | +For the **3D → 1D** coupling, the 3D inlet velocity is prescribed as a **parabolic (Poiseuille)** profile with a bulk velocity of $u_{\mathrm{in}} = 0.1 \mathrm{m/s}$ |
| 34 | +implemented using a `codedFixedValue` boundary condition. This ensures a physically realistic velocity distribution consistent with the 1D model. |
| 35 | + |
| 36 | +For the **1D → 3D** coupling, the inlet velocity is set to $u_{\mathrm{in}} = 0.1 \mathrm{m/s}$. |
| 37 | + |
| 38 | +## Configuration |
| 39 | + |
| 40 | +preCICE configuration for the 1D-3D simulation (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +preCICE configuration for the 3D-1D simulation: |
| 45 | + |
| 46 | + |
| 47 | + |
| 48 | +## Available solvers |
| 49 | + |
| 50 | +- OpenFOAM (**pimpleFoam**). An incompressible/transient OpenFOAM solver. See the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html). |
| 51 | +- Nutils. A Python-based finite element framework. For more information, see the [Nutils adapter documentation](https://precice.org/adapter-nutils.html) |
| 52 | + |
| 53 | +## Running the Simulation |
| 54 | + |
| 55 | +First, select which coupling you want to run. This sets the correct `precice-config.xml` symlink (by default, set to `1d3d`): |
| 56 | + |
| 57 | +```bash |
| 58 | +# Choose one configuration |
| 59 | +./setcase.sh 1d3d |
| 60 | +# or |
| 61 | +./setcase.sh 3d1d |
| 62 | +# or |
| 63 | +./setcase.sh 1d1d |
| 64 | +# or |
| 65 | +./setcase.sh 3d3d |
| 66 | +``` |
| 67 | + |
| 68 | +Open **two terminals** and start the corresponding participants for your chosen setup. |
| 69 | + |
| 70 | +### Example A — 1D → 3D coupling |
| 71 | + |
| 72 | +Terminal 1: |
| 73 | + |
| 74 | +```bash |
| 75 | +cd fluid1d-left-nutils |
| 76 | +./run.sh |
| 77 | +``` |
| 78 | + |
| 79 | +Terminal 2: |
| 80 | + |
| 81 | +```bash |
| 82 | +cd fluid3d-right-openfoam |
| 83 | +./run.sh |
| 84 | +``` |
| 85 | + |
| 86 | +### Example B — 3D → 1D coupling |
| 87 | + |
| 88 | +Run `./setcase.sh 3d1d` and then navigate to the respective directories. |
| 89 | + |
| 90 | +Terminal 1: |
| 91 | + |
| 92 | +```bash |
| 93 | +cd fluid3d-left-openfoam |
| 94 | +./run.sh |
| 95 | +``` |
| 96 | + |
| 97 | +Terminal 2: |
| 98 | + |
| 99 | +```bash |
| 100 | +cd fluid1d-right-nutils |
| 101 | +./run.sh |
| 102 | +``` |
| 103 | + |
| 104 | +## Visualization |
| 105 | + |
| 106 | +The output of the coupled simulation is written into the folders `fluid1d-left-nutils`, `fluid1d-right-nutils`, `fluid3d-left-openfoam`, and `fluid3d-right-openfoam`, depending on which coupling direction (`1d3d` or `3d1d`) you selected. |
| 107 | + |
| 108 | +### 3D domain (OpenFOAM) |
| 109 | + |
| 110 | +For the 3D participant, all simulation results are stored in the time directories inside the respective case folder (e.g., `fluid3d-right-openfoam/`). |
| 111 | +You can visualize the flow field and pressure distribution using **ParaView** by opening the case file: |
| 112 | + |
| 113 | +```bash |
| 114 | +paraview fluid3d-right-openfoam/fluid3d-right-openfoam.foam |
| 115 | +``` |
| 116 | + |
| 117 | +or, for the left domain if applicable: |
| 118 | + |
| 119 | +```bash |
| 120 | +paraview fluid3d-left-openfoam/fluid3d-left-openfoam.foam |
| 121 | +``` |
| 122 | + |
| 123 | +Typical fields to inspect include: |
| 124 | + |
| 125 | +- `p` – pressure |
| 126 | +- `U` – velocity |
| 127 | + |
| 128 | +We also record pressure and velocity at fixed points each time step using the OpenFOAM `probes` function object. |
| 129 | + |
| 130 | +**Probe setup (excerpt):** |
| 131 | + |
| 132 | +```c |
| 133 | +#includeEtc "caseDicts/postProcessing/probes/probes.cfg" |
| 134 | + |
| 135 | +fields (p U); |
| 136 | +probeLocations |
| 137 | +( |
| 138 | + (0 0 20) |
| 139 | + (0 0 40) |
| 140 | +); |
| 141 | +// For the left 3D domain use instead: |
| 142 | +// probeLocations ((0 0 0) (0 0 20)); |
| 143 | +``` |
| 144 | + |
| 145 | +**Output location:** |
| 146 | + |
| 147 | +- `fluid3d-right-openfoam/postProcessing/probes/0/p` |
| 148 | +- `fluid3d-right-openfoam/postProcessing/probes/0/U` |
| 149 | + |
| 150 | +In addition to point probes, the 3D participant samples the **axial pressure distribution** along the pipe centerline using `sampleDict`. This provides the spatial pressure variation along the pipe and allows direct comparison with the 1D solution at the latest time step. |
| 151 | + |
| 152 | +The tutorial includes a `sampleDict` in the 3D cases: |
| 153 | + |
| 154 | +- `fluid3d-left-openfoam/system/sampleDict` |
| 155 | +- `fluid3d-right-openfoam/system/sampleDict` |
| 156 | + |
| 157 | +**sampleDict (excerpt):** |
| 158 | + |
| 159 | +```cpp |
| 160 | +FoamFile |
| 161 | +{ |
| 162 | + version 2.0; |
| 163 | + format ascii; |
| 164 | + class dictionary; |
| 165 | + location "system"; |
| 166 | + object sampleDict; |
| 167 | +} |
| 168 | + |
| 169 | +type sets; |
| 170 | +libs ("libsampling.so"); |
| 171 | + |
| 172 | +setFormat raw; |
| 173 | + |
| 174 | +sets |
| 175 | +( |
| 176 | + centerline |
| 177 | + { |
| 178 | + type uniform; |
| 179 | + axis z; |
| 180 | + start (0 0 0); |
| 181 | + end (0 0 20); |
| 182 | + nPoints 200; |
| 183 | + } |
| 184 | +); |
| 185 | + |
| 186 | +fields (p); |
| 187 | +``` |
| 188 | +
|
| 189 | +The sampling is executed automatically during the run. |
| 190 | +
|
| 191 | +**Output location:** |
| 192 | +
|
| 193 | +```text |
| 194 | +postProcessing/sampleDict/<latestTime>/centerline_p.xy |
| 195 | +``` |
| 196 | + |
| 197 | +The file contains two columns: |
| 198 | + |
| 199 | +1. axial coordinate `z` |
| 200 | +2. pressure `p` |
| 201 | + |
| 202 | +### 1D domain (Nutils) |
| 203 | + |
| 204 | +The 1D solver writes a `probes.txt` with semicolon-separated time series: |
| 205 | + |
| 206 | +```text |
| 207 | +time; p_in; u_in; p_out; u_out; p_mid; u_mid |
| 208 | +``` |
| 209 | + |
| 210 | +where: |
| 211 | + |
| 212 | +- `p_in`, `u_in` → pressure and velocity at the inlet of the 1D domain |
| 213 | +- `p_out`, `u_out` → pressure and velocity at the outlet of the 1D domain |
| 214 | +- `p_mid`, `u_mid` → pressure and velocity at the midpoint of the 1D domain |
| 215 | + |
| 216 | +The 1D solver also writes a `final_fields.txt` with space-separated values: |
| 217 | + |
| 218 | +```text |
| 219 | +x u p |
| 220 | +``` |
| 221 | + |
| 222 | +They correspond to the axial position, velocity and pressure at the last time-step, i.e., at $t = 5 \mathrm{s}$. |
| 223 | + |
| 224 | +### Plotting axial pressure distribution (optional) |
| 225 | + |
| 226 | +To reproduce the axial pressure distribution shown in the figure below, a helper script is provided: |
| 227 | + |
| 228 | +```bash |
| 229 | +python plot-pressure-distribution.py |
| 230 | +``` |
| 231 | + |
| 232 | +By default, the script uses the `1d3d` case. |
| 233 | + |
| 234 | +You can also specify the coupling configuration explicitly: |
| 235 | + |
| 236 | +```bash |
| 237 | +python plot-pressure-distribution.py 1d3d |
| 238 | +``` |
| 239 | + |
| 240 | +```bash |
| 241 | +python plot-pressure-distribution.py 3d1d |
| 242 | +``` |
| 243 | + |
| 244 | +```bash |
| 245 | +python plot-pressure-distribution.py 1d1d |
| 246 | +``` |
| 247 | + |
| 248 | +```bash |
| 249 | +python plot-pressure-distribution.py 3d3d |
| 250 | +``` |
| 251 | + |
| 252 | +Allowed cases are: |
| 253 | + |
| 254 | +- `1d3d` |
| 255 | +- `3d1d` |
| 256 | +- `1d1d` |
| 257 | +- `3d3d` |
| 258 | + |
| 259 | +Depending on the selected case, the script reads: |
| 260 | + |
| 261 | +- `final_fields.txt` from the 1D Nutils solver |
| 262 | +- `centerline_p.xy` from the 3D OpenFOAM participant |
| 263 | + |
| 264 | +and combines both datasets to plot the pressure distribution along the coupled pipe. |
| 265 | + |
| 266 | +By default, the figures are saved to: |
| 267 | + |
| 268 | +```text |
| 269 | +images/pressure_distribution_<case>.png |
| 270 | +``` |
| 271 | + |
| 272 | +### Example visualization |
| 273 | + |
| 274 | + |
| 275 | + |
| 276 | +**Pressure along the pipe centerline.** The pressure decreases nearly linearly from **≈12.8 Pa** at the 3D inlet to **0 Pa** at the 1D outlet, consistent with steady, laminar Poiseuille flow. The 3D (0–20 m) and 1D (20–40 m) sections connect smoothly at the coupling interface. |
| 277 | + |
| 278 | + |
| 279 | + |
| 280 | +**Parabolic velocity profile at the 3D outlet / coupling interface (z = 20 m).** |
| 281 | +The profile is Poiseuille-like with a bulk velocity of **0.1 m/s**; consequently the **centerline velocity is ≈ 0.2 m/s** (≈ 2 × bulk) and vanishes at the wall (no-slip). This is the velocity state at the interface used for coupling to the 1D domain. |
0 commit comments