Notebook 7: Unsteady Flow¶

Flow in a pipe with inflow at the left boundary after 50, 100, 150 timesteps (top to bottom) showing the progression of the impulsive initial condition. For details, see the notebook code.
We’ll look at tracking an unsteady flow using a swarm of particle flow-tracers. In this case, the flow is unsteady because we solve the Navier-Stokes equation (that is, the flow has inertia) and we impose an impulsive, initial boundary velocity.
To begin with, the set up follows the same path as all previous notebooks:
Create a mesh
Add some variables
Create the solver we need (
NavierStokesthis time)Add boundary conditions and constitutive properties.
We also add a projection solver to compute the vorticity of the flow as we did in Notebook 4 when we needed to compute a heat-flux (thermal gradient) term.
To track the time evolution of the flow, we introduce a “passive” particle swarm. Passive, here, refers to the fact that the flow is not changed by the presence of the marker particles.
In the time-loop we have to update the particle locations and we keep this as an explicity operation, in general, because it provide the opportunity for you to make changes or perform analyses. In this case, we are adding new particles near the inflow to track the flow.
To learn more about flow goverened by the Navier-Stokes equation, it may be he helpful to read an elementary fluid dynamics textbook and reproduce some of the simple “toy” examples. For example, Acheson, 1990.
#| echo: false # Hide in html version
# This is required to fix pyvista
# (visualisation) crashes in interactive notebooks (including on binder)
import nest_asyncio
nest_asyncio.apply()
#| output: false # Suppress warnings in html version
import numpy as np
import sympy
import underworld3 as uw
res = 8
width = 4
reynolds_number = 1000
mesh = uw.meshing.UnstructuredSimplexBox(
cellSize=1 / res,
minCoords=(0.0, 0.0),
maxCoords=(width, 1.0),
qdegree=3,
)
# Coordinate directions etc
x, y = mesh.CoordinateSystem.X
# Mesh variables for the unknowns
v_soln = uw.discretisation.MeshVariable("V0", mesh, 2, degree=2, varsymbol=r"{v_0}")
p_soln = uw.discretisation.MeshVariable("p", mesh, 1, degree=1, continuous=True)
vorticity = uw.discretisation.MeshVariable(
"omega", mesh, 1, degree=1, continuous=True, varsymbol=r"\omega"
)
navier_stokes = uw.systems.NavierStokes(
mesh,
velocityField=v_soln,
pressureField=p_soln,
rho=reynolds_number,
order=1,
)
navier_stokes.constitutive_model = uw.constitutive_models.ViscousFlowModel
navier_stokes.constitutive_model.Parameters.shear_viscosity_0 = 1
navier_stokes.tolerance = 1.0e-3
navier_stokes.petsc_options["fieldsplit_velocity_mg_coarse_pc_type"] = "svd"
navier_stokes.bodyforce = sympy.Matrix((0, 0))
# Inflow boundary - incoming jet
navier_stokes.add_essential_bc(((4 * y * (1 - y)) ** 8, 0), "Left")
navier_stokes.add_essential_bc((0, 0), "Bottom")
navier_stokes.add_essential_bc((0, 0), "Top")