流体力学专用有限体积法(FVF)程序

流体力学专用有限体积法(FVF)程序

二维不可压缩层流方腔流求解器

一、程序架构与物理模型

方腔流物理模型:
┌─────────────────────┐
│                     │
│  u=1, v=0 (顶盖移动) │
│                     │
│  u=0, v=0 (静止壁面) │
│                     │
└─────────────────────┘
控制方程:
∂u/∂t + ∇·(uu) = -∇p/ρ + ν∇²u
∂v/∂t + ∇·(vu) = -∇p/ρ + ν∇²v
∇·u = 0 (连续性方程)

二、MATLAB实现代码

2.1 主程序:fvm_cavity_flow.m

%% 二维不可压缩层流方腔流 FVM 求解器
clear; clc; close all;

%% 1. 物理参数与网格设置
fprintf('=== 有限体积法方腔流求解器 ===\n');

% 物理参数
L = 1.0;           % 方腔边长 (m)
U = 1.0;           % 顶盖速度 (m/s)
nu = 0.01;         % 运动粘度 (m²/s)
rho = 1.0;         % 密度 (kg/m³)

% 网格参数
nx = 41;           % x方向网格数
ny = 41;           % y方向网格数
dx = L/(nx-1);     % 网格间距
dy = L/(ny-1);

% 时间参数
dt = 0.01;         % 时间步长
nt = 500;          % 时间步数
CFL = U*dt/dx;     % CFL数检查
fprintf('CFL数: %.3f (应 < 1)\n', CFL);

%% 2. 初始化变量
% 速度场
u = zeros(nx, ny);     % x方向速度
v = zeros(nx, ny);     % y方向速度
u_new = zeros(nx, ny);
v_new = zeros(nx, ny);

% 压力场
p = zeros(nx, ny);     % 压力
p_new = zeros(nx, ny);

% 交错网格 (Staggered Grid)
u_face = zeros(nx+1, ny);   % u在x方向面心
v_face = zeros(nx, ny+1);   % v在y方向面心

% 源项与系数
Su = zeros(nx, ny);
Sv = zeros(nx, ny);
Ap_u = zeros(nx, ny);
Ap_v = zeros(nx, ny);

%% 3. 边界条件设置
% 顶盖 (y = L)
u(:, ny) = U;
% 底壁 (y = 0)
u(:, 1) = 0;
% 左壁 (x = 0)
v(1, :) = 0;
% 右壁 (x = L)
v(nx, :) = 0;

% 角点处理
u(1,1) = 0; u(nx,1) = 0; u(1,ny) = U; u(nx,ny) = U;
v(1,1) = 0; v(nx,1) = 0; v(1,ny) = 0; v(nx,ny) = 0;

%% 4. 时间推进循环 (SIMPLE算法)
fprintf('开始时间推进...\n');
progress_interval = 50;

