Couche limite
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 14Couche limite¶
from IPython.display import YouTubeVideo
YouTubeVideo('GgVCTNCwfQk', width=600, height=400)Fundamentals of Boundary Layers (MIT)¶
from IPython.display import IFrame
#IFrame("https://techtv.mit.edu/videos/a081da3d343242bd845ab379f72c281c/embed/",width="560",height="315")Equation de Blasius¶
Avec les hypothèses de couche limite bi-dimensionnelle sans gradient de pression (voir Blasius boundary layer), les composantes de vitesse s’écrivent en fonction de , la fonction de courant
dont on cherche une forme auto-similaire en éffectuant un changement de variable
Recherche d’une solution auto-similaire¶
solution en fonction de courant
où est solution de
avec les conditions:
, et
Problème: ce n’est pas une ODE classique, car on a pas 3 conditions initiales !!!
Il faut donc trouvez la condition initiale manquante
telle que
résolution numérique par transformation en ODE d’ordre 1
import sympy as sp
x,y = sp.symbols('x y',positive=True)
nu, U0 = sp.symbols('nu U0',positive=True)
u = sp.Function('u')(x,y)
v = sp.Function('v')(x,y)
p = sp.Function('p')(x)
eta = sp.symbols('eta',positive=True)
f = sp.Function('f')(eta)
psi = sp.Function('psi')(x,y)
eq = u*sp.diff(u,x) + v*sp.diff(u,y) + sp.diff(p,x) - nu*(sp.diff(u,x,x)+sp.diff(u,y,y))
display(eq)
deq = sp.diff(eq,y)
deq1=deq.subs({u:sp.diff(psi,y),v:-sp.diff(psi,x)})
display(deq1)
deq2=deq1.subs(psi,sp.sqrt(nu*U0*x)*f.subs(eta,y*sp.sqrt(U0/x)))
#deq2.simplify().subs(import sympy as sp
x,y = sp.symbols('x y')
U0, nu = sp.symbols('U_0 nu')
eta = y*sp.sqrt(U0/(nu*x))
delta = y/eta
f = sp.Function('f')(eta)
psi = sp.sqrt(nu*U0*x)*f
display("psi=",psi)'psi='U = sp.diff(psi,y)
V = -sp.diff(psi,x)
display(U,V)ODE d’ordre 3 transformée en 3 ODEs d’ordre 1¶
forme canonique: ODE d’ordre 1
avec les C.L.
### on en déduit la solution autosimilaire fonction de
résolution numérique¶
Utilisation de solveur classique ODE
from scipy.integrate import odeint
def ODEBlasius(x,Y):
'''systeme ODE Blasius'''
dY = np.array([Y[1],Y[2],-0.5*Y[0]*Y[2]])
return dY
def Blasius(beta0):
"""resoud BLASIUS pour une valeur de beta"""
Tmax = 10.
X = np.linspace(0,Tmax,500)
Y0 = np.array([0,0,beta0])
Y = odeint(ODEBlasius,Y0,X,tfirst=True)
return X,Y
def ErrBlasius(beta):
"""calcul l'erreur sur la CL en 0"""
X,Y = Blasius(beta[0])
err = Y[-1,1] - 1.0
#print("beta={} err={}".format(Beta[0],err))
return errProblème choix de la bonne valeur de !
# verification pour beta = 0.3
beta0 = 0.3
X,Y = Blasius(beta0)
print("err=",ErrBlasius([beta0]))
plt.figure(figsize=(10,6))
plt.plot(X,Y[:,0],X,Y[:,1],X,Y[:,2])
plt.legend(["f","f'","f''"])
plt.hlines(1.,0,10.,linestyles='--')
plt.ylim([0,2])
plt.xlabel("$\eta$")
plt.title("solution EDO pour $\\beta$ fixé -> CL # 1");err= -0.06544374655251373

détermination de la solution par optimisation (racine)¶
from scipy.optimize import fsolve
beta_opt= fsolve(ErrBlasius,[beta0],xtol=1.e-12)[0]
print("beta opt=",beta_opt)beta opt= 0.3320573347194112
On retrouve bien l’approximation classique de pour petit:
tracé de la solution¶
X,Y = Blasius(beta_opt)
plt.figure(figsize=(10,6))
plt.plot(X,Y[:,0],X,Y[:,1],X,Y[:,2])
plt.legend(["f","f'","f''"])
plt.xlabel("$\eta$")
plt.hlines(1.,0,10.,linestyles='--')
plt.ylim(0,1.25)
plt.title("solution autosimilaire");
plt.figure(figsize=(8,6))
plt.plot(Y[:,1],X)
plt.ylim(0,5.)
plt.xlim(0,1.)
plt.xlabel("$U/U_0$")
plt.ylabel("$\eta$")
plt.title("Profil de vitesse auto-similaire");
nu = 15e-6
U0 = 1.0
Xp = np.array([0.2, 1., 2., 5.,10.])
plt.figure(figsize=(15,6))
for k,x in enumerate(Xp):
eta0 = np.sqrt(U0/(nu*x))
plt.subplot(1,len(Xp),k+1)
ax = plt.gca()
if k>0:
ax.get_yaxis().set_visible(False)
else:
plt.ylabel("y")
plt.ylim(0,0.04)
plt.xlim(0,1.)
plt.plot(Y[:,1],(X/eta0))
plt.title("x={:.2f} ".format(x))
# valeur de eta0 tq V=0.99 U0
i0 = np.abs(Y[:,1]-0.99).argmin()
eta0 = X[i0]
print("eta0=",eta0,Y[i0,1])
plt.plot(X,Y[:,1])
plt.hlines(Y[i0,1],X[0],X[-1],linestyles='dashed')
plt.plot([eta0],[Y[i0,1]],'o')eta0= 4.909819639278557 0.9899968804588336

