MATLAB 工具箱傻瓜式求解 NS(Navier Stoke)方程
Posted 陆嵩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MATLAB 工具箱傻瓜式求解 NS(Navier Stoke)方程相关的知识,希望对你有一定的参考价值。
文章目录
NS 方程是偏微分方程领域最重要的一个方程,没有之一。可惜的是,MATLAB 的自带的工具箱无法对它进行很好地求解,主要原因在于非线性项(对流项)无法处理,如果把它和右端载荷项放在一块处理,显然 MATLAB 工具箱是没办法支持这件事情的。
那么,对于不想写太多代码,又想用 MATLAB 这个工具求解 NS 方程,有什么好办法呢?我给大家推荐 FEATool Multiphysics。这个工具够傻瓜够强大,能求解很多 CFD 的问题,能和 FEniCS 和 Openfoam 联动,求足够完整的文档,以及完备的社区。我是推荐。下面举两个简单的例子来说明怎么使用它求解 NS 方程。安装就不用说,一搜就有了。
绕柱平流问题
问题描述
这是一个典型的 Benchmark 的问题了,也可以参考 DFG flow around cylinder benchmark 2D-1, laminar case Re=20。
考虑这样一个区域(图画得很清楚了,不用多解释):
我们要求解的问题是:
ρ
(
∂
u
∂
t
+
(
u
⋅
∇
)
u
)
−
∇
⋅
(
μ
(
∇
u
+
∇
u
T
)
)
+
p
=
F
∇
⋅
u
=
0
\\left\\\\beginarrayr \\rho\\left(\\frac\\partial \\mathbfu\\partial t+(\\mathbfu \\cdot \\nabla) \\mathbfu\\right)-\\nabla \\cdot\\left(\\mu\\left(\\nabla \\mathbfu+\\nabla \\mathbfu^T\\right)\\right)+p=\\mathbfF \\\\ \\nabla \\cdot \\mathbfu=0 \\endarray\\right.
ρ(∂t∂u+(u⋅∇)u)−∇⋅(μ(∇u+∇uT))+p=F∇⋅u=0
其中:
ρ
=
1
,
μ
=
0.001
\\rho=1,\\mu=0.001
ρ=1,μ=0.001。
左边界条件:
u
inflow
=
u
(
0
,
y
)
=
4
U
max
H
−
2
(
y
(
H
−
y
)
,
0
)
\\mathbfu_\\text inflow =\\mathbfu(0, y)=4 U_\\max H^-2(y(H-y), 0)
uinflow =u(0,y)=4UmaxH−2(y(H−y),0)
这里的
U
max
=
0.3
U_\\max =0.3
Umax=0.3。
H
=
0.41
H=0.41
H=0.41 表示上图区域的高度。
在这条件下, U mean = 0.2 U_\\text mean =0.2 Umean =0.2, R e = ρ U mean D / μ = 20 R e=\\rho U_\\text mean D / \\mu=20 Re=ρUmean D/μ=20,这就导致了层流。此时,变成了一个稳态问题。
右边界条件:
ν
∂
η
u
−
p
η
=
0
\\nu \\partial_\\eta u-p \\eta=0
ν∂ηu−pη=0
这里的
η
\\eta
η 是外法向。
其他的边界是无滑移边界条件(名词看起来高大上,其实就是速度为 0)。
观察量
我们定义阻力系数和升力系数如下:
c
d
=
2
F
d
ρ
U
mean
2
D
,
c
l
=
2
F
l
ρ
U
mean
2
D
c_d=\\frac2 F_d\\rho U_\\text mean ^2 D, \\quad c_l=\\frac2 F_l\\rho U_\\text mean ^2 D
cd=ρUmean 2D2Fd,cl=ρUmean 2D2Fl
其中的阻力和升力定义为:
F
d
=
∫
S
(
μ
∂
u
τ
(
t
)
∂
n
n
y
−
p
n
x
)
d
S
,
F
l
=
−
∫
S
(
μ
∂
u
τ
(
t
)
∂
n
n
x
+
p
n
y
)
d
S
F_d=\\int_S\\left(\\mu \\frac\\partial \\mathbfu_\\tau(t)\\partial n n_y-p n_x\\right) d S, \\quad F_l=-\\int_S\\left(\\mu \\frac\\partial \\mathbfu_\\tau(t)\\partial n n_x+p n_y\\right) d S
Fd=∫S(μ∂n∂uτ(t)ny−pnx)dS,Fl=−∫S(μ∂n∂uτ(t)nx+pny)dS
其中的
u
τ
\\mathbfu_\\tau
uτ 是切方向。
工具箱实现
Benchmark 1。
这个问题是 FEATool Multiphysics 的一个算例。打开工具箱,选择圆柱绕流算例,就是这个例子,点击 Run,它会自动地给你演示如何做。演示完也就做完了,你可以把变量导入到工作空间,也可以把整个过程生成代码。看一下代码:
%% FEATool Multiphysics Version 1.16, Build 22.08.241, Model M-Script file.
%% Created on 18-Oct-2022 11:22:20 with MATLAB 9.9.0.1467703 (R2020b) PCWIN64.
clc
clear
close all
%% Starting new model.
fea.sdim = 'x', 'y' ;
fea.geom = struct;
fea = addphys( fea, @navierstokes, 'u', 'v', 'p' );
%% Geometry operations.
gobj = gobj_rectangle( 0, 1, 0, 1, 'R1');
fea = geom_add_gobj( fea, gobj );
gobj = gobj_rectangle( [0], [2.2], [0], [0.41], 'R1' );
fea.geom.objects1 = gobj;
gobj = gobj_ellipse( [ 0.4;0.2 ], 0.2, 0.1, 'E1');
fea = geom_add_gobj( fea, gobj );
gobj = gobj_ellipse( [0.2 0.2], [0.05], [0.05], 'E1' );
fea.geom.objects2 = gobj;
fea.geom = geom_apply_formula( fea.geom, 'R1-E1' );
%% Grid operations.
fea.grid = gridgen( fea, 'gridgen', 'default', 'hmax', 0.13, 'grading', 0.3 );
fea.grid = gridgen( fea, 'gridgen', 'default', 'hmax', 0.02, 'grading', 0.3 );
%% Equation settings.
fea.phys.ns.dvar = 'u', 'v', 'p' ;
fea.phys.ns.sfun = 'sflag1', 'sflag1', 'sflag1' ;
fea.phys.ns.eqn.coef = 'rho_ns', 'rho', 'Density', 'rho' ;
'miu_ns', 'mu', 'Viscosity', 'miu' ;
'Fx_ns', 'F_x', 'Volume force in x-direction', '0' ;
'Fy_ns', 'F_y', 'Volume force in y-direction', '0' ;
'u0_ns', 'u_0', 'Initial condition for u', '0' ;
'v0_ns', 'v_0', 'Initial condition for v', '0' ;
'p0_ns', 'p_0', 'Initial condition for p', '0' ;
'miuT_ns', [], 'Turbulent viscosity', 0 ;
fea.phys.ns.eqn.sdiff = ' - (miu_ns+miuT_ns)*(2*ux_x + uy_y + vx_y)', ' - (miu_ns+miuT_ns)*(vx_x + uy_x + 2*vy_y)', [] ;
fea.phys.ns.eqn.sconv = 'rho_ns*(u*ux_t + v*uy_t)', 'rho_ns*(u*vx_t + v*vy_t)', [] ;
fea.phys.ns.eqn.seqn = 'rho_ns*u'' - (miu_ns+miuT_ns)*(2*ux_x + uy_y + vx_y) + rho_ns*(u*ux_t + v*uy_t) + p_x = Fx_ns', 'rho_ns*v'' - (miu_ns+miuT_ns)*(vx_x + uy_x + 2*vy_y) + rho_ns*(u*vx_t + v*vy_t) + p_y = Fy_ns', 'ux_t + vy_t = 0' ;
fea.phys.ns.eqn.vars = 'Velocity field', 'sqrt(u^2+v^2)';
'x-velocity', 'u';
'y-velocity', 'v';
'Pressure', 'p';
'Vorticity', 'vx-uy';
'Velocity field', 'u', 'v' ;
fea.phys.ns.prop.isaxi = 0;
fea.phys.ns.prop.artstab.id = 0;
fea.phys.ns.prop.artstab.id_coef = 0.5;
fea.phys.ns.prop.artstab.sd = 0;
fea.phys.ns.prop.artstab.sd_coef = 0.25;
fea.phys.ns.prop.artstab.ps = 1;
fea.phys.ns.prop.artstab.ps_coef = 1;
fea.phys.ns.prop.artstab.iupw = 0;
fea.phys.ns.prop.turb.model = 'laminar';
fea.phys.ns.prop.turb.wallf = 1;
fea.phys.ns.prop.turb.inlet = [];
fea.phys.ns.prop.active = [ 1;
1;
1 ];
fea.phys.ns.prop.intb = 0;
%% Constants and expressions.
fea.expr = 'h', '0.41';
'diam', '0.1';
'rho', '1';
'miu', '0.001';
'umax', '0.3';
'umean', '2/3*umax';
'fx', 'nx*p+miu*(-2*nx*ux-ny*(uy+vx))';
'cd', '2*fx/(rho*umean^2*diam)' ;
%% Boundary settings.
fea.phys.ns.bdr.sel = [ 1, 4, 1, 2, 1, 1, 1, 1 ];
fea.phys.ns.bdr.coef = 'bw_ns', 'u = 0', 'Wall/no-slip', [], 1, 1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1, 1;
0, 0, 0, 0, 0, 0, 0, 0 , [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
'bv_ns', 'u = u_0', 'Inlet/velocity', 'u_0';
'v_0';
[] , 1, 1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1, 1;
0, 0, 0, 0, 0, 0, 0, 0 , [], 0, 0, 0, '4*umax*y*(h-y)/h^2', 0, 0, 0, 0;
0, 0, 0, '0', 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
'bn_ns', '-n.(-pI + mu(grad u+grad uT)) = 0', 'Neutral outflow/stress boundary', [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 , [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
'bp_ns', 'p = p_0', 'Outflow/pressure', [];
[];
'p_0' , 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
1, 1, 1, 1, 1, 1, 1, 1 , '-p*nx';
'-p*ny';
'0' ;
[] , 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, '0', 0, 0, 0, 0, 0, 0 ;
'bs_ns', 'n&.u = 0, -n.(-pI + mu(grad u+grad uT)).t = 0', 'Symmetry/slip', [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 , [], 'solve_hook_bdrslip', 'solve_hook_bdrslip', 'solve_hook_bdrslip', 'solve_hook_bdrslip', 'solve_hook_bdrslip', 'solve_hook_bdrslip', 'solve_hook_bdrslip', 'solve_hook_bdrslip';
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
fea.phys.ns.bdr.coefi = 'bcic_ns', 'n.(F_1-F_2) = 0, F_i=-p_iI + mu_i(grad u_i+grad u_iT)', 'Continuity', [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 , [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
'bcij_ns', 'u = u_0', 'Prescribed velocity', 'u_0';
'v_0';
[] , 1, 1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1, 1;
0, 0, 0, 0, 0, 0, 0, 0 , [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
'bcir_ns', 'p = p_0', 'Prescribed pressure', [];
[];
'p_0' , 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
1, 1, 1, 1, 1, 1, 1, 1 , [], 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0 ;
fea.phys.ns.bdr.vars = 'Viscous force, x-component', '(miu_ns+miuT_ns)*(2*nx*ux+ny*(uy+vx))';
'Viscous force, y-component', '(miu_ns+miuT_ns)*(nx*(vx+uy)+2*ny*vy)';
'Total force, x-component', '-nx*p+(miu_ns+miuT_ns)*(2*nx*ux+ny*(uy+vx))';
'Total force, y-component', '-ny*p+(miu_ns+miuT_ns)*(nx*(vx+uy)+2*ny*vy)' ;
fea.phys.ns.prop.intb = 0;
%% Solver call.
fea = parsephys( fea );
fea = parseprob( fea );
fea.sol.u = solvestat( fea, ...
'iupw', [ 0, 0, 0 ], ...
'linsolv', 'backslash', ...
'icub', 'auto', ...
'nlrlx', 1, ...
'toldef', 1e-06, ...
'tolchg', 1e-06, ...
'reldef', 0, ...
'relchg', 1, ...
'maxnit', 20, ...
'hook', [], ...
'nproc', 2, ...
'init', 'u0_ns', 'v0_ns', 'p0_ns' , ...
'solcomp', [ 1; 1; 1 ] );
%% Postprocessing.
postplot( fea, ...
'surfexpr', 'sqrt(u^2+v^2)', ...
'title', 'surface: Velocity field', ...
'solnum', 1 );
postplot( fea, ...
'surfexpr', 'sqrt(u^2+v^2)', ...
'isoexpr', 'p', ...
'isolev', 10, ...
'arrowexpr', 'u', 'v' , ...
'arrowspacing', 10, 10 , ...
'arrowscale', 1, ...
'title', 'surface: Velocity field, contour: Pressure, arrow: Velocity field', ...
'solnum', 1 );
postplot( fea, ...
'surfexpr', 'sqrt(u^2+v^2)', ...
'isoexpr', 'p', ...
'isolev', 10, ...
'arrowexpr', 'u', 'v' , ...
'arrowspacing', 10, 10 , ...
'arrowscale', 1, ...
'title', 'surface: Velocity field, contour: Pressure, arrow: Velocity field', ...
'solnum', 1 );
integral_value = intbdr( 'cd', fea, [5 6 7 8], 2, 1 );
需要指明的是,这份代码的运行需要在工具箱打开,变量载入空间的时候才能 work。
周期圆柱绕流问题
这也是个 Benchmark2,可以参考 DFG flow around cylinder benchmark 2D-2, time-periodic case Re=100,此时它不再是工具箱的一个算例,我们需要做简单的修改。几何剖分沿用上面的两个例子。
别的不需要变,我们唯一要改的只是 U max U_\\max Umax,从 0.3 改为 U max = 1.5 U_\\max =1.5 Umax=1.5。
在这个情况下, U mean = 2 3 ⋅ 1.5 = 1.0 U_\\text mean =\\frac23 \\cdot 1.5=1.0 Umean =32⋅1.5=1.0, L = 2 ⋅ 0.05 = 0.1 L=2 \\cdot 0.05=0.1 L=2⋅0.05=MATLAB 工具箱傻瓜式求解 NS(Navier Stoke)方程