有限元计算2D稳态热传导方程

时间:2022-12-16 18:49:49

本文程序,使用有限元计算2D稳态热传导方程。

本程序只使用2D三角形单元求解,没有四边形单元求解。不过,也非常容易就可做到。

主程序为:

Heat_Conduction_steady.m

需要用到的子程序有:

coord3.m  用来生成节点坐标,节点坐标与单元的链接。边界条件等等。

生成文件

coordinates.dat  包含两列,第一列节点x坐标,第二列,节点y坐标

elements3.dat  包含三列:分别是各个单元的i,j,k节点的总体编号。

dirichlet.dat  包含两列:分别是第一类边界条件的两端点节点的总体编号。

 

另外,

coord4.m与coord3相同,但是,生成的是四边形单元。

即:
elements4.dat

 

f.m  生成由内生热产生的节点载荷qv/K,其中,qv为体积生热率,K为热导率

g.m  生成由表面热流产生的节点载荷。在有第二类边界条件的时候才使用。

stima3.m  计算三角形单元的单元刚度矩阵

stima4.m  计算四边形单元的单元刚度矩阵

u_d.m  狄利克雷边界条件。

 

先将各个函数列于下方:

----------------------------------------------------------------------------------------

% coord3.m

% the coordinate index is from 1~Nx(from left to right) for the bottom line
% and then from Nx+1~2*Nx  (from left to right) for the next line above
% and then next
xmin=0;xmax=1;
ymin=0;ymax=1;
Nx=13;Ny=13;
x=linspace(xmin,xmax,Nx);
y=linspace(ymin,ymax,Ny);

k=0;
for i1=1:Ny
    for i2=1:Nx
        k=k+1;
        Coord(k,:)=[x(i2),y(i1)];    
    end
end

save coordinates.dat Coord -ascii


% the element index
k=0;
vertices=zeros((Nx-1)*(Ny-1)*2,3);
for i1=1:Ny-1
    for i2=1:Nx-1
        k=k+1;
        ijm1=i2+(i1-1)*Nx;
        ijm2=i2+1+(i1-1)*Nx;
        ijm3=i2+1+i1*Nx;
        vertices(k,:)=[ijm1,ijm2,ijm3];
        
        k=k+1;
        ijm1=i2+1+i1*Nx;
        ijm2=i2+i1*Nx;
        ijm3=i2+(i1-1)*Nx;
        vertices(k,:)=[ijm1,ijm2,ijm3];
        
    end
end
save elements3.dat vertices -ascii

