% 三维热传导模拟 - 含高斯热源与边界条件
clear; clc; close all;
%% ====================== 参数设置 ======================
params = struct(...
'Lx', 0.2, ... % X方向长度 (m)
'Ly', 0.1, ... % Y方向长度 (m)
'Lz', 0.05, ... % Z方向长度 (m)
'Nx', 50, ... % X方向网格数
'Ny', 30, ... % Y方向网格数
'Nz', 20, ... % Z方向网格数
'alpha', 1e-5, ... % 热扩散系数 (m²/s)
'k', 50, ... % 热导率 (W/m·K)
'T0', 20, ... % 初始温度 (°C)
'T_amb', 20, ... % 环境温度 (°C)
'totalTime', 100, ... % 总模拟时间 (s)
'dt', 0.5, ... % 时间步长 (s)
'Q0', 1e6, ... % 热源峰值强度 (W/m³)
'sourcePos', [0.1, 0.05, 0.025], ... % 热源中心位置
'sigma', 0.01, ... % 高斯热源标准差 (m)
'h_conv', 50, ... % 对流换热系数 (W/m²·K)
'outputInterval', 10 ...% 输出间隔 (时间步)
);
%% ====================== 网格生成 ======================
% 空间网格
x = linspace(0, params.Lx, params.Nx);
y = linspace(0, params.Ly, params.Ny);
z = linspace(0, params.Lz, params.Nz);
dx = x(2) - x(1);
dy = y(2) - y(1);
dz = z(2) - z(1);
% 时间网格
time = 0:params.dt:params.totalTime;
numSteps = numel(time);
% 创建三维网格坐标
[X, Y, Z] = meshgrid(x, y, z);
%% ====================== 初始化温度场 ======================
T = params.T0 * ones(size(X)); % 初始温度场
% 高斯热源函数
heat_source = @(x,y,z) params.Q0 * exp(-((x-params.sourcePos(1)).^2 + ...
(y-params.sourcePos(2)).^2 + ...
(z-params.sourcePos(3)).^2) / ...
(2*params.sigma^2));
%% ====================== 边界条件设置 ======================
% 边界类型标识 (1: Dirichlet, 2: Neumann, 3: Convection)
boundary = struct(...
'xmin', 1, ... % x=0: 固定温度
'xmax', 3, ... % x=Lx: 对流换热
'ymin', 2, ... % y=0: 绝热
'ymax', 2, ... % y=Ly: 绝热
'zmin', 2, ... % z=0: 绝热
'zmax', 3 ... % z=Lz: 对流换热
);
% 边界值
boundaryValue = struct(...
'xmin', params.T0, ...
'xmax', params.T_amb, ...
'ymin', 0, ...
'ymax', 0, ...
'zmin', 0, ...
'zmax', params.T_amb ...
);
%% ====================== 可视化设置 ======================
fig = figure('Color', 'w', 'Position', [100, 100, 1200, 800]);
% 温度场切片可视化
subplot(2,3,[1,2,4,5]);
sliceHandle = slice(X, Y, Z, T, params.Lx/2, params.Ly/2, params.Lz/2);
set(sliceHandle, 'EdgeColor', 'none');
shading interp;
colormap jet;
colorbar;
caxis([params.T0, params.T0 + 300]); % 固定颜色范围
xlabel('X (m)'); ylabel('Y (m)'); zlabel('Z (m)');
title(sprintf('温度分布 (t = %.1f s)', 0));
axis tight equal;
view(45,30);
rotate3d on;
% 热源位置标记
hold on;
sourcePlot = scatter3(params.sourcePos(1), params.sourcePos(2), params.sourcePos(3), ...
150, 'ro', 'filled');
% 温度监测点
monitorPos = [0.05, 0.03, 0.01; % 近热源点
0.15, 0.05, 0.025; % 远端点
0.1, 0.05, 0.04]; % 上表面点
monitorLabels = {'A', 'B', 'C'};
monitorPlot = scatter3(monitorPos(:,1), monitorPos(:,2), monitorPos(:,3), ...
100, 'kh', 'filled');
text(monitorPos(1,1)+0.005, monitorPos(1,2), monitorPos(1,3), 'A', 'FontSize', 12);
text(monitorPos(2,1)+0.005, monitorPos(2,2), monitorPos(2,3), 'B', 'FontSize', 12);
text(monitorPos(3,1)+0.005, monitorPos(3,2), monitorPos(3,3), 'C', 'FontSize', 12);
% 温度曲线
subplot(2,3,3);
tempPlot = plot(0, [params.T0, params.T0, params.T0], 'LineWidth', 2);
legend('A', 'B', 'C', 'Location', 'northwest');
xlabel('时间 (s)'); ylabel('温度 (°C)');
title('监测点温度变化');
grid on;
% 热通量分布
subplot(2,3,6);
[~, midZ] = min(abs(z - params.Lz/2)); % 中间Z平面
heatFluxPlot = imagesc(x, y, zeros(size(X(:,:,midZ))));
axis equal tight;
xlabel('X (m)'); ylabel('Y (m)');
title('热通量分布 (|q|)');
colorbar;
set(gca, 'YDir', 'normal');
% 视频记录
videoFile = VideoWriter('3d_heat_conduction.mp4', 'MPEG-4');
videoFile.FrameRate = 10;
open(videoFile);
%% ====================== 主计算循环 ======================
% 存储监测点温度
monitorTemps = zeros(numSteps, size(monitorPos,1));
monitorTemps(1,:) = params.T0;
% 计算稳定性条件
dt_max = 1/(2*params.alpha*(1/dx^2 + 1/dy^2 + 1/dz^2));
if params.dt > 0.9*dt_max
warning('时间步长可能不稳定,建议小于 %.4f s', dt_max);
params.dt = 0.8*dt_max;
end
for n = 2:numSteps
currentTime = time(n);
% 创建新温度场副本
T_new = T;
% 应用热源
Q = heat_source(X, Y, Z);
T_new = T_new + Q * params.dt / (params.k * params.alpha);
% 三维热传导计算 (有限差分法)
for i = 2:params.Ny-1
for j = 2:params.Nx-1
for k = 2:params.Nz-1
% 拉普拉斯项 (二阶中心差分)
d2Tdx2 = (T(i, j+1, k) - 2*T(i, j, k) + T(i, j-1, k)) / dx^2;
d2Tdy2 = (T(i+1, j, k) - 2*T(i, j, k) + T(i-1, j, k)) / dy^2;
d2Tdz2 = (T(i, j, k+1) - 2*T(i, j, k) + T(i, j, k-1)) / dz^2;
% 时间积分 (显式欧拉法)
T_new(i, j, k) = T(i, j, k) + params.alpha * params.dt * ...
(d2Tdx2 + d2Tdy2 + d2Tdz2);
end
end
end
% 应用边界条件
T_new = applyBoundaryConditions(T_new, boundary, boundaryValue, dx, dy, dz, params);
% 更新温度场
T = T_new;
% 记录监测点温度
for m = 1:size(monitorPos,1)
[~, idxX] = min(abs(x - monitorPos(m,1)));
[~, idxY] = min(abs(y - monitorPos(m,2)));
[~, idxZ] = min(abs(z - monitorPos(m,3)));
monitorTemps(n, m) = T(idxY, idxX, idxZ);
end
% 更新可视化
if mod(n, params.outputInterval) == 0
% 更新切片图
set(sliceHandle, 'CData', T);
title(subplot(2,3,[1,2,4,5]), sprintf('温度分布 (t = %.1f s)', currentTime));
% 更新温度曲线
set(tempPlot(1), 'XData', time(1:n), 'YData', monitorTemps(1:n,1));
set(tempPlot(2), 'XData', time(1:n), 'YData', monitorTemps(1:n,2));
set(tempPlot(3), 'XData', time(1:n), 'YData', monitorTemps(1:n,3));
% 更新热通量图
[qx, qy, qz] = gradient(T, dy, dx, dz);
qx = -params.k * qx;
qy = -params.k * qy;
qz = -params.k * qz;
q_mag = sqrt(qx.^2 + qy.^2 + qz.^2);
set(heatFluxPlot, 'CData', q_mag(:,:,midZ));
drawnow;
% 记录视频帧
writeVideo(videoFile, getframe(fig));
end
end
% 关闭视频文件
close(videoFile);
disp('模拟完成,视频已保存为 3d_heat_conduction.mp4');
%% ====================== 后处理分析 ======================
% 最终温度分布分析
figure('Color', 'w', 'Position', [100, 100, 1000, 800]);
% 三维等温面
subplot(2,2,1);
isovalue = params.T0 + 0.7*(max(T(:)) - params.T0);
p = patch(isosurface(X, Y, Z, T, isovalue));
isonormals(X, Y, Z, T, p);
set(p, 'FaceColor', 'red', 'EdgeColor', 'none');
daspect([1 1 1]);
view(3);
axis tight;
camlight;
lighting gouraud;
title(sprintf('等温面 T = %.1f °C', isovalue));
xlabel('X'); ylabel('Y'); zlabel('Z');
colorbar;
% 温度曲线对比
subplot(2,2,2);
plot(time, monitorTemps, 'LineWidth', 2);
xlabel('时间 (s)'); ylabel('温度 (°C)');
title('监测点温度变化曲线');
legend(monitorLabels, 'Location', 'northwest');
grid on;
% 沿X轴温度分布
subplot(2,2,3);
[~, midY] = min(abs(y - params.Ly/2));
[~, midZ] = min(abs(z - params.Lz/2));
plot(x, squeeze(T(midY, :, midZ)), 'LineWidth', 2);
xlabel('X (m)'); ylabel('温度 (°C)');
title(sprintf('Y=%.3f, Z=%.3f 处温度分布', y(midY), z(midZ)));
grid on;
% 热通量分布
subplot(2,2,4);
[qx, qy, qz] = gradient(T, dy, dx, dz);
qx = -params.k * qx;
qy = -params.k * qy;
qz = -params.k * qz;
q_mag = sqrt(qx.^2 + qy.^2 + qz.^2);
imagesc(x, y, q_mag(:,:,midZ));
axis equal tight;
xlabel('X (m)'); ylabel('Y (m)');
title('最终热通量分布 (|q|)');
colorbar;
set(gca, 'YDir', 'normal');
%% ====================== 边界条件应用函数 ======================
function T = applyBoundaryConditions(T, boundary, boundaryValue, dx, dy, dz, params)
[Ny, Nx, Nz] = size(T);
% X方向边界 (j=1和j=Nx)
for i = 1:Ny
for k = 1:Nz
% xmin边界 (j=1)
if boundary.xmin == 1 % Dirichlet
T(i, 1, k) = boundaryValue.xmin;
elseif boundary.xmin == 2 % Neumann (绝热)
T(i, 1, k) = T(i, 2, k);
elseif boundary.xmin == 3 % Convection
h = params.h_conv;
k_mat = params.k;
T_inf = boundaryValue.xmin;
T(i, 1, k) = (k_mat*T(i, 2, k) + h*dx*T_inf) / (k_mat + h*dx);
end
% xmax边界 (j=Nx)
if boundary.xmax == 1 % Dirichlet
T(i, Nx, k) = boundaryValue.xmax;
elseif boundary.xmax == 2 % Neumann (绝热)
T(i, Nx, k) = T(i, Nx-1, k);
elseif boundary.xmax == 3 % Convection
h = params.h_conv;
k_mat = params.k;
T_inf = boundaryValue.xmax;
T(i, Nx, k) = (k_mat*T(i, Nx-1, k) + h*dx*T_inf) / (k_mat + h*dx);
end
end
end
% Y方向边界 (i=1和i=Ny)
for j = 1:Nx
for k = 1:Nz
% ymin边界 (i=1)
if boundary.ymin == 1 % Dirichlet
T(1, j, k) = boundaryValue.ymin;
elseif boundary.ymin == 2 % Neumann (绝热)
T(1, j, k) = T(2, j, k);
elseif boundary.ymin == 3 % Convection
h = params.h_conv;
k_mat = params.k;
T_inf = boundaryValue.ymin;
T(1, j, k) = (k_mat*T(2, j, k) + h*dy*T_inf) / (k_mat + h*dy);
end
% ymax边界 (i=Ny)
if boundary.ymax == 1 % Dirichlet
T(Ny, j, k) = boundaryValue.ymax;
elseif boundary.ymax == 2 % Neumann (绝热)
T(Ny, j, k) = T(Ny-1, j, k);
elseif boundary.ymax == 3 % Convection
h = params.h_conv;
k_mat = params.k;
T_inf = boundaryValue.ymax;
T(Ny, j, k) = (k_mat*T(Ny-1, j, k) + h*dy*T_inf) / (k_mat + h*dy);
end
end
end
% Z方向边界 (k=1和k=Nz)
for i = 1:Ny
for j = 1:Nx
% zmin边界 (k=1)
if boundary.zmin == 1 % Dirichlet
T(i, j, 1) = boundaryValue.zmin;
elseif boundary.zmin == 2 % Neumann (绝热)
T(i, j, 1) = T(i, j, 2);
elseif boundary.zmin == 3 % Convection
h = params.h_conv;
k_mat = params.k;
T_inf = boundaryValue.zmin;
T(i, j, 1) = (k_mat*T(i, j, 2) + h*dz*T_inf) / (k_mat + h*dz);
end
% zmax边界 (k=Nz)
if boundary.zmax == 1 % Dirichlet
T(i, j, Nz) = boundaryValue.zmax;
elseif boundary.zmax == 2 % Neumann (绝热)
T(i, j, Nz) = T(i, j, Nz-1);
elseif boundary.zmax == 3 % Convection
h = params.h_conv;
k_mat = params.k;
T_inf = boundaryValue.zmax;
T(i, j, Nz) = (k_mat*T(i, j, Nz-1) + h*dz*T_inf) / (k_mat + h*dz);
end
end
end
end
最新发布