CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Wiki > PFV diffusion matrix

PFV diffusion matrix

From CFD-Wiki

(Difference between revisions)
Jump to: navigation, search
(Created page with "Function '''DMatW.m''' for pressure-free velocity diffusion matrix <pre> function [Dm,RowNdx,ColNdx]=DMatW(Xe,Elcon,nn2nft) %DMATW - Returns the affine-mapped element diffusion...")
 
Line 2: Line 2:
<pre>
<pre>
-
function [Dm,RowNdx,ColNdx]=DMatW(Xe,Elcon,nn2nft)
+
function [Dm,RowNdx,ColNdx]=DMatW(eu,Xe,Elcon,nn2nft)
-
%DMATW - Returns the affine-mapped element diffusion matrix for the simple cubic Hermite  
+
%DMatW - Returns the element diffusion matrix for the Hermite basis
-
basis functions on 4-node straight-sided quadrilateral elements with 3 DOF
+
%  functions with 3, 4, or 6 degrees-of-freedom and defined on a
-
%  per node using Gauss quadrature on the reference square and row/col indices.
+
3-node (triangle) or 4-node (quadrilateral) element by the class
-
 
+
instance es using Gauss quadrature on the reference element.  
-
%
+
-
% Cubic-complete, fully-conforming, divergence-free, Hermite basis
+
-
functions on 4-node rectangular elements with 3 DOF per node using
+
-
%  Gauss quadrature on the 2x2 reference square.
+
-
% The assumed nodal numbering starts with 1 at the lower left corner
+
-
%  of the element and proceeds counter-clockwise around the element.
+
-
% Uses second derivatives of stream function.
+
%
%
% Usage:
% Usage:
-
%  [Dm,Rndx,Cndx] = DMatW(Xe,Elcon,nn2nft)
+
%  [Dm,Rndx,Cndx] = DMatW(Xe,Elcon,nn2nft,es)
 +
%  es    - reference for basis function definitions
%  Xe(1,:) -  x-coordinates of corner nodes of element.   
%  Xe(1,:) -  x-coordinates of corner nodes of element.   
%  Xe(2,:) -  y-coordinates of corner nodes of element.   
%  Xe(2,:) -  y-coordinates of corner nodes of element.   
-
%      and shape of the element. It is constant for affine elements.
+
%  Elcon - connectivity matrix for this element.  
-
%  Elcon - connectivity matrix for this element.  
+
%  nn2nft - global DOF and type of DOF at each node  
-
%  nn2nft - global number and type of DOF at each node  
+
%
%
-
% Jonas Holdeman, August 2007, revised June 2011
+
% Indirectly may use (handle passed by eu):
 +
%  GQuad2  - function providing 2D rectangle quadrature rules.
 +
%  TQuad2  - function providing 2D triangle quadrature rules.
 +
%
 +
% Jonas Holdeman, January 2007, revised March 2013
-
% Constants and fixed data
+
% ------------------- Constants and fixed data ---------------------------
-
nd = 3;  nd4=4*nd; ND=1:nd;  % nd = number of dofs per node,  
+
nnodes = eu.nnodes;        % number of nodes per element (4);
-
nn=[-1 -1; 1 -1; 1 1; -1 1];  % defines local nodal order
+
nndofs = eu.nndofs;        % nndofs = number of dofs per node, (3|6);   
 +
nedofs=nnodes*nndofs;       % nndofs = number of dofs per node,  
 +
nn = eu.nn;          % defines local nodal order, [-1 -1; 1 -1; 1 1; -1 1]
-
% Define 4-point quadrature data once, on first call.
+
% ------------------------------------------------------------------------
-
% Gaussian weights and absissas to integrate 7th degree polynomials exactly.
+
persistent QQDM4;  
-
global GQ4;
+
if isempty(QQDM4)  
-
if (isempty(GQ4))       % Define 4-point quadrature data once, on first call.
+
    QRorder = 2*(eu.mxpowr-1)+1; % =9
-
  Aq=[-.861136311594053,-.339981043584856,.339981043584856, .861136311594053]; %Abs
+
    [QQDM4.xa, QQDM4.ya, QQDM4.wt, QQDM4.nq] = eu.hQuad(QRorder);
-
  Hq=[ .347854845137454, .652145154862546,.652145154862546, .347854845137454]; %Wts
+
end  % if isempty...
-
  GQ4.size=16; GQ4.xa=[Aq;Aq;Aq;Aq]; GQ4.ya=GQ4.xa';  
