[关闭]
@su 2014-06-22T01:51:10.000000Z 字数 5408 阅读 3957

偏微分方程数值解上机实验报告

matlab 偏微分 Freefem++ 计算

上机试验报告

第一题 求解 Helmholtz 方程的边值问题

题目

求解 Helmholtz 方程的边值问题:

Δuk2u=1,G=(0,1)×(0,1),u=0,Γ1={x=0,0y1}{0x1,y=1}un=0,Γ2={0x1,y=0}{x=1,0y1}
其中 k=1,5,10,15,20

分析

利用虚功原理求解 Helmholtz 方程的变分形式

G(Δu)vdxdv+Gk2uvdxdy=Gvdxdy
因为
Γ1={x=0,0y1}{0x1,y=1}Γ2={0x1,y=0}{x=1,0y1}
由格林第一公式
G(Δu)vdxdy==Guxvx+uyvydxdyΓun.vdsGuxvx+uyvydxdy

代码

使用 Freefem++ 编写程序实现使用有限元算法计算 Helmholtz 方程的边值问题,代码如下:

  1. func z=0;
  2. border a0(t=0,1){x=1; y=t;}
  3. border a1(t=0,1){x=1-t;y=1;}
  4. border a2(t=0,1){x=0; y=1-t;}
  5. border a3(t=0,1){x=t;y=0;}
  6. mesh Th = buildmesh(a0(150)+a1(150)+a2(150)+a3(150));
  7. fespace Vh(Th,P2);
  8. Vh phi,w,f=x*y;
  9. solve Laplace(phi,w)=int2d(Th)(dx(phi)*dx(w) + dy(phi)*dy(w))
  10. - int2d(Th)(f*w)+on(a1,phi=z)+on(a2,phi=z) ;
  11. plot(phi,wait=true,ps="phi.eps");
  12. plot(Th,wait=true, ps="membraneTh.eps");
  13. savemesh(Th,"trace.msh");

结果

绘制的图形如下:
此处输入图片的描述

第二题 差分法求解 possion 问题

题目

用差分法求解如下 Laplace 方程 (N=400)

