-
Notifications
You must be signed in to change notification settings - Fork 166
Rayleigh-Benard demo using Irksome and patch smoothing #4319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
fe0cfe6
1d154ca
5066a62
8a14150
0d5ba26
96ce83a
659ad4d
6238f05
9b4f147
7008cd7
5b670ef
54a9ddc
982437f
bb26a0a
944aa16
4503ca6
dcdbe43
fd30db6
bab5c96
e3b7c29
155d48b
426e696
2311f10
c85ecdf
8e50f9e
f29173d
8283c02
7e041b1
3856d9d
aee4060
787993c
6569df2
91257b9
9bf34f1
9aadc16
ab3409b
57fd4f3
2e73b0c
90cc320
c579a94
4b1cfc3
7c154b0
28fa2d0
9c5d76e
7241a12
62a50a4
f39c413
62395dc
f40eb35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,175 @@ | ||||||||||||
Rayleigh-Benard Convection | ||||||||||||
========================== | ||||||||||||
|
||||||||||||
Contributed by `Robert Kirby <https://sites.baylor.edu/robert_kirby/>`_ | ||||||||||||
and `Pablo Brubeck <https://www.maths.ox.ac.uk/people/pablo.brubeckmartinez/>`_. | ||||||||||||
|
||||||||||||
This problem involves a variable-temperature incompressible fluid. | ||||||||||||
Variations in the fluid temperature are assumed to affect the momentum | ||||||||||||
balance through a buoyant term (the Boussinesq approximation), leading | ||||||||||||
to a Navier-Stokes equation with a nonlinear coupling to a | ||||||||||||
convection-diffusion equation for temperature. | ||||||||||||
|
||||||||||||
We will set up the problem using Taylor-Hood elements for | ||||||||||||
the Navier-Stokes part, and piecewise linear elements for the | ||||||||||||
temperature. :: | ||||||||||||
|
||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
from firedrake import * | ||||||||||||
from firedrake.pyplot import FunctionPlotter, tripcolor | ||||||||||||
import math | ||||||||||||
import matplotlib.pyplot as plt | ||||||||||||
from matplotlib.animation import FuncAnimation | ||||||||||||
|
||||||||||||
try: | ||||||||||||
from irksome import Dt, RadauIIA, TimeStepper | ||||||||||||
except ImportError: | ||||||||||||
import sys | ||||||||||||
warning("Unable to import irksome.") | ||||||||||||
sys.exit(0) | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than do this I would just include a bit like: "This tutorial assumes that you have Irksome installed as well as Firedrake. Instructions for installing Irksome can be found ." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how the netgen tutorial is written. But, to make sure the demo runs in our CI, we'll either need to fail gracefully (without an exception) or put Irksome in our CI. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We definitely need irksome in CI for this to land. |
||||||||||||
|
||||||||||||
Nbase = 8 | ||||||||||||
ref_levels = 2 | ||||||||||||
N = Nbase * 2**ref_levels | ||||||||||||
|
||||||||||||
base_msh = UnitSquareMesh(Nbase, Nbase) | ||||||||||||
mh = MeshHierarchy(base_msh, ref_levels) | ||||||||||||
msh = mh[-1] | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
V = VectorFunctionSpace(msh, "CG", 2) | ||||||||||||
W = FunctionSpace(msh, "CG", 1) | ||||||||||||
Q = FunctionSpace(msh, "CG", 1) | ||||||||||||
Z = V * W * Q | ||||||||||||
|
||||||||||||
upT = Function(Z) | ||||||||||||
u, p, T = split(upT) | ||||||||||||
v, q, S = TestFunctions(Z) | ||||||||||||
|
||||||||||||
Two key physical parameters are the Rayleigh number (Ra), which | ||||||||||||
measures the ratio of energy from buoyant forces to viscous | ||||||||||||
dissipation and heat conduction and the | ||||||||||||
Prandtl number (Pr), which measures the ratio of viscosity to heat | ||||||||||||
conduction. :: | ||||||||||||
|
||||||||||||
Ra = Constant(2000.0) | ||||||||||||
Pr = Constant(6.8) | ||||||||||||
|
||||||||||||
Along with gravity, which points down. :: | ||||||||||||
|
||||||||||||
g = Constant((0, -1)) | ||||||||||||
|
||||||||||||
Set up variables for time and time-step size. :: | ||||||||||||
|
||||||||||||
t = Constant(0.0) | ||||||||||||
dt = Constant(1.0 / N) | ||||||||||||
|
||||||||||||
F = ( | ||||||||||||
inner(Dt(u), v)*dx | ||||||||||||
+ inner(grad(u), grad(v))*dx | ||||||||||||
+ inner(dot(grad(u), u), v)*dx | ||||||||||||
- inner(p, div(v))*dx | ||||||||||||
- (Ra/Pr)*inner(T*g, v)*dx | ||||||||||||
+ inner(div(u), q)*dx | ||||||||||||
+ inner(Dt(T), S)*dx | ||||||||||||
+ inner(dot(grad(T), u), S)*dx | ||||||||||||
+ 1/Pr * inner(grad(T), grad(S))*dx | ||||||||||||
) | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
There are two common versions of this problem. In one case, heat is | ||||||||||||
applied from bottom to top so that the temperature gradient is | ||||||||||||
enforced parallel to the gravitation. In this case, the temperature | ||||||||||||
difference is applied horizontally, perpendicular to gravity. It | ||||||||||||
tends to make prettier pictures for low Rayleigh numbers, but also | ||||||||||||
tends to take more Newton iterations since the coupling terms in the | ||||||||||||
Jacobian are a bit stronger. Switching to the first case would be a | ||||||||||||
simple change of bits of the boundary associated with the second and | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
third boundary conditions below:: | ||||||||||||
|
||||||||||||
bcs = [ | ||||||||||||
DirichletBC(Z.sub(0), Constant((0, 0)), (1, 2, 3, 4)), | ||||||||||||
DirichletBC(Z.sub(2), Constant(1.0), (3,)), | ||||||||||||
DirichletBC(Z.sub(2), Constant(0.0), (4,)) | ||||||||||||
] | ||||||||||||
|
||||||||||||
Like Navier-Stokes, the pressure is only defined up to a constant.:: | ||||||||||||
|
||||||||||||
nullspace = [(1, VectorSpaceBasis(constant=True))] | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
Set up the Butcher tableau to use for time-stepping:: | ||||||||||||
|
||||||||||||
num_stages = 2 | ||||||||||||
butcher_tableau = RadauIIA(num_stages) | ||||||||||||
|
||||||||||||
We are going to carry out time stepping via Irksome, but we need | ||||||||||||
to say how to solve the rather interesting stage-coupled system. :: | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
exclude_inds = ",".join([str(3*i+j) for i in range(num_stages) for j in (1, 2)]) | ||||||||||||
params = { | ||||||||||||
"mat_type": "aij", | ||||||||||||
"snes_type": "newtonls", | ||||||||||||
"snes_converged_reason": None, | ||||||||||||
"snes_linesearch_type": "l2", | ||||||||||||
"snes_monitor": None, | ||||||||||||
"ksp_type": "fgmres", | ||||||||||||
"ksp_monitor": None, | ||||||||||||
"ksp_max_it": 200, | ||||||||||||
"ksp_atol": 1.e-12, | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
"ksp_gmres_restart": 30, | ||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
"snes_rtol": 1.e-10, | ||||||||||||
"snes_atol": 1.e-10, | ||||||||||||
"snes_ksp_ew": None, | ||||||||||||
"pc_type": "mg", | ||||||||||||
"mg_levels": { | ||||||||||||
"ksp_type": "gmres", | ||||||||||||
"ksp_max_it": 3, | ||||||||||||
"ksp_convergence_test": "skip", | ||||||||||||
"pc_type": "python", | ||||||||||||
"pc_python_type": "firedrake.ASMVankaPC", | ||||||||||||
"pc_vanka_construct_dim": 0, | ||||||||||||
"pc_vanka_sub_sub_pc_type": "lu", | ||||||||||||
"pc_vanka_sub_sub_pc_factor_mat_solver_type": "umfpack", | ||||||||||||
"pc_vanka_exclude_subspaces": exclude_inds}, | ||||||||||||
"mg_coarse": { | ||||||||||||
"ksp_type": "preonly", | ||||||||||||
"pc_type": "lu", | ||||||||||||
"pc_factor_mat_solver_type": "mumps", | ||||||||||||
"mat_mumps_icntl_14": 200} | ||||||||||||
} | ||||||||||||
|
||||||||||||
stepper = TimeStepper(F, butcher_tableau, t, dt, upT, bcs=bcs, | ||||||||||||
nullspace=nullspace, solver_parameters=params) | ||||||||||||
|
||||||||||||
Now that the stepper is set up, let's run over many time steps:: | ||||||||||||
|
||||||||||||
|
||||||||||||
plot_freq = 10 | ||||||||||||
Ts = [] | ||||||||||||
cur_step = 0 | ||||||||||||
while float(t) < 1.0: | ||||||||||||
print(f"t = {float(t)}") | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I had intended you to put print statements in time loops, I would never have given you There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be the only firedrake demo with a progress bar, FYI. |
||||||||||||
stepper.advance() | ||||||||||||
|
||||||||||||
t.assign(float(t) + float(dt)) | ||||||||||||
cur_step += 1 | ||||||||||||
if cur_step % plot_freq == 0: | ||||||||||||
Ts.append(upT.subfunctions[2].copy(deepcopy=True)) | ||||||||||||
|
||||||||||||
|
||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
nsp = 16 | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the plotting in the time loop code block? This looks quite odd on the rendered version. |
||||||||||||
fn_plotter = FunctionPlotter(msh, num_sample_points=nsp) | ||||||||||||
fig, axes = plt.subplots() | ||||||||||||
axes.set_aspect('equal') | ||||||||||||
Tzero = Function(Q) | ||||||||||||
colors = tripcolor(Tzero, num_sample_points=nsp, vmin=0, vmax=1, axes=axes) | ||||||||||||
fig.colorbar(colors) | ||||||||||||
|
||||||||||||
def animate(q): | ||||||||||||
colors.set_array(fn_plotter(q)) | ||||||||||||
|
||||||||||||
The last step is to make the animation and save it to a file. :: | ||||||||||||
|
||||||||||||
rckirby marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
interval = 1e3 * plot_freq * float(dt) | ||||||||||||
animation = FuncAnimation(fig, animate, frames=Ts, interval=interval) | ||||||||||||
try: | ||||||||||||
animation.save("benard_temp.mp4", writer="ffmpeg") | ||||||||||||
except: | ||||||||||||
print("Failed to write movie! Try installing `ffmpeg`.") | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing link to Python version of demo. |
Uh oh!
There was an error while loading. Please reload this page.