+
xa = QQDM4.xa; ya = QQDM4.ya; wt = QQDM4.wt; Nq = QQDM4.nq;
-
  wt=[Hq;Hq;Hq;Hq]; GQ4.wt=wt.*wt';
+
% ------------------------------------------------------------------------
-
end
+
-
 
+
-
xa=GQ4.xa; ya=GQ4.ya; wt=GQ4.wt; Nq=GQ4.size;
+
-
% -----------------------------------------------
+
persistent ZZ_SXd; persistent ZZ_SYd;  
-
global Zs3412d2;
+
if (isempty(ZZ_SXd)||isempty(ZZ_SYd)||size(ZZ_SXd,2)~=Nq)
-
if (isempty(Zs3412d2)|size(Zs3412d2,2)~=Nq)
+
% Evaluate and save/cache the set of shape functions at quadrature pts.  
% Evaluate and save/cache the set of shape functions at quadrature pts.  
-
  Zs3412d2=cell(4,Nq);
+
  ZZ_SXd=cell(nnodes,Nq); ZZ_SYd=cell(nnodes,Nq);  
-
    for k=1:Nq
+
  for k=1:Nq
-
       for m=1:4
+
       for m=1:nnodes
-
      Zs3412d2{m,k}=D3s(nn(m,:),xa(k),ya(k));
+
      [ZZ_SXd{m,k},ZZ_SYd{m,k}]=eu.DS(nn(m,:),xa(k),ya(k));
       end
       end
   end
   end
end  % if(isempty(*))
end  % if(isempty(*))
-
% --------------- End fixed data ----------------
+
% -------------------------- End fixed data ------------------------------
-
Ti=cell(4);
+
affine = eu.isaffine(Xe);      % affine?
-
    
+
%affine = (sum(abs(Xe(:,1)-Xe(:,2)+Xe(:,3)-Xe(:,4)))<4*eps);    % affine?
-
for m=1:4
+
 
-
   Jt=Xe*GBL(nn(:,:),nn(m,1),nn(m,2));   % transpose of Jacobian at node m
+
Ti=cell(nnodes);
-
  JtiD=[Jt(2,2),-Jt(1,2); -Jt(2,1),Jt(1,1)];  % det(J)*inv(Jt)
+
% Jt=[x_q, x_r; y_q, y_r]; 
-
  Ti{m}=blkdiag(1,JtiD);   
+
if affine  % (J constant)
 +
  Jt=Xe*eu.Gm(nn(:,:),eu.cntr(1),eu.cntr(2));
 +
  JtiD=[Jt(2,2),-Jt(1,2); -Jt(2,1),Jt(1,1)];  % det(J)*inv(J)
 +
  if nndofs==3
 +
    TT=blkdiag(1,JtiD);
 +
  elseif nndofs==4
 +
      TT=blkdiag(1,JtiD,Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1));
 +
   else
 +
    T2=[Jt(1,1)^2, 2*Jt(1,1)*Jt(1,2), Jt(1,2)^2; ...  % alt
 +
    Jt(1,1)*Jt(2,1), Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1), Jt(1,2)*Jt(2,2); ...
 +
    Jt(2,1)^2, 2*Jt(2,1)*Jt(2,2), Jt(2,2)^2];
 +
    TT=blkdiag(1,JtiD,T2);
 +
    Bxy=Xe*eu.DGm(nn(:,:),0,0); % Second cross derivatives
 +
    TT(5,2)= Bxy(2);
 +
    TT(5,3)=-Bxy(1);
 +
  end  % nndofs...
 +
  for m=1:nnodes, Ti{m}=TT; end
 +
   Det=Jt(1,1)*Jt(2,2)-Jt(1,2)*Jt(2,1);  % Determinant of Jt & J
 +
  Jtd=Jt/Det;
 +
  Ji=[Jt(2,2),-Jt(2,1); -Jt(1,2),Jt(1,1)]/Det;
 +
else
 +
  for m=1:nnodes  % Loop over corner nodes
 +
    Jt=Xe*eu.Gm(nn(:,:),nn(m,1),nn(m,2));  
 +
    JtiD=[Jt(2,2),-Jt(1,2); -Jt(2,1),Jt(1,1)];  % det(J)*inv(J)
 +
    if nndofs==3,
 +
        TT=blkdiag(1,JtiD);
 +
    elseif nndofs==4
 +
        TT=blkdiag(1,JtiD,(Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1)));
 +
    else
 +
        T2=[Jt(1,1)^2, 2*Jt(1,1)*Jt(1,2), Jt(1,2)^2; ...
 +
        Jt(1,1)*Jt(2,1), Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1), Jt(1,2)*Jt(2,2);...
 +
        Jt(2,1)^2, 2*Jt(2,1)*Jt(2,2), Jt(2,2)^2];
 +
        TT=blkdiag(1,JtiD,T2);
 +
        Bxy=Xe*eu.DGm(nn(:,:),nn(m,1),nn(m,2));  % 2nd cross derivatives
 +
        TT(5,2)= Bxy(2);
 +
        TT(5,3)=-Bxy(1);
 +
    end
 +
    Ti{m}=TT;
 +
  end  % Loop m