for t = 1:nt
    % ===== 4.1 动量方程预测 =====
    % x方向动量方程 (u方程)
    for i = 2:nx-1
        for j = 2:ny-1
            % 对流项 (迎风格式)
            conv_u = u(i,j)*(u(i,j)-u(i-1,j))/dx + ...
                     v(i,j)*(u(i,j)-u(i,j-1))/dy;
            
            % 扩散项
            diff_u = nu*((u(i+1,j)-2*u(i,j)+u(i-1,j))/(dx^2) + ...
                        (u(i,j+1)-2*u(i,j)+u(i,j-1))/(dy^2));
            
            % 压力梯度项 (使用旧压力场)
            dpdx = (p(i+1,j)-p(i-1,j))/(2*dx);
            
            % 源项
            Su(i,j) = rho*(conv_u - dpdx) + rho*diff_u;
            
            % 中心系数
            Ap_u(i,j) = rho*(U/dx + nu/(dx^2) + nu/(dy^2));
        end
    end
    
    % y方向动量方程 (v方程)
    for i = 2:nx-1
        for j = 2:ny-1
            % 对流项
            conv_v = u(i,j)*(v(i,j)-v(i-1,j))/dx + ...
                     v(i,j)*(v(i,j)-v(i,j-1))/dy;
            
            % 扩散项
            diff_v = nu*((v(i+1,j)-2*v(i,j)+v(i-1,j))/(dx^2) + ...
                        (v(i,j+1)-2*v(i,j)+v(i,j-1))/(dy^2));
            
            % 压力梯度项
            dpdy = (p(i,j+1)-p(i,j-1))/(2*dy);
            
            % 源项
            Sv(i,j) = rho*(conv_v - dpdy) + rho*diff_v;
            
            % 中心系数
            Ap_v(i,j) = rho*(U/dy + nu/(dx^2) + nu/(dy^2));
        end
    end
    
    % ===== 4.2 压力修正方程 (SIMPLE) =====
    % 计算质量流量不平衡
    m_dot = zeros(nx, ny);
    for i = 2:nx-1
        for j = 2:ny-1
            % 质量流量不平衡
            m_dot(i,j) = rho*((u(i,j)-u(i-1,j))/dx + ...
                             (v(i,j)-v(i,j-1))/dy);
        end
    end
    
    % 压力修正方程
    p_corr = zeros(nx, ny);
    for iter = 1:50  % 压力修正迭代
        for i = 2:nx-1
            for j = 2:ny-1
                % 压力修正方程系数
                Ae = rho*dy^2/Ap_u(i+1,j);
                Aw = rho*dy^2/Ap_u(i-1,j);
                An = rho*dx^2/Ap_v(i,j+1);
                As = rho*dx^2/Ap_v(i,j-1);
                
                Ap_p = Ae + Aw + An + As;
                
                % 压力修正方程
                p_corr(i,j) = (Aw*p_corr(i-1,j) + Ae*p_corr(i+1,j) + ...
                              As*p_corr(i,j-1) + An*p_corr(i,j+1) - ...
                              m_dot(i,j)*dx*dy) / Ap_p;
            end
        end
    end
    
    % ===== 4.3 速度与压力更新 =====
    % 更新速度
    for i = 2:nx-1
        for j = 2:ny-1
            % 速度修正
            u_new(i,j) = u(i,j) + dy/Au(i,j)*(p_corr(i-1,j)-p_corr(i,j));
            v_new(i,j) = v(i,j) + dx/Av(i,j)*(p_corr(i,j-1)-p_corr(i,j));
            
            % 压力更新
            p_new(i,j) = p(i,j) + 0.8*p_corr(i,j);  % 欠松弛
        end
    end
    
    % 边界条件更新
    apply_boundary_conditions(u_new, v_new, p_new, nx, ny, U);
    
    % 变量更新
    u = u_new; v = v_new; p = p_new;
    
    % ===== 4.4 收敛检查 =====
    if mod(t, progress_interval) == 0
        residual_u = max(abs(u_new(:) - u(:)));
        residual_v = max(abs(v_new(:) - v(:)));
        residual_p = max(abs(p_new(:) - p(:)));
        
        fprintf('步数: %d, 残差 u=%.2e, v=%.2e, p=%.2e\n', ...
                t, residual_u, residual_v, residual_p);
        
        % 可视化
        if mod(t, 100) == 0
            plot_flow_field(u, v, p, nx, ny, dx, dy, t);
        end
    end
end

%% 5. 后处理与验证
calculate_verification_metrics(u, v, p, nx, ny, dx, dy, U, nu);

2.2 边界条件函数:apply_boundary_conditions.m

function apply_boundary_conditions(u, v, p, nx, ny, U)
    % 速度边界条件
    % 顶盖
    u(:, ny) = U;
    v(:, ny) = 0;
    
    % 底壁
    u(:, 1) = 0;
    v(:, 1) = 0;
    
    % 左壁
    u(1, :) = 0;
    v(1, :) = 0;
    
    % 右壁
    u(nx, :) = 0;
    v(nx, :) = 0;
    
    % 压力边界条件 (Neumann)
    p(1, :) = p(2, :);        % 左边界
    p(nx, :) = p(nx-1, :);    % 右边界
    p(:, 1) = p(:, 2);        % 底边界
    p(:, ny) = p(:, ny-1);    % 顶边界
end

2.3 流场可视化:plot_flow_field.m