% The direchlet boundary condition (index of the two end nodes for each boundary line)
boundary=zeros(2*(Nx+Ny-2),2);
temp1=1:Nx-1;
temp2=2:Nx;
temp3=1:Nx-1;
boundary(temp3',:)=[temp1',temp2'];
temp1=Nx*(1:Ny-1);
temp2=temp1+Nx;
temp3=temp3+Nx-1;
boundary(temp3',:)=[temp1',temp2'];
temp1=Ny*Nx:-1:Ny*Nx-Nx+2;
temp2=temp1-1;
temp3=temp3+Nx-1;
boundary(temp3',:)=[temp1',temp2'];
temp1=Nx*(Ny-1)+1:-Nx:Nx+1;
temp2=temp1-Nx;
temp3=temp3+Nx-1;
boundary(temp3',:)=[temp1',temp2'];
save dirichlet.dat boundary -ascii
----------------------------------------------------------------------------------------

% coord4.m

% the coordinate index is from 1~Nx(from left to right) for the bottom line
% and then from Nx+1~2*Nx  (from left to right) for the next line above
% and then next
xmin=0;xmax=1;
ymin=0;ymax=1;
Nx=13;Ny=13;
x=linspace(xmin,xmax,Nx);
y=linspace(ymin,ymax,Ny);

k=0;
for i1=1:Ny
    for i2=1:Nx
        k=k+1;
        Coord(k,:)=[x(i2),y(i1)];    
    end
end

save coordinates.dat Coord -ascii


% the element index
k=0;
vertices=zeros((Nx-1)*(Ny-1),4);
for i1=1:Ny-1
    for i2=1:Nx-1
        k=k+1;
        il1=(i1-1)*Nx+i2;
        il2=il1+1;
        il3=il2+Nx;
        il4=il1+Nx;
        vertices(k,:)=[il1,il2,il3,il4];
    end
end
save elements4.dat vertices -ascii

% The direchlet boundary condition (index of the two end nodes for each boundary line)
boundary=zeros(2*(Nx+Ny-2),2);
temp1=1:Nx-1;
temp2=2:Nx;
temp3=1:Nx-1;
boundary(temp3',:)=[temp1',temp2'];
temp1=Nx*(1:Ny-1);
temp2=temp1+Nx;
temp3=temp3+Nx-1;
boundary(temp3',:)=[temp1',temp2'];
temp1=Ny*Nx:-1:Ny*Nx-Nx+2;
temp2=temp1-1;
temp3=temp3+Nx-1;
boundary(temp3',:)=[temp1',temp2'];
temp1=Nx*(Ny-1)+1:-Nx:Nx+1;
temp2=temp1-Nx;
temp3=temp3+Nx-1;
boundary(temp3',:)=[temp1',temp2'];
save dirichlet.dat boundary -ascii


----------------------------------------------------------------------------------------

% 主程序Heat_Conduction_steady.m

%*****************************************************************************80
%
%% Aapplies the finite element method to steady heat conduction equation,
%  that is Poission's equation
%
%
%    The user supplies datafiles that specify the geometry of the region
%    and its arrangement into triangular or quadrilateral elements, and
%    the location and type of the boundary conditions, which can be any
%    mixture  of Neumann and Dirichlet.
%    
%    The unknown state variable U(x,y) is assumed to satisfy
%    Poisson's equation (steady heat conduction equation):
%      -Uxx(x,y) - Uyy(x,y) = F(x,y) in Omega
%    with Dirichlet boundary conditions
%      U(x,y) = U_D(x,y) on Gamma_D
%    and Neumann boundary conditions on the outward normal derivative:
%      Un(x,y) = G(x,y) on Gamma_N
%    If Gamma designates the boundary of the region Omega,
%    then we presume that
%      Gamma = Gamma_D + Gamma_N
%    F(x,y) is qv/K,here qv means volumetric heat generation rate
%    but the user is free to determine which boundary conditions to
%    apply.
%    
%    The code uses piecewise linear basis functions for triangular elements,
%    and piecewise isoparametric bilinear basis functions for quadrilateral
%    elements.
%    
%    
%
  clear

%
%  Read the nodal coordinate data file.
%
  load coordinates.dat;
%
%  Read the triangular element data file.
%
  load elements3.dat;
%
%  Read the quadrilateral element data file.
%
%  load elements4.dat;
%
%  Read the Neumann boundary condition data file.
%  I THINK the purpose of the EVAL command is to create an empty NEUMANN array
%  if no Neumann file is found.
%
  eval ( 'load neumann.dat;', 'neumann=[];' );
%
%  Read the Dirichlet boundary condition data file.
%
  load dirichlet.dat;

  A = sparse ( size(coordinates,1), size(coordinates,1) );
  b = sparse ( size(coordinates,1), 1 );
%
%  Assembly.
%
  for j = 1 : size(elements3,1)
    A(elements3(j,:),elements3(j,:)) = A(elements3(j,:),elements3(j,:)) ...
      + stima3(coordinates(elements3(j,:),:));
  end
%{
  for j = 1 : size(elements4,1)
    A(elements4(j,:),elements4(j,:)) = A(elements4(j,:),elements4(j,:)) ...
      + stima4(coordinates(elements4(j,:),:));
  end
%}
%  Volume Forces.
%
% from the center of each element to Nodes
% Notice that the result of f here means qv/K instead of qv
  for j = 1 : size(elements3,1)
    b(elements3(j,:)) = b(elements3(j,:)) ...
      + det( [1,1,1; coordinates(elements3(j,:),:)'] ) * ...
      f(sum(coordinates(elements3(j,:),:))/3)/6;
  end
%{
  for j = 1 : size(elements4,1)
    b(elements4(j,:)) = b(elements4(j,:)) ...
      + det([1,1,1; coordinates(elements4(j,1:3),:)'] ) * ...
      f(sum(coordinates(elements4(j,:),:))/4)/4;
  end
%}
%  Neumann conditions.
%
  if ( ~isempty(neumann) )
    for j = 1 : size(neumann,1)
      b(neumann(j,:)) = b(neumann(j,:)) + ...
        norm(coordinates(neumann(j,1),:) - coordinates(neumann(j,2),:)) * ...
        g(sum(coordinates(neumann(j,:),:))/2)/2;
    end
  end
%
%  Determine which nodes are associated with Dirichlet conditions.
%  Assign the corresponding entries of U, and adjust the right hand side.
%
  u = sparse ( size(coordinates,1), 1 );
  BoundNodes = unique ( dirichlet );
  u(BoundNodes) = u_d ( coordinates(BoundNodes,:) );
  b = b - A * u;
%
%  Compute the solution by solving A * U = B for the remaining unknown values of U.
%
  FreeNodes = setdiff ( 1:size(coordinates,1), BoundNodes );

  u(FreeNodes) = A(FreeNodes,FreeNodes) \ b(FreeNodes);
%
%  Graphic representation.
%
%  show ( elements3, elements4, coordinates, full ( u ) );

figure
   trisurf ( elements3, coordinates(:,1), coordinates(:,2), (full ( u )));

    view ( -67.5, 30 );
shading interp

----------------------------------------------------------------------------------------

%stima3.m

function M = stima3 ( vertices )

%*****************************************************************************80
%
%% STIMA3 determines the local stiffness matrix for a triangular element.
%
%  Discussion:
%
%    Although this routine is intended for 2D usage, the same formulas
%    work for tetrahedral elements in 3D.  The spatial dimension intended
%    is determined implicitly, from the spatial dimension of the vertices.
%
%  Parameters:
%
%    Input, real VERTICES(1:(D+1),1:D), contains the D-dimensional
%    coordinates of the vertices.
%
%    Output, real M(1:(D+1),1:(D+1)), the local stiffness matrix
%    for the element.
%
  d = size ( vertices, 2 );

  D_eta = [ ones(1,d+1); vertices' ] \ [ zeros(1,d); eye(d) ];

  M = det ( [ ones(1,d+1); vertices' ] ) * D_eta * D_eta' / prod ( 1:d );

 

----------------------------------------------------------------------------------------

%stima4.m

function M = stima4 ( vertices )

%*****************************************************************************80
%
%% STIMA4 determines the local stiffness matrix for a quadrilateral element.
%
%
%  Parameters:
%
%    Input, real VERTICES(1:4,1:2), contains the coordinates of the vertices.
%
%    Output, real M(1:4,1:4), the local stiffness matrix for the element.
%
  D_Phi = [ vertices(2,:) - vertices(1,:); vertices(4,:) - vertices(1,:) ]';

  B = inv ( D_Phi' * D_Phi );

  C1 =  [  2, -2; -2,  2 ] * B(1,1) ...
      + [  3,  0;  0, -3 ] * B(1,2) ...
      + [  2,  1;  1,  2 ] * B(2,2);

  C2 =  [ -1,  1;  1, -1 ] * B(1,1) ...
      + [ -3,  0;  0,  3 ] * B(1,2) ...
      + [ -1, -2; -2, -1 ] * B(2,2);

  M = det ( D_Phi ) * [ C1 C2; C2 C1 ] / 6;

 

----------------------------------------------------------------------------------------

%f.g

function value = f ( u )



%*****************************************************************************80

%

%% F evaluates the right hand side of Laplace's equation. NOtice that F is qv/K instead of qv.

%

%

%    This routine must be changed by the user to reflect a particular problem.

%

%

%  Parameters:

%

%    Input, real U(N,M), contains the M-dimensional coordinates of N points.

%

%    Output, VALUE(N), contains the value of the right hand side of Laplace's

%    equation at each of the points.

%

  n = size ( u, 1 );



  value(1:n) = ones(n,1);

%2.0 * pi * pi * sin ( pi * u(1:n,1) ) .* sin ( pi * u(1:n,2) );



 

----------------------------------------------------------------------------------------

%g.m

function value = g ( u )



%*****************************************************************************

%

%% G evaluates the outward normal values assigned at Neumann boundary conditions.

%

%

%    This routine must be changed by the user to reflect a particular problem.

%

%  Parameters:

%

%    Input, real U(N,M), contains the M-dimensional coordinates of N points.

%

%    Output, VALUE(N), contains the value of outward normal at each point

%    where a Neumann boundary condition is applied.

%

  value = zeros ( size ( u, 1 ), 1 );





 

----------------------------------------------------------------------------------------

%u_d.m

function value = u_d ( u )



%*****************************************************************************80

%

%% U_D evaluates the Dirichlet boundary conditions.

%

%

%    The user must supply the appropriate routine for a given problem

%

%

%  Parameters:

%

%    Input, real U(N,M), contains the M-dimensional coordinates of N points.

%

%    Output, VALUE(N), contains the value of the Dirichlet boundary

%    condition at each point.

%

  value = zeros ( size ( u, 1 ), 1 );

value(1:13)=1;

 

----------------------------------------------------------------------------------------

上面的程序计算了内生热为均匀qv/K=1,在底边界温度为1,在其它边界温度为0的计算的结果:

结果如下图

有限元计算2D稳态热传导方程

 

对于四边形单元,将主函数Heat_Conduction_steady.m修改如下

--------------------------------------------------------------------------------------

%Heat_Conduction_steady.m

%*****************************************************************************80
%
%% Aapplies the finite element method to steady heat conduction equation,
%  that is Poission's equation
%
%
%    The user supplies datafiles that specify the geometry of the region
%    and its arrangement into triangular or quadrilateral elements, and
%    the location and type of the boundary conditions, which can be any
%    mixture  of Neumann and Dirichlet.
%    
%    The unknown state variable U(x,y) is assumed to satisfy
%    Poisson's equation (steady heat conduction equation):
%      -Uxx(x,y) - Uyy(x,y) = F(x,y) in Omega
%    with Dirichlet boundary conditions
%      U(x,y) = U_D(x,y) on Gamma_D
%    and Neumann boundary conditions on the outward normal derivative:
%      Un(x,y) = G(x,y) on Gamma_N
%    If Gamma designates the boundary of the region Omega,
%    then we presume that
%      Gamma = Gamma_D + Gamma_N
%    F(x,y) is qv/K,here qv means volumetric heat generation rate
%    but the user is free to determine which boundary conditions to
%    apply.
%    
%    The code uses piecewise linear basis functions for triangular elements,
%    and piecewise isoparametric bilinear basis functions for quadrilateral
%    elements.
%    
%    
%
  clear

%
%  Read the nodal coordinate data file.
%
  load coordinates.dat;
%
%  Read the triangular element data file.
%
%  load elements3.dat;
%
%  Read the quadrilateral element data file.
%
  load elements4.dat;
%
%  Read the Neumann boundary condition data file.
%  I THINK the purpose of the EVAL command is to create an empty NEUMANN array
%  if no Neumann file is found.
%
  eval ( 'load neumann.dat;', 'neumann=[];' );
%
%  Read the Dirichlet boundary condition data file.
%
  load dirichlet.dat;

  A = sparse ( size(coordinates,1), size(coordinates,1) );
  b = sparse ( size(coordinates,1), 1 );
%
%  Assembly.
%{
  for j = 1 : size(elements3,1)
    A(elements3(j,:),elements3(j,:)) = A(elements3(j,:),elements3(j,:)) ...
      + stima3(coordinates(elements3(j,:),:));
  end
%}
%%{
  for j = 1 : size(elements4,1)
    A(elements4(j,:),elements4(j,:)) = A(elements4(j,:),elements4(j,:)) ...
      + stima4(coordinates(elements4(j,:),:));
  end
%%}
%  Volume Forces.
%
% from the center of each element to Nodes
% Notice that the result of f here means qv/K instead of qv
%{
  for j = 1 : size(elements3,1)
    b(elements3(j,:)) = b(elements3(j,:)) ...
      + det( [1,1,1; coordinates(elements3(j,:),:)'] ) * ...
      f(sum(coordinates(elements3(j,:),:))/3)/6;
  end
%}
%%{
  for j = 1 : size(elements4,1)
    b(elements4(j,:)) = b(elements4(j,:)) ...
      + det([1,1,1; coordinates(elements4(j,1:3),:)'] ) * ...
      f(sum(coordinates(elements4(j,:),:))/4)/4;
  end
%%}
%  Neumann conditions.
%
  if ( ~isempty(neumann) )
    for j = 1 : size(neumann,1)
      b(neumann(j,:)) = b(neumann(j,:)) + ...
        norm(coordinates(neumann(j,1),:) - coordinates(neumann(j,2),:)) * ...
        g(sum(coordinates(neumann(j,:),:))/2)/2;
    end
  end
%
%  Determine which nodes are associated with Dirichlet conditions.
%  Assign the corresponding entries of U, and adjust the right hand side.
%
  u = sparse ( size(coordinates,1), 1 );
  BoundNodes = unique ( dirichlet );
  u(BoundNodes) = u_d ( coordinates(BoundNodes,:) );
  b = b - A * u;
%
%  Compute the solution by solving A * U = B for the remaining unknown values of U.
%
  FreeNodes = setdiff ( 1:size(coordinates,1), BoundNodes );

  u(FreeNodes) = A(FreeNodes,FreeNodes) \ b(FreeNodes);
%
%  Graphic representation.
%
%  show ( elements3, elements4, coordinates, full ( u ) );

trisurf ( elements4, coordinates(:,1), coordinates(:,2), u')
shading interp
xlabel('x')

--------------------------------------------------------------------------------------

结果如下,和三节点完全相同:

有限元计算2D稳态热传导方程