Delta = eta0*np.sqrt(nu*Xp/U0)
plt.figure(figsize=(15,6))
plt.plot(Xp,Delta,'-o')
plt.xlabel("x")
plt.ylabel("$\\delta$")
plt.title("Epaisseur de CL : $\\delta =\eta_0\\sqrt{\\nu X/U_0}$");
Equation de Falkner Scan¶
prise en compte d’un gradient de pression avec un champ de vitesse extérieur
recherche d’une solution auto-similaire
on se ramène a résoudre une EDO d’ordre 3
avec
où m représente l’angle de la plaque / à l’horizontal
blasius avec une échelle
adverse pressure gradient
favorable pressure gradient
résolution numérique¶
def ODEFalkner(x,Y):
global BETA
'''systeme ODE Falkner scan'''
dY = np.array([Y[1],Y[2],-Y[0]*Y[2] + BETA*(Y[1]**2 - 1.0 )])
return dY
def Falkner(beta0):
"""resoud Falkner pour une valeur de beta"""
Tmax = 10.
X = np.linspace(0,Tmax,50)
Y0 = np.array([0,0,beta0])
Y = odeint(ODEFalkner,Y0,X,tfirst=True)
return X,Y
def ErrFalkner(beta):
"""calcul l'erreur sur la CL en 0"""
X,Y = Falkner(beta[0])
err = Y[-1,1] - 1.0
#print("beta={} err={}".format(Beta[0],err))
return errgradient de pression favorable m > 0¶
m = 1
BETA = 2*m/(m+1)beta0 = 1.23
X1,Y1 = Falkner(beta0)
print("err=",ErrFalkner([beta0]))
plt.figure(figsize=(10,6))
plt.plot(X1,Y1[:,0],X1,Y1[:,1],X1,Y1[:,2]);
plt.hlines(1.,0,10.,linestyles='--')
plt.ylim([0,2])
plt.xlabel("$\eta$")
plt.title("solution EDO pour $\\beta$ fixé -> CL # 1");err= -0.23391875896336956

beta_opt= fsolve(ErrFalkner,[beta0])[0]
print("beta opt=",beta_opt)beta opt= 1.232587684584402
X1,Y1 = Falkner(beta_opt)
plt.figure(figsize=(10,6))
plt.plot(X1,Y1[:,0],X1,Y1[:,1],X1,Y1[:,2])
plt.legend(["f","f'","f''"])
plt.xlabel("$\eta$")
plt.hlines(1.,0,10.,linestyles='--')
plt.ylim(0,2)
plt.title("solution autosimilaire");
plt.figure(figsize=(10,6))
plt.plot(Y[:,1],X,'--',label="blasius")
plt.plot(Y1[:,1],X1,label="grad p <0")
plt.ylim(0,5.)
plt.xlim(0,1.)
plt.xlabel("$U/U_0$")
plt.ylabel("$\eta$")
plt.legend()
plt.title("Profil de vitesse auto-similaire");
gradient de pression adverse¶
m = -0.08
BETA = 2*m/(m+1)beta0 = 0.1
X2,Y2 = Falkner(beta0)
print("err=",ErrFalkner([beta0]))
plt.figure(figsize=(10,6))
plt.plot(X2,Y2[:,0],X2,Y2[:,1],X2,Y2[:,2]);
plt.hlines(1.,0,10.,linestyles='--')
plt.ylim([0,2])
plt.xlabel("$\eta$")
plt.title("solution EDO pour $\\beta$ fixé -> CL # 1");err= -0.014668533761202918

beta_opt= fsolve(ErrFalkner,[beta0])[0]
print("beta opt=",beta_opt)beta opt= 0.14973564750325108
X2,Y2 = Falkner(beta_opt)
plt.figure(figsize=(10,6))
plt.plot(X2,Y2[:,0],X2,Y2[:,1],X2,Y2[:,2])
plt.legend(["f","f'","f''"])
plt.xlabel("$\eta$")
plt.hlines(1.,0,10.,linestyles='--')
plt.ylim(0,2)
plt.title("solution autosimilaire");
plt.plot(Y[:,1],X)
plt.ylim(0,4)
plt.title("Profil de vitesse");
plt.figure(figsize=(10,6))
plt.plot(Y[:,1],X,'--',label="blasius")
plt.plot(Y1[:,1],X1,label="grad p <0")
plt.plot(Y2[:,1],X2,lw=3,label="grad p >0")
plt.ylim(0,5.)
plt.xlim(0,1.)
plt.xlabel("$U/U_0$")
plt.ylabel("$\eta$")
plt.legend()
plt.title("Profil de vitesse auto-similaire");
Analyse dimensionnelle¶
paramètres : , , ,
deux nombres sans dimension: et $
bilan de masse
ordre de grandeur de v
bilan de quantité de mouvement suivant x
couhe limite laminaire stationnaire sans gradient de pression
d’où
soit
