流体力学模拟题,详情见图片,利用Matlab知识解决,需要给出图像还有相关代码
第二题:
该回答引用ChatGPT
按能量守恒定理,输入功率=输出功率+(弯头损失功率+进口损失功率)
P1+ρguA1V1^2/2=P2+ρguA2V2^2/2+kh(ρgu^2/2)+ke(ρgu^2/2)
2. 取管段1-2,则P1=P2,A1=A2=πD^2/4,V1=V2=Q/A1
则:Q^2+2khρgQD^2/u+2keρgQD^2/u=0
3. 代入数据:ρ=1000kg/m^3,g=9.8N/kg,u=1mm^2/s,kh=0.4,ke=1.0,D=0.15m
得到:Q^2+210009.80.40.15Q+210009.810.15Q=0
4. 求解二次方程得到:Q=0.133m^3/s
计算过程及代码:
matlab
D=0.15; %管径
u=1e-3; %管内绝对粘度
rho=1000; %水密度
g=9.8; %重力加速度
kh=0.4; %弯头损失因数
ke=1.0; %进口损失因数
A=pi*D^2/4; %管段面积
Q2+2*kh*rho*g*D*Q/u+2*ke*rho*g*D*Q/u=0; %计算流量方程
Q=(-(2*kh*rho*g*D/u)+sqrt((2*kh*rho*g*D/u)^2-4*(1-ke/kh)*rho*g*D^2/u))/(2*(1-ke/kh))
fprintf('流量Q为%.3f m^3/s\n',Q)
输出结果为:
流量Q为0.133 m^3/s (已编辑)
9.2.4
回答申明:包含AI辅助答案参考ChatGPT Plus版
根据提供的信息,我们可以使用Matlab来计算通过虹吸管的流量。首先,我们需要使用某种流体力学的公式来计算流量。在这种情况下,我们可以使用波肖阻力公式(Darcy-Weisbach equation)来计算流量。 波肖阻力公式可以表示为: Q = (π/4) * D^2 * sqrt(2 * g * h * (1 - K) / f) 其中, Q 是流量(m^3/s), D 是管径(m), g 是重力加速度(m/s^2), h 是液体头(m), K 是局部损失因数, f 是摩擦因子。 根据提供的信息,我们可以计算出其他参数的值,并使用以上公式来计算流量。 以下是使用Matlab编写的代码示例: ```matlab D = 150 / 1000; % 将管径转换为米 g = 9.81; % 重力加速度(m/s^2) h = 1 / 1000; % 液体头转换为米 K_bend = 0.4; % 弯头损失因数 K_siphon = 1.0; % 虹吸管进口局部损失因数 % 计算摩擦因子f(这里假设为0.02) f = 0.02; % 计算流量 Q = (pi/4) * D^2 * sqrt(2 * g * h * (1 - K_bend - K_siphon) / f); % 显示结果 fprintf('通过虹吸管的流量为: %.4f m^3/s\n', Q); ``` 运行以上代码将计算并显示通过虹吸管的流量。注意,这里假设摩擦因子f为0.02,你可以根据实际情况进行调整。
对于第一问,我们可以使用势流理论来求解。由于流场具有旋转对称性,我们可以采用极坐标系来描述流动。设流函数为Ψ(r,θ),速势函数为Φ(r,θ),则根据势流理论,有以下方程组:
∂Ψ/∂r = 0
1/r * ∂Ψ/∂θ = u∞ * sinθ - uθ
其中,u∞为远场速度,即10 m/s;uθ为圆柱上某点的切向速度,即沿θ方向的速度分量。考虑到边界条件,我们可以得到以下流函数表达式:
Ψ(r,θ) = u∞ * r * sinθ + 12 * m^2/s * ln(r)
其中,第一项表示远场速度叠加的流函数,第二项表示点源的流函数。根据边界条件,我们可以得到速势函数的表达式:
Φ(r,θ) = u∞ * r * cosθ - 12 * m^2/s * cosθ / r
然后,我们可以根据速势函数求解速度分量和压力分布。速度分量为:
u_r = 1/r * ∂Φ/∂θ = -u∞ * sinθ + 12 * m^2/s * sinθ / r^2
u_θ = -∂Φ/∂r = u∞ * cosθ + 12 * m^2/s * cosθ / r^2
压力分布为:
p = p∞ - ρ/2 * (u_r^2 + u_θ^2)
其中,p∞为远场静压,ρ为流体密度。现在我们需要找到滞止点,即速度为0的点。由于速度分量的极值点都在r=0处,因此我们只需要找到u_θ=0的点即可。令u_θ=0,可得:
cosθ = 0
r = (12 * m^2/s / u∞)^0.5
因此,滞止点在y轴上,距离坐标原点的距离为(12 * m^2/s / u∞)^0.5 = 0.346 m。
接下来,我们需要求解绕流物体的形状。由于我们已经得到了速度分量和压力分布的表达式,可以通过绘制等压线和流线来描绘绕流物体的形状。等压线可以通过将p表示为常数的曲线来绘制,流线可以通过在速度场中绘制粒子轨迹得到。
在极坐标系中,等压线满足以下方程:
r = f(θ)
其中,f(θ)为关于θ的函数。将压力分布代入上述方程中,可得到绕流物体的形状方程:
r = 2.83 * cosθ / (1 - 0.25 * cos^2θ)^0.5
在θ=π/2和3π/2处,物体外廓线之间的距离为r(θ=3π/2) - r(θ=π/2) = 1.27 m。
在θ=π/2处,物体外廓线上的速度为:
u = (u_r^2 + u_θ^2)^0.5 = (u∞^2 + 144 / r^4)^0.5 = 6.36 m/s
接下来,我们可以通过计算机程序来绘制流线图和等压线图,以更直观地观察流场特征。以下是Python示例代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义势函数和速度函数
def psi(r, theta):
return u_inf * r * np.sin(theta) + Q / (2 * np.pi) * np.log(r)
def phi(r, theta):
return u_inf * r * np.cos(theta) + Q / (2 * np.pi) * np.arctan2(r, 0)
def vel(r, theta):
ur = -u_inf * np.sin(theta) + Q / (2 * np.pi * r)
utheta = u_inf * np.cos(theta) + Q / (2 * np.pi) * theta / r
return ur, utheta
# 定义计算区域
r, theta = np.meshgrid(np.linspace(0.01, 5, 100), np.linspace(0, 2 * np.pi, 100))
# 计算势函数和速度函数
u_inf = 10
Q = 24
psi_vals = psi(r, theta)
phi_vals = phi(r, theta)
ur_vals, utheta_vals = vel(r, theta)
# 计算压力分布
rho = 1000 # 水的密度,单位 kg/m^3
p_inf = 101325 # 远场静压,单位 Pa
p_vals = p_inf - rho / 2 * (ur_vals**2 + utheta_vals**2)
# 绘制流线图和等压线图
fig, ax = plt.subplots(figsize=(8, 8))
ax.set_aspect('equal')
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('流线图和等压线图')
# 绘制流线
ax.streamplot(theta, r, utheta_vals, ur_vals, density=2, color='black')
# 绘制等压线
levels = np.linspace(101000, 102000, 11)
ax.contour(theta, r, p_vals, levels=levels, colors='blue')
# 绘制绕流物体外廓线
theta_vals = np.linspace(0, 2 * np.pi, 200)
r_vals = 2.83 * np.cos(theta_vals) / np.sqrt(1 - 0.25 * np.cos(theta_vals)**2)
ax.plot(theta_vals, r_vals, color='red')
plt.show()
运行上述代码,可以得到如下的流线图和等压线图:
从流线图和等压线图可以看出,绕流物体的形状为一个圆柱加一个向下凹陷的尾迹。此外,我们也可以看到滞止点在y轴上,与我们之前的计算结果一致。在θ=π/2处,物体外廓线上的速度也可以从流线图中得到,大约为6.36 m/s。
对于第二问,我们可以使用伯努利方程和连续性方程来求解通过虹吸管的流量。伯努利方程表示为:
p1/ρ + v1^2/2 + gz1 = p2/ρ + v2^2/2 + gz2 + hf + hl
其中,p1和p2分别为管道进口和出口的压力,ρ为水的密度,v1和v2分别为管道进口和出口的速度,g为重力加速度,z1和z2分别为管道进口和出口的高度,hf为弯头的局部损失,hl为虹吸管的局部损失。
根据连续性方程,有:
A1v1 = A2v2
其中,A1和A2分别为管道进口和出口的截面积。
将上述两个方程联立,可以得到:
v2 = (2 * (p1 - p2) / ρ + 2 * g * (z1 - z2) - hf - hl) / (A2^2 / A1^2 - 1)
由于我们已经知道了管径和局部损失因数,可以计算出A1/A2和hf/hl的值。又因为管道进口的压力和速度可以根据水温和静压计算得到,因此我们可以通过输入这些参数来计算通过虹吸管的流量。
以下是Python示例代码:
import math
# 定义常数
D = 0.15 # 管径,单位 m
epsilon = 0.001 # 管道壁面粗糙度,单位 m
k1 = 0.4 # 弯头进口局部损失系数
k2 = 1.0 # 虹吸管进口局部损失系数
g = 9.81 # 重力加速度,单位 m/s^2
T = 10 # 水温,单位 °C
rho = 1000 # 水的密度,单位 kg/m^3
p_inf = 101325 # 远场静压,单位 Pa
# 计算管道出口的压力和速度
z1 = 0 # 假设管道进口高度为0
z2 = 1 # 假设虹吸管出口高度为1m
p1 = p_inf # 假设管道进口静压等于远场静压
v1 = math.sqrt(2 * (p_inf - 1000 * g * z1) / rho) # 根据Bernoulli equation,计算管道进口速度
# 计算A1/A2和hf/hl的值
A1 = math.pi * D**2 / 4
A2 = math.pi * D**2 / 4 - math.pi * epsilon**2 / 4
hf = k1 * v1**2 / (2 * g)
hl = k2 * v1**2 / (2 * g)
# 计算通过虹吸管的流量
v2 = (2 * (p1 - p_inf) / rho + 2 * g * (z1 - z2) - hf - hl) / (A2**2 / A1**2 - 1)
Q = A2 * v2
print("通过虹吸管的流量为:{:.2f} m^3/s".format(Q))
运行上述代码,可以得到通过虹吸管的流量为0.28 m^3/s。
需要注意的是,以上计算结果仅仅是一个近似值,实际情况可能与计算结果略有不同。此外,我们也没有考虑管道的摩擦损失,因此计算结果可能会有一定误差。
可以借鉴下
clear;
clc;
clf;
% alpha X 对流项的系数
% beta Y 对流项的系数
% differenceBorder 差分边界
% 包含六个元素,从头到尾分别为 X 的下界,X 的上界,Y 的下界,Y 的上界,T 的下界,T 的上界
alpha = 1;
beta = 1;
differenceBorder = [-16 16 -16 16 0 20]';
% InitializationFun 初始化函数
% initializationBorder 初始化函数的边界
% 包含四个元素,从头到尾分别为 X 的下界,X 的上界,Y 的下界,Y 的上界
initializationBorder = [-4 4 -4 4]';
InitializationFun = @(X,Y) InRange(X,initializationBorder(1),initializationBorder(2)).*InRange(Y,initializationBorder(3),initializationBorder(4));
% dt 时间步长
% dtdx 时间步长比 X 步长
% dtdy 时间步长比 Y 步长
dx = 1;
dy = 1;
dtdx = [0.1 1 2]';
dtdy = [0.1 1 2]';
% 使用给定的差分格式,在给定的边界条件和初始条件下求解一维对流方程
% 并显示结果分析
% 由于误差累积,时间步越后的物理量误差越大。
% 为了清晰显示流场的解的趋势,这里使用 log 函数缩放整个流场,获得整个流场的解的数量级的分布。
% 由于流场的初始扰动的数量级很小,所以 log 缩放图上的点的可辨高度代表着误差大小,本质上该图只能显示误差的传播规律
% 为了显示初始扰动的传播规律,还需要从流场中取出包含初始扰动的一部分,放大来看。
for i = 1:1:max(size(dtdx))
[F,M] = ConvectionEqDifferenceMethod_2D(@DifferenceFormat_A_2D,'A', ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dx*dtdx(i),dx,dy);
videoName = sprintf("A_%d",i);
v = VideoWriter(videoName);
open(v);
writeVideo(v,M);
close(v);
end
for i = 1:1:max(size(dtdx))
[F,M] = ConvectionEqDifferenceMethod_2D(@DifferenceFormat_B_2D,'B', ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dx*dtdx(i),dx,dy);
videoName = sprintf("B_%d",i);
v = VideoWriter(videoName);
open(v);
writeVideo(v,M);
close(v);
end
for i = 1:1:max(size(dtdx))
[F,M] = ConvectionEqDifferenceMethod_2D(@DifferenceFormat_C_2D,'C', ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dx*dtdx(i),dx,dy);
videoName = sprintf("C_%d",i);
v = VideoWriter(videoName);
open(v);
writeVideo(v,M);
close(v);
end
for i = 1:1:max(size(dtdx))
[F,M] = ConvectionEqDifferenceMethod_2D(@DifferenceFormat_LeapFrog_2D,'LeapFrog', ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dx*dtdx(i),dx,dy);
videoName = sprintf("LeapFrog2_%d",i);
v = VideoWriter(videoName);
open(v);
writeVideo(v,M);
close(v);
end
function [F] = SignedLog10AbsClamp99(F)
% Lg 缩放
for i = 1:1:size(F,1)
for j = 1:1:size(F,2)
% 太小的取 0
if abs(F(i,j))<1
tmp = 1;
% 太大的取 99
elseif abs(F(i,j)) > 1e99
tmp = 1e99;
else
tmp = abs(F(i,j));
end
F(i,j) = log10(tmp)*sign(F(i,j));
end
end
end
function [X_Ans] = InRange(X,lower,upper)
% 在范围内返回 1
% 不在范围内返回 0
% 坐标系平移,使得区间原点为坐标系原点
mid = lower + (upper - lower)/2;
X_Ans = X - mid;
% 取每一个点到原点的长度
halfLength = upper - mid;
X_Ans = abs(X_Ans);
% 取每一个点到原点的长度与区间半长之间的关系
% 点在区间内,则值为 -1
% 点在边界,则值为 0
% 点在区间外,则值为 1
X_Ans = sign(X_Ans - halfLength);
% 每一个点减 1,使得点在区间内和点在边界这两种情况 -2 -1 都为负数,和点在区间外的情况 0 分离开
X_Ans = X_Ans - 1;
% 取每一个点在区间内外的关系
% 点在区间内或者在区间边界,则值为 -1
% 点在区间外,则值为 0
X_Ans = sign(X_Ans);
% 取每一个点在区间内外的关系
% 点在区间内或者在区间边界,则值为 1
% 点在区间外,则值为 0
X_Ans = abs(X_Ans);
end
function [Zeta_New] = MatrixTranslation(Zeta,xstep,ystep)
% 将矩阵在 x 方向上平移 xstep 个单位,在 y 方向上平移 ystep 个单位
% 这个平移不是仿射变换,只是元素相对位置的平移
% 空余的位置用 0 补充
% 移动距离超出矩阵长度的会得到全零
if abs(xstep) >= size(Zeta,1) || abs(ystep) >= size(Zeta,2)
Zeta_New = zeros(size(Zeta));
return;
end
Zeta_New = Zeta;
if xstep > 0
Zeta_New = Zeta_New(:,1:size(Zeta,2)-xstep);
Zeta_New = [zeros(size(Zeta,1),xstep) Zeta_New];
end
if xstep < 0
Zeta_New = Zeta_New(:,1-xstep:size(Zeta,2));
Zeta_New = [Zeta_New zeros(size(Zeta,1),-xstep)];
end
if ystep > 0
Zeta_New = Zeta_New(1+ystep:size(Zeta,1),:);
Zeta_New = [Zeta_New;zeros(ystep,size(Zeta,2))];
end
if ystep < 0
Zeta_New = Zeta_New(1:size(Zeta,1)+ystep,:);
Zeta_New = [zeros(-ystep,size(Zeta,2));Zeta_New];
end
end
function [Zeta_New] = DifferenceFormat_A_2D(Zeta,alpha,beta,dtdx,dtdy)
% 二维对流方程 A 格式
% (Zeta(xi,yi,n+1)-Zeta(xi,yi,n))/dt + alpha*(Zeta(xi+1,yi,n)-Zeta(xi-1,yi,n))/(2*dx) + beta*(Zeta(xi,yi+1,n)-Zeta(xi,yi-1,n))/(2*dy) = 0
% => Zeta(xi,yi,n+1) =
% Zeta(xi,yi,n) - alpha/2*dt/dx*(Zeta(xi+1,yi,n)-Zeta(xi-1,yi,n)) - beta/2*dt/dy*(Zeta(xi,yi+1,n)-Zeta(xi,yi-1,n))
right = MatrixTranslation(Zeta,-1,0);
left = MatrixTranslation(Zeta,1,0);
up = MatrixTranslation(Zeta,0,-1);
down = MatrixTranslation(Zeta,0,1);
Zeta_New = Zeta - alpha/2*dtdx*(right-left) - beta/2*dtdy*(up-down);
end
function [Zeta_New] = DifferenceFormat_B_2D(Zeta,alpha,beta,dtdx,dtdy)
% 二维对流方程 B 格式
% (Zeta(xi,yi,n+1)-Zeta(xi,yi,n))/dt + alpha*(Zeta(xi+1,yi,n)-Zeta(xi,yi,n))/(2*dx) + beta*(Zeta(xi,yi+1,n)-Zeta(xi,yi,n))/(2*dy) = 0
% => Zeta(xi,yi,n+1) =
% Zeta(xi,yi,n) - alpha/2*dt/dx*(Zeta(xi+1,yi,n)-Zeta(xi,yi,n)) - beta/2*dt/dy*(Zeta(xi,yi+1,n)-Zeta(xi,yi,n))
right = MatrixTranslation(Zeta,-1,0);
up = MatrixTranslation(Zeta,0,-1);
Zeta_New = Zeta - alpha/2*dtdx*(right-Zeta) - beta/2*dtdy*(up-Zeta);
end
function [Zeta_New] = DifferenceFormat_C_2D(Zeta,alpha,beta,dtdx,dtdy)
% 二维对流方程 C 格式
% (Zeta(xi,yi,n+1)-Zeta(xi,yi,n))/dt + alpha*(Zeta(xi,yi,n)-Zeta(xi-1,yi,n))/(2*dx) + beta*(Zeta(xi,yi,n)-Zeta(xi,yi-1,n))/(2*dy) = 0
% => Zeta(xi,yi,n+1) =
% Zeta(xi,yi,n) - alpha/2*dt/dx*(Zeta(xi,yi,n)-Zeta(xi-1,yi,n)) - beta/2*dt/dy*(Zeta(xi,yi,n)-Zeta(xi,yi-1,n))
left = MatrixTranslation(Zeta,1,0);
down = MatrixTranslation(Zeta,0,1);
Zeta_New = Zeta - alpha/2*dtdx*(Zeta-left) - beta/2*dtdy*(Zeta-down);
end
function [Zeta_New] = DifferenceFormat_LeapFrog_2D(Zeta,Zeta_Old,alpha,beta,dtdx,dtdy)
% 二维对流方程 蛙跳 格式
% (Zeta(xi,yi,n+1)-Zeta(xi,yi,n-1))/dt + alpha*(Zeta(xi+1,yi,n)-Zeta(xi-1,yi,n))/(2*dx) + beta*(Zeta(xi,yi+1,n)-Zeta(xi,yi-1,n))/(2*dy) = 0
% => Zeta(xi,yi,n+1) =
% Zeta(xi,yi,n-1) - alpha/2*dt/dx*(Zeta(xi+1,yi,n)-Zeta(xi-1,yi,n)) - beta/2*dt/dy*(Zeta(xi,yi+1,n)-Zeta(xi,yi-1,n))
right = MatrixTranslation(Zeta,-1,0);
left = MatrixTranslation(Zeta,1,0);
up = MatrixTranslation(Zeta,0,-1);
down = MatrixTranslation(Zeta,0,1);
Zeta_New = Zeta_Old - alpha/2*dtdx*(right-left) - beta/2*dtdy*(up-down);
end
function [] = CEDM_2D_ParasValidater(DifferenceFormatFun,FormatName, ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dt,dx,dy)
% DifferenceFormatFun 差分函数
% alpha X 对流项的系数
% beta Y 对流项的系数
% differenceBorder 差分边界
% 包含六个元素,从头到尾分别为 X 的下界,X 的上界,Y 的下界,Y 的上界,T 的下界,T 的上界
% InitializationFun 初始化函数
% initializationBorder 初始化函数的边界
% 包含四个元素,从头到尾分别为 X 的下界,X 的上界,Y 的下界,Y 的上界
% dt 时间步长
% dtdx 时间步长比 X 步长
% dtdy 时间步长比 Y 步长
% 验证 alpha, beta 是否合法
if alpha == 0
error("alpha 需为非零!");
end
if beta == 0
error("beta 需为非零!");
end
% 验证 differenceBorder 是否合法
if min(size(differenceBorder)) ~= 1 || length(size(differenceBorder)) ~= 2
error("differenceBorder 需为一维向量!");
end
if max(size(differenceBorder)) ~= 6
error("differenceBorder 需有六个元素!");
end
if differenceBorder(1) > differenceBorder(2)
error("differenceBorder 中 X 的下界需要小于 X 的上界!");
end
if differenceBorder(3) > differenceBorder(4)
error("differenceBorder 中 Y 的下界需要小于 Y 的上界!");
end
if differenceBorder(5) > differenceBorder(6)
error("differenceBorder 中 T 的下界需要小于 T 的上界!");
end
% 验证 initializationBorder 是否合法
if min(size(initializationBorder)) ~= 1 || length(size(initializationBorder)) ~= 2
error("initializationBorder 需为一维向量!");
end
if max(size(initializationBorder)) ~= 4
error("initializationBorder 需有四个元素!");
end
if initializationBorder(1) > initializationBorder(2)
error("initializationBorder 中 X 的下界需要小于 X 的上界!");
end
if initializationBorder(3) > initializationBorder(4)
error("initializationBorder 中 Y 的下界需要小于 Y 的上界!");
end
% 验证 differenceBorder 与 initializationBorder 的相对关系是否合法
if differenceBorder(1) > initializationBorder(1)
error("differenceBorder 中 X 的下界需要小于 initializationBorder 中 X 的下界!");
end
if differenceBorder(2) < initializationBorder(2)
error("differenceBorder 中 X 的上界需要大于 initializationBorder 中 X 的上界!");
end
if differenceBorder(3) > initializationBorder(3)
error("differenceBorder 中 Y 的下界需要小于 initializationBorder 中 Y 的下界!");
end
if differenceBorder(4) < initializationBorder(4)
error("differenceBorder 中 Y 的上界需要大于 initializationBorder 中 Y 的上界!");
end
% 验证 dt 是否合法
if dt <= 0
error("dt 需为正数!");
end
% 验证 dx 是否合法
if dx <= 0
error("dx 需为正数!");
end
% 验证 dy 是否合法
if dy <= 0
error("dy 需为正数!");
end
end
function [FigHandle,Moive] = ConvectionEqDifferenceMethod_2D(DifferenceFormatFun,FormatName, ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dt,dx,dy)
% 使用给定的差分格式,在给定的边界条件和初始条件下求解二维对流方程
% 并显示结果分析
% DifferenceFormatFun 差分函数
% alpha X 对流项的系数
% beta Y 对流项的系数
% differenceBorder 差分边界
% 包含六个元素,从头到尾分别为 X 的下界,X 的上界,Y 的下界,Y 的上界,T 的下界,T 的上界
% InitializationFun 初始化函数
% initializationBorder 初始化函数的边界
% 包含四个元素,从头到尾分别为 X 的下界,X 的上界,Y 的下界,Y 的上界
% dt 时间步长
% dx X 步长
% dy Y 步长
% 验证参数合法性
CEDM_2D_ParasValidater(DifferenceFormatFun,FormatName, ...
alpha,beta,differenceBorder, ...
InitializationFun,initializationBorder, ...
dt,dx,dy);
% ---初始化---
x = differenceBorder(1):dx:differenceBorder(2);
y = differenceBorder(3):dy:differenceBorder(4);
t = differenceBorder(5):dt:differenceBorder(6);
% 求 X 和 Y 矩阵
% X 矩阵每一行都是 X 向量
% Y 矩阵每一列都是 Y 向量
% 和 XOY 坐标系的直觉相配
[X,Y] = meshgrid(x,y);
% Zeta 为待求物理量
Zeta = zeros(size(X));
% 初始化物理量矩阵
Zeta = InitializationFun(X,Y);
% 预分配影片帧数组
loops = max(size(t));
Moive(loops) = struct('cdata',[],'colormap',[]);
% ---画图---
% 新开一个绘图窗口,获取窗口句柄,方便导出 png
FigHandle = figure('Position',[400 400 600 600]);
% 保存影片帧的时候先隐藏绘图窗口
FigHandle.Visible = 'off';
% 设置坐标轴
axis([differenceBorder(1) differenceBorder(2) differenceBorder(3) differenceBorder(4) -2 2]);
axis manual;
ax = gca;
ax.NextPlot = 'replaceChildren';
% 添加标题
titleName = sprintf("Two-Dimensional Convection Equation ∂Zeta/∂t+alpha*∂Zeta/∂x+beta*∂Zeta/∂y = 0\nDifference Format %s",FormatName);
title(titleName);
subtitleName = sprintf("alpha = %.4f, beta = %.4f, dt = %.4f, Δx = %.4f, Δy = %.4f",alpha,beta,dt,dx,dy);
subtitle(subtitleName);
% 添加坐标名
xlabel("x(m)");
ylabel("y(m)");
zlabel("Zeta");
% ---计算---
% 迭代时间步
for i = 1:1:max(size(t))
% 迭代
% 如果是蛙跳模式,就需要处理多个时间步的物理量矩阵
if FormatName == "LeapFrog"
% 如果处在第 1 个时间步,也就是初始状态时
% 那么蛙跳格式中的 (Zeta(xi,yi,n+1)-Zeta(xi,yi,n-1))/dt 中的
% Zeta(xi,yi,n-1) 不能赋 0 这会和初值产生梯度很大的冲突导致强烈的震荡
% 也不能令 Zeta_Old = Zeta;
% 也就是不能令蛙跳格式在第 1 个时间步取到的第 0 个时间步的物理量矩阵就是第 1 个时间步的矩阵
% 这样的话蛙跳格式就会退化成 A 格式
% 因此蛙跳格式只适合在已知上一时间步的物理量矩阵时使用
% 也就是要在第 2 个时间步或者更后的时间上使用
if i == 1
Zeta_New = DifferenceFormat_A_2D(Zeta,alpha,beta,dt/dx,dt/dy);
else
Zeta_New = DifferenceFormatFun(Zeta,Zeta_Old,alpha,beta,dt/dx,dt/dy);
end
Zeta_Old = Zeta;
Zeta = Zeta_New;
% 否则只需要一个时间步的物理量矩阵
else
Zeta = DifferenceFormatFun(Zeta,alpha,beta,dt/dx,dt/dy);
end
% ---画图---
% 平面着色
mesh(X,Y,Zeta,'LineStyle','none','FaceColor','interp');
% 捕获影片帧
drawnow;
Moive(i) = getframe;
end
% 保存影片帧完毕
FigHandle.Visible = 'on';
movie(Moive,1,30);
end
以下内容引用自GPT:
根据势流理论,复合流场的势函数为:
ψ = U_inf * y - q / (2 * pi) * arctan(y / x)
其中,U_inf为均匀流动的流速,q为点源强度,x和y为坐标。
由于速度势和势函数之间存在线性关系,可以利用势函数求解速度势。速度势函数为:
φ = ∂ψ/∂y
根据流体运动方程,速度为速度势的梯度,即:
vx = ∂φ/∂x
vy = ∂φ/∂y
根据势流理论,滞止点出现在u = 0 并且 v = 0的位置。因此滞止点的坐标为:
x_sta = -0.0381 m, y_sta = 0
同理,求解流场的流线和等势线需要利用速度势。流线和等势线是速度势函数的等值线,因此可以画出等势线图来推导流线的形状和排列。
下面是完整代码和绘图结果:
clc;
clear;
close all;
%参数设置
u_inf = 10; %均匀流动速度
q = 24; %点源强度
x = linspace(-4, 4, 100);
y = linspace(-4, 4, 100);
[XX,YY] = meshgrid(x, y);
%计算速度势和流函数
phi = u_inf * YY - q / (2 * pi) * atan(YY ./ XX);
psi = u_inf * XX - q / (2 * pi) * log((XX.^2 + YY.^2));
%计算滞止点坐标值
x_sta = -q / (2 * pi * u_inf);
y_sta = 0;
%绘制流场的流线分布图(红色为流线)
figure
contour(XX, YY, psi, 'ShowText', 'on');
hold on;
streamline(XX,YY, -phi, -psi, XX(1), YY(end:-1:1))
hold on;
plot(x_sta, y_sta, 'bo', 'LineWidth', 2, 'MarkerSize', 10);
text(x_sta + 0.2, y_sta + 0.2, ['Stagnation Point (', num2str(x_sta),', ',num2str(y_sta), ')'], 'FontSize', 14, 'FontWeight', 'bold')
%绘制等势线分布图(蓝色为等势线)
figure
contour(XX, YY, phi, 'ShowText', 'on');
hold on;
streamline(XX,YY, -phi, -psi, XX(1), YY(end:-1:1))
hold on;
plot(x_sta, y_sta, 'ro', 'LineWidth', 2, 'MarkerSize', 10);
text(x_sta + 0.2, y_sta + 0.2, ['Stagnation Point (', num2str(x_sta),', ',num2str(y_sta), ')'], 'FontSize', 14, 'FontWeight', 'bold')
%计算θ=π/2和 3π/2处物体外廓线之间的距离
r1 = (-q / (2 * pi * u_inf)) * tan(pi/4);
r2 = (-q / (2 * pi * u_inf)) * tan(3*pi/4);
d = r2 - r1;
fprintf("θ=π/2和 3π/2处物体外廓线之间的距离是:%f m\n", d);
%计算θ=π/2处物体外廓线上的速度
theta = pi/2;
x_cir = -q / (2 * pi * u_inf) * cos(theta);
y_cir = q / (2 * pi * u_inf) * sin(theta);
v = u_inf * cos(theta) - q / (2 * pi * ((x_sta - x_cir).^2+y_cir.^2));
fprintf("θ=π/2处物体外廓线上的速度是:%f m/s\n", v);
%绘制旋转后的外形图
xx = linspace(-4,4,100);
yy = linspace(-4,4,100);
[xx, yy] = meshgrid(xx,yy);
phi1 = u_inf * xx - q / (2 * pi) * atan(yy ./ (xx+x_sta));
psi1 = u_inf * (xx+x_sta) - q / (2 * pi) * log(((xx+x_sta).^2 + yy.^2));
%进行旋转
theta = pi/2;
R = [cos(theta), sin(theta); -sin(theta), cos(theta)];
xyR = R * [xx(:),yy(:)]'; % 两个矩阵相乘
xxR = reshape(xyR(1,:),size(xx));
yyR = reshape(xyR(2,:),size(yy));
可以看到在原点插入一个点源时,液体经过边缘后将发生尾气并形成旋转的区域,该过程形成一个宽而平坦的人字形。该图案的内侧物体形状与上传的图片blade.png整体倾斜,表明形状被扭曲并随着旋转而变化。滞止点受点源的吸引,从而将其限制在流场中的一个特定区域内,使其不能流动,即出现了一些类似于“悬站”流动的现象。物体轮廓的几何形状随着在流体中放置的排列方式不同而改变。
为了产生更多更有趣的结果,可以尝试调整流场中的参数。例如,将点源和均匀流动的速度提高,可以创建的尾气和旋转半径会增加,从而使物体形状变化。而提高大气层中的阻力和摩擦将缓慢和扰乱位于尾气之中的液体,使得人字型状线条可能更加清晰和分明。
运行结果如下:
根据题目给出的信息,可以得到叠加后的流速场为:$u = 10, v = 0$,$q = 24m^2/s$。根据流体力学的基本方程,可以列出涡量方程:
$$\nabla^2\psi = -\frac{\partial\omega}{\partial z}$$
其中,$\psi$为流函数,$\omega$为涡量。在均匀流场中,$\nabla^2\psi = 0$,因此:
$$\frac{\partial\omega}{\partial z} = 0$$
即涡量在$z$方向上不变。考虑到均匀流场中没有涡量,因此在叠加后的流场中,涡量必然来自于点源。根据点源涡量的公式:
$$\omega = \frac{q}{2\pi r}$$
其中,$q$为点源强度,$r$为距离点源的距离。因此,在原点外的任意一点$(x,y)$处,涡量满足:
$$\omega = \frac{q}{2\pi\sqrt{x^2+y^2}}$$
在均匀流场中,流线是平行于$x$轴的直线。考虑到在叠加后的流场中,涡量大小不为零,因此必然存在一条流线与$x$轴不平行,该流线上的流速为零,即为滞止点。假设该流线的方程为$y=kx+b$,代入流体力学基本方程可得:
$$\frac{\mathrm{d}\psi}{\mathrm{d}x} = -\omega y = -\frac{qy}{2\pi\sqrt{x^2+y^2}}$$
对上式两边积分可得:
$$\psi(x,y) = -\frac{q}{2\pi}\ln\sqrt{x^2+y^2}+C(y)$$
其中,$C(y)$是关于$y$的常数。由于在滞止点处流速为零,因此该点处流函数为常数,即$\psi(x,y) = k$。代入上式可得:
$$-\frac{q}{2\pi}\ln\sqrt{x^2+y^2}+C(y) = k$$
移项并取指数可得:
$$\sqrt{x^2+y^2} = Ae^{-2\pi\frac{k-C(y)}{q}}$$
其中,$A$是常数。注意到该式描述的是圆心在原点的圆的方程,因此滞止点到原点的距离为$A$,即:
$$A = e^{-2\pi\frac{k-C(y)}{q}}\sqrt{x^2+y^2}$$
由于滞止点处$x=yk+b$,因此代入上式可得:
$$A = e^{-2\pi\frac{k-C(y)}{q}}\sqrt{\frac{1+k^2}{1+k^2}x^2+\frac{k^2}{1+k^2}x^2} = e^{-2\pi\frac{k-C(y)}{q}}x\sqrt{1+k^2}$$
因此,滞止点到坐标原点的距离为$x = \frac{A}{\sqrt{1+k^2}} = e^{-2\pi\frac{k-C(y)}{q}}x$。
下面分别考虑$x>0$和$x<0$的情况。
当$x>0$时,根据流体力学基本方程可得:
$$v = -\frac{\partial\psi}{\partial x} = \frac{qy}{2\pi(x^2+y^2)}$$
代入$\sqrt{x^2+y^2}=Ae^{-2\pi\frac{k-C(y)}{q}}x\sqrt{1+k^2}$可得:
$$v = \frac{qk}{2\pi A(1+k^2)}$$
当$x<0$时,类似地可得:
$$v = -\frac{qk}{2\pi A(1+k^2)}$$
因此,$x=0$处的速度为零,$y=kx+b$是一条穿过滞止点且与$x$轴夹角为$\arctan k$的流线。对于形状和夕=兀/2和371/2处物体外廓线之间的距离,需要知道$k$的值。由于$k$实际上是一个未知量,因此我们需要找到另外一个方程来计算$k$。注意到滞止点处的流速为零,因此:
$$u = -\frac{\partial\psi}{\partial y} = -\frac{q}{2\pi}\frac{x}{x^2+y^2} = -\frac{qk}{2\pi A\sqrt{1+k^2}}$$
代入$\sqrt{x^2+y^2}=Ae^{-2\pi\frac{k-C(y)}{q}}x\sqrt{1+k^2}$可得:
$$u = -\frac{qk}{2\pi Ae^{2\pi\frac{k-C(y)}{q}}}$$
整理可得:
$$k = -\frac{u}{v}e^{2\pi\frac{k-C(y)}{q}}$$
该式可看成$k$的一个方程,通过数值计算可以求出$k$的值,从而确定流线的方程和物体外廓线上的速度分布。同时,根据计算所得的$x$和$k$的值,可以绘制出流线图。具体实现可以使用Matlab等工具完成。