[计算流体力学] A,B,C 格式与蛙跳格式使用示例

题目

[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第1张图片

Matlab 代码

% 中山大学 2019级 廉

clear;
clc;
clf;

% 对流项系数
a = 1;
% x 的求解边界
x_border = 8;
% x 的步长
Delta_x = 0.05;
% x 的初始化边界
x_initialBorder = 1;

% Delta_x/Delta_t
dxdt = [0.5 1 2];

ODCE_DifferenceProcess(@DifferenceFormat_A,'A',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);
ODCE_DifferenceProcess(@DifferenceFormat_B,'B',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);
ODCE_DifferenceProcess(@DifferenceFormat_C,'C',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);
ODCE_DifferenceProcess(@DifferenceFormat_LeapFrog,'LeapFrog',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);


function [F] = SignedLog10AbsClamp99(F)
    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 [f_inital] = InitialCondition(x)
    % 初始条件
    
    if -1<=x && x<0
        f_inital = 1+x;
    elseif 0<= x && x<=1
        f_inital = 1-x;
    else
        f_inital = 0;
    end
end

function [F,X,T] = PreDifferenceProcess(x_border,x_initialBorder,Delta_x,Delta_t,InitialCondition)
    % 求差分格式之前需要的前处理
    
    % t 的最大步数 
    % 由 x_initialBorder 与 x_border 之间的空隙决定
    n_border = (x_border - x_initialBorder)/Delta_x + 1;
    % x 的向量
    X = -x_border : Delta_x : x_border;
    % t 的向量
    T = 0 : Delta_t : n_border * Delta_t;
    % 流场物理量矩阵初始化
    F = zeros(size(X,2),size(T,2));
    % 初始条件
    for i = 1:1:size(F,1)
        F(i,1) = InitialCondition(X(i));
    end
end

function [F] = DifferenceFormat_A(F,a,Delta_x,Delta_t)
    % A 格式
    % (F(i,n+1)-F(i,n))/Delta_t + a*(F(i+1,n)-F(i-1,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n) -a/2*Delta_t/Delta_x*(F(i+1,n)-F(i-1,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if i<2 
                tmp2 = 0;
            else
                tmp2 = F(i-1,n);
            end
            if i>size(F,1)-1 
                tmp1 = 0;
            else
                tmp1 = F(i+1,n);
            end
            F(i,n+1) = F(i,n) - a/2*Delta_t/Delta_x*(tmp1-tmp2);
        end
    end
end

function [F] = DifferenceFormat_B(F,a,Delta_x,Delta_t)
    % B 格式
    % (F(i,n+1)-F(i,n))/Delta_t + a*(F(i+1,n)-F(i,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n) -a/2*Delta_t/Delta_x*(F(i+1,n)-F(i,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if(i>size(F,1)-1)
                tmp1 = 0;
            else
                tmp1 = F(i+1,n);
            end
            F(i,n+1) = F(i,n) - a/2*Delta_t/Delta_x*(tmp1-F(i,n));
        end
    end
end

function [F] = DifferenceFormat_C(F,a,Delta_x,Delta_t)
    % C 格式
    % (F(i,n+1)-F(i,n))/Delta_t + a*(F(i,n)-F(i-1,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n) -a/2*Delta_t/Delta_x*(F(i,n)-F(i-1,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if i<2 
                tmp2 = 0;
            else
                tmp2 = F(i-1,n);
            end
            F(i,n+1) = F(i,n) - a/2*Delta_t/Delta_x*(F(i,n)-tmp2);
        end
    end
end

function [F] = DifferenceFormat_LeapFrog(F,a,Delta_x,Delta_t)
    % 蛙跳格式
    % (F(i,n+1)-F(i,n-1))/Delta_t + a*(F(i+1,n)-F(i-1,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n-1) -a/2*Delta_t/Delta_x*(F(i+1,n)-F(i-1,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if i<2
                tmp2 = 0;
            else
                tmp2 = F(i-1,n);
            end
            if i>size(F,1)-1 
                tmp1 = 0;
            else
                tmp1 = F(i+1,n);
            end
            if n<2 
                tmp3 = 0;
            else
                tmp3 = F(i,n-1);
            end
            F(i,n+1) = tmp3 - a/2*Delta_t/Delta_x*(tmp1-tmp2);
        end
    end
end

function [F] = ODCE_DifferenceProcess(DifferenceFormat,formatType,InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt)
    % 对于一维对流方程
    
    % 显示总体趋势
    
    figure();
    
    % 多个 dxdt 情况对比
    for i = 1:1:size(dxdt,2)
        
        Delta_t = Delta_x/dxdt(i);
        [F,X,T] = PreDifferenceProcess(x_border,x_initialBorder,Delta_x,Delta_t,@InitialCondition);
        [F] = DifferenceFormat(F,a,Delta_x,Delta_t);
        F_log = SignedLog10AbsClamp99(F);
        
        subplot(size(dxdt,2),1,i);
        mesh(T,X,F_log,'FaceColor','flat');
        if(i == 1)
            title("One-Dimensional Convection Equation ∂F/∂t+a*∂F/∂x = 0");
            subStr = sprintf("Difference Format %s\nF' = sign(F)*log10(clamp(abs(F),1,1e99))\na = 1, Δx = %.4f, Δt = %.4f",formatType,Delta_x,Delta_t);
            subtitle(subStr);
        else
            Str = sprintf("a = 1, Δx = %.4f, Δt = %.4f",Delta_x,Delta_t);
            title(Str);
        end
        xlabel("t(s)");
        ylabel("x(m)");
        zlabel("F'");
    end
   

    % 显示局部细节
    
    figure();
    
    % 缩放系数
    scale = [10 5];
    % X 的中心序号
    X_centerIndex = (size(X,2)-1)/2+1;
    
    % 多个缩放情况对比
    for i = 1:1:size(scale,2)
        
        % X 的缩放半长
        X_halfScaledLength = floor((size(X,2)-1)/2/scale(i));
        % 缩放 X
        X_scaled = X(X_centerIndex-X_halfScaledLength:X_centerIndex+X_halfScaledLength);
        % 缩放 T
        T_scaled = T(1:floor(size(T,2)/scale(i)));
        % 缩放 F
        F_scaled = F(X_centerIndex-X_halfScaledLength:X_centerIndex+X_halfScaledLength,1:floor(size(T,2)/scale(i)));
        
        subplot(size(scale,2),1,i);
        mesh(T_scaled,X_scaled,F_scaled,'FaceColor','flat');
        if(i == 1)
            title("One-Dimensional Convection Equation ∂F/∂t+a*∂F/∂x = 0");
            subStr = sprintf("Difference Format %s\na = 1, Δx = %.4f, Δt = %.4f\nscale = %.4f",formatType,Delta_x,Delta_t,scale(i));
            subtitle(subStr);
        else
            Str = sprintf("scale = %.4f",scale(i));
            title(Str);
        end
        xlabel("t(s)");
        ylabel("x(m)");
        zlabel("F");
    end
end

计算结果

[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第2张图片

具体的就自己跑吧

第二版

% 中山大学 2019级 廉

clear;
clc;
clf;

% 对流项系数
a = 1;
% x 的求解边界
x_border = 8;
% x 的步长
Delta_x = 0.05;
% x 的初始化边界
x_initialBorder = 1;

% Delta_x/Delta_t
dxdt = [0.5 1 2];

% 使用给定的差分格式,在给定的边界条件和初始条件下求解一维对流方程
% 并显示结果分析

% 由于误差累积,时间步越后的物理量误差越大。
% 为了清晰显示流场的解的趋势,这里使用 log 函数缩放整个流场,获得整个流场的解的数量级的分布。
% 由于流场的初始扰动的数量级很小,所以 log 缩放图上的点的可辨高度代表着误差大小,本质上该图只能显示误差的传播规律
% 为了显示初始扰动的传播规律,还需要从流场中取出包含初始扰动的一部分,放大来看。

ODCE_DifferenceProcess(@DifferenceFormat_A,'A',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);
ODCE_DifferenceProcess(@DifferenceFormat_B,'B',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);
ODCE_DifferenceProcess(@DifferenceFormat_C,'C',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);
ODCE_DifferenceProcess(@DifferenceFormat_LeapFrog,'LeapFrog',@InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt);


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 [f_inital] = InitialCondition(x)
    % 初始条件
    
    if -1<=x && x<0
        f_inital = 1+x;
    elseif 0<= x && x<=1
        f_inital = 1-x;
    else
        f_inital = 0;
    end
end

function [F,X,T] = PreDifferenceProcess(x_border,x_initialBorder,Delta_x,Delta_t,InitialCondition)
    % 求差分格式之前需要的前处理
    
    % t 的最大步数 
    % 由 x_initialBorder 与 x_border 之间的空隙决定
    n_border = (x_border - x_initialBorder)/Delta_x + 1;
    % x 的向量
    X = -x_border : Delta_x : x_border;
    % t 的向量
    T = 0 : Delta_t : n_border * Delta_t;
    % 流场物理量矩阵初始化
    F = zeros(size(X,2),size(T,2));
    % 初始条件
    for i = 1:1:size(F,1)
        F(i,1) = InitialCondition(X(i));
    end
end

function [F] = DifferenceFormat_A(F,a,Delta_x,Delta_t)
    % A 格式
    % (F(i,n+1)-F(i,n))/Delta_t + a*(F(i+1,n)-F(i-1,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n) -a/2*Delta_t/Delta_x*(F(i+1,n)-F(i-1,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if i<2 
                tmp2 = 0;
            else
                tmp2 = F(i-1,n);
            end
            if i>size(F,1)-1 
                tmp1 = 0;
            else
                tmp1 = F(i+1,n);
            end
            F(i,n+1) = F(i,n) - a/2*Delta_t/Delta_x*(tmp1-tmp2);
        end
    end
end

function [F] = DifferenceFormat_B(F,a,Delta_x,Delta_t)
    % B 格式
    % (F(i,n+1)-F(i,n))/Delta_t + a*(F(i+1,n)-F(i,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n) -a/2*Delta_t/Delta_x*(F(i+1,n)-F(i,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if(i>size(F,1)-1)
                tmp1 = 0;
            else
                tmp1 = F(i+1,n);
            end
            F(i,n+1) = F(i,n) - a/2*Delta_t/Delta_x*(tmp1-F(i,n));
        end
    end
end

function [F] = DifferenceFormat_C(F,a,Delta_x,Delta_t)
    % C 格式
    % (F(i,n+1)-F(i,n))/Delta_t + a*(F(i,n)-F(i-1,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n) -a/2*Delta_t/Delta_x*(F(i,n)-F(i-1,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if i<2 
                tmp2 = 0;
            else
                tmp2 = F(i-1,n);
            end
            F(i,n+1) = F(i,n) - a/2*Delta_t/Delta_x*(F(i,n)-tmp2);
        end
    end
end

function [F] = DifferenceFormat_LeapFrog(F,a,Delta_x,Delta_t)
    % 蛙跳格式
    % (F(i,n+1)-F(i,n-1))/Delta_t + a*(F(i+1,n)-F(i-1,n))/(2*Delta_x) = 0
    % => F(i,n+1) = F(i,n-1) -a/2*Delta_t/Delta_x*(F(i+1,n)-F(i-1,n))
    
    for n = 1:1:size(F,2)-1
        for i = 1:1:size(F,1)
            % 超出边界的可以取 0 而不损失精度
            if i<2
                tmp2 = 0;
            else
                tmp2 = F(i-1,n);
            end
            if i>size(F,1)-1 
                tmp1 = 0;
            else
                tmp1 = F(i+1,n);
            end
            if n<2 
                tmp3 = 0;
            else
                tmp3 = F(i,n-1);
            end
            F(i,n+1) = tmp3 - a/2*Delta_t/Delta_x*(tmp1-tmp2);
        end
    end
end

function [] = ODCE_DifferenceProcess(DifferenceFormat,formatType,InitialCondition,a,x_border,x_initialBorder,Delta_x,dxdt)
    % 使用给定的差分格式,在给定的边界条件和初始条件下求解一维对流方程
    % 并显示结果分析
    
    % 显示总体趋势
    
    figure();
    
    % 多个 dxdt 情况对比
    for i = 1:1:size(dxdt,2)
        
        Delta_t = Delta_x/dxdt(i);
        [F{i},X,T{i}] = PreDifferenceProcess(x_border,x_initialBorder,Delta_x,Delta_t,@InitialCondition);
        [F{i}] = DifferenceFormat(F{i},a,Delta_x,Delta_t);
        F_log = SignedLog10AbsClamp99(F{i});
        
        subplot(size(dxdt,2),1,i);
        mesh(T{i},X,F_log,'FaceColor','flat');
        if(i == 1)
            title("One-Dimensional Convection Equation ∂F/∂t+a*∂F/∂x = 0");
            subStr = sprintf("Difference Format %s\nF' = sign(F)*log10(clamp(abs(F),1,1e99))\na*Δt/Δx = %.4f",formatType,a/dxdt(i));
            subtitle(subStr);
        else
            Str = sprintf("a*Δt/Δx = %.4f",a/dxdt(i));
            title(Str);
        end
        xlabel("t(s)");
        ylabel("x(m)");
        zlabel("F'");
    end
   

    % 显示局部细节
    
    figure();
    
    % 缩放系数
    scale = [10 5];
    % X 的中心序号
    X_centerIndex = (size(X,2)-1)/2+1;
    
    % 多个 dxdt 情况, 多个缩放情况对比
    for i = 1:1:size(dxdt,2)
        
        figure();
        
        for j = 1:1:size(scale,2)
            
            % X 的缩放半长
            X_halfScaledLength = floor((size(X,2)-1)/2/scale(j));
            % 缩放 X
            X_scaled = X(X_centerIndex-X_halfScaledLength:X_centerIndex+X_halfScaledLength);
            % 缩放 T
            T_tmp = T{i};
            T_scaled = T_tmp(1:floor(size(T_tmp,2)/scale(j)));
            % 缩放 F
            F_tmp = F{i};
            F_scaled = F_tmp(X_centerIndex-X_halfScaledLength:X_centerIndex+X_halfScaledLength,1:floor(size(T_tmp,2)/scale(j)));
            
            subplot(size(scale,2),1,j);
            mesh(T_scaled,X_scaled,F_scaled,'FaceColor','flat');
            if(j == 1)
                title("One-Dimensional Convection Equation ∂F/∂t+a*∂F/∂x = 0");
                subStr = sprintf("Difference Format %s\na*Δt/Δx = %.4f\nscale = %.4f",formatType,a/dxdt(i),scale(j));
                subtitle(subStr);
            else
                Str = sprintf("scale = %.4f",scale(j));
                title(Str);
            end
            xlabel("t(s)");
            ylabel("x(m)");
            zlabel("F");
        end
    end
end

计算结果

[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第3张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第4张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第5张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第6张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第7张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第8张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第9张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第10张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第11张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第12张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第13张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第14张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第15张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第16张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第17张图片
[计算流体力学] A,B,C 格式与蛙跳格式使用示例_第18张图片

你可能感兴趣的:(计算流体力学,流体力学,Matlab,力学,差分)