[关闭]
@why-math 2015-04-08T20:32:53.000000Z 字数 3888 阅读 9525

差分法求解一维热传导方程matlab程序

teaching matlab


uta2ux2=0,u(0,t)=0,u(1,t)=0,u(x,0)=e(x0.25)20.01+0.1sin(20πx).

其中系数a=1. 上述模型的Matlab代码如下:

  1. function pde = model_data()
  2. % MODEL_DATA 模型数据
  3. pde = struct('u_initial',@u_initial,'u_left',@u_left,...
  4. 'u_right',@u_right,'f',@f,'time_grid',@time_grid,...
  5. 'space_grid',@space_grid,'a',@a);
  6. function [T,tau] = time_grid(NT)
  7. T = linspace(0,0.1,NT+1);
  8. tau = 0.1/NT;
  9. end
  10. function [X,h] = space_grid(NS)
  11. X = linspace(0,1,NS+1)';
  12. h = 1/NS;
  13. end
  14. function u = u_initial(x)
  15. u = exp(-(x-0.025).^2/0.01)+0.1*sin(20*pi*x);
  16. end
  17. function u = u_left(t)
  18. u = zeros(size(t));
  19. end
  20. function u = u_right(t)
  21. u = zeros(size(t));
  22. end
  23. function f = f(x,t)
  24. f = zeros(size(x));
  25. end
  26. function a = a()
  27. a = 1;
  28. end
  29. end
  1. %% 一维热传导方程有限差分方法主测试脚本 main_test.m
  2. % 依次测试:
  3. % 向前差分
  4. % 向后差分
  5. % 六点对称格式
  6. % 并可视化数值计算结果。
  7. %
  8. % 作者:魏华祎 <weihuayi@xtu.edu.cn>
  9. pde = model_data(); %模型数据结构体
  10. % 向前差分格式
  11. [X,T,U] = heat_equation_fd1d(100,10000,pde,'forward');
  12. showvarysolution(X,T,U);% 以随时间变化方式显示数值解
  13. showsolution(X,T,U); % 以二元函数方式显示数值解
  14. % 向后差分格式
  15. [X,T,U] = heat_equation_fd1d(100,100,pde,'backward');
  16. showvarysolution(X,T,U);% 以随时间变化方式显示数值解
  17. showsolution(X,T,U); % 以二元函数方式显示数值解
  18. % 六点对称格式,即 Crank-Nicholson 格式
  19. [X,T,U] = heat_equation_fd1d(100,100,pde,'crank-nicholson');
  20. showvarysolution(X,T,U);% 以随时间变化方式显示数值解
  21. showsolution(X,T,U); % 以二元函数方式显示数值解
  1. function [X,T,U] = heat_equation_fd1d(NS,NT,pde,method)
  2. %% HEAT_EQUATION_FD1D 利用有限差分方法计算一维热传导方程
  3. %
  4. % 输入参数:
  5. % NS 整型,空间剖分段数
  6. % NT 整型,时间剖分段数
  7. % pde 结构体,待求解的微分方程模型的已知数据,
  8. % 如边界、初始、系数和右端项等条件
  9. % method 字符串,代表求解所用离散格式
  10. % F f forward 向前差分格式
  11. % B b backward 向后差分格式
  12. % CN cn crank-nicholson Crank-Nicholson
  13. % -- 六点对称格式( Crank-Nicholson 格式)
  14. % 输出参数:
  15. % X 长度为 NS+1 的列向量,空间网格剖分
  16. % T 长度为 NT+1 的行向量,时间网格剖分
  17. % U (NS+1)*(NT+1) 矩阵,U(:,i) 表示第 i 个时间层网格部分上的数值解
  18. %
  19. % 作者:魏华祎 <weihuayi@xtu.edu.cn>
  20. [X,h] = pde.space_grid(NS);
  21. [T,tau] = pde.time_grid(NT);
  22. N = length(X);M = length(T);
  23. r = pde.a()*tau/h/h;
  24. if r >= 0.5 && ismember(method,{'F','f','forward'})
  25. error('时间空间离散不满足向前差分的稳定条件!')
  26. end
  27. U = zeros(N,M);
  28. U(:,1) = pde.u_initial(X);
  29. U(1,:) = pde.u_left(T);
  30. U(end,:) = pde.u_right(T);
  31. switch(method)
  32. case {'F','f','forward'}
  33. forward();
  34. case {'B','b','backward'}
  35. backward();
  36. case {'CN','cn','crank-nicholson','Crank-Nicholson'}
  37. crank_nicholson();
  38. otherwise
  39. disp(['Sorry, I do not know your ', method]);
  40. end
  41. %% 向前差分方法
  42. function forward()
  43. d = 1 - 2*ones(N-2,1)*r;
  44. c = ones(N-3,1)*r;
  45. A = diag(c,-1) + diag(c,1)+diag(d);
  46. for i = 2:M
  47. RHS = tau*td.f(X,T(i));
  48. RHS(2) = RHS(2) + r*U(1,i-1);
  49. RHS(end-1) = RHS(end-1) + r*U(end,i-1);
  50. U(2:end-1,i)=A*U(2:end-1,i-1)+ RHS(2:end-1);
  51. end
  52. end
  53. %% 向后差分方法
  54. function backward()
  55. d = 1 + 2*ones(N-2,1)*r;
  56. c = -ones(N-3,1)*r;
  57. A = diag(c,-1) + diag(c,1)+diag(d);
  58. for i = 2:M
  59. RHS = tau*td.f(X,T(i));
  60. RHS(2) = RHS(2) + r*U(1,i);
  61. RHS(end-1) = RHS(end-1) + r*U(end,i);
  62. U(2:end-1,i)=A\(U(2:end-1,i-1)+ RHS(2:end-1));
  63. end
  64. end
  65. %% 六点对称格式, Crank_Nicholson 格式
  66. function crank_nicholson()
  67. d1 = 1 + ones(N-2,1)*r;
  68. d2 = 1 - ones(N-2,1)*r;
  69. c = 0.5*ones(N-3,1)*r;
  70. A1 = diag(-c,-1) + diag(-c,1)+diag(d1);
  71. A0 = diag(c,-1) + diag(c,1) + diag(d2);
  72. for i = 2:M
  73. RHS = tau*td.f(X,T(i));
  74. RHS(2) = RHS(2) + 0.5*r*(U(1,i)+U(1,i-1));
  75. RHS(end-1) = RHS(end-1) + ...
  76. 0.5*r*(U(end,i)+U(end,i-1));
  77. U(2:end-1,i)=A1\(A0*U(2:end-1,i-1)+ RHS(2:end-1));
  78. end
  79. end
  80. end
  1. function showvarysolution(X,T,U)
  2. %% SHOWVARYSOLUTION 显示数值解随着时间的变化
  3. %
  4. % 输入参数:
  5. % X 长度为N的列向量,空间网格剖分
  6. % T 第度为M的行向量,时间网格剖分
  7. % U N*M 矩阵,U(:,i) 表示第 i 个时间层网格部分上的数值解
  8. %
  9. % 作者:魏华祎 <weihuayi@xtu.edu.cn>
  10. M = size(U,2);
  11. figure
  12. xlabel('X');
  13. ylabel('U');
  14. s = [X(1),X(end),min(min(U)),max(max(U))];
  15. axis(s);
  16. for i = 1:M
  17. plot(X,U(:,i));
  18. axis(s);
  19. pause(0.0001);
  20. title(['T=',num2str(T(i)),' 时刻的温度分布'])
  21. end
  1. function showsolution(X,T,U)
  2. %% SHOWSOLUTION 以二元函数方式显示数值解
  3. %
  4. % 输入参数:
  5. % X 长度为N的列向量,空间网格剖分
  6. % T 第度为M的行向量,时间网格剖分
  7. % U N*M 矩阵,U(:,i) 表示第 i 个时间层网格部分上的数值解
  8. %
  9. % 作者:魏华祎 <weihuayi@xtu.edu.cn>
  10. [x,t] = meshgrid(X,T);
  11. mesh(x,t,U');
  12. xlabel('X');
  13. ylabel('T');
  14. zlabel('U(X,T)');
  15. end
  1. function e = getmaxerror(X,T,U,u_exact)
  2. %% GETMAXERROR 求最大模误差
  3. % E(h,\tau) = max_{x_i,t_j}| u_exact(x_i,t_j) - U(i,j)|
  4. % = O( \tau + h^2)
  5. %
  6. % 输入参数:
  7. % X 长度为 N 的列向量,空间剖分
  8. % T 长度为 M 的行向量,时间剖分
  9. % U N*M 的矩阵,U(:,i) 表示第 i 个时间步的数值解
  10. % u_exact 函数句柄,真解函数
  11. % 输出参数:
  12. % e 最大模误差
  13. %
  14. % 作者:魏华祎 <weihuayi@xtu.edu.cn>
  15. [x,t] = meshgrid(X,T);
  16. ue = u_exact(x',t');
  17. e = max(max(abs(ue - U)));
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注