image thumbnail
from BEM Code for 2D Pulsating Cylinder by Agustinus Oey
2-D Helmholtz Integral Equation code for computing sound pressure given by a pulsating cylinder.

hie2dcyl.m
%=========================================================================%
% HIE2DCYL.M                                                              %
%                                                                         %
% This is the code for calculating solid angle C, surface pressure ps,    %
% and field pressure pf coming out from a pulsating cylinder with radius  %
% of r and normal velocity vn using the solution of Helmholtz Integral    %
% Equation. For verifying the calculation result, it will also presents   %
% the analytical solution. In case of non-uniqueness problem, r = 1 m     %
% and f = 131 Hz, up to 10 CHIEF points can be implemented.               %
%                                                                         %
% The code is written in a very simple and traditional way so that any    %
% beginner in MATLAB programming would be able to understand it easily.   %
%                                                                         %
% Developed by Agustinus Oey <oeyaugust@gmail.com>                        %
% As a short project of Acoustics Laboratory Summer Camp 2006, Week 5-6   %
% Center of Noise and Vibration Control (NoViC)                           %
% Department of Mechanical Engineering                                    %
% Korea Advanced Institute of Science and Technology (KAIST)              %
% Daejeon, South Korea                                                    %
%                                                                         %
% Ref., T.W. Wu, "Boundary Element Acoustics: Fundamentals and Computer   %
% Codes", WIT Press, Computational Mechanics, 2001"                       %
%=========================================================================% 

% preparing the environment
close all; 
clear;
clc;

% defining medium and wave parameter
rho0=1.21;
cair=343;

% asking problem parameter 
r=0;
while r<0.5 | r>2,
r     = input('Cylinder radius [0.5 ... 2 m]? ');
end
nnode=0;
while nnode<16 | nnode>128,
nnode = floor(input('Number of node [16 ... 128]? '));
end
freq=0;
while freq<20 | freq>500,
freq  = input('Pulsating frequency [25 ... 250 Hz]? ');  
end
vr=10;
while vr<-2 | vr>2,
vr    = input('Surface velocity vr [-2 ... 2 m/s]? ');
end
disp('-');
vn=-ones(1,nnode)'*vr;

% calculating angular frequency and wave number
omega=2*pi*freq;
kwave=omega/cair;

% calculating angle spacing inside the cylinder
dteta=360/nnode;				
teta=-360:dteta:0-dteta;			
teta=-teta/90*1.5708;

% calculating coordinate of nodes
xnode=r*cos(teta);
ynode=r*sin(teta);
clear teta dteta

% defining basic linier shape function
tshp1=[0.5 -0.5];				
tshp2=[0.5  0.5];

% calculating x and y as functions of zeta
xzeta=zeros(2, nnode);				
yzeta=zeros(2, nnode);	
for k=1:nnode-1,
    xzeta(:,k)=(xnode(k)*tshp1+xnode(k+1)*tshp2)';
    yzeta(:,k)=(ynode(k)*tshp1+ynode(k+1)*tshp2)';
end
k=nnode;
xzeta(:,k)=(xnode(k)*tshp1+xnode(1)*tshp2)';
yzeta(:,k)=(ynode(k)*tshp1+ynode(1)*tshp2)';

% calculating dN1/dzeta and dN2/dzeta
dtshp1=-0.5;					
dtshp2= 0.5;
dxzta=zeros(1, nnode);
dyzta=zeros(1, nnode);
for k=1:nnode-1,
    dxzta(k)=xnode(k)*dtshp1+xnode(k+1)*dtshp2;
    dyzta(k)=ynode(k)*dtshp1+ynode(k+1)*dtshp2;
end
k=nnode;
dxzta(k)=xnode(k)*dtshp1+xnode(1)*dtshp2;
dyzta(k)=ynode(k)*dtshp1+ynode(1)*dtshp2;

% calculating Jacobian and normal vectors
Jacb=sqrt(dxzta.^2+dyzta.^2);			
nvect=[dyzta./Jacb; -dxzta./Jacb];
clear dtshp1 dtshp2 dxzta dyzta

% defining spacing and weighting of 6 points Gaussian Quadrature Int.
ngaus=6;					 
wzeta=[-0.93246951 -0.66120939 -0.23861918 ...
        0.23861918 0.66120939 0.93246951];	
wgaus=[0.17132449 0.36076157 0.46791393 ...
        0.46791393 0.36076157 0.17132449];

% calculating [C], [H*], and [G]
czero=eye(nnode);				
hzero=zeros(nnode, nnode);			
gzero=zeros(nnode, nnode);

