Matlab解决大学问题并画出图像

流体力学模拟题,详情见图片,利用Matlab知识解决,需要给出图像还有相关代码

img

第二题:

该回答引用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整体倾斜,表明形状被扭曲并随着旋转而变化。滞止点受点源的吸引,从而将其限制在流场中的一个特定区域内,使其不能流动,即出现了一些类似于“悬站”流动的现象。物体轮廓的几何形状随着在流体中放置的排列方式不同而改变。

为了产生更多更有趣的结果,可以尝试调整流场中的参数。例如,将点源和均匀流动的速度提高,可以创建的尾气和旋转半径会增加,从而使物体形状变化。而提高大气层中的阻力和摩擦将缓慢和扰乱位于尾气之中的液体,使得人字型状线条可能更加清晰和分明。
运行结果如下:

img

img

img

根据题目给出的信息,可以得到叠加后的流速场为:$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等工具完成。