Skip to content

Commit 2e1e2b5

Browse files
Merge branch 'main' into feature/license-header-manager
2 parents 1266889 + 8b8a10f commit 2e1e2b5

16 files changed

Lines changed: 1667 additions & 4 deletions

File tree

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# 2D Channel Flow with a Cylinder
2+
3+
This example solves the two-dimensional incompressible Navier-Stokes equations in a channel using MOLE mimetic operators and a projection (pressure-correction) method.
4+
5+
The cylinder obstacle is introduced as a masked no-slip region inside the channel. To make things easy, the current implementation uses an axis-aligned masked block of cells rather than a fitted curved boundary. The purpose of this example is to show how MOLE operators can be combined to build a transient incompressible flow solver in a direct and compact way.
6+
7+
## Governing Equations
8+
9+
We solve the incompressible Navier-Stokes equations
10+
11+
$$
12+
\frac{\partial \mathbf{u}}{\partial t}
13+
+ (\mathbf{u}\cdot\nabla)\mathbf{u}
14+
= -\frac{1}{\rho}\nabla p + \nu \nabla^2 \mathbf{u}
15+
$$
16+
17+
$$
18+
\nabla \cdot \mathbf{u} = 0
19+
$$
20+
21+
where $\mathbf{u} = (u,v)$ is the velocity field, $p$ is the pressure, $\rho$ is the density, and $\nu$ is the kinematic viscosity.
22+
23+
## Spatial Domain
24+
25+
The computational domain is
26+
27+
$$
28+
x \in [0,8], \qquad y \in [-1,1]
29+
$$
30+
31+
The default grid is
32+
33+
- $m = 481$ cells in the $x$-direction
34+
- $n = 121$ cells in the $y$-direction
35+
36+
The Reynolds number is defined through
37+
38+
$$
39+
\nu = \frac{U_{\mathrm{init}} D_0}{Re}
40+
$$
41+
42+
with the default values
43+
44+
- $Re = 200$
45+
- $U_{\mathrm{init}} = 1$
46+
47+
## Initial and Boundary Conditions
48+
49+
### Initial Conditions
50+
51+
At $t = 0$,
52+
53+
$$
54+
u = U_{\mathrm{init}}, \qquad v = 0
55+
$$
56+
57+
in the fluid region, and the masked obstacle region is initialized with
58+
59+
$$
60+
u = 0, \qquad v = 0
61+
$$
62+
63+
### Velocity Boundary Conditions
64+
65+
- **Inlet (left):** Dirichlet inflow
66+
67+
$$
68+
u = U_{\mathrm{init}}, \qquad v = 0
69+
$$
70+
71+
- **Outlet (right):** zero streamwise gradient
72+
73+
$$
74+
\frac{\partial u}{\partial x} = 0, \qquad \frac{\partial v}{\partial x} = 0
75+
$$
76+
77+
- **Top and bottom walls:** no-slip
78+
79+
$$
80+
u = 0, \qquad v = 0
81+
$$
82+
83+
- **Obstacle mask:** no-slip
84+
85+
$$
86+
u = 0, \qquad v = 0
87+
$$
88+
89+
### Pressure Boundary Conditions
90+
91+
During the pressure Poisson step,
92+
93+
- **Outlet (right):** reference pressure
94+
95+
$$
96+
p = 0
97+
$$
98+
99+
- **All other boundaries:** homogeneous Neumann
100+
101+
$$
102+
\frac{\partial p}{\partial n} = 0
103+
$$
104+
105+
## Numerical Method
106+
107+
A projection method is used to enforce incompressibility.
108+
109+
This is the same overall time-stepping strategy used in both the MATLAB/Octave and C++ implementations.
110+
111+
### Time Integration
112+
113+
The momentum equation is advanced with a mixed time discretization:
114+
115+
- the **convective term** is treated explicitly with **AB2** (Adams-Bashforth 2)
116+
- the **first time step** uses **AB1**
117+
- the **diffusive term** is treated implicitly with **Crank-Nicolson**
118+
119+
The convective term is nonlinear, so an explicit AB2 treatment keeps the method simple and avoids solving a nonlinear system at each time step. The diffusive term is linear and is treated with Crank-Nicolson to obtain a stable and second-order accurate semi-implicit update.
120+
121+
As a result, the intermediate velocity solve uses the matrices
122+
123+
$$
124+
M = I - \frac{1}{2}\Delta t \, \nu L,
125+
\qquad
126+
M_p = I + \frac{1}{2}\Delta t \, \nu L
127+
$$
128+
129+
which are the Crank-Nicolson diffusion matrices used in the Helmholtz-type solves for $u^*$ and $v^*$.
130+
131+
### Intermediate Velocity
132+
133+
An intermediate velocity $\mathbf{u}^*$ is computed first from the momentum equation using the explicit convective update and the semi-implicit diffusive update.
134+
135+
### Pressure Poisson Equation
136+
137+
The pressure is then obtained from
138+
139+
$$
140+
\nabla^2 p^{n+1}
141+
=
142+
\frac{\rho}{\Delta t}\nabla \cdot \mathbf{u}^*
143+
$$
144+
145+
### Velocity Correction
146+
147+
The velocity is corrected by
148+
149+
$$
150+
\mathbf{u}^{n+1}
151+
=
152+
\mathbf{u}^*
153+
-
154+
\frac{\Delta t}{\rho}\nabla p^{n+1}
155+
$$
156+
157+
### Re-application of Velocity Boundary Conditions and Mask
158+
159+
After the pressure correction step, the code re-applies the velocity boundary values and the obstacle mask.
160+
161+
This is done because the projection step updates the full cell-centered velocity field. Re-applying these values ensures that the final updated velocity satisfies the intended inlet, wall, outlet, corner, and masked-region constraints exactly.
162+
163+
## Role of the MOLE Operators
164+
165+
This example is intended to highlight how MOLE operators are used in an incompressible flow solver.
166+
167+
The main operators are
168+
169+
- **Laplacian $L$:** used for viscous diffusion
170+
- **Divergence $D$:** used in the convective flux form and in the pressure Poisson right-hand side
171+
- **Gradient $G$:** used in the pressure correction step
172+
- **Interpolation operators:** used to map between cell-centered values and face-based quantities for flux evaluation and projection
173+
174+
These operators are combined to build
175+
176+
- the Crank-Nicolson diffusion operators
177+
- the pressure Poisson operator
178+
- the interpolation maps needed for face fluxes and pressure-gradient correction
179+
180+
181+
## Running the Example
182+
183+
After building the C++ examples, run
184+
185+
```bash
186+
cd <mole-repo>/examples/cpp
187+
../../build/examples/cpp/cylinder_flow_2D
188+
```
189+
190+
## MATLAB and C++ Versions
191+
192+
MATLAB/Octave and C++ versions of this example are provided with the same problem setup and the same overall projection-method structure. In particular, both versions use
193+
194+
- AB2 for the convective term
195+
- AB1 at the first step
196+
- Crank-Nicolson for the diffusive term
197+
- a pressure Poisson solve followed by velocity correction
198+
199+
This makes it easier to compare the two implementations and to see how the same MOLE operators are used in each language.
200+
201+
## Results
202+
203+
### C++ result
204+
205+
![C++ final fields](figures/cylinder_flow_2D_plot_cpp.png)
206+
207+
### MATLAB result
208+
209+
![MATLAB final fields](figures/cylinder_flow_2D_plot_matlab.png)
99.1 KB
Loading
191 KB
Loading

doc/sphinx/source/examples/Navier-Stokes/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ The Navier-Stokes equations describe the motion of viscous fluid substances, for
77
:caption: Contents
88
99
Lock-Exchange
10+
Cylinder-Flow-2D
1011
```

examples/cpp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(EXAMPLE_SOURCES
55
backward_euler.cpp
66
burgers1D.cpp
77
convection_diffusion3D.cpp
8+
cylinder_flow_2D.cpp
89
elliptic1D.cpp
910
elliptic1DHomogeneousDirichlet.cpp
1011
elliptic1DLeftNeumannRightDirichlet.cpp

0 commit comments

Comments
 (0)