end
end
-
% Move Jacobian evaluation inside k-loop for general convex quadrilateral.
+
% Allocate arrays 
-
% Jt=[x_q, x_r; y_q, y_r];
+
Dm=zeros(nedofs,nedofs); Sx=zeros(2,nedofs); Sy=zeros(2,nedofs);  
-
 
+
ND=1:nndofs;
-
Dm=zeros(nd4,nd4); Sx=zeros(2,nd4); Sy=zeros(2,nd4);   % Pre-allocate arrays
+
-
 
+
for k=1:Nq   
for k=1:Nq   
-
 
+
   if ~affine
-
   Jt=Xe*GBL(nn(:,:),xa(k),ya(k));       % transpose of Jacobian at (xa,ya)
+
    Jt=Xe*eu.Gm(nn(:,:),xa(k),ya(k)); % transpose of Jacobian at (xa,ya)
-
  Det=Jt(1,1)*Jt(2,2)-Jt(1,2)*Jt(2,1);  % Determinant of Jt & J  
+
    Det=Jt(1,1)*Jt(2,2)-Jt(1,2)*Jt(2,1);  % Determinant of Jt & J  
-
  TL=[Jt(2,2)^2, -2*Jt(2,1)*Jt(2,2), Jt(2,1)^2; ...
+
    Jtd=Jt/Det;
-
     -Jt(1,2)*Jt(2,2), Jt(1,1)*Jt(2,2)+Jt(2,1)*Jt(1,2), -Jt(1,1)*Jt(2,1); ...
+
     Ji=[Jt(2,2),-Jt(2,1); -Jt(1,2),Jt(1,1)]/Det;
-
      Jt(1,2)^2, -2*Jt(1,1)*Jt(1,2), Jt(1,1)^2]/Det^2;
+
  end
-
 
+
% Initialize functions and derivatives at the quadrature point (xa,ya).
% Initialize functions and derivatives at the quadrature point (xa,ya).
-
   for m=1:4
+
   for m=1:nnodes
-
     mm=nd*(m-1);
+
     mm=nndofs*(m-1);
-
    Ds = TL*Zs3412d2{m,k}*Ti{m};  
+
     Sx(:,mm+ND)=Jtd*(Ji(1,1)*ZZ_SXd{m,k}+Ji(1,2)*ZZ_SYd{m,k})*Ti{m};
-
     Sx(:,mm+ND) = [Ds(2,:); -Ds(1,:)];    % [Pyx, -Pxx]
+
     Sy(:,mm+ND)=Jtd*(Ji(2,1)*ZZ_SXd{m,k}+Ji(2,2)*ZZ_SYd{m,k})*Ti{m};
-
     Sy(:,mm+ND) = [Ds(3,:); -Ds(2,:)];    % [Pyy, -Pxy]
+
   end  % loop m
   end  % loop m
    
    
Line 87: Line 116:
end  % end loop k over quadrature points
end  % end loop k over quadrature points
-
gf=zeros(nd4,1);
+
gf=zeros(nedofs,1);
m=0;  
m=0;  
-
for n=1:4                 % Loop over element nodes  
+
for n=1:nnodes                 % Loop over element nodes  
-
   gf(m+ND)=(nn2nft(1,Elcon(n))-1)+ND;  % Get global freedoms
+
   gf(m+ND)=(nn2nft(Elcon(n),1)-1)+ND;  % Get global freedoms
-
   m=m+nd;
+
   m=m+nndofs;
end
end
-
RowNdx=repmat(gf,1,nd4);     % Row indices
+
RowNdx=repmat(gf,1,nedofs);   % Row indices
-
ColNdx=RowNdx';               % Col indices
+
ColNdx=RowNdx';               % Col indices
   
   
-
Dm = reshape(Dm,nd4*nd4,1);
+
Dm = reshape(Dm,nedofs*nedofs,1);
-
RowNdx=reshape(RowNdx,nd4*nd4,1);
+
RowNdx=reshape(RowNdx,nedofs*nedofs,1);
-
ColNdx=reshape(ColNdx,nd4*nd4,1);   
+
ColNdx=reshape(ColNdx,nedofs*nedofs,1);   
-
 
