Dear Fenics Community,
I am trying to simulate the classical laminar flow with heat transfer in a square duct with fixed temperature at the wall, which should yield a Nusselt number of 2.98, but I cannot make it work. It converges, but the values are clearly wrong. The code I am using is below:
from dolfin import *
from msh2xdmf import import_mesh_from_xdmf, msh2xdmf
# MAKE CFD
def sim_flow(u_0, nu, cp, k, p_0, T_0, fileName, Le, He, We):
# LOAD MESH
mesh, boundaries, association_table = import_mesh_from_xdmf(prefix=fileName, dim=3)
# Build function space
P2 = VectorElement('Lagrange', mesh.ufl_cell() , 2)
P1 = FiniteElement('Lagrange', mesh.ufl_cell(), 1)
element = MixedElement([P2, P1, P1])
W = FunctionSpace(mesh, element)
#define test functions
(v, q, s) = TestFunctions(W)
#split functions
upT = Function(W)
(u, p, T) = split(upT)
n = FacetNormal(mesh)
# Define boundary conditions
# FLOW
# Define inflow profile from Shah & London 1976 (velocity profile in a rectangular duct)
alpha = min(We/He, He/We) # <1
mv = 1.7 + 0.5 * alpha**-1.4
if alpha<=1./3.:
nv = 2
else:
nv = 2 + 0.3 * (alpha - 1./3.)
Umax = u_0 * (mv+1)/mv * (nv+1)/nv
print("alpha, m, n, Umax = ", alpha, mv, nv, Umax)
inflow_profile = ('0', '0', 'Umax * (1. - pow(abs(x[0]/H*2), n)) * (1. - pow(abs(x[1]/W*2), m))')
inflow_profile = Expression(inflow_profile, Umax=Constant(Umax), H=Constant(He), W=Constant(We), m=Constant(mv), n=Constant(nv), degree=2)
bcu_inflow = DirichletBC(W.sub(0), inflow_profile, boundaries, association_table["inlet"])
bcu_noslip = DirichletBC(W.sub(0), Constant((0, 0 ,0 )), boundaries, association_table["noslip"])
bcu_outflow = DirichletBC(W.sub(1), Constant(p_0), boundaries, association_table["outlet"])
bcu = [bcu_inflow, bcu_noslip, bcu_outflow]
# ENERGY
bcT_inflow = DirichletBC(W.sub(2), Constant(T_0), boundaries, association_table["inlet"])
bcT_noslip = DirichletBC(W.sub(2), Constant(T_0+10.), boundaries, association_table["noslip"])
bcT = [bcT_inflow, bcT_noslip]
bcs = bcu + bcT
# DEFINE VARIATIONAL FORM
F1 = (inner(grad(u)*u, v)*dx + # Momentum advection term
nu*inner(grad(u), grad(v))*dx - # Momentum diffusion term
inner(p, div(v))*dx + # Pressure term
div(u)*q*dx # Divergence term
)
F2 = (cp*inner(dot(grad(T), u), s)*dx - # Energy advection term
k*inner(grad(T), grad(s))*dx # Energy diffusion term
)
F = F1 + F2
# Create VTK files for visualization output
vtkfile_u = File('results/u.pvd')
vtkfile_p = File('results/p.pvd')
vtkfile_T = File('results/T.pvd')
J = derivative(F, upT) # Jacobian
solve(F == 0, upT, bcs)
# Save solution to file (VTK)
(u, p, T) = upT.split(deepcopy=True)
vtkfile_u << u
vtkfile_p << p
vtkfile_T << T
# POST-PROCESSING
ds_bc = ds(subdomain_data=boundaries)
T_in_avg = assemble(T*ds_bc(association_table["inlet"])) / (We * He)
T_out_avg = assemble(T*ds_bc(association_table["outlet"])) / (We * He)
DT_avg = T_out_avg - T_in_avg
Heat_Load = u_0 * We * He * rho * cp * DT_avg
htc = project(k*grad(T), VectorFunctionSpace(mesh, 'Lagrange', 1))
s_htc = 2 * (We + He) * Le
Tbulk = (T_0 + DT_avg) / 2.
htc_avg = assemble(dot(n, htc)/(T-Tbulk)*ds_bc(association_table["noslip"])) / s_htc
Nu = htc_avg * Dh / k
print("htc_avg = ", htc_avg)
print("Nu = ", Nu)
return Nu
# Dimensions
Le = 55e-3
He = We = Dh = 2.8e-3
# Fluid properties
rho = 1.127 # air density at 20 degC, 1 atm, [kg/m3]
nu = 16.92E-6 # air kinematic viscosity at 20 degC, 1 atm, [m2/s]
cp = 1008. # air heat capacity @ 40°C (J/kg K)
k = 27.35e-3 # air thermal conductivity @40°C (W/m/K)
p_0 = 0. # outlet air pressure (atmospheric pressure), normalized
T_0 = 0. # Inlet temperature (K)
fileName = "SquareDuct"
u_0 = 5.67 # Inlet velocity (m/s)
Re = u_0 * Dh / nu
print("Dh = ", Dh)
print("Re = ", Re)
res = sim_flow(u_0, nu, cp, k, p_0, T_0, fileName, Le, He, We)
The velocity profile looks good with 0 at the wall and maximum at center, but the temperature profile below does not look physical. The mesh file is here https://github.com/bragostin/Fenics. Is there anything obviously wrong in this code?