[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算

1. 代码

% 中山大学 19320053 廉嘉诚

clc;
clf;
clear;

% ---参数初始化---

% 流体密度
rho = 1e3;
% 雷诺数
Re = 3200;
% 动力粘性系数
mu = 1/Re;
% 误差限度
SOR_error_limit = 1e-3;
% 迭代次数限度
FTCS_MaxTimes = 1e5;
SOR_MaxTimes = 1e5;

% 题设顶部移动速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.01;
% 时间步长
dt = 0.001;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(y,x);

% 矩阵长度
length = size(X,1);

% 场 
Zeta = zeros(size(X));
Psi = zeros(size(X));
P = zeros(size(X));
PG = zeros([length 4]); % 1 左边界 2 右边界 3 下边界 4 上边界
Sp = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
U1 = zeros(size(X));
V1 = zeros(size(X));

% 缓存
tmp = zeros(size(X));

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(length,length);

% 开始求解
for Zeta_FTCS_times = 1:1:FTCS_MaxTimes
    
    % 流函数 超松弛迭代
        
    % 内点
    
    for Psi_SOR_times = 1:1:SOR_MaxTimes
        
        dPsi_max = 0;
        
        for i = 2:1:length-1
            for j = 2:1:length-1
                
                % 增量
                dPsi = -factor*Psi(i,j)...
                    +factor/4*(...
                    Psi(i,j+1)...
                    +Psi(i,j-1)...
                    +Psi(i+1,j)...
                    +Psi(i-1,j)...
                    +h^2*Zeta(i,j));
                % 取增量绝对值的最大值
                dPsi_max = max([dPsi_max abs(dPsi)]);
                % 基点的新值
                Psi(i,j) = Psi(i,j) + dPsi;
            end
        end
        
        % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
        if dPsi_max < SOR_error_limit
            break;
        end
    end
    
    % 涡量 FTCS 格式

    % 边界点(跳过角点)
    
    for i = 2:1:length-1
        
        % 下侧
        Zeta(i,1) = -2.0*Psi(i,2)/(h*h)+2.0*U_assume/h;
        % 上侧
        Zeta(i,length) = -2.0*Psi(i,length-1)/(h*h);
    end
    for j = 2:1:length-1
        
        % 左侧
        Zeta(1,j) = -2.0*Psi(2,j)/(h*h);
        % 右侧
        Zeta(length,j) = -2.0*Psi(length-1,j)/(h*h);
    end
    
    % 内点
    
    Zeta_right = MatrixTranslation(Zeta,1,0);
    Zeta_left = MatrixTranslation(Zeta,-1,0);
    Zeta_up = MatrixTranslation(Zeta,0,1);
    Zeta_down = MatrixTranslation(Zeta,0,-1);
    
    Psi_right = MatrixTranslation(Psi,1,0);
    Psi_left = MatrixTranslation(Psi,-1,0);
    Psi_up = MatrixTranslation(Psi,0,1);
    Psi_down = MatrixTranslation(Psi,0,-1);
    
    U_dZeta_dx = (Psi_up-Psi_down).*(Zeta_right-Zeta_left)/(4*h^2);
    V_dZeta_dy = -(Psi_right-Psi_left).*(Zeta_up-Zeta_down)/(4*h^2);
    mu_Nabla_Zeta = mu*(Zeta_right+Zeta_left+Zeta_up+Zeta_down-4*Zeta)/h^2;
    Zeta_tmp = Zeta + dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);
    Zeta(2:length-1,2:length-1) = Zeta_tmp(2:length-1,2:length-1);
end

% 流速
U = (Psi_up-Psi_down)/(2*h);
V = -(Psi_right-Psi_left)/(2*h);
        
% 压强梯度

% 边界点(跳过角点)

for i = 2:1:length-1
    
    % 下侧
    PG(i,3) = rho/h^2*mu*V(i,2);
    % 上侧
    PG(i,4) = rho/h^2*mu*V(i,length-1);;
end
for j = 2:1:length-1
    
    % 左侧
    PG(j,1) = rho/h^2*mu*U(2,j);
    % 右侧
    PG(j,2) = rho/h^2*mu*U(length-1,j);
end
        
% 压强 超松弛迭代

Psi_right_up = MatrixTranslation(Psi,1,1);
Psi_right_down = MatrixTranslation(Psi,1,-1);
Psi_left_up = MatrixTranslation(Psi,-1,1);
Psi_left_down = MatrixTranslation(Psi,-1,-1);

Sp = 2*rho/h^2*(...
    (Psi_right-2*Psi+Psi_left)*(Psi_up-2*Psi+Psi_down) ...
    -(Psi_right_up-Psi_right_down-Psi_left_up+Psi_left_down)/4);

for P_SOR_times = 1:1:SOR_MaxTimes
    
    dP_max = 0;
    
    for i = 1:1:length
        for j = 1:1:length
            
            % 跳过角点
            if i == 1 || i == length
                if j == 1 || j == length
                    continue;
                end
            end
            
            p1 = P(i,j);
            
            % 边界点
            
            % 下侧
            if j == 1
                p1 = P(i,2)-PG(i,3)*h;
                continue;
            % 上侧
            elseif j == length
                p1 = P(i,length-1)+PG(i,4)*h;
                continue;
            end
            
            % 左侧
            if i == 1
                p1 = P(2,j)-PG(j,1)*h;
                continue;
            % 右侧
            elseif i == length
                p1 = P(length-1,j)+PG(j,2)*h;
                continue;
            end
            
            % 内点

            p2 = (...
                P(i,j+1)...
                +P(i,j-1)...
                +P(i+1,j)...
                +P(i-1,j)...
                +h^2*Sp(i,j));
            
            dP = -factor*p1+factor/4*p2;
            
            % 取增量绝对值的最大值
            dP_max = max([dP_max abs(dP)]);
            % 基点的新值
            P(i,j) = P(i,j) + dP;
        end
    end
    
    % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
    if dP_max < SOR_error_limit
        break;
    end
end