+
-
return;
+
-
 
+
-
 
+
-
% -------------------------------------------------------------------
+
-
 
+
-
function P2=D3s(ni,q,r)
+
-
% Second derivatives [Pxx; Pxy; Pyy] of simple cubic stream function.
+
-
qi=ni(1); q0=q*ni(1); q1=1+q0;
+
-
ri=ni(2); r0=r*ni(2); r1=1+r0;
+
-
  P2=[-.75*qi^2*(r0+1)*q0, 0, -.25*qi*(r0+1)*(3*q0+1); ...
+
-
      .125*qi*ri*(4-3*(q^2+r^2)), .125*qi*(r0+1)*(3*r0-1), ...
+
-
      -.125*ri*(q0+1)*(3*q0-1); -.75*ri^2*(q0+1)*r0, .25*ri*(q0+1)*(3*r0+1), 0] ; 
+
-
return;
+
-
function G=GBL(ni,q,r)
 
-
% Transposed gradient (derivatives) of scalar bilinear mapping function.
 
-
% The parameter ni can be a vector of coordinate pairs.
 
-
  G=[.25*ni(:,1).*(1+ni(:,2).*r), .25*ni(:,2).*(1+ni(:,1).*q)];
 
return;
return;
</pre>
</pre>

Latest revision as of 15:58, 15 March 2013

Function DMatW.m for pressure-free velocity diffusion matrix

function [Dm,RowNdx,ColNdx]=DMatW(eu,Xe,Elcon,nn2nft)
%DMatW - Returns the element diffusion matrix for the Hermite basis 
%   functions with 3, 4, or 6 degrees-of-freedom and defined on a 
%   3-node (triangle) or 4-node (quadrilateral) element by the class
%   instance es using Gauss quadrature on the reference element. 
%
% Usage:
%   [Dm,Rndx,Cndx] = DMatW(Xe,Elcon,nn2nft,es)
%   es    - reference for basis function definitions
%   Xe(1,:) -  x-coordinates of corner nodes of element.  
%   Xe(2,:) -  y-coordinates of corner nodes of element.  
%   Elcon - connectivity matrix for this element. 
%   nn2nft - global DOF and type of DOF at each node 
%
% Indirectly may use (handle passed by eu):
%   GQuad2   - function providing 2D rectangle quadrature rules.
%   TQuad2   - function providing 2D triangle quadrature rules.
%
% Jonas Holdeman, January 2007, revised March 2013 

% ------------------- Constants and fixed data ---------------------------
nnodes = eu.nnodes;         % number of nodes per element (4);
nndofs = eu.nndofs;         % nndofs = number of dofs per node, (3|6);  
nedofs=nnodes*nndofs;       % nndofs = number of dofs per node, 
nn = eu.nn;          % defines local nodal order, [-1 -1; 1 -1; 1 1; -1 1]

% ------------------------------------------------------------------------
persistent QQDM4; 
if isempty(QQDM4) 
     QRorder = 2*(eu.mxpowr-1)+1; % =9
    [QQDM4.xa, QQDM4.ya, QQDM4.wt, QQDM4.nq] = eu.hQuad(QRorder);
end  % if isempty...
xa = QQDM4.xa; ya = QQDM4.ya; wt = QQDM4.wt; Nq = QQDM4.nq;
% ------------------------------------------------------------------------

persistent ZZ_SXd; persistent ZZ_SYd; 
if (isempty(ZZ_SXd)||isempty(ZZ_SYd)||size(ZZ_SXd,2)~=Nq)
% Evaluate and save/cache the set of shape functions at quadrature pts. 
   ZZ_SXd=cell(nnodes,Nq); ZZ_SYd=cell(nnodes,Nq); 
   for k=1:Nq
      for m=1:nnodes
      [ZZ_SXd{m,k},ZZ_SYd{m,k}]=eu.DS(nn(m,:),xa(k),ya(k));
      end
   end
end  % if(isempty(*))
% -------------------------- End fixed data ------------------------------

affine = eu.isaffine(Xe);       % affine?
%affine = (sum(abs(Xe(:,1)-Xe(:,2)+Xe(:,3)-Xe(:,4)))<4*eps);    % affine?