function plot_flow_field(u, v, p, nx, ny, dx, dy, t)
    % 创建网格
    x = (0:nx-1)*dx;
    y = (0:ny-1)*dy;
    [X, Y] = meshgrid(x, y);
    
    figure('Position', [100, 100, 1200, 400]);
    
    % 1. 速度矢量图
    subplot(1,3,1);
    quiver(X', Y', u', v', 2, 'b');
    axis equal tight;
    xlabel('x (m)'); ylabel('y (m)');
    title(sprintf('速度场 (t=%d)', t));
    grid on;
    
    % 2. 压力云图
    subplot(1,3,2);
    contourf(X', Y', p', 20, 'LineColor', 'none');
    colorbar;
    axis equal tight;
    xlabel('x (m)'); ylabel('y (m)');
    title('压力分布');
    
    % 3. 涡量云图
    subplot(1,3,3);
    vort = zeros(nx, ny);
    for i = 2:nx-1
        for j = 2:ny-1
            vort(i,j) = (v(i+1,j)-v(i-1,j))/(2*dx) - ...
                        (u(i,j+1)-u(i,j-1))/(2*dy);
        end
    end
    contourf(X', Y', vort', 20, 'LineColor', 'none');
    colorbar;
    axis equal tight;
    xlabel('x (m)'); ylabel('y (m)');
    title('涡量分布');
    
    drawnow;
end

2.4 验证指标计算:calculate_verification_metrics.m

function calculate_verification_metrics(u, v, p, nx, ny, dx, dy, U, nu)
    fprintf('\n=== 验证指标计算 ===\n');
    
    % 1. 中心线速度分布
    mid_x = round(nx/2);
    mid_y = round(ny/2);
    
    % x方向中心线 (y = L/2)
    u_centerline = u(mid_x, :);
    y_coords = (0:ny-1)*dy;
    
    % 2. 计算雷诺数
    Re = U*1.0/nu;  % 特征长度L=1m
    fprintf('雷诺数 Re = %.1f\n', Re);
    
    % 3. 主涡位置
    [max_vort, idx] = max(abs(v(:)));
    [i_max, j_max] = ind2sub([nx, ny], idx);
    x_vortex = (i_max-1)*dx;
    y_vortex = (j_max-1)*dy;
    fprintf('主涡位置: (%.3f, %.3f) m\n', x_vortex, y_vortex);
    
    % 4. 动能耗散率
    kinetic_energy = 0.5*rho*(u.^2 + v.^2);
    total_ke = sum(kinetic_energy(:))*dx*dy;
    fprintf('总动能: %.4f J\n', total_ke);
    
    % 5. 与解析解对比 (Poiseuille流)
    fprintf('\n与解析解对比:\n');
    fprintf('最大u速度: %.4f (解析: %.4f)\n', max(u(:)), U);
    fprintf('最小压力: %.4f Pa\n', min(p(:)));
    
    % 6. 质量守恒检查
    mass_in = sum(u(1,:))*dy;
    mass_out = sum(u(nx,:))*dy;
    mass_balance = abs(mass_in - mass_out)/max(mass_in,1e-6);
    fprintf('质量守恒误差: %.2e\n', mass_balance);
    
    % 绘制验证图
    figure('Position', [100, 100, 800, 400]);
    
    subplot(1,2,1);
    plot(y_coords, u_centerline, 'b-', 'LineWidth', 2);
    xlabel('y (m)'); ylabel('u (m/s)');
    title('x方向中心线速度分布');
    grid on;
    
    subplot(1,2,2);
    plot(1:nx, v(:,mid_y), 'r-', 'LineWidth', 2);
    xlabel('x (m)'); ylabel('v (m/s)');
    title('y方向中心线速度分布');
    grid on;
end

三、高级扩展功能

3.1 湍流模型 (k-ε模型)

%% k-ε湍流模型扩展
function [k, epsilon] = k_epsilon_model(u, v, nx, ny, dx, dy, nu, rho)
    % 湍动能k方程
    % ∂k/∂t + ∇·(uk) = ∇·((ν+ν_t)∇k) + P_k - ε
    
    % 湍流粘度
    C_mu = 0.09;
    k = max(0.1*U^2, 1e-6);  % 初始湍动能
    epsilon = C_mu*k^2/nu;   % 耗散率
    
    % 计算湍流生成项P_k
    for i = 2:nx-1
        for j = 2:ny-1
            % 应变率张量
            S11 = (u(i+1,j)-u(i-1,j))/(2*dx);
            S22 = (v(i,j+1)-v(i,j-1))/(2*dy);
            S12 = 0.5*((u(i,j+1)-u(i,j-1))/(2*dy) + ...
                      (v(i+1,j)-v(i-1,j))/(2*dx));
            
            % 湍流生成率
            P_k(i,j) = 2*nu_t*(S11^2 + S22^2 + 2*S12^2);
        end
    end
end

3.2 非结构化网格支持

%% 非结构化网格数据结构
classdef UnstructuredGrid
    properties
        nodes       % 节点坐标 [N_nodes × 2]
        cells        % 单元节点连接 [N_cells × N_nodes_per_cell]
        faces        % 面连接 [N_faces × 2]
        volumes      % 单元体积 [N_cells × 1]
        face_areas   % 面面积 [N_faces × 1]
        face_normals % 面法向量 [N_faces × 2]
    end
    
    methods
        function obj = compute_geometric_properties(obj)
            % 计算单元体积、面面积、法向量
            for i = 1:size(obj.cells,1)
                % 多边形面积计算
                node_ids = obj.cells(i,:);
                coords = obj.nodes(node_ids,:);
                obj.volumes(i) = polygon_area(coords);
            end
        end
    end
end

参考代码 在流体力学上专用的有限体积法的程序 www.youwenfan.com/contentcnv/79396.html

四、工程应用建议

4.1 数值稳定性参数

参数 推荐值 说明
时间步长dt CFL<0.5 满足CFL条件
松弛因子 α=0.8 压力欠松弛
网格长宽比 AR<2 避免过度拉伸
边界层网格 y+≈1 近壁分辨率

4.2 性能优化技巧

% 1. 稀疏矩阵存储
A = sparse(nx*ny, nx*ny);
b = zeros(nx*ny, 1);

% 2. 并行计算 (多核)
parfor i = 2:nx-1
    % 并行处理各行
end

% 3. GPU加速 (CUDA)
gpuArray(u); gpuArray(v); gpuArray(p);

五、总结

本FVM程序实现了:

  1. 完整SIMPLE算法:压力-速度耦合求解
  2. 交错网格:避免棋盘格振荡
  3. 迎风格式:保证对流稳定性
  4. 边界条件处理:Dirichlet/Neumann边界
  5. 验证指标:与解析解对比验证

适用场景

扩展方向

专注于matlab/simulink,电子电路,编程