% 流函数等高线
figure(1);
clf;
contour(Y,X,Psi,Psi(floor(length/2),:));
shading interp;
hold on;
contour(Y,X,Psi,Psi(:,floor(6*length/7)));
hold off;
title('流函数等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;



% 涡量等高线
figure(2);
clf;
hold on;
contour(Y,X,Zeta,Zeta(floor(length/2),:));
hold off;
shading interp;
title('涡量等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;



% 水平速度等高线
figure(3);
clf;
hold on;
contour(Y,X,U,U(:,floor(length/5)));
contour(Y,X,U,U(:,floor(2*length/5)));
contour(Y,X,U,U(:,floor(3*length/5)));
contour(Y,X,U,U(:,floor(4*length/5)));
hold off;
shading interp;
title('水平速度等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;



% 竖直速度等高线
figure(4);
clf;
hold on;
contour(Y,X,V,V(floor(length/5),:));
contour(Y,X,V,V(floor(2*length/5),:));
contour(Y,X,V,V(floor(3*length/5),:));
contour(Y,X,V,V(floor(4*length/5),:));
hold off;
shading interp;
title('竖直速度等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;


% 压强等高线
figure(4);
clf;
hold on;
contour(Y,X,P,P(floor(length/2),:));
contour(Y,X,P,P(floor(length/4),:));
contour(Y,X,P,P(floor(3*length/4),:));
hold off;
shading interp;
title('压强等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;

function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,xstep,ystep)
    % 将矩阵在 x 方向上平移 xstep 个单位,在 y 方向上平移 ystep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(xstep) >= size(A,1) || abs(ystep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    A = A;
    
    if xstep > 0
        A = A(:,1:size(A,2)-xstep);
        A = [zeros(size(A,1),xstep) A];
    end
    
    if xstep < 0
        A = A(:,1-xstep:size(A,2));
        A = [A zeros(size(A,1),-xstep)];
    end
    
    if ystep > 0
        A = A(1+ystep:size(A,1),:);
        A = [A;zeros(ystep,size(A,2))];
    end
    
    if ystep < 0
        A = A(1:size(A,1)+ystep,:);
        A = [zeros(-ystep,size(A,2));A];
    end
end

function [A] = DeleteElementForLargerSpace(A,n)
    % 输入一个行向量或者列向量,输出一个全部元素属于输入的列向量
    % 使得输出的列向量各元素之间的间隔变大
    % 共减少 n 个元素
    
    for times = 1:1:n
        
        length = size(A,1)*size(A,2);
        delta = zeros(length-1,1);
        
        for i = 1:1:length-1
            delta(i) = abs(A(i)-A(i+1));
        end
        
        [M,I] = min(delta);
        
        A_tmp = zeros(length-1,1);
        for i = 1:1:I-1
            A_tmp(i) = A(i);
        end
        for i = I+1:1:length
            A_tmp(i-1) = A(i);
        end
        A = A_tmp;
    end
end

2. 报告

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第1张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第2张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第3张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第4张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第5张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第6张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第7张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第8张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第9张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第10张图片












3. Debug

3.1 格式

第一版代码

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 误差限度
error_limit = 1e-6;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 100;
% 迭代次数
iterationTimes = 0;

% ---网格初始化---

% 步长
dx = 0.005;
dy = 0.005;

% 边界
x_border = [-0.5 0.5]';
y_border = [0 1]';

% 边界向量
x = x_border(1):dx:x_border(2);
y = y_border(1):dy:y_border(2);

% 求 X 和 Y 矩阵
% X 矩阵每一行都是 X 向量
% Y 矩阵每一列都是 Y 向量
% 和 XOY 坐标系的直觉相配 
[X,Y] = meshgrid(x,y);

% 涡量初始化
Zeta = zeros(size(X));
% 流函数初始化
Psi = zeros(size(X));
% 速度初始化
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = 1;
end

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));
% error > error_limit &&  
% 循环迭代
while iterationTimes < iterationTimes_limit
    % 迭代涡量
    [Zeta,dZeta_max] = Iteration_Vorticity(Zeta,Psi,U,V,factor,dx,1/Re);
    % 迭代流函数
    [Psi,dPsi_max] = Iteration_StreamFunction(Psi,Zeta,factor,dx);
    % 迭代速度
    [U,V,dU_max,dV_max] = Iteration_Velocity(Psi,U,V,dx);
    
    % 取最大误差
    error = max([dZeta_max dPsi_max dU_max dV_max]);
    % 迭代次数加 1
    iterationTimes = iterationTimes + 1;
end

figure();
% 等高线
contour(X,Y,Psi,50);
shading interp;

function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
    
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:size(Zeta,1)-ystep,:);
        Zeta_New = [zeros(ystep,size(Zeta,2));Zeta_New];
    end
    
    if ystep < 0
        Zeta_New = Zeta_New(1-ystep:size(Zeta,1),:);
        Zeta_New = [Zeta_New;zeros(-ystep,size(Zeta,2))];
    end
end

function [Zeta_new,dZeta_max] = Iteration_Vorticity(Zeta,Psi,U,V,factor,h,mu)
    % 迭代涡量
    
    % Zeta 涡量矩阵
    % Psi 流函数矩阵
    % U,V 速度矩阵
    % factor 超松弛因子
    % h 步长
    % mu 动力粘性系数
    
    % 使用 mesh 函数得到的 X,Y 得到的坐标系为
    % i 行号从小到大代表直角坐标系中纵坐标从小到大
    % j 列号从小到大代表直角坐标系中横坐标从小到大
    
    % 初始化
    Zeta_new = zeros(size(Zeta));
    dZeta_max = 0;
    
    % 迭代 Zeta
    for i = 1:1:size(Zeta,1)
        for j = 1:1:size(Zeta,2)
            
            % 边界条件
            
            % 顶部的水平固壁边界
            if i == 1
                Zeta_new(i,j) = 2*(Psi(i,j)-Psi(i+1,j)+U(i,j)*h)/h^2;
                continue;
            % 底部的水平移动边界
            elseif i == size(Zeta,1)
                Zeta_new(i,j) = 2*(Psi(i-1,j)-Psi(i,j))/h^2;
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                Zeta_new(i,j) = 2*(Psi(i,j)-Psi(i,j+1))/h^2;
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(Zeta,2)
                Zeta_new(i,j) = 2*(Psi(i,j-1)-Psi(i,j))/h^2;
                continue;
            end
            
            % 超松弛迭代
            
            % 增量
            dZeta = (1-factor)*Zeta(i,j)+factor*((1-1/mu*h*U(i,j))*Zeta(i,j+1)+Zeta(i,j-1)+(1-1/mu*h*V(i,j))*Zeta(i+1,j)+Zeta(i-1,j))/(4-1/mu*h*(U(i,j)+V(i,j)));
            % 取增量绝对值的最大值
            dZeta_max = max([dZeta_max abs(dZeta)]);
            % 基点的新值
            Zeta_new(i,j) = Zeta(i,j) + dZeta;
        end
    end
end

function [Psi_new,dPsi_max] = Iteration_StreamFunction(Psi,Zeta,factor,h)
    % 迭代流函数
    
    % Psi 流函数矩阵
    % Zeta 涡量矩阵
    % factor 超松弛因子
    % h 步长
    
    % 使用 mesh 函数得到的 X,Y 得到的坐标系为
    % i 行号从小到大代表直角坐标系中纵坐标从小到大
    % j 列号从小到大代表直角坐标系中横坐标从小到大
    
    % 初始化
    Psi_new = zeros(size(Zeta));
    dPsi_max = 0;
    
    % 迭代 Zeta
    for i = 1:1:size(Psi,1)
        for j = 1:1:size(Psi,2)
            
            % 边界条件
            
            % 顶部的水平固壁边界
            if i == 1
                continue;
            % 底部的水平移动边界
            elseif i == size(Zeta,1)
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(Zeta,2)
                continue;
            end
            
            % 超松弛迭代
            
            % 增量
            dPsi = (1-factor)*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
            % 取增量绝对值的最大值
            dPsi_max = max([dPsi_max abs(dPsi)]);
            % 基点的新值
            Psi_new(i,j) = Psi(i,j) + dPsi;
        end
    end
end

function [U_new,V_new,dU_max,dV_max] = Iteration_Velocity(Psi,U,V,h)
    % 迭代速度
    
    % Psi 流函数矩阵
    % U,V 速度矩阵
    % h 步长
    
    % 使用 mesh 函数得到的 X,Y 得到的坐标系为
    % i 行号从小到大代表直角坐标系中纵坐标从小到大
    % j 列号从小到大代表直角坐标系中横坐标从小到大
    
    % ψ_(row+1,col) 公式语境下的 ψ_(i,j+1)
    Psi_right = MatrixTranslation(Psi,-1,0);
    % ψ_(row-1,col) 公式语境下的 ψ_(i,j-1)
    Psi_left = MatrixTranslation(Psi,1,0);
    % ψ_(row,col+1) 公式语境下的 ψ_(i+1,j)
    Psi_up = MatrixTranslation(Psi,0,-1);
    % ψ_(row,col-1) 公式语境下的 ψ_(i-1,j)
    Psi_down = MatrixTranslation(Psi,0,1);
    
    % 公式语境下的 u_(i,j+1/2)
    U_right = (Psi_right-Psi)/h;
    % 公式语境下的 u_(i,j-1/2)
    U_left = (Psi-Psi_left)/h;
    % 公式语境下的 v_(i+1/2,j)
    V_down = -(Psi_up-Psi)/h;
    % 公式语境下的 v_(i-1/2,j)
    V_up = -(Psi-Psi_down)/h;
    
    U_tmp = 1/2*(U_left+U_right);
    V_tmp = 1/2*(V_up+V_down);
    
    U_new = U;
    V_new = V;
    
    U_new(2:size(U,1)-1,2:size(U,2)-1) = U_tmp(2:size(U,1)-1,2:size(U,2)-1);
    V_new(2:size(V,1)-1,2:size(V,2)-1) = V_tmp(2:size(V,1)-1,2:size(V,2)-1);
    
    dU_max = max(max(abs(U_new-U)));
    dV_max = max(max(abs(V_new-V)));
end

% function [U_new,V_new,dU_max,dV_max] = Iteration_PressureGradient(Psi,U,V,h)
% 
% end
% function [U_new,V_new,dU_max,dV_max] = Iteration_PoissonEqTerm_Sp(Psi,U,V,h)
% 
% end

做出来是发散的
看了工作区,我觉得应该是 Zeta 的问题,虽然 Zeta 和 Psi 是交替迭代的,但是 Zeta 发散得更快

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第11张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第12张图片

后面发现我是把增量写错了……因为是增量,所以开头不是 (1-ω) ζ_(i,j)^n 而是 -ω ζ_(i,j)^n

            % 增量
            dZeta = -factor*Zeta(i,j)+factor*((1-1/mu*h*U(i,j))*Zeta(i,j+1)+Zeta(i,j-1)+(1-1/mu*h*V(i,j))*Zeta(i+1,j)+Zeta(i-1,j))/(4-1/mu*h*(U(i,j)+V(i,j)));   
            % 增量
            dPsi = factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));    

然后又发散了

在这里插入图片描述
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第13张图片

实在是不知道哪里有问题,看公式,如果公式没错的话,那么 Zeta 不用改,那就是速度有问题了

在这里插入图片描述

工作区里面的速度确实很怪

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第14张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第15张图片

速度的公式是

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第16张图片

从工作区看 Psi 也挺正常的,数量级一直很小,为什么会出错呢……

手算了一下,跟工作区还是比较符合的

 u(2,5/2) = (454.59-(-519.44))/0.005 = 194806
 u(2,3/2) = (-519.44-0)/0.005 = -103888
 u(2,2) = (194806+(-103888))/2 = 45459

之后又看到了超松弛的一个错误
我没有在迭代的时候实时更新……

正确的更新是

            % 基点的新值
            Zeta(i,j) = Zeta(i,j) + dZeta;
            % 基点的新值
            Psi(i,j) = Psi(i,j) + dPsi;

改了之后还是发散……
这次我觉得已经不需要看工作区了
或者说看头几次工作区是什么样子的我看不出什么东西

为了方便排错,我把矩阵平移的函数重新写为更和谐的形式

function [A] = MatrixTranslation(A,istep,jstep)
    % 将矩阵在行号增大的方向上平移 istep 个单位,在列号增大的方向上平移 jstep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(istep) >= size(A,1) || abs(jstep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    if istep > 0
        A = A(1:size(A,1)-istep,:);
        A = [zeros(istep,size(A,2));A];
    end
    
    if istep < 0
        A = A(1-istep:size(A,1),:);
        A = [A;zeros(-istep,size(A,2))];
    end
    
    if jstep > 0
        A = A(:,1:size(A,2)-jstep);
        A = [zeros(size(A,1),jstep) A];
    end
    
    if jstep < 0
        A = A(:,1-jstep:size(A,2));
        A = [A zeros(size(A,1),-jstep)];
    end
end

之前想的是在 x y 正方向上移动……现在已经看不懂了

一步步走,发现有一步中从 e2 跳到 e50 多,Zeta 的误差是第一个飙上去的

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第17张图片

朋友说是有可能公式中分母接近 0 的问题
因此我把一阶导的差分格式中的基点去掉了

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第18张图片

但是还是发散……

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 误差限度
error_limit = 1e-6;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 9999;
% 迭代次数
iterationTimes = 0;

% ---网格初始化---

% 步长
dx = 0.01;
dy = 0.01;

% 边界
x_border = [-0.5 0.5]';
y_border = [0 1]';

% 边界向量
x = x_border(1):dx:x_border(2);
y = y_border(1):dy:y_border(2);

% 求 X 和 Y 矩阵
% X 矩阵每一行都是 X 向量
% Y 矩阵每一列都是 Y 向量
% 和 XOY 坐标系的直觉相配 
[X,Y] = meshgrid(x,y);

% 涡量初始化
Zeta = zeros(size(X));
% 流函数初始化
Psi = zeros(size(X));
% 速度初始化
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = 1;
end

figure();

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));