{Δu=xy,u=0,(x,y)Ω=[0,1]×[0,1](x,y)Ω

分析

代码

主函数 main

  1. function [] = main()
  2. N = input('lxease Input N:');
  3. [value, cow, row, b]=getmatrix(N);
  4. % for m=1:(N+1)^2
  5. % fprintf('\n')
  6. % for n = 1:(N+1)^2
  7. % %fprintf('%f',m)
  8. % temp = getvalue(m,n,value,cow,row);
  9. % fprintf('%f\t',temp)
  10. % end
  11. % end
  12. % b;
  13. %% 使用基本迭代法求解方程组,( E+ Tx = b. then x = b-t*x
  14. res = solve_equation(value,cow,row,b);
  15. %% now plot the shape
  16. [y,x]=meshgrid(1:-1/N:0);
  17. Z =flipud( reshape(res,N+1,N+1));
  18. mesh(x,y,Z);
  19. end

getmatrix 函数 主要用来获得系数矩阵的压缩行存储格式

  1. function [value, cow, row,b] = getmatrix(N)
  2. %% 使用addm 差值节点的地址信息。
  3. [xsta, xend, ysta, yend] = deal(0, 1, 0, 1);%多变量同时赋值
  4. xh = (xend-xsta)/N;
  5. yh = (yend-ysta)/N;
  6. addm = {};
  7. for m = 1:N+1
  8. for n = 1:N+1
  9. xtemp = xsta + (m-1)*xh;
  10. ytemp = ysta + (n-1)*yh;
  11. addm(m,n) = {[xtemp, ytemp, xtemp*ytemp ],};
  12. end
  13. end
  14. %disp(addm);
  15. %% 使用crs存储方法记录系数矩阵A
  16. valuelen = (N*3-2)*N + N*(N-1)*2;
  17. value = ones(valuelen,1);
  18. cow = ones(N*N,1);
  19. row = ones(valuelen,1);
  20. tempadr = 1;%利用 tempadr 记录 value 数值变化的位置;
  21. cowadr = 1;%利用 cowadr 记录 cow 列号变化的位置;
  22. rowadr = 1 ;%利用 row 记录行变化的位置
  23. b = zeros(N*N+2*N+1,1);
  24. badr = 1;
  25. %% 从第一行开始逐个记录系数矩阵每行的
  26. for t = 1:N+1
  27. if t==1
  28. for n = 1:N+1
  29. value(tempadr) = 1;
  30. tempadr = tempadr + 1;
  31. cow(cowadr) = tempadr;
  32. cowadr = cowadr +1;
  33. row(rowadr) = (t-1)*(N-1)+n;
  34. rowadr = rowadr + 1;
  35. b(badr) = 0;
  36. badr = badr + 1;
  37. end
  38. else
  39. if t<=N
  40. value(tempadr) = 1;
  41. tempadr = tempadr + 1;
  42. cow(cowadr) = tempadr;
  43. cowadr = cowadr +1;
  44. row(rowadr) = (t-1)*(N+1)+1;
  45. rowadr = rowadr + 1;
  46. b(badr) = 0;
  47. badr = badr + 1;
  48. for n=2:N
  49. value(tempadr:tempadr+4) = [-1/4 -1/4 1 -1/4 -1/4];
  50. tempadr = tempadr +5;
  51. cow(cowadr) = tempadr;
  52. cowadr = cowadr +1;
  53. row(rowadr:rowadr+4) = [(t-2)*(N+1)+n, (t-1)*(N+1)+n-1, (t-1)*(N+1)+n, (t-1)*(N+1)+n+1, t*(N+1)+n];
  54. rowadr = rowadr + 5;
  55. b(badr) = xh*xh*addm{t,n}(3);
  56. badr = badr + 1;
  57. end
  58. value(tempadr) = 1;
  59. tempadr = tempadr + 1;
  60. cow(cowadr) = tempadr;
  61. cowadr = cowadr +1;
  62. row(rowadr) = t*(N+1);
  63. rowadr = rowadr + 1;
  64. b(badr) = 0;
  65. badr = badr + 1;
  66. else
  67. for n = 1:N+1
  68. value(tempadr) = 1;
  69. tempadr = tempadr + 1;
  70. cow(cowadr) = tempadr;
  71. cowadr = cowadr +1;
  72. row(rowadr) = (t-1)*(N+1)+n;
  73. rowadr = rowadr + 1;
  74. b(badr) = 0;
  75. badr = badr + 1;
  76. end
  77. end
  78. end
  79. end
  80. end

solve_equation 主要使用基本迭代法求解方程组

  1. function [ x ] = solve_equation( value, cow, row, b )
  2. %This function is used to solve equation
  3. %% get size of x;
  4. lenth = length(b);
  5. x0 = ones(lenth,1);
  6. x = x0;
  7. error = 1;
  8. %% 方程的解为x
  9. while error>=1e-5
  10. for m=1:lenth
  11. temp = 0;
  12. if m == 1
  13. for t = 1:(cow(m)-1)
  14. if row(t) ~= m
  15. n = row(t);
  16. temp = temp + x0(n)*value(t);
  17. end
  18. end
  19. else
  20. for t = cow(m-1):(cow(m)-1)
  21. if row(t) ~= m
  22. n = row(t);
  23. temp = temp + x0(n)*value(t);
  24. end
  25. end
  26. end
  27. temp = b(m)- temp;
  28. x(m) = temp;
  29. end
  30. error = norm(x0-x,2);
  31. x0 = x;
  32. end
  33. end

getvalue 函数 检查系数矩阵是否正确

  1. function[val] = getvalue(m,n,value,cow,row)
  2. % 这个函数通过 crs 存储的 value , cow ,row 计算出矩阵第m n列的元素的值并返回
  3. %%
  4. lenth = length(cow);
  5. if m>lenth || m<=0
  6. fprintf('Larger than the matrix')
  7. else
  8. val = 0;
  9. if m==1
  10. for t=1:(cow(m)-1)
  11. if n == row(t)
  12. val =value(t);
  13. return;
  14. end
  15. end
  16. else
  17. val = 0;
  18. for t=cow(m-1):(cow(m)-1)
  19. if n == row(t)
  20. val =value(t);
  21. return;
  22. end
  23. end
  24. end
  25. end

使用 freefem++ 通过变分法计算,代码如下:

  1. real theta=4.*pi/3;
  2. real a=2. ,b=1.;
  3. func z=0;
  4. border a0(t=0,1){x=1; y=t;}
  5. border a1(t=0,1){x=1-t;y=1;}
  6. border a2(t=0,1){x=0; y=1-t;}
  7. border a3(t=0,1){x=t;y=0;}
  8. mesh Th = buildmesh(a0(50)+a1(50)+a2(50)+a3(50));
  9. fespace Vh(Th,P2);
  10. Vh phi,w,f=x*y;
  11. solve Laplace(phi,w)=int2d(Th)(dx(phi)*dx(w) + dy(phi)*dy(w))
  12. - int2d(Th)(f*w)+on(a0,phi=z)+on(a1,phi=z)+on(a2,phi=z)+on(a3,phi=z) ;
  13. plot(phi,wait=true);
  14. plot(Th,wait=true, ps="membraneTh.eps");
  15. savemesh(Th,"trace.msh");

结果

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注