11from os import path
22
33from fenics import *
4- from mshr import *
5-
6-
7- def navier_stokes (mesh , boundaries , nu , pin , pout , inflow_marker , outflow_marker , no_slip_marker ):
8- # discrete function space
4+ from mshr import Cylinder , generate_mesh
5+
6+
7+ def solve_navier_stokes (mesh , boundaries , nu , pin , pout , inflow_marker , outflow_marker , no_slip_marker ):
8+ """
9+ Setup and solve the incompressible Navier-Stokes equations given a pressure drop throughout
10+ the domain.
11+
12+ Args:
13+ mesh (Mesh): Mesh of problem domain
14+ boundaries (MeshFunction): Function determining the boundaries of the mesh
15+ nu (float): Dynamic viscosity
16+ pin (float): Predefined pressure value at inlet(s)
17+ pout (float): Predefined pressure value at outlet(s)
18+ inflow_marker (list): ID(s) corresponding to inlet(s) of mesh
19+ outflow_marker (list): ID(s) corresponding to outlet(s) of mesh
20+ no_slip_marker (list): ID(s) corresponding to wall(s) of mesh
21+
22+ Returns:
23+ u (Function): Velocity field solution
24+ p (Function): Pressure field solution
25+ """
26+ # Set up discrete function space
927 P2 = VectorElement ("Lagrange" , mesh .ufl_cell (), 2 )
1028 P1 = FiniteElement ("Lagrange" , mesh .ufl_cell (), 1 )
1129
@@ -16,8 +34,8 @@ def navier_stokes(mesh, boundaries, nu, pin, pout, inflow_marker, outflow_marker
1634 (u , p ) = split (up )
1735 (v , q ) = TestFunctions (W )
1836
19- # boundary conditions
20- bcu_noslip = DirichletBC (W .sub (0 ), Constant ((0.0 , 0.0 , 0.0 )), boundaries , no_slip_marker [0 ])
37+ # Set boundary conditions
38+ bcu_no_slip = DirichletBC (W .sub (0 ), Constant ((0.0 , 0.0 , 0.0 )), boundaries , no_slip_marker [0 ])
2139
2240 dx = Measure ('dx' , domain = mesh )
2341 ds = Measure ('ds' , domain = mesh , subdomain_data = boundaries )
@@ -39,13 +57,13 @@ def navier_stokes(mesh, boundaries, nu, pin, pout, inflow_marker, outflow_marker
3957 a += - Constant (nu ) * dot (nabla_grad (u ) * n , v ) * ds (om )
4058 L += - Constant (pout ) * dot (n , v ) * ds (om )
4159
42- # solve
60+ # Solve variational problem
4361 F = a - L
4462 dF = derivative (F , up )
4563
46- PETScOptions .set ("mat_mumps_icntl_4" , 1 ) # level of printing from the solver (0-4)
47- PETScOptions .set ("mat_mumps_icntl_14" , 300 ) # percentage increase in the working space wrt memory
48- problem = NonlinearVariationalProblem (F , up , bcu_noslip , dF )
64+ PETScOptions .set ("mat_mumps_icntl_4" , 1 ) # Level of printing from the solver (0-4)
65+ PETScOptions .set ("mat_mumps_icntl_14" , 300 ) # Percentage increase in the working space wrt memory
66+ problem = NonlinearVariationalProblem (F , up , bcu_no_slip , dF )
4967 solver = NonlinearVariationalSolver (problem )
5068 prm = solver .parameters
5169 prm ['newton_solver' ]['absolute_tolerance' ] = 5E-8
@@ -60,16 +78,29 @@ def navier_stokes(mesh, boundaries, nu, pin, pout, inflow_marker, outflow_marker
6078 return u , p
6179
6280
63- def make_pipe_mesh (radius , nelem ):
64- # define a cylinder domain
81+ def make_pipe_mesh (radius , n_elem ):
82+ """
83+ Setup mesh for the cylinder problem and define
84+ domain boundaries used to set boundary conditions.
85+
86+ Args:
87+ radius (float): Radius of cylinder
88+ n_elem (int): Mesh resolution
89+
90+ Returns:
91+ mesh (Mesh): Mesh of cylinder domain
92+ boundaries (MeshFunction): Function determining the boundaries of the mesh
93+ """
94+ # Define a cylinder domain
6595 cylinder = Cylinder (Point (0 , 0 , 0 ), Point (1 , 0 , 0 ), radius , radius )
6696 geometry = cylinder
67- # define the mesh
68- mesh = generate_mesh (geometry , nelem )
97+
98+ # Define the mesh
99+ mesh = generate_mesh (geometry , n_elem )
69100 boundaries = MeshFunction ('size_t' , mesh , mesh .topology ().dim () - 1 )
70101 boundaries .set_all (0 )
71102
72- # mark the inflow, outflow and the walls
103+ # Mark the inflow, outflow and the walls
73104 class Noslip (SubDomain ):
74105 def inside (self , x , on_boundary ):
75106 return on_boundary and x [1 ] ** 2 + x [2 ] ** 2 > 0.95 * radius ** 2
@@ -90,10 +121,23 @@ def inside(self, x, on_boundary):
90121
91122 pressure_outflow = Outflow ()
92123 pressure_outflow .mark (boundaries , 3 )
124+
93125 return mesh , boundaries
94126
95127
96128def get_marker_ids (case ):
129+ """
130+ Determine the IDs which define the inlet(s), outlet(s) and wall(s)
131+ of the given case.
132+
133+ Args:
134+ case (int): Number corresponding to case ID
135+
136+ Returns:
137+ inflow_marker (list): ID(s) corresponding to inlet(s) of mesh
138+ outflow_marker (list): ID(s) corresponding to outlet(s) of mesh
139+ no_slip_marker (list): ID(s) corresponding to wall(s) of mesh
140+ """
97141 if case in [0 , 1 ]:
98142 inflow_marker = [1 ]
99143 outflow_marker = [2 , 3 ]
@@ -121,14 +165,14 @@ def D(u):
121165 pout = 1.0
122166 mu = 1.0
123167 radius = 1.0
124- nelem = 15
168+ n_elem = 15
125169
126170 poise_case = 0
127171 artery_case = 1
128172
129173 if poise_case :
130174 # Make pipe mesh so we can solve for Poiseuille flow
131- mesh , boundaries = make_pipe_mesh (radius , nelem )
175+ mesh , boundaries = make_pipe_mesh (radius , n_elem )
132176 inflow_marker = [2 ]
133177 outflow_marker = [3 ]
134178 no_slip_marker = [1 ]
@@ -143,10 +187,10 @@ def D(u):
143187 inflow_marker , outflow_marker , no_slip_marker = get_marker_ids (case )
144188
145189 # Solve for NS flow in mesh domain
146- u , p = navier_stokes (mesh , boundaries , mu , pin , pout , inflow_marker , outflow_marker , no_slip_marker )
190+ u , p = solve_navier_stokes (mesh , boundaries , mu , pin , pout , inflow_marker , outflow_marker , no_slip_marker )
147191
148- file = File ("Plots /u.pvd" )
192+ file = File ("Baseflow /u.pvd" )
149193 file << u
150194
151- file = File ("Plots /p.pvd" )
195+ file = File ("Baseflow /p.pvd" )
152196 file << p
0 commit comments