% 循环迭代
while error > error_limit && iterationTimes < iterationTimes_limit
    
    % 迭代涡量
    [Zeta,dZeta_max] = Iteration_Vorticity(Zeta,Psi,U,V,factor,dx,1/Re);
    % 迭代流函数
    [Psi,dPsi_max] = Iteration_StreamFunction(Psi,Zeta,factor,dx);
    % 迭代速度
    [U,V,dU_max,dV_max] = Iteration_Velocity(Psi,U,V,dx);
    
    % 取最大误差
    error = max([dZeta_max dPsi_max dU_max dV_max]);
    % 迭代次数加 1
    iterationTimes = iterationTimes + 1;
    
    % 等高线
    contour(X,Y,Psi,50);
    shading interp;
end


function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
    
end

function [A] = MatrixTranslation(A,istep,jstep)
    % 将矩阵在行号增大的方向上平移 istep 个单位,在列号增大的方向上平移 jstep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(istep) >= size(A,1) || abs(jstep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    if istep > 0
        A = A(1:size(A,1)-istep,:);
        A = [zeros(istep,size(A,2));A];
    end
    
    if istep < 0
        A = A(1-istep:size(A,1),:);
        A = [A;zeros(-istep,size(A,2))];
    end
    
    if jstep > 0
        A = A(:,1:size(A,2)-jstep);
        A = [zeros(size(A,1),jstep) A];
    end
    
    if jstep < 0
        A = A(:,1-jstep:size(A,2));
        A = [A zeros(size(A,1),-jstep)];
    end
end

function [Zeta,dZeta_max] = Iteration_Vorticity(Zeta,Psi,U,V,factor,h,mu)
    % 迭代涡量
    
    % Zeta 涡量矩阵
    % Psi 流函数矩阵
    % U,V 速度矩阵
    % factor 超松弛因子
    % h 步长
    % mu 动力粘性系数
    
    % 使用 mesh 函数得到的 X,Y 得到的坐标系为
    % i 行号从小到大代表直角坐标系中纵坐标从小到大
    % j 列号从小到大代表直角坐标系中横坐标从小到大
    
    % 初始化
    dZeta_max = 0;
    
    % 迭代 Zeta
    for i = 1:1:size(Zeta,1)
        for j = 1:1:size(Zeta,2)
            
            % 边界条件
            
            % 顶部的水平固壁边界
            if i == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i+1,j)+U(i,j)*h)/h^2;
                continue;
            % 底部的水平移动边界
            elseif i == size(Zeta,1)
                Zeta(i,j) = 2*(Psi(i-1,j)-Psi(i,j))/h^2;
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i,j+1))/h^2;
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(Zeta,2)
                Zeta(i,j) = 2*(Psi(i,j-1)-Psi(i,j))/h^2;
                continue;
            end
            
            % 超松弛迭代
            
            % 增量
            dZeta = -factor*Zeta(i,j)+factor/4*((1-1/2*1/mu*h*U(i,j))*Zeta(i,j+1)+(1+1/2*1/mu*h*U(i,j))*Zeta(i,j-1)+(1-1/2*1/mu*h*V(i,j))*Zeta(i+1,j)+(1+1/2*1/mu*h*V(i,j))*Zeta(i-1,j));
            % 取增量绝对值的最大值
            dZeta_max = max([dZeta_max abs(dZeta)]);
            % 基点的新值
            Zeta(i,j) = Zeta(i,j) + dZeta;
        end
    end
end

function [Psi,dPsi_max] = Iteration_StreamFunction(Psi,Zeta,factor,h)
    % 迭代流函数
    
    % Psi 流函数矩阵
    % Zeta 涡量矩阵
    % factor 超松弛因子
    % h 步长
    
    % 使用 mesh 函数得到的 X,Y 得到的坐标系为
    % i 行号从小到大代表直角坐标系中纵坐标从小到大
    % j 列号从小到大代表直角坐标系中横坐标从小到大
    
    % 初始化
    dPsi_max = 0;
    
    % 迭代 Zeta
    for i = 1:1:size(Psi,1)
        for j = 1:1:size(Psi,2)
            
            % 边界条件
            
            % 顶部的水平固壁边界
            if i == 1
                continue;
            % 底部的水平移动边界
            elseif i == size(Zeta,1)
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(Zeta,2)
                continue;
            end
            
            % 超松弛迭代
            
            % 增量
            dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
            % 取增量绝对值的最大值
            dPsi_max = max([dPsi_max abs(dPsi)]);
            % 基点的新值
            Psi(i,j) = Psi(i,j) + dPsi;
        end
    end
end

function [U_new,V_new,dU_max,dV_max] = Iteration_Velocity(Psi,U,V,h)
    % 迭代速度
    
    % Psi 流函数矩阵
    % U,V 速度矩阵
    % h 步长
    
    % 使用 mesh 函数得到的 X,Y 得到的坐标系为
    % i 行号从小到大代表直角坐标系中纵坐标从小到大
    % j 列号从小到大代表直角坐标系中横坐标从小到大
    
    % ψ_(row+1,col) 公式语境下的 ψ_(i,j+1)
    Psi_up = MatrixTranslation(Psi,-1,0);
    % ψ_(row-1,col) 公式语境下的 ψ_(i,j-1)
    Psi_down = MatrixTranslation(Psi,1,0);
    % ψ_(row,col+1) 公式语境下的 ψ_(i+1,j)
    Psi_right = MatrixTranslation(Psi,0,-1);
    % ψ_(row,col-1) 公式语境下的 ψ_(i-1,j)
    Psi_left = MatrixTranslation(Psi,0,1);
    
    % 公式语境下的 u_(i,j+1/2)
    U_up = (Psi_up-Psi)/h;
    % 公式语境下的 u_(i,j-1/2)
    U_down = (Psi-Psi_down)/h;
    % 公式语境下的 v_(i+1/2,j)
    V_right = -(Psi_right-Psi)/h;
    % 公式语境下的 v_(i-1/2,j)
    V_left = -(Psi-Psi_left)/h;
    
    U_tmp = 1/2*(U_down+U_up);
    V_tmp = 1/2*(V_left+V_right);
    
    U_new = U;
    V_new = V;
    
    U_new(2:size(U,1)-1,2:size(U,2)-1) = U_tmp(2:size(U,1)-1,2:size(U,2)-1);
    V_new(2:size(V,1)-1,2:size(V,2)-1) = V_tmp(2:size(V,1)-1,2:size(V,2)-1);
    
    dU_max = max(max(abs(U_new-U)));
    dV_max = max(max(abs(V_new-V)));
end

% function [U_new,V_new,dU_max,dV_max] = Iteration_PressureGradient(Psi,U,V,h)
% 
% end
% function [U_new,V_new,dU_max,dV_max] = Iteration_PoissonEqTerm_Sp(Psi,U,V,h)
% 
% end

迭代前几步,contour(X,Y,Psi,50); 画图得到

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第19张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第20张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第21张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第22张图片

到这里已经发散得很厉害了

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第23张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第24张图片

之后就不用看了

看了很多遍了,实在觉得没有问题
我想想,SOR 涉及到三个变量
我现在的做法是,在 while 中对这三个变量分开迭代,每一个变量迭代的时候其他变量不变
如果我真的什么地方都没有错了的话,那就说明我不能在一个变量迭代的时候保持别人不变

合在一起求的代码

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 动力粘性系数
mu = 1/Re;
% 误差限度
error_limit = 1e-6;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 9999;
% 迭代次数
iterationTimes = 0;

% ---网格初始化---

% 步长
h = 0.01;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 涡量场 
Zeta = zeros(size(X));
Psi = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = 1;
end

figure();

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));

% 直到误差小于误差限度或者迭代次数超过迭代次数限度时才停止迭代
while error > error_limit && iterationTimes < iterationTimes_limit
    
    dZeta_max = 0;
    dPsi_max = 0;
    dU_max = 0;
    dV_max = 0;
    
    % 迭代
    for i = 1:1:size(Zeta,1)
        for j = 1:1:size(Zeta,2)
            
            % 边界条件
            
            % 顶部的水平固壁边界
            if i == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i+1,j)+U(i,j)*h)/h^2;
                continue;
            % 底部的水平移动边界
            elseif i == size(Zeta,1)
                Zeta(i,j) = 2*(Psi(i-1,j)-Psi(i,j))/h^2;
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i,j+1))/h^2;
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(Zeta,2)
                Zeta(i,j) = 2*(Psi(i,j-1)-Psi(i,j))/h^2;
                continue;
            end
            
            % 超松弛迭代
            
            % 增量
            dZeta = -factor*Zeta(i,j)+factor/4*((1-1/2*1/mu*h*U(i,j))*Zeta(i,j+1)+(1+1/2*1/mu*h*U(i,j))*Zeta(i,j-1)+(1-1/2*1/mu*h*V(i,j))*Zeta(i+1,j)+(1+1/2*1/mu*h*V(i,j))*Zeta(i-1,j));
            % 取增量绝对值的最大值
            dZeta_max = max([dZeta_max abs(dZeta)]);
            % 基点的新值
            Zeta(i,j) = Zeta(i,j) + dZeta;
            
            % 增量
            dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
            % 取增量绝对值的最大值
            dPsi_max = max([dPsi_max abs(dPsi)]);
            % 基点的新值
            Psi(i,j) = Psi(i,j) + dPsi;
            
            u_half_up = (Psi(i+1,j)-Psi(i,j))/h;
            u_half_down = (Psi(i,j)-Psi(i-1,j))/h;
            v_half_right = -(Psi(i,j+1)-Psi(i,j))/h;
            v_half_left = -(Psi(i,j)-Psi(i,j-1))/h;
            
            u_new = 1/2*(u_half_up+u_half_down);
            v_new = 1/2*(v_half_right+v_half_left);
            
            dU = u_new - U(i,j);
            dV = v_new - V(i,j);
            
            dU_max = max([dU_max abs(dU)]);
            dV_max = max([dV_max abs(dU)]);
            
            U(i,j) = u_new;
            V(i,j) = v_new;
        end
    end
    
    % 取最大误差
    error = max([dZeta_max dPsi_max dU_max dV_max]);
    % 迭代次数加 1
    iterationTimes = iterationTimes + 1;
    
end

% 等高线
contour(X,Y,Psi,50);
shading interp;


function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

结果还是发散

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第25张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第26张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第27张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第28张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第29张图片

