All pastes #386355 Raw Edit

Stuff

public text v1 · immutable
·published 2007-03-08 15:29 UTC
rendered paste body
% date: 16.12.04
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  simple FEM program
%
%  schreiben Sie in die Funktionen 
%
%    fems, femm, femc, feme und femf
%
%  die fehlenden Anweisungen
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [] = fem
%----------------  
% compute FEM solution U of the problem 
%--------------------------------------
  global TEST;
  %show results (1=show, 0=don't)
  global ourTEST
  ourTEST = [0 0 0 0 0]; %femf, feme, femc, femm, fems

  %TEST = 1; % test display  
  TEST = 0; % no test display
  
  % define/ init problem data

  %bnr = 4; 
  %ng = 1;
  %coeffall(bnr,ng); % init example 
  
  femi; % initialize fem computation
  femc; % compile SV and SM
  femm; % modify SV
  fems; % compute solution U  
  femp; % plot solution
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%             functions for FEM computation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [] = fems
%-----------------
% solve system equation SM * U = SV
%----------------------------------------------------
  global L N
  global Z  
  global SV SM  
  global U      % calculated
  global ourTEST
  global TEST
  global ERROR
  global maxERROR
    
  %solve equation
  U = SM\SV;
  U = reshape(U,[L N]);
  ERROR = [NaN]; maxERROR = NaN; exactResult = NaN;
  %calc Error if L=1
  if L==1
    % calc exact result
    for i = 1:N
      V(i) = uexact([Z(i,1) Z(i,2)]);
    end
    exactResult = reshape(V,[1 N]);
    % calc ERROR
    for i = 1:N
      ERROR( i ) = abs( V(i) - U(i) );
    end
    ERROR = reshape( ERROR,[1 N] );
     maxERROR = max( ERROR );
  end
  %Show Results
  if ourTEST(5)
    disp('fems ready, U and ERROR calculated:');
    disp('U = ');disp(U);
    disp('exact result ');disp(exactResult);
    disp('ERROR = '); disp(ERROR);
    disp('maxERROR = '); disp(maxERROR);
    disp('SYSTEM EQUATION SM * U = SV is solved for U');
  end    
  
function [] = femm
%-----------------
% MODIFY SV and SM for DIRICHLET boundary condition
%
% use variable ID = 1 x N - matrix of kinnd of knotes 
%----------------------------------------------------  
  global SV  % modified
  global SM  % modified
  global ID  % Nodetable
  global Z   % x,y values
  global L
  global ourTEST
  global TEST

  ind = find(ID == 1); % all dirichlet nodes k
  for k = ind %dirichlet node k
       uk = u0(Z(k,:));      
       indk  = ((L*(k-1)) + 1) : (L*(k-1)+L);  % Columnnumber
       % overwrite SV with new and old known values
       SV = SV - SM(:,indk) * uk;
       SV(indk) = uk;
       % modify SM
       SM(indk,:) = 0;
       SM(:,indk) = 0;
       SM(indk,indk) = eye(L);
  end
  
  figure; spy(SM); figure
  
  %Debug
  if ourTEST(4)
      disp('femm ready, SV modified: ');
      disp(SV);
      disp('--------------------- press any key --------------------');
      pause
  end

function [] = femc
%-----------------
% compile global system variables 
%
%  SM = C = L x L cell = stiffness matrices for each solution component  
%  SV = b = L x 1 cell = load vectors
%
% some other used variables:
%
%  L    = # of unknown functions = components of u
%  M    = # of domain triangles
%  TOP = all domain knotes 
%
%  SME  = system matrix on domain ELEMENT # r 
%  SVE  = system vector on domain ELEMENT # r
%
% call function feme(r) = compute elemnt variables SME and SVE 
%--------------------------------------------------------------
  global TOP
  global L M N  
  global SVE SME
  global SV SM   % calculated
  global ourTEST
  
  SV = zeros(N*L,1); %b:=0
  SM = zeros(N*L,N*L); %C:=0
  
  for r =1:M
      feme(r); %calc SVE and SME
      for alpha = 1:3
          i = TOP(r,alpha);
          indi  = L*(i-1)+1 : L*(i-1)+L;
          indalpha = L*(alpha-1)+1 : L*(alpha-1)+L;
          SV(indi) = SV(indi) + SVE(indalpha);
          for beta = 1:3
              k = TOP(r,beta);
              indk  = L*(k-1)+1 : L*(k-1)+L;
              indbeta = L*(beta-1)+1: L*(beta-1)+L;
              SM(indi,indk) = SM(indi,indk) + SME(indalpha,indbeta);
          end
      end      
  end
  
  figure; spy(SM); 
  
  if ourTEST(3)
    disp('femc ready, SV and SM calculated:');
    disp('SV:');disp(reshape(SV, [L N]));
    disp('press any key');pause;
    disp('SM:');disp(SM);
    disp('--------------------- press any key --------------------');
    pause;
  end
  
  
function [] = feme(r)
%--------------------
% compute on DOMAIN triangle/element # r the system variables 
%
%  SVE = b = L x 1 cell = lokal ELEMENT load vector 
%  SME = C = L X L cell = lokal ELEMENT stiffness matrix 
%  
% where 
%
%  r   = domain # of actual triangle/element
%
% use FFIA/FFIB = cells of FF integrals for element r 
%
%  FFIA = {FIA1 FIA2 FIAx FIAy FIAxx FIAxy FIAyx FIAyy} = area integrals 
%  FFIB = {FIB1 FIB2 FIB3}                              = boundary integrals
%
%  call function femf(r) = compute FF integrals FFIA and FFIB on element r
%----------------------------------------------------------------------------
  global ourTEST
  global TEST
  global INC
  global L
  global XE
  global FFIA FFIB  
  global SVE SME % calculated
 
  femf(r); % compute FF integrals FFIA and FFIB on element r
  
  % init SVE,SME
  SVE=zeros( 3*L,1 );
  SME=zeros( 3*L,3*L );
  
  % get the center of element r
  center= zeros( 1,2 );
  for i=1:3
      center=center+XE( i,: );
  end
  center=center/3;
  
  % get Coeffs for AreaInt1&2
  F1=f1( center );
  F2=f2( center );
    
  SVE = kron( FFIA{1},f0( center ) );
  
  SME = kron( FFIA{2}, a0(center) );
  SME = SME + kron( FFIA{3}, F1{1} );
  SME = SME + kron( FFIA{4}, F2{1} );
  SME = SME + kron( FFIA{5}, F1{2} );
  SME = SME + kron( FFIA{7}, F2{2} );
  SME = SME + kron( FFIA{6}, F1{3} );
  SME = SME + kron( FFIA{8}, F2{3} );
  
  if TEST && ourTEST(2)
    disp('r = ');disp(r);
    disp('SVE:');disp(SVE);
    disp('SME:');disp(SME);
  end
  
  for delta=1:3
      if INC( r,delta )>0
          % compute barycenter
          barycenter = ( 3*center-XE( delta,: ) ) / 2;
          
          % determine which border and the corresponding function g and a
          if INC( r,delta )==1
              my_g=g1( barycenter );
              my_alpha=zeros( L,L );
          else
              my_g=g2( barycenter );
              my_alpha=a2( barycenter );
          end
          
          % adjust load vector and stiffness matrix
          SVE = SVE + kron( sum( FFIB{delta},2 ), my_g );
          SME = SME + kron( FFIB{delta}, my_alpha );
          
          if TEST && ourTEST(2)
            disp('delta-Iteration');disp(delta);
            disp('SVE:');disp(SVE);
            disp('SME:');disp(SME);
          end
      end
  end
  
  if ourTEST(2)
    disp('feme ready, SVE and SME calculated:');
    disp('r =');disp(r);
    disp('SVE:');disp(SVE);
    disp('SME:');disp(SME);
    disp('--------------------- press any key --------------------');
    pause;
  end  
  
function [] = femf(r)
%--------------------
% calculate element dependent integrals 
% FFIA = AREA and FFIB = BOUNDARY INTEGRALS 
% of products of FF on triangle element number r
%
%  FFIA = {FIA1 FIA2 FIAx FIAy FIAxx FIAxy FIAyx FIAyy} = cell of AREA integrals
%  FIA1,FIA2               = integrals of 1 and 2 FF with no derivation
%  FIAx,FIAy               = integrals of 2 FF with one derivation
%  FIAxx,FIAxy,FIAyx,FIAyy = integrals of 2 FF with two derivations
%
%  FFIB = {FIB1 FIB2 FIB3} = cell of BOUNDARY integrals
%
% some used/defined variables:
%
%  JD = jacobi determinante     JA = adjunct of jacobi matrix
%  XE = element knotes = 3 x 2 - matrix   
%
%  FFSIA/FFSIB = STANDARD area/boundary integrals
%------------------------------------------------------------
  global ourTEST
  global TEST
  global Z TOP
  global FFSIA FFSIB % given  
  global XE
  global FFIA FFIB % calculated
  
  if TEST && ourTEST(1)
    disp( 'r= ' );
    disp( r );
  end
  
  % element nodes
  XE = zeros( 3,2 );
  XE = [ Z( TOP( r,1 ),: ); Z( TOP( r,2 ),: ); Z( TOP( r,3 ),: )];
   
  % calculate the jacobi matrix
  JM = transpose( [ XE(2,:)-XE(1,:); XE(3,:)-XE(1,:)] );
  %debug jacobi matrix
  if TEST && ourTEST(1)  
    disp( 'This is JM' );
    disp( JM );
  end
  
  % calculate JD
  JD = det( JM );

  % calculate JA
  JA = [ JM( 2,2 ) -JM( 1,2 ); -JM( 2,1 ) JM( 1,1 ) ];
  
  % element lengths
  XE_diff = [ XE(3,:)-XE(2,:);  
              XE(1,:)-XE(3,:); 
              XE(2,:)-XE(1,:)];
  
  % calculate the Ls (don't use "L" as Var because needed elsewhere -> "eL")
  eL = [ norm( XE_diff( 1,: ) ) norm( XE_diff( 2,: ) ) norm( XE_diff( 3,: ) ) ];
  
  %calcuöate FIA1 FIA2
  FFIA{1} = JD * FFSIA{1};
  FFIA{2} = JD * FFSIA{2};
  
  % Area-Integrals
  n=1;
  for i=1:2
      FFIA{i+2} = JA(1,i) * FFSIA{3} + JA(i,2) * FFSIA{4};
      for k=1:2
          % calculate Sum
          FFIA{n+4} = 0;
          m=1;
          for s=1:2
              for t=1:2
                    FFIA{n+4} = FFIA{n+4} + JA(s,i) * JA(t,k) * FFSIA{m+4};
                    m = m+1;
              end
          end
          FFIA{n+4} = FFIA{n+4}/JD;
          n = n+1;                
      end
  end
  
  % Border-Integrals
  for delta=1:3
      FFIB{delta} = eL(delta)*FFSIB{delta};
  end
  
  if ourTEST(1)
    disp('femf ready, FFIA and FFIB calculated:');
    disp('r =');disp(r);
    disp('FFIA:');disp(FFIA);
    disp('FFIB:');disp(FFIB);
    disp('--------------------- press any key --------------------');
    pause;
  end
     
  
function [] = femi
%-----------------
% initialize variables needed for fem computation; compute 
%
%  M  = # of domain triangles
%  N  = # of all knotes 
%  
%  FFSIA/FFSIB = STANDARD area/boundary integrals
%  FFSIA = {I1 I2 Ix Iy Ixx Ixy Iyx Iyy} 
%           1  2  3  4   5   6   7   8
%  FFSIB = {I1 I2 I3}
%
%  ID    = 1 x N - matrix of kinnd of knotes 
%  INC   = M x 3 - matrix of kiind of triangle sides
%
%  call function setbart = define ID and INC
%                ploted  = plot triangles
%----------------------------------------------------------

  global Z TOP  
  global L M N         
  global FFSIA FFSIB  % calculated
  global ID
  
  [M dummy] = size(TOP);  % M = # of triangles
  [N dummy] = size(Z);    % N = # of global knotes 
    
  disp(['[L M N] = ' num2str([L M N])])
  
  % plot domain tringles
  %---------------------
  
  figure(1); clf;          % clear figure 1 for plot
  
  if M < 100               % M = # of domain triangles 
    plotel(Z,[1 2]);   % plot triangles with triangle # 
  else  
    plotel(Z,[0 1]);   % plot triangles without number 
  end  
  
  disp('domain triangles are ploted. enter any key'); pause

  % define standard area and boundary integrals 
  
  I1  = [1; 1; 1] / 6; 
  I2  = [2 1 1; 1 2 1; 1 1 2]/24;
  Ix  = [-1 -1 -1; 1 1 1; 0 0 0]/6;
  Iy  = [-1 -1 -1; 0 0 0; 1 1 1]/6;
  Ixx = [1 -1 0; -1 1 0; 0 0 0]/2;
  Ixy = [1 0 -1; -1 0 1; 0 0 0]/2; Iyx = Ixy';
  Iyy = [1 0 -1; 0 0 0; -1 0 1]/2; 

  FFSIA = {I1 I2 Ix Iy Ixx Ixy Iyx Iyy};  % standard area integrals 

  %I  = [0 1 1; 1 0 1; 1 1 0]/2;
  I1 = [0 0 0; 0 2 1; 0 1 2]/6;
  I2 = [2 0 1; 0 0 0; 1 0 2]/6;
  I3 = [2 1 0; 1 2 0; 0 0 0]/6; 

  FFSIB = {I1 I2 I3};  % standard boubdary integrals
  
  setbart; % calculate INC = M x 3 matrix of kind of boundary conditions of all triangle sides
           %           ID  = 1 x N matrix of kind of all global knotes
           
  %ID(7) = 0; % set some extra dirichlet knotes
  
  %ind = find(ID == 1)
  %disp(['all dirichlet knotes']); pause 
  
function [] = setbart
%--------------------
% set/calculate/initialize ID and INC  
%  ID = 1 x N - matrix of DIRICHLET knotes 
%       ID(i) = 1  knot i is a DIRICHLET knot
%            = -2  knot i is inner knote
%            =  0  knot i is boundary knot and not dirichlet 
% INC = M x 3 matrix 
%     = -2  for all INNER sides and 
%     = art of BND for all BOUNDARY sides  
%
%  INC(r,jj) = bart <=> side jj in element r is of type bart
%
%  side jj = 1 = (2 3) , jj = 2 = (3 1) and jj = 3 = (1 2)
%
%  bart > -2 <=> jj = BOUNDARY side for component l    
%       = -1        = homogen NC  0 = Dirichlet  1 = Neumann  2 = Cauchy
%
% used global variable:
%
%  BART = given matrix of boundary types (defied in example files)
%-----------------------------------------------------------------------

  global TOP M N
  global BART      % given boundary types
  
  global INC ID    % are calculated !!!!!!!!
  global TEST
  
  INC = (-2)*ones(M,3);    % initialize INC = -2 for all triangle sides 
  ID =  (-2)*ones(1,N) ;   % init ID
  
  % set INC with art or artm for domain boundary sides (i j)
  
  for r = 1:M     % loop over all DOMAIN triangles
        
    tri = TOP(r,:);
    tri = [tri tri];
    
    for jj = 1:3         % jj = # of actual triangle side 

       i = tri(jj+1); j = tri(jj+2); % (i j) = side jj of element r
       w = inel(i,j);                % find n triangles in TOPD with side (i j) or side (j,i)
       
       if w{1} == 1            % n = w{1} = 1 => (i j) = BOUNDARY side of domain
 
         % (i j) = boundary side 
         
         ind = find(BART(:,1) == i);  
         
         if isempty(ind) bart = BART(1,2);          % default boundary type
         else            bart = BART(ind(1),2);     % extra   boundary type                
         end

         if TEST
           disp(['boundary side [r i j jj] = ' num2str([r i j jj]) ' is of type = ' num2str(bart)]) 
         end
           
         INC(r,jj) = bart;   % jj = boundary side of kind = bart
         
         if bart == 0        % i and j are dirichlet knotes 
           ID([i j]) = 1; 
         else                % i and j are not dirichlet boundary knotes 
           if ID(i) ~= 1 ID(i) = 0; end
           if ID(j) ~= 1 ID(j) = 0; end
         end
                            
  end; end; end  

  if TEST
    ind = find(ID == 1)
    disp(['all dirichlet knotes']); pause 
  end