for k=1:nnode,
    xp=xnode(k);					
    yp=ynode(k);
    % calculate Ck, hkj, and gkj
    for j=1:nnode,					
        for m=1:ngaus,
            xpoin=[1 wzeta(m)]*xzeta(:,j);
            ypoin=[1 wzeta(m)]*yzeta(:,j);
            rdist=sqrt((xpoin-xp)^2+(ypoin-yp)^2);
            dpsdr=-1/(2*pi*rdist);
            drdn=[xpoin-xp ypoin-yp]*nvect(:,j)/rdist;
            % arranging Ck into [C]
            czero(k,k)=czero(k,k)-dpsdr*drdn*Jacb(j)*wgaus(m);
            psi=-i*besselh(0,2,kwave*rdist)/4;
            dpsidn=i*kwave*besselh(1,2,kwave*rdist)*drdn/4;
            n1=tshp1*[1; wzeta(m)];
            n2=tshp2*[1; wzeta(m)];
            % arranging hkj into [H*] and gkj into [G]
            hzero(k,j)=hzero(k,j)+dpsidn*n1*Jacb(j)*wgaus(m);
            gzero(k,j)=gzero(k,j)-i*rho0*omega*psi*n1*Jacb(j)*wgaus(m);
            if j==nnode 
                hzero(k,1)=hzero(k,1)+ ...
                    dpsidn*n2*Jacb(1)*wgaus(m);
                gzero(k,1)=gzero(k,1)- ...
                    i*rho0*omega*psi*n2*Jacb(1)*wgaus(m);
            else
                hzero(k,j+1)=hzero(k,j+1)+ ...
                    dpsidn*n2*Jacb(j+1)*wgaus(m);
                gzero(k,j+1)=gzero(k,j+1)- ...
                    i*rho0*omega*psi*n2*Jacb(j+1)*wgaus(m);
            end
        end
    end
end

% calculating condition number Cn
Cn=max(svd(czero+hzero))/min(svd(czero+hzero));

% offering CHIEF point if needed
nchif=0;
teks=['Condition number is ' num2str(Cn)];
disp(teks);
clear teks
k     = floor(input('Add CHIEF points [0 or 1]? '));
disp('-');
if k==1,
    % ploting solid angle
    while nchif<1 | nchif>10,
        nchif = floor(input('Number of CHIEF points [1 .. 10]? '));
    end
    disp('-');
    xchif=0:r/nchif:r-r/nchif;
    for k=1:nchif,
        xchif(k)=xchif(k)*(-1)^(k-1);
    end
    ychif=zeros(1,nchif);
    
    % calculating [Hc*] and [Gc] from CHIEF points
    hchif=zeros(nchif, nnode);			
    gchif=zeros(nchif, nnode);
    for k=1:nchif,
        xp=xchif(k);
        yp=ychif(k);
        % calculating hc and gc from CHIEF points
        for j=1:nnode,
            for m=1:ngaus,
                xpoin=[1 wzeta(m)]*xzeta(:,j);
                ypoin=[1 wzeta(m)]*yzeta(:,j);
                rdist=sqrt((xpoin-xp)^2+(ypoin-yp)^2);
                drdn=[xpoin-xp ypoin-yp]*nvect(:,j)/rdist;
                psi=i*besselh(0,2,kwave*rdist)/4;
                dpsidn=i*kwave*besselh(1,2,kwave*rdist)*drdn/4;
                n1=tshp1*[1; wzeta(m)];
                n2=tshp2*[1; wzeta(m)];
                % arranging hc into [Hc*] and gc into [Gc]
                hchif(k,j)=hchif(k,j)+dpsidn*n1*Jacb(j)*wgaus(m);
                gchif(k,j)=gchif(k,j)+i*rho0*omega*psi*n1*Jacb(j)*wgaus(m);
                if j==nnode 
                    hchif(k,1)=hchif(k,1) + ...
                        dpsidn*n2*Jacb(1)*wgaus(m);
                    gchif(k,1)=gchif(k,1) + ...
                        i*rho0*omega*psi*n2*Jacb(1)*wgaus(m);
                else
                    hchif(k,j+1)=hchif(k,j+1) + ...
                        dpsidn*n2*Jacb(j+1)*wgaus(m);
                    gchif(k,j+1)=gchif(k,j+1) + ...
                        i*rho0*omega*psi*n2*Jacb(j+1)*wgaus(m);
                end
            end
        end
    end
    Hchif = [hzero; hchif];
    Gchif = [gzero; gchif];
    Cchif = [czero; zeros(nchif, nnode)];
    Cn=max(svd(Cchif+Hchif))/min(svd(Cchif+Hchif));
    teks=['New condition number is ' num2str(Cn)];
    disp(teks);
    clear teks
    % calculating surface pressure HIE solution ps with CHIEF points
    ps=pinv(Cchif+Hchif)*(Gchif*vn);
else
    % calculating surface pressure HIE solution ps w/o CHIEF points
    ps=inv(czero+hzero)*(gzero*vn);			
end

% calculating surface pressure analytical solution psa
psa=i*rho0*cair*vr*besselh(0,2,kwave*1)/besselh(1,2,kwave*1);