我看别人对涡量使用 FTCS 是可以的
于是我也写了一个对涡量使用 FTCS 的

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 动力粘性系数
mu = 1/Re;
% 误差限度
error_limit = 1e-6;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 9999;
% 迭代次数
iterationTimes = 0;

% 网格步长
h = 0.01;
% 时间步长
dt = h^2/(4*mu);

% ---网格初始化---

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 涡量场 
Zeta = zeros(size(X));
Zeta_old = zeros(size(X));
Psi = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = 1;
end

figure();

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));

% 直到误差小于误差限度或者迭代次数超过迭代次数限度时才停止迭代
while error > error_limit && iterationTimes < iterationTimes_limit
    
    % 迭代
    for i = 1:1:size(X,1)
        for j = 1:1:size(X,2)
            
            % 边界条件
            
            % 速度和流函数的边界值保持不变,所以这里只有涡量的边界值更新
            
            % 顶部的水平固壁边界
            if i == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i+1,j)+U(i,j)*h)/h^2;
                continue;
            % 底部的水平移动边界
            elseif i == size(X,1)
                Zeta(i,j) = 2*(Psi(i-1,j)-Psi(i,j))/h^2;
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i,j+1))/h^2;
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(X,2)
                Zeta(i,j) = 2*(Psi(i,j-1)-Psi(i,j))/h^2;
                continue;
            end
            
            % 流函数 超松弛迭代
            
            dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
            
            error = max([error abs(dPsi)]);
            
            Psi(i,j) = Psi(i,j) + dPsi;
            
            % 速度
            
            U(i,j) = (Psi(i+1,j)-Psi(i-1,j))/(2*h);
            V(i,j) = -(Psi(i,j+1)-Psi(i,j-1))/(2*h);
            
            % 涡量 FTCS 格式
            U_dZeta_dx = U(i,j)*(Zeta_old(i,j+1)-Zeta_old(i,j-1))/(2*h);
            V_dZeta_dy = V(i,j)*(Zeta_old(i+1,j)-Zeta_old(i-1,j))/(2*h);
            mu_Nabla_Zeta = mu*(Zeta_old(i,j+1)+Zeta_old(i,j-1)+Zeta_old(i+1,j)+Zeta_old(i-1,j)-4*Zeta_old(i,j))/h^2;
            Zeta(i,j) = Zeta_old(i,j)+dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);

        end
    end
    
    Zeta_old = Zeta;
    
    % 迭代次数加 1
    iterationTimes = iterationTimes + 1;
end

% 等高线
contour(X,Y,Psi,50);
shading interp;


function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

但是还是发散……不懂

对各变量超松弛放在一起的方法加密网格,得到

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第30张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第31张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第32张图片

唉……这个趋势是真的看不出来什么东西

我反复看了别人的计算
别人都没有在迭代公式中计算速度

https://www.zhihu.com/question/52835189
https://curiosityfluids.com/2016/03/14/streamfunction-vorticity-solution-lid-driven-cavity-flow/

虽然我觉得没有差别,但是我还是做了一个

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 动力粘性系数
mu = 1/Re;
% 误差限度
error_limit = 1e-6;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 9999;
% 迭代次数
iterationTimes = 0;

% 顶板速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.005;
% 时间步长
dt = h^2/(4*mu);

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 涡量场
Zeta = zeros(size(X));
Psi = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = U_assume;
end

figure();

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));

% 直到误差小于误差限度或者迭代次数超过迭代次数限度时才停止迭代
while error > error_limit && iterationTimes < iterationTimes_limit
    
    % 涡量 FTCS 格式
    Zeta_right = MatrixTranslation(Zeta,0,1);
    Zeta_left = MatrixTranslation(Zeta,0,-1);
    Zeta_up = MatrixTranslation(Zeta,1,0);
    Zeta_down = MatrixTranslation(Zeta,-1,0);
    
    Psi_right = MatrixTranslation(Psi,0,1);
    Psi_left = MatrixTranslation(Psi,0,-1);
    Psi_up = MatrixTranslation(Psi,1,0);
    Psi_down = MatrixTranslation(Psi,-1,0);
    
    U_dZeta_dx = (Psi_up-Psi_down).*(Zeta_right-Zeta_left)/(4*h^2);
    V_dZeta_dy = -(Psi_right-Psi_left).*(Zeta_up-Zeta_down)/(4*h^2);
    mu_Nabla_Zeta = mu*(Zeta_right+Zeta_left+Zeta_up+Zeta_down-4*Zeta)/h^2;
    Zeta = Zeta + dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);
    
    % 涡量边界条件
    for i = 1:1:size(Zeta,1)
        for j = 1:1:size(Zeta,2)
            
            % 底部的水平移动边界
            if i == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i+1,j)+U_assume*h)/h^2;
                continue;
            % 顶部的水平固壁边界
            elseif i == size(Zeta,1)
                Zeta(i,j) = 2*(Psi(i-1,j)-Psi(i,j))/h^2;
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i,j+1))/h^2;
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(Zeta,2)
                Zeta(i,j) = 2*(Psi(i,j-1)-Psi(i,j))/h^2;
                continue;
            end
        end
    end
    
    % 流函数 普通迭代
    Psi_right = MatrixTranslation(Psi,0,1);
    Psi_left = MatrixTranslation(Psi,0,-1);
    Psi_up = MatrixTranslation(Psi,1,0);
    Psi_down = MatrixTranslation(Psi,-1,0);
    
    Psi_tmp = 1/4*(Psi_right+Psi_left+Psi_up+Psi_down+h^2*Zeta);
    error = max(max(abs(Psi_tmp-Psi)));
    Psi = Psi_tmp;
    
    iterationTimes = iterationTimes + 1;
end

% 等高线
contour(X,Y,Psi,50);
shading interp;



function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,istep,jstep)
    % 将矩阵在行号增大的方向上平移 istep 个单位,在列号增大的方向上平移 jstep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(istep) >= size(A,1) || abs(jstep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    if istep > 0
        A = A(1+istep:size(A,1),:);
        A = [A;zeros(istep,size(A,2))];
    end
    
    if istep < 0
        A = A(1:size(A,1)+istep,:);
        A = [zeros(-istep,size(A,2));A];
    end
    
    if jstep > 0
        A = A(:,1+jstep:size(A,2));
        A = [A zeros(size(A,1),jstep)];
    end
    
    if jstep < 0
        A = A(:,1:size(A,2)+jstep);
        A = [zeros(size(A,1),-jstep) A];
    end
end

仍然发散

用回超松弛

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 动力粘性系数
mu = 1/Re;
% 误差限度
error_limit = 1e-6;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 9999;
% 迭代次数
iterationTimes = 0;

% 网格步长
h = 0.01;
% 时间步长
dt = h^2/(4*mu);

% 顶板速度
U_assume = 1;

% ---网格初始化---

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 涡量场 
Zeta = zeros(size(X));
Psi = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = U_assume;
end

figure();

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));

% 直到误差小于误差限度或者迭代次数超过迭代次数限度时才停止迭代
while error > error_limit && iterationTimes < iterationTimes_limit
    
    % 涡量 FTCS 格式
    Zeta_right = MatrixTranslation(Zeta,0,1);
    Zeta_left = MatrixTranslation(Zeta,0,-1);
    Zeta_up = MatrixTranslation(Zeta,1,0);
    Zeta_down = MatrixTranslation(Zeta,-1,0);
    
    Psi_right = MatrixTranslation(Psi,0,1);
    Psi_left = MatrixTranslation(Psi,0,-1);
    Psi_up = MatrixTranslation(Psi,1,0);
    Psi_down = MatrixTranslation(Psi,-1,0);
    
    U_dZeta_dx = (Psi_up-Psi_down).*(Zeta_right-Zeta_left)/(4*h^2);
    V_dZeta_dy = -(Psi_right-Psi_left).*(Zeta_up-Zeta_down)/(4*h^2);
    mu_Nabla_Zeta = mu*(Zeta_right+Zeta_left+Zeta_up+Zeta_down-4*Zeta)/h^2;
    Zeta = Zeta + dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);
    
    % 迭代
    for i = 1:1:size(X,1)
        for j = 1:1:size(X,2)
            
            % 边界条件
            
            % 速度和流函数的边界值保持不变,所以这里只有涡量的边界值更新
            
            % 顶部的水平固壁边界
            if i == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i+1,j)+U_assume*h)/h^2;
                continue;
            % 底部的水平移动边界
            elseif i == size(X,1)
                Zeta(i,j) = 2*(Psi(i-1,j)-Psi(i,j))/h^2;
                continue;
            end
            
            % 左侧的竖直固壁边界
            if j == 1
                Zeta(i,j) = 2*(Psi(i,j)-Psi(i,j+1))/h^2;
                continue;
            % 右侧的竖直固壁边界
            elseif j == size(X,2)
                Zeta(i,j) = 2*(Psi(i,j-1)-Psi(i,j))/h^2;
                continue;
            end
            
            % 流函数 超松弛迭代
            
            dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
            
            error = max([error abs(dPsi)]);
            
            Psi(i,j) = Psi(i,j) + dPsi;
        end
    end
    
    % 迭代次数加 1
    iterationTimes = iterationTimes + 1;
    
    % 等高线
    contour(X,Y,Psi,50);
    shading interp;
end

% 等高线
contour(X,Y,Psi,50);
shading interp;