Ti=cell(nnodes);
% Jt=[x_q, x_r; y_q, y_r];   
if affine   % (J constant)
  Jt=Xe*eu.Gm(nn(:,:),eu.cntr(1),eu.cntr(2)); 
  JtiD=[Jt(2,2),-Jt(1,2); -Jt(2,1),Jt(1,1)];   % det(J)*inv(J)
  if nndofs==3
     TT=blkdiag(1,JtiD); 
  elseif nndofs==4
      TT=blkdiag(1,JtiD,Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1));
  else
    T2=[Jt(1,1)^2, 2*Jt(1,1)*Jt(1,2), Jt(1,2)^2; ...  % alt
    Jt(1,1)*Jt(2,1), Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1), Jt(1,2)*Jt(2,2); ...
    Jt(2,1)^2, 2*Jt(2,1)*Jt(2,2), Jt(2,2)^2];
    TT=blkdiag(1,JtiD,T2); 
    Bxy=Xe*eu.DGm(nn(:,:),0,0); % Second cross derivatives
    TT(5,2)= Bxy(2);
    TT(5,3)=-Bxy(1);
  end  % nndofs...
  for m=1:nnodes, Ti{m}=TT; end
  Det=Jt(1,1)*Jt(2,2)-Jt(1,2)*Jt(2,1);  % Determinant of Jt & J 
  Jtd=Jt/Det;
  Ji=[Jt(2,2),-Jt(2,1); -Jt(1,2),Jt(1,1)]/Det;
else
   for m=1:nnodes   % Loop over corner nodes 
     Jt=Xe*eu.Gm(nn(:,:),nn(m,1),nn(m,2)); 
     JtiD=[Jt(2,2),-Jt(1,2); -Jt(2,1),Jt(1,1)];   % det(J)*inv(J)
     if nndofs==3, 
        TT=blkdiag(1,JtiD);
     elseif nndofs==4
        TT=blkdiag(1,JtiD,(Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1)));
     else
        T2=[Jt(1,1)^2, 2*Jt(1,1)*Jt(1,2), Jt(1,2)^2; ...
        Jt(1,1)*Jt(2,1), Jt(1,1)*Jt(2,2)+Jt(1,2)*Jt(2,1), Jt(1,2)*Jt(2,2);...
        Jt(2,1)^2, 2*Jt(2,1)*Jt(2,2), Jt(2,2)^2];
        TT=blkdiag(1,JtiD,T2); 
        Bxy=Xe*eu.DGm(nn(:,:),nn(m,1),nn(m,2));  % 2nd cross derivatives
        TT(5,2)= Bxy(2);
        TT(5,3)=-Bxy(1);
     end
     Ti{m}=TT;
   end  % Loop m 
end

% Allocate arrays  
Dm=zeros(nedofs,nedofs); Sx=zeros(2,nedofs); Sy=zeros(2,nedofs); 
 ND=1:nndofs;
for k=1:Nq  
  if ~affine
     Jt=Xe*eu.Gm(nn(:,:),xa(k),ya(k)); % transpose of Jacobian at (xa,ya)
     Det=Jt(1,1)*Jt(2,2)-Jt(1,2)*Jt(2,1);  % Determinant of Jt & J 
     Jtd=Jt/Det;
     Ji=[Jt(2,2),-Jt(2,1); -Jt(1,2),Jt(1,1)]/Det;
  end
% Initialize functions and derivatives at the quadrature point (xa,ya).
  for m=1:nnodes 
    mm=nndofs*(m-1);
    Sx(:,mm+ND)=Jtd*(Ji(1,1)*ZZ_SXd{m,k}+Ji(1,2)*ZZ_SYd{m,k})*Ti{m};
    Sy(:,mm+ND)=Jtd*(Ji(2,1)*ZZ_SXd{m,k}+Ji(2,2)*ZZ_SYd{m,k})*Ti{m};
  end  % loop m
   
  Dm = Dm+(Sx'*Sx+Sy'*Sy)*(wt(k)*Det);
   
end  % end loop k over quadrature points

gf=zeros(nedofs,1);
m=0; 
for n=1:nnodes                 % Loop over element nodes 
  gf(m+ND)=(nn2nft(Elcon(n),1)-1)+ND;  % Get global freedoms
  m=m+nndofs;
end

RowNdx=repmat(gf,1,nedofs);    % Row indices
ColNdx=RowNdx';                % Col indices
 
Dm = reshape(Dm,nedofs*nedofs,1);
RowNdx=reshape(RowNdx,nedofs*nedofs,1);
ColNdx=reshape(ColNdx,nedofs*nedofs,1);   

return;
My wiki