% ploting elements, nodes, normal vector, and CHIEF points
k=0;
k     = floor(input('Ploting the geometry [0 or 1]? '));
disp('-');
if k==1,
    %ploting the elements, nodes, and CHIEF points
    if nchif>0 & nchif<11,
        plot([xnode xnode(1)], [ynode ynode(1)], 'r', ...
        xnode, ynode, '*', ...
        xchif, ychif, 'x')
    else
        plot([xnode xnode(1)], [ynode ynode(1)], 'r', ...
        xnode, ynode, '*')
    end
    %lining normal vectors
    for k=1:nnode-1,				
        xelm(k)=0.5*(xnode(k)+xnode(k+1));
        yelm(k)=0.5*(ynode(k)+ynode(k+1));
    end
    k=nnode;
    xelm(k)=0.5*(xnode(k)+xnode(1));
    yelm(k)=0.5*(ynode(k)+ynode(1));
    for k=1:nnode,					
        line([xelm(k) xelm(k)+0.05*nvect(1,k)], ...
            [yelm(k) yelm(k)+0.05*nvect(2,k)])
    end
    clear xelm yelm
    title('Geometry of Cylinder')
    xlabel('x axis (m)')
    ylabel('y axis (m)')
    axis square
    disp('Legend: asterix - node, green x - CHIEF point');
    disp('        red line - surface element, blue line - normal vector');
    disp('-');
end

% ploting solid angles and surface pressure, if needed
k=0;
k     = floor(input('Ploting Cp, ps, and pf [0 or 1]? '));
if k==1,
    % ploting solid angle
    figure
    subplot(3,1,1)
    k=1:nnode;
    plot(k, diag(czero), k, 0.5*ones(1,nnode),'r')
    axis([1 nnode 0.4950 1.01*max(diag(czero))])
    legend('HIE', 'Analytic', 4)
    title('Solid Angle C(p) and Surface Pressure ps')
    ylabel('C(p)')    
    % ploting real surface pressure
    subplot(3,1,2)
    plot(k, real(ps), k, real(psa)*ones(1,nnode),'r')
    legend('HIE', 'Analytic', 4)
    ylabel('real ps (Pa)')
    xaxis=[real(psa) min(real(ps)) max(real(ps))];
    axis([1 nnode 0.999*min(xaxis) 1.001*max(xaxis)])
    % ploting real surface pressure
    subplot(3,1,3)
    plot(k, imag(ps), k, imag(psa)*ones(1,nnode),'r')
    legend('HIE', 'Analytic', 4)
    xlabel('Number of Node (n)')
    ylabel('imaginer ps (Pa)')
    xaxis=[imag(psa) min(imag(ps)) max(imag(ps))];
    axis([1 nnode 0.999*min(xaxis) 1.001*max(xaxis)])
    clear xaxis
end

% noticing for next process
disp('-');
disp('Calculating field pressure pf.');
disp('Press any key to continue.');
pause

% defining field points
xfild=r:0.25:20;
yfild=0*xfild;

% calculating [H*] and [G] from field points
npoin=length(xfild);
hfild=zeros(npoin, nnode);			
gfild=zeros(npoin, nnode);
for k=1:npoin,
    xp=xfild(k);
    yp=yfild(k);
    % calculating hc and gc from field points
    for j=1:nnode,
        for m=1:ngaus,
            xpoin=[1 wzeta(m)]*xzeta(:,j);
            ypoin=[1 wzeta(m)]*yzeta(:,j);
            rdist=sqrt((xpoin-xp)^2+(ypoin-yp)^2);
            drdn=[xpoin-xp ypoin-yp]*nvect(:,j)/rdist;
            psi=i*besselh(0,2,kwave*rdist)/4;
            dpsidn=i*kwave*besselh(1,2,kwave*rdist)*drdn/4;
            n1=tshp1*[1; wzeta(m)];
            n2=tshp2*[1; wzeta(m)];
            % arranging hc into [Hc*] and gc into [Gc]
            hfild(k,j)=hfild(k,j)+dpsidn*n1*Jacb(j)*wgaus(m);
            gfild(k,j)=gfild(k,j)+i*rho0*omega*psi*n1*Jacb(j)*wgaus(m);
            if j==nnode 
                hfild(k,1)=hfild(k,1) + ...
                    dpsidn*n2*Jacb(1)*wgaus(m);
                gfild(k,1)=gfild(k,1) + ...
                    i*rho0*omega*psi*n2*Jacb(1)*wgaus(m);
            else
                hfild(k,j+1)=hfild(k,j+1) + ...
                    dpsidn*n2*Jacb(j+1)*wgaus(m);
                gfild(k,j+1)=gfild(k,j+1) + ...
                    i*rho0*omega*psi*n2*Jacb(j+1)*wgaus(m);
            end
        end
    end
end

% calculating field pressure HIE solution pf
pf=gfild*vn-hfild*ps;

% calculating surface pressure analytical solution psa
pfa=i*rho0*cair*vr*besselh(0,2,kwave*xfild)/besselh(1,2,kwave*r);

% ploting pf and pfa
figure;
plot(xfild, real(pfa), 'b', xfild, real(pf), ...
    'b*', xfild, imag(pfa), 'r', xfild, imag(pf), 'r*')
legend('re(pf), analytic', 're(pf), HIE', 'im(pf), analytic', 'im(pf), HIE')
title('Field Pressure (pf) in Acoustic Domain')
xlabel('distance from the surface (m)')
ylabel('real and imaginer pressure (Pa)')
axis tight
disp('-');
disp('End of calculation, thank you.');

Contact us at files@mathworks.com