function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,istep,jstep)
    % 将矩阵在行号增大的方向上平移 istep 个单位,在列号增大的方向上平移 jstep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(istep) >= size(A,1) || abs(jstep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    if istep > 0
        A = A(1+istep:size(A,1),:);
        A = [A;zeros(istep,size(A,2))];
    end
    
    if istep < 0
        A = A(1:size(A,1)+istep,:);
        A = [zeros(-istep,size(A,2));A];
    end
    
    if jstep > 0
        A = A(:,1+jstep:size(A,2));
        A = [A zeros(size(A,1),jstep)];
    end
    
    if jstep < 0
        A = A(:,1:size(A,2)+jstep);
        A = [zeros(size(A,1),-jstep) A];
    end
end

感觉结果都是一样的

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第33张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第34张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第35张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第36张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第37张图片
[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第38张图片

我换了这么多格式,等高线图的趋势还是一样的,那肯定问题出在一个不随格式改变的地方
同时我觉得这个 FTCS 格式还不如我的超松弛快呢

搜到了别人包含可以跑的代码的文章
extension://bfdogplmndidlpjfhoijckpakkdjkkil/pdf/viewer.html?file=http%3A%2F%2Fakshaybatra.yolasite.com%2Fresources%2F2D%2520lid%2520diven%2520cavity%2520final%2520%2520report.pdf

%AuthorAKSHAY BATRA
%MAE 561 Computational Fluid Dynamics

%FINAL PROJECT - LID DRIVEN CAVITY FLOW IN RECATANGULAR CAVITY
%Due on Dec 12 2014.

%-------------------------------------------------------------------------
clear all
close all
clf;

nx=101;ny=101; nt=100000; re=1000; dt=0.001;% Settting the initial parameters
no_it=100000;% number of iterations

Beta=1.5;% relaxation factors
err=0.001;% parameter for SOR iteration

ds=.01;%dx=dy=ds
x=0:ds:1; y=0:ds:1;%dimensions of the cavity

t=0.0;
%-------------------------------------------------------------------------

phi=zeros(nx,ny); omega=zeros(nx,ny); % initializing the variables
u = zeros(nx,ny); v = zeros(nx,ny);

x2d=zeros(nx,ny); y2d=zeros(nx,ny);
b=zeros(nx,ny);p=zeros(nx,ny);pn=zeros(nx,ny);

w=zeros(nx,ny); %p-q/(nx-1),
%-------------------------------------------------------------------------
%Stream Function calculation

for t_step=1:nt % time steps starts
    for iter=1:no_it % streamfunction calculation
    
        w=phi; % by SOR iteration
        for i=2:nx-1;
        
            for j=2:ny-1
                phi(i,j)=0.25*Beta*(phi(i+1,j)+phi(i-1,j)+phi(i,j+1)+phi(i,j-1)+ds*ds*omega(i,j))+(1.0-Beta)*phi(i,j);
            
            end
        end
    
        Err=0.0;
        for i=1:nx
            
            for j=1:ny
                Err=Err+abs(w(i,j)-phi(i,j));
            
            end
        end
        
        if Err <= err,
            break;
        
        end % stop if iteration has converged
    end

    %--------------------------------------------------------------------------
    %boundary conditions for the Vorticity
    
    for i=2:nx-1
        for j=2:ny-1
        
            omega(i,1)=-2.0*phi(i,2)/(ds*ds); % bottom wall
            omega(i,ny)=-2.0*phi(i,ny-1)/(ds*ds)-2.0/ds; % top wall
            
            omega(1,j)=-2.0*phi(2,j)/(ds*ds); % right wall
            omega(nx,j)=-2.0*phi(nx-1,j)/(ds*ds); % left wall
        
        end
    end
    %--------------------------------------------------------------------------
    % RHS Calculation
    for i=2:nx-1;
        for j=2:ny-1 % compute
            w(i,j)=-0.25*((phi(i,j+1)-phi(i,j-1))*(omega(i+1,j)-omega(i-1,j))...
            -(phi(i+1,j)-phi(i-1,j))*(omega(i,j+1)-omega(i,j-1)))/(ds*ds)...
            +(1/re)*(omega(i+1,j)+omega(i-1,j)+omega(i,j+1)+omega(i,j-1)-4.0*omega(i,j))/(ds*ds);
        end
    end
    %--------------------------------------------------------------------------
    % Update the vorticity
    omega(2:nx-1,2:ny-1)=omega(2:nx-1,2:ny-1)+dt*w(2:nx-1,2:ny-1);
    t=t+dt; % increment the time
    for i=1:nx
        for j=1:ny
            x2d(i,j)=x(i);
            y2d(i,j)=y(j);
        end
    end
    %-------------------------------------------------------------------------
    %calculation of U and V
    for i = 2:nx-1
        for j = 2:ny-1
            u(i,j)=(phi(i,j+1)-phi(i,j))/(2*ds);
            v(i,j)=(phi(i+1,j)-phi(i,j))/(2*ds);
            u(:,ny) = 1;
            v(nx,:) =.02;
        end
    end
end
%--------------------------------------------------------------------------
%calculation of pressure
rhs=zeros(nx,ny);
for i=2:nx-1
    for j=2:ny-1
        rhs(i,j)=(((phi(i-1,j)-2*phi(i,j)+phi(i+1,j))/(ds*ds))...
        *((phi(i,j-1)-2*phi(i,j)+phi(i,j+1))/(ds*ds)))...
        - (phi(i+1,j+1)-phi(i+1,j-1)-phi(i-1,j+1)+phi(i-1,j-1))/(4*(ds*ds));
        p(i,j)=(.25*(pn(i+1,j)+pn(i-1,j) + pn(i,j+1)+pn(i,j-1))- 0.5*((rhs(i,j)*ds^2*ds^2)));
    end
    pn=p;
end
%--------------------------------------------------------------------------
% Visualization of the results
figure(1)
contourf(x2d,y2d,omega,[-3:1:-1 -0.5 0.0 0.5 1:1:5 ]),xlabel('nx'),...
ylabel('ny'),title('Vorticity');axis('square','tight');colorbar
title('Vorticity') % plot vorticity
figure(2)
contour(x2d,y2d,phi,[10^-10 10^-7 10^-5 10^-4 0.0100...
0.0300 0.0500 0.0700 0.0900 0.100 0.1100 0.1150 0.1175]),xlabel('nx'),

ylabel('ny'),title('stream function');axis('square','tight');colorbar %streamfunction
figure(3)
contourf(x2d,y2d,u),xlabel('nx'),ylabel('ny'),...

title('U-velocity');axis('square','tight');colorbar
figure(4)
contourf(x2d,y2d,v),xlabel('nx'),ylabel('ny'),...

title('V-velocity');axis('square','tight');colorbar
figure(5)
contourf(x2d,y2d,p,([-2.0:.01:2])),xlabel('nx'),ylabel('ny'),...

title('pressure');
figure(6)

quiver (x2d,y2d,u,v)...,xlabel('nx'),ylabel('ny'),title('VelocityVectour Plot'); axis([0 1 0 1]),axis('square')

%-------------------------------------------------------------------------
%I have been able to get the vorticies in the stream function contour at the corner but

%they are really small(for re 100). I have run the solution to 100,000 iteration at a
%time step of .001. It took 9-10 hours for the solution to compute.Then

%similarlyfor the Re 1000 took even longer but i was able to get the vorticies.

别人的结果是真的漂亮

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第39张图片

我发现我跟别人的思路主要不同就在于,别人是在每一个时间步内都要把流函数的迭代格式迭代若干不,一直到流函数收敛,而我是对于每一个时间步,只对流函数迭代一次
这是正确的,因为实际上迭代格式迭代到收敛才代表这个方程解出来了

照着他的写,我写出来就不一样……佛了

正确的是

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第40张图片

我写的是

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第41张图片

我在右侧比他少了一个负号
噢……我知道了,是我泰勒推错了

即使如此,我改了之后还是写出不出来,会卡在流函数的超松弛迭代那一步

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 动力粘性系数
mu = 1/Re;
% 误差限度
FTCS_error_limit = 1e-6;
SOR_error_limit = 1e-3;
% 误差
error = 9999;
% 迭代次数限度
iterationTimes_limit = 9999;
% 迭代次数
iterationTimes = 0;

% 题设顶部移动速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.01;
% 时间步长
dt = 0.001;
% 涡量最大迭代次数
MaxTimes = 1e5;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 涡量场 
Zeta = zeros(size(X));
Zeta_old = zeros(size(X));
Psi = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
for j = 1:1:size(X,2)
    U(1,j) = U_assume;
end

figure();

% 获得 SOR 迭代法最佳松弛因子
% factor = GetOptimalRelaxationFactor(size(Zeta,1),size(Zeta,2));
factor = 1.5;

% 开始求解
for times = 1:1:MaxTimes
    
    while true
        
        % 流函数 超松弛迭代
        
        % 内点
        
        dPsi_max = 0;
        
        for i = 2:1:size(Zeta,1)-1
            for j = 2:1:size(Zeta,2)-1
                
                % 增量
                dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
                % 取增量绝对值的最大值
                dPsi_max = max([dPsi_max abs(dPsi)]);
                % 基点的新值
                Psi(i,j) = Psi(i,j) + dPsi;
            end
        end
        
        % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
        if dPsi_max < SOR_error_limit
            break;
        end
    end
    
    % 涡量 FTCS 格式

    % 边界点(跳过角点)
    
    for j = 2:1:size(Zeta,2)-1
        
        Zeta(1,j) = 2*(-Psi(i+1,j)+U_assume*h)/h^2;
        Zeta(size(Zeta,1),j) = -2*Psi(i-1,j)/h^2;
    end
    for i = 2:1:size(Zeta,1)-1
        
        Zeta(i,1) = -2*Psi(i,j+1)/h^2;
        Zeta(i,size(Zeta,2)) = -2*Psi(i,j-1)/h^2;
    end
    
    % 内点
    
%     Zeta_right = MatrixTranslation(Zeta,0,1);
%     Zeta_left = MatrixTranslation(Zeta,0,-1);
%     Zeta_up = MatrixTranslation(Zeta,1,0);
%     Zeta_down = MatrixTranslation(Zeta,-1,0);
%     
%     Psi_right = MatrixTranslation(Psi,0,1);
%     Psi_left = MatrixTranslation(Psi,0,-1);
%     Psi_up = MatrixTranslation(Psi,1,0);
%     Psi_down = MatrixTranslation(Psi,-1,0);
%     
%     U_dZeta_dx = (Psi_up-Psi_down).*(Zeta_right-Zeta_left)/(4*h^2);
%     V_dZeta_dy = -(Psi_right-Psi_left).*(Zeta_up-Zeta_down)/(4*h^2);
%     mu_Nabla_Zeta = mu*(Zeta_right+Zeta_left+Zeta_up+Zeta_down-4*Zeta)/h^2;
%     Zeta_tmp = Zeta + dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);
%     Zeta(2:size(Zeta,1)-1,2:size(Zeta,2)-1) = Zeta_tmp(2:size(Zeta,1)-1,2:size(Zeta,2)-1);
    
    Zeta_old = Zeta;
    
    for i = 2:1:size(Zeta,1)-1
        for j = 2:1:size(Zeta,2)-1
            dZeta = dt*(-(Psi(i+1,j)-Psi(i-1,j))*(Zeta_old(i,j+1)-Zeta_old(i,j-1))/(4*h^2)...
                +(Psi(i,j+1)-Psi(i,j-1))*(Zeta_old(i+1,j)-Zeta_old(i-1,j))/(4*h^2)...
                +mu*(Zeta_old(i,j+1)+Zeta_old(i,j-1)+Zeta_old(i+1,j)+Zeta_old(i-1,j)-4*Zeta_old(i,j))/h^2);
            Zeta_old(i,j) = Zeta(i,j) + dZeta;
        end
    end
    
    Zeta(2:size(Zeta,1)-1,2:size(Zeta,2)-1) = Zeta_old(2:size(Zeta,1)-1,2:size(Zeta,2)-1);
end



% 等高线
contour(X,Y,Psi,50);
shading interp;



function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,istep,jstep)
    % 将矩阵在行号增大的方向上平移 istep 个单位,在列号增大的方向上平移 jstep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(istep) >= size(A,1) || abs(jstep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    if istep > 0
        A = A(1+istep:size(A,1),:);
        A = [A;zeros(istep,size(A,2))];
    end
    
    if istep < 0
        A = A(1:size(A,1)+istep,:);
        A = [zeros(-istep,size(A,2));A];
    end
    
    if jstep > 0
        A = A(:,1+jstep:size(A,2));
        A = [A zeros(size(A,1),jstep)];
    end
    
    if jstep < 0
        A = A(:,1:size(A,2)+jstep);
        A = [zeros(size(A,1),-jstep) A];
    end
end

照着答案写的 FTCS 也还是不行

    Zeta_old = Zeta;
    
    for i = 2:1:length-1
        for j = 2:1:size(Zeta,2)-1
            dZeta = -0.25*((Psi(i,j+1)-Psi(i,j-1))*(Zeta(i+1,j)-Zeta(i-1,j))...
            -(Psi(i+1,j)-Psi(i-1,j))*(Zeta(i,j+1)-Zeta(i,j-1)))/(h*h)...
            +mu*(Zeta(i+1,j)+Zeta(i-1,j)+Zeta(i,j+1)+Zeta(i,j-1)-4.0*Zeta(i,j))/(h*h);
            Zeta_old(i,j) = Zeta(i,j) + dt*dZeta;
        end
    end
    
    Zeta = Zeta_old;

再改,我直接全部都复制他的

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 10;
% 动力粘性系数
mu = 1/Re;
% 误差限度
SOR_error_limit = 1e-3;
% 迭代次数限度
FTCS_MaxTimes = 1e5;
SOR_MaxTimes = 1e5;

% 题设顶部移动速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.01;
% 时间步长
dt = 0.001;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 矩阵长度
length = size(X,1);

% 涡量场 
Zeta = zeros(size(X));
Psi = zeros(size(X));

tmp = zeros(size(X));

figure();

% 获得 SOR 迭代法最佳松弛因子
% factor = GetOptimalRelaxationFactor(length,length);
factor = 1.5;

% 开始求解
for FTCS_times = 1:1:FTCS_MaxTimes
    
    for SOR_times = 1:1:SOR_MaxTimes
        
%         % 流函数 超松弛迭代
%         
%         % 内点
%         
%         dPsi_max = 0;
%         
%         for i = 2:1:length-1
%             for j = 2:1:length-1
%                 
%                 % 增量
%                 dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
%                 % 取增量绝对值的最大值
%                 dPsi_max = max([dPsi_max abs(dPsi)]);
%                 % 基点的新值
%                 Psi(i,j) = Psi(i,j) + dPsi;
%             end
%         end
%         
%         % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
%         if dPsi_max < SOR_error_limit
%             break;
%         end
        
        tmp = Psi; % by SOR iteration
        for i=2:length-1;
        
            for j=2:length-1
                Psi(i,j)=0.25*factor*(Psi(i+1,j)+Psi(i-1,j)+Psi(i,j+1)+Psi(i,j-1)+h*h*Zeta(i,j))+(1.0-factor)*Psi(i,j);
            
            end
        end
    
        Err=0.0;
        for i=1:length
            
            for j=1:length
                Err=Err+abs(tmp(i,j)-Psi(i,j));
            
            end
        end
        
        if Err <= SOR_error_limit
            break;
        
        end % stop if iteration has converged
    end
    
    % 涡量 FTCS 格式

    % 边界点(跳过角点)
    
    for i = 2:1:length-1
        
        Zeta(i,1) = -2.0*Psi(i,2)/(h*h);
        Zeta(i,length) = -2.0*Psi(i,length-1)/(h*h)-2.0*U_assume/h;
    end
    for j = 2:1:length-1
        
        Zeta(1,j) = -2.0*Psi(2,j)/(h*h);
        Zeta(length,j) = -2.0*Psi(length-1,j)/(h*h);
    end
    
    % 内点
    
%     Zeta_right = MatrixTranslation(Zeta,1,0);
%     Zeta_left = MatrixTranslation(Zeta,-1,0);
%     Zeta_up = MatrixTranslation(Zeta,0,1);
%     Zeta_down = MatrixTranslation(Zeta,0,-1);
%     
%     Psi_right = MatrixTranslation(Psi,1,0);
%     Psi_left = MatrixTranslation(Psi,-1,0);
%     Psi_up = MatrixTranslation(Psi,0,1);
%     Psi_down = MatrixTranslation(Psi,0,-1);
%     
%     U_dZeta_dx = (Psi_up-Psi_down).*(Zeta_right-Zeta_left)/(4*h^2);
%     V_dZeta_dy = -(Psi_right-Psi_left).*(Zeta_up-Zeta_down)/(4*h^2);
%     mu_Nabla_Zeta = mu*(Zeta_right+Zeta_left+Zeta_up+Zeta_down-4*Zeta)/h^2;
%     Zeta_tmp = Zeta + dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);
%     Zeta(2:length-1,2:length-1) = Zeta_tmp(2:length-1,2:length-1);

    for i=2:length-1;
        for j=2:length-1 % compute
            tmp(i,j) = -0.25*((Psi(i,j+1)-Psi(i,j-1))*(Zeta(i+1,j)-Zeta(i-1,j))...
            -(Psi(i+1,j)-Psi(i-1,j))*(Zeta(i,j+1)-Zeta(i,j-1)))/(h*h)...
            +mu*(Zeta(i+1,j)+Zeta(i-1,j)+Zeta(i,j+1)+Zeta(i,j-1)-4.0*Zeta(i,j))/(h*h);
        end
    end
    Zeta(2:length-1,2:length-1) = Zeta(2:length-1,2:length-1)+dt*tmp(2:length-1,2:length-1);
end



% 等高线
contour(X,Y,Psi,50);
shading interp;



function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,xstep,ystep)
    % 将矩阵在 x 方向上平移 xstep 个单位,在 y 方向上平移 ystep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(xstep) >= size(A,1) || abs(ystep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    A = A;
    
    if xstep > 0
        A = A(:,1:size(A,2)-xstep);
        A = [zeros(size(A,1),xstep) A];
    end
    
    if xstep < 0
        A = A(:,1-xstep:size(A,2));
        A = [A zeros(size(A,1),-xstep)];
    end
    
    if ystep > 0
        A = A(1+ystep:size(A,1),:);
        A = [A;zeros(ystep,size(A,2))];
    end
    
    if ystep < 0
        A = A(1:size(A,1)+ystep,:);
        A = [zeros(-ystep,size(A,2));A];
    end
end

还是不行……太怪了
后面试出来是我雷诺数太小了,设了 Re = 1000 就好了

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第42张图片

更进一步,都用我自己写的

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 1000;
% 动力粘性系数
mu = 1/Re;
% 误差限度
SOR_error_limit = 1e-3;
% 迭代次数限度
FTCS_MaxTimes = 1e5;
SOR_MaxTimes = 1e5;

% 题设顶部移动速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.01;
% 时间步长
dt = 0.001;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 矩阵长度
length = size(X,1);

% 涡量场 
Zeta = zeros(size(X));
Psi = zeros(size(X));

tmp = zeros(size(X));

figure();

% 获得 SOR 迭代法最佳松弛因子
% factor = GetOptimalRelaxationFactor(length,length);
factor = 1.5;

% 开始求解
for FTCS_times = 1:1:FTCS_MaxTimes
    
    for SOR_times = 1:1:SOR_MaxTimes
        
        % 流函数 超松弛迭代
        
        % 内点
        
        dPsi_max = 0;
        
        for i = 2:1:length-1
            for j = 2:1:length-1
                
                % 增量
                dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
                % 取增量绝对值的最大值
                dPsi_max = max([dPsi_max abs(dPsi)]);
                % 基点的新值
                Psi(i,j) = Psi(i,j) + dPsi;
            end
        end
        
        % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
        if dPsi_max < SOR_error_limit
            break;
        end
    end
    
    % 涡量 FTCS 格式

    % 边界点(跳过角点)
    
    for i = 2:1:length-1
        
        Zeta(i,1) = -2.0*Psi(i,2)/(h*h);
        Zeta(i,length) = -2.0*Psi(i,length-1)/(h*h)-2.0*U_assume/h;
    end
    for j = 2:1:length-1
        
        Zeta(1,j) = -2.0*Psi(2,j)/(h*h);
        Zeta(length,j) = -2.0*Psi(length-1,j)/(h*h);
    end
    
    % 内点
    
    Zeta_right = MatrixTranslation(Zeta,1,0);
    Zeta_left = MatrixTranslation(Zeta,-1,0);
    Zeta_up = MatrixTranslation(Zeta,0,1);
    Zeta_down = MatrixTranslation(Zeta,0,-1);
    
    Psi_right = MatrixTranslation(Psi,1,0);
    Psi_left = MatrixTranslation(Psi,-1,0);
    Psi_up = MatrixTranslation(Psi,0,1);
    Psi_down = MatrixTranslation(Psi,0,-1);
    
    U_dZeta_dx = (Psi_up-Psi_down).*(Zeta_right-Zeta_left)/(4*h^2);
    V_dZeta_dy = -(Psi_right-Psi_left).*(Zeta_up-Zeta_down)/(4*h^2);
    mu_Nabla_Zeta = mu*(Zeta_right+Zeta_left+Zeta_up+Zeta_down-4*Zeta)/h^2;
    Zeta_tmp = Zeta + dt*(-U_dZeta_dx-V_dZeta_dy+mu_Nabla_Zeta);
    Zeta(2:length-1,2:length-1) = Zeta_tmp(2:length-1,2:length-1);

end



% 等高线
contourf(Y,X,Psi,15);
shading interp;



function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,xstep,ystep)
    % 将矩阵在 x 方向上平移 xstep 个单位,在 y 方向上平移 ystep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(xstep) >= size(A,1) || abs(ystep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    A = A;
    
    if xstep > 0
        A = A(:,1:size(A,2)-xstep);
        A = [zeros(size(A,1),xstep) A];
    end
    
    if xstep < 0
        A = A(:,1-xstep:size(A,2));
        A = [A zeros(size(A,1),-xstep)];
    end
    
    if ystep > 0
        A = A(1+ystep:size(A,1),:);
        A = [A;zeros(ystep,size(A,2))];
    end
    
    if ystep < 0
        A = A(1:size(A,1)+ystep,:);
        A = [zeros(-ystep,size(A,2));A];
    end
end

图片输出方式改一下就好了

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第43张图片

这个时候输出的 dPsi_max = 8.89e-10

如果我再回来使用两个超松弛,那依然是发散的

% 中山大学 19320053 廉嘉诚

clc;
clear;

% ---参数初始化---

% 雷诺数
Re = 1000;
% 动力粘性系数
mu = 1/Re;
% 误差限度
SOR_error_limit = 1e-3;
% 迭代次数限度
FTCS_MaxTimes = 1e5;
SOR_MaxTimes = 1e5;

% 题设顶部移动速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.01;
% 时间步长
dt = 0.001;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(x,y);

% 矩阵长度
length = size(X,1);

% 涡量场 
Zeta = zeros(size(X));
Psi = zeros(size(X));

tmp = zeros(size(X));

figure();

% 获得 SOR 迭代法最佳松弛因子
% factor = GetOptimalRelaxationFactor(length,length);
factor = 1.5;

% 开始求解
for FTCS_times = 1:1:FTCS_MaxTimes
    
    for SOR_times = 1:1:SOR_MaxTimes
        
        % 流函数 超松弛迭代
        
        % 内点
        
        dPsi_max = 0;
        
        for i = 2:1:length-1
            for j = 2:1:length-1
                
                % 增量
                dPsi = -factor*Psi(i,j)+factor/4*(Psi(i,j+1)+Psi(i,j-1)+Psi(i+1,j)+Psi(i-1,j)+h^2*Zeta(i,j));
                % 取增量绝对值的最大值
                dPsi_max = max([dPsi_max abs(dPsi)]);
                % 基点的新值
                Psi(i,j) = Psi(i,j) + dPsi;
            end
        end
        
        % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
        if dPsi_max < SOR_error_limit
            break;
        end
    end
    
    % 速度
    
    Psi_right = MatrixTranslation(Psi,1,0);
    Psi_left = MatrixTranslation(Psi,-1,0);
    Psi_up = MatrixTranslation(Psi,0,1);
    Psi_down = MatrixTranslation(Psi,0,-1);
    
    U_tmp = (Psi_up-Psi_down)/(2*h);
    V_tmp = -(Psi_right-Psi_left)/(2*h);
    
    U(2:length-1,2:length-1) = U_tmp(2:length-1,2:length-1);
    V(2:length-1,2:length-1) = V_tmp(2:length-1,2:length-1);
    
    % 涡量 超松弛迭代

    % 边界点(跳过角点)
    
    for i = 2:1:length-1
        
        Zeta(i,1) = -2.0*Psi(i,2)/(h*h);
        Zeta(i,length) = -2.0*Psi(i,length-1)/(h*h)-2.0*U_assume/h;
    end
    for j = 2:1:length-1
        
        Zeta(1,j) = -2.0*Psi(2,j)/(h*h);
        Zeta(length,j) = -2.0*Psi(length-1,j)/(h*h);
    end
    
    % 涡量
    
    % 内点
    
    for i = 2:1:length-1
        for j = 2:1:length-1
            
            dZeta = -factor*Zeta(i,j)...
                +factor/4*(...
                (1-1/2*1/mu*h*U(i,j))*Zeta(i+1,j)...
                +(1+1/2*1/mu*h*U(i,j))*Zeta(i-1,j)...
                +(1-1/2*1/mu*h*V(i,j))*Zeta(i,j+1)...
                +(1+1/2*1/mu*h*V(i,j))*Zeta(i,j-1));
            Zeta(i,j) = Zeta(i,j) + dZeta;
        end
    end
end



% 等高线
contourf(Y,X,Psi,15);
shading interp;



function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,xstep,ystep)
    % 将矩阵在 x 方向上平移 xstep 个单位,在 y 方向上平移 ystep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(xstep) >= size(A,1) || abs(ystep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    A = A;
    
    if xstep > 0
        A = A(:,1:size(A,2)-xstep);
        A = [zeros(size(A,1),xstep) A];
    end
    
    if xstep < 0
        A = A(:,1-xstep:size(A,2));
        A = [A zeros(size(A,1),-xstep)];
    end
    
    if ystep > 0
        A = A(1+ystep:size(A,1),:);
        A = [A;zeros(ystep,size(A,2))];
    end
    
    if ystep < 0
        A = A(1:size(A,1)+ystep,:);
        A = [zeros(-ystep,size(A,2));A];
    end
end

那就这样吧hhhh起码能算出来了,而且也有我自己做的

之后我灵光一闪,想到,既然一个超松弛要迭代到收敛才能进行下一步,那我是不是可以在一个循环体里面一前一后放两个超松弛,它们都收敛了再进入下一个循环,于是我写了这样的代码
可惜还是发散,那我就没辙了,理论知识不足

% 中山大学 19320053 廉嘉诚

clc;
clf;
clear;

% ---参数初始化---

% 流体密度
rho = 1e3;
% 雷诺数
Re = 3200;
% 动力粘性系数
mu = 1/Re;
% 误差限度
SOR_error_limit = 1e-3;
% 迭代次数限度
MaxTimes = 1e5;
SOR_MaxTimes = 1e5;

% 题设顶部移动速度
U_assume = 1;

% ---网格初始化---

% 步长
h = 0.01;
% 时间步长
dt = 0.001;

% 坐标系
x_border = [-0.5 0.5]';
y_border = [0 1]';
x = x_border(1):h:x_border(2);
y = y_border(1):h:y_border(2);
[X,Y] = meshgrid(y,x);

% 矩阵长度
length = size(X,1);

% 场 
Zeta = zeros(size(X));
Psi = zeros(size(X));
P = zeros(size(X));
PG = zeros([length 4]); % 1 左边界 2 右边界 3 下边界 4 上边界
Sp = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
U1 = zeros(size(X));
V1 = zeros(size(X));

% 缓存
tmp = zeros(size(X));

% 获得 SOR 迭代法最佳松弛因子
factor = GetOptimalRelaxationFactor(length,length);

% 开始求解
for times = 1:1:MaxTimes
    
    % 流函数 超松弛迭代

    for Psi_SOR_times = 1:1:SOR_MaxTimes
        
        % 内点
        
        dPsi_max = 0;
        
        for i = 2:1:length-1
            for j = 2:1:length-1
                
                % 增量
                dPsi = -factor*Psi(i,j)...
                    +factor/4*(...
                    Psi(i,j+1)...
                    +Psi(i,j-1)...
                    +Psi(i+1,j)...
                    +Psi(i-1,j)...
                    +h^2*Zeta(i,j));
                % 取增量绝对值的最大值
                dPsi_max = max([dPsi_max abs(dPsi)]);
                % 基点的新值
                Psi(i,j) = Psi(i,j) + dPsi;
            end
        end
        
        % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
        if dPsi_max < SOR_error_limit
            break;
        end
    end
    
    % 涡量 超松弛迭代

    % 速度
    
    Psi_right = MatrixTranslation(Psi,1,0);
    Psi_left = MatrixTranslation(Psi,-1,0);
    Psi_up = MatrixTranslation(Psi,0,1);
    Psi_down = MatrixTranslation(Psi,0,-1);
    
    U_tmp = (Psi_up-Psi_down)/(2*h);
    V_tmp = -(Psi_right-Psi_left)/(2*h);
    
    U(2:length-1,2:length-1) = U_tmp(2:length-1,2:length-1);
    V(2:length-1,2:length-1) = V_tmp(2:length-1,2:length-1);
    
    for Zeta_SOR_times = 1:1:SOR_MaxTimes
        
        dZeta_max = 0;
        
        % 边界点(跳过角点)
        
        for i = 2:1:length-1
            
            % 下侧
            dZeta = -2.0*Psi(i,2)/(h*h)+2.0*U_assume/h-Zeta(i,1);
            dZeta_max = max([dZeta_max abs(dZeta)]);
            Zeta(i,1) = Zeta(i,1) + dZeta;
            % 上侧
            dZeta = -2.0*Psi(i,length-1)/(h*h)-Zeta(i,length);
            dZeta_max = max([dZeta_max abs(dZeta)]);
            Zeta(i,length) = Zeta(i,length) + dZeta;
        end
        for j = 2:1:length-1
            
            % 左侧
            dZeta = -2.0*Psi(2,j)/(h*h)-Zeta(1,j);
            dZeta_max = max([dZeta_max abs(dZeta)]);
            Zeta(1,j) = Zeta(1,j) + dZeta;
            % 右侧
            dZeta = -2.0*Psi(length-1,j)/(h*h)-Zeta(length,j);
            dZeta_max = max([dZeta_max abs(dZeta)]);
            Zeta(length,j) = Zeta(length,j) + dZeta;
        end
        
        % 内点
        
        for i = 2:1:length-1
            for j = 2:1:length-1
            
                dZeta = -factor*Zeta(i,j)...
                    +factor/4*(...
                    (1-1/2*1/mu*h*U(i,j))*Zeta(i+1,j)...
                    +(1+1/2*1/mu*h*U(i,j))*Zeta(i-1,j)...
                    +(1-1/2*1/mu*h*V(i,j))*Zeta(i,j+1)...
                    +(1+1/2*1/mu*h*V(i,j))*Zeta(i,j-1));
                dZeta_max = max([dZeta_max abs(dZeta)]);
                Zeta(i,j) = Zeta(i,j) + dZeta;
            end
        end
        
        % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
        if dZeta_max < SOR_error_limit
            break;
        end
        
    end
end



% 流速
U = (Psi_up-Psi_down)/(2*h);
V = -(Psi_right-Psi_left)/(2*h);
        
% 压强梯度

% 边界点(跳过角点)

for i = 2:1:length-1
    
    % 下侧
    PG(i,3) = rho/h^2*mu*V(i,2);
    % 上侧
    PG(i,4) = rho/h^2*mu*V(i,length-1);;
end
for j = 2:1:length-1
    
    % 左侧
    PG(j,1) = rho/h^2*mu*U(2,j);
    % 右侧
    PG(j,2) = rho/h^2*mu*U(length-1,j);
end
        
% 压强 超松弛迭代

Psi_right_up = MatrixTranslation(Psi,1,1);
Psi_right_down = MatrixTranslation(Psi,1,-1);
Psi_left_up = MatrixTranslation(Psi,-1,1);
Psi_left_down = MatrixTranslation(Psi,-1,-1);

Sp = 2*rho/h^2*(...
    (Psi_right-2*Psi+Psi_left)*(Psi_up-2*Psi+Psi_down) ...
    -(Psi_right_up-Psi_right_down-Psi_left_up+Psi_left_down)/4);

for P_SOR_times = 1:1:SOR_MaxTimes
    
    dP_max = 0;
    
    for i = 1:1:length
        for j = 1:1:length
            
            % 跳过角点
            if i == 1 || i == length
                if j == 1 || j == length
                    continue;
                end
            end
            
            p1 = P(i,j);
            
            % 边界点
            
            % 下侧
            if j == 1
                p1 = P(i,2)-PG(i,3)*h;
                continue;
            % 上侧
            elseif j == length
                p1 = P(i,length-1)+PG(i,4)*h;
                continue;
            end
            
            % 左侧
            if i == 1
                p1 = P(2,j)-PG(j,1)*h;
                continue;
            % 右侧
            elseif i == length
                p1 = P(length-1,j)+PG(j,2)*h;
                continue;
            end
            
            % 内点

            p2 = (...
                P(i,j+1)...
                +P(i,j-1)...
                +P(i+1,j)...
                +P(i-1,j)...
                +h^2*Sp(i,j));
            
            dP = -factor*p1+factor/4*p2;
            
            % 取增量绝对值的最大值
            dP_max = max([dP_max abs(dP)]);
            % 基点的新值
            P(i,j) = P(i,j) + dP;
        end
    end
    
    % 直到误差小于一定限度,流函数的迭代方程收敛,才能进入涡量的迭代
    if dP_max < SOR_error_limit
        break;
    end
end




% 流函数等高线
figure(1);
clf;
contour(Y,X,Psi,Psi(floor(length/2),:));
shading interp;
hold on;
contour(Y,X,Psi,Psi(:,floor(6*length/7)));
hold off;
title('流函数等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;



% 涡量等高线
figure(2);
clf;
hold on;
contour(Y,X,Zeta,Zeta(floor(length/2),:));
hold off;
shading interp;
title('涡量等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;



% 水平速度等高线
figure(3);
clf;
hold on;
contour(Y,X,U,U(:,floor(length/5)));
contour(Y,X,U,U(:,floor(2*length/5)));
contour(Y,X,U,U(:,floor(3*length/5)));
contour(Y,X,U,U(:,floor(4*length/5)));
hold off;
shading interp;
title('水平速度等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;



% 竖直速度等高线
figure(4);
clf;
hold on;
contour(Y,X,V,V(floor(length/5),:));
contour(Y,X,V,V(floor(2*length/5),:));
contour(Y,X,V,V(floor(3*length/5),:));
contour(Y,X,V,V(floor(4*length/5),:));
hold off;
shading interp;
title('竖直速度等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;


% 压强等高线
figure(4);
clf;
hold on;
contour(Y,X,P,P(floor(length/2),:));
contour(Y,X,P,P(floor(length/4),:));
contour(Y,X,P,P(floor(3*length/4),:));
hold off;
shading interp;
title('压强等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;


function [factor] = GetOptimalRelaxationFactor(m,n)
    % 获得 SOR 法最佳松弛因子
    
    mu = 1/2*(cos(pi/m)+cos(pi/n));
    factor = 2*(1-(1-mu^2)^0.5)/mu^2;
end

function [A] = MatrixTranslation(A,xstep,ystep)
    % 将矩阵在 x 方向上平移 xstep 个单位,在 y 方向上平移 ystep 个单位
    % 这个平移不是仿射变换,只是元素相对位置的平移
    % 空余的位置用 0 补充
    
    % 移动距离超出矩阵长度的会得到全零
    if abs(xstep) >= size(A,1) || abs(ystep) >= size(A,2)
        A = zeros(size(A));
        return;
    end
    
    A = A;
    
    if xstep > 0
        A = A(:,1:size(A,2)-xstep);
        A = [zeros(size(A,1),xstep) A];
    end
    
    if xstep < 0
        A = A(:,1-xstep:size(A,2));
        A = [A zeros(size(A,1),-xstep)];
    end
    
    if ystep > 0
        A = A(1+ystep:size(A,1),:);
        A = [A;zeros(ystep,size(A,2))];
    end
    
    if ystep < 0
        A = A(1:size(A,1)+ystep,:);
        A = [zeros(-ystep,size(A,2));A];
    end
end

function [A] = DeleteElementForLargerSpace(A,n)
    % 输入一个行向量或者列向量,输出一个全部元素属于输入的列向量
    % 使得输出的列向量各元素之间的间隔变大
    % 共减少 n 个元素
    
    for times = 1:1:n
        
        length = size(A,1)*size(A,2);
        delta = zeros(length-1,1);
        
        for i = 1:1:length-1
            delta(i) = abs(A(i)-A(i+1));
        end
        
        [M,I] = min(delta);
        
        A_tmp = zeros(length-1,1);
        for i = 1:1:I-1
            A_tmp(i) = A(i);
        end
        for i = I+1:1:length
            A_tmp(i-1) = A(i);
        end
        A = A_tmp;
    end
end



3.2 画图

这个涡量图是真的难画得好看
如果单纯让 contourf 来选择等高线分布的话,那么等高线条数加到很大也画不出正中心的涡

% 涡量等高线
figure(2);
[M,c] = contourf(Y,X,Zeta,5000);
shading interp;
title('涡量等高线图');
axis('square','tight');
colorbar;

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第44张图片

但是如果直接取涡量场的一行作为等高线值的话,又会在一些地方特别密集,也很丑

% 涡量等高线
figure(2);
[M,c] = contourf(Y,X,Zeta,Zeta(floor(length/2),:));
shading interp;
title('涡量等高线图');
axis('square','tight');
colorbar;

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第45张图片

tmp1 = Zeta(floor(length/2),1:floor(2*length/5));
tmp2 = Zeta(floor(length/2),floor(2*length/5):floor(3*length/5));
tmp3 = Zeta(floor(length/2),floor(3*length/5):length);

tmp1 = DeleteElementForLargerSpace(tmp1,10);
tmp2 = tmp2';
tmp3 = DeleteElementForLargerSpace(tmp3,10);

tmp = [tmp1;tmp2;tmp3];

% 涡量等高线
figure(2);
[M,c] = contourf(Y,X,Zeta,tmp);
shading interp;
title('涡量等高线图');
axis('square','tight');
colorbar;
function [A] = DeleteElementForLargerSpace(A,n)
    % 输入一个行向量或者列向量,输出一个全部元素属于输入的列向量
    % 使得输出的列向量各元素之间的间隔变大
    % 共减少 n 个元素
    
    for times = 1:1:n
        
        length = size(A,1)*size(A,2);
        delta = zeros(length-1,1);
        
        for i = 1:1:length-1
            delta(i) = abs(A(i)-A(i+1));
        end
        
        [M,I] = min(delta);
        
        A_tmp = zeros(length-1,1);
        for i = 1:1:I-1
            A_tmp(i) = A(i);
        end
        for i = I+1:1:length
            A_tmp(i-1) = A(i);
        end
        A = A_tmp;
    end
end

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第46张图片

最后没有办法,只能放弃填充的计划了hhh

然后是流函数图中的小涡的问题

首先我觉得应该是看小涡的数量级,然后人为地按照那个数量级去画
噢,这里我改了边界条件,所以图的方向和上面的图不一样

% 流函数等高线
figure(1);
contour(Y,X,Psi,Psi(floor(length/2),:));
shading interp;
hold on;
contour(Y,X,Psi,[1e-7:1e-7:1e-6]);
contour(Y,X,Psi,[1e-6:1e-6:1e-5]);
contour(Y,X,Psi,[1e-5:1e-5:1e-4]);
contour(Y,X,Psi,[1e-4:1e-4:1e-3]);
hold off;
title('流函数等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第47张图片

后来果然发现人为做数量级是不可靠的,真正的等高线值还是要从原矩阵之中取

% 流函数等高线
figure(1);
contour(Y,X,Psi,Psi(floor(length/2),:));
shading interp;
hold on;
contour(Y,X,Psi,Psi(:,floor(6*length/7)));
hold off;
title('流函数等高线图');
xlabel('x');
ylabel('y');
axis('square','tight');
colorbar;

[计算流体力学][Matlab] 二维方腔环流情景下流函数涡量的超松弛迭代法计算_第48张图片

你可能感兴趣的:(Matlab,matlab,CFD,FTCS,SOR,流函数涡量法)