├── IB_matlab_2D ├── Force.m ├── README ├── fluid.m ├── ib2D.m ├── init_a.m ├── initialize.m ├── laplacian.m ├── sk.m ├── skew.m ├── vec_interp.m ├── vec_phi1.m ├── vec_phi2.m └── vec_spread.m ├── README.md └── ib_matlab_3D ├── .gitignore ├── Forcespr.m ├── Forcesurf.m ├── README ├── dodec.m ├── fluid.m ├── grad.m ├── ib3D.m ├── init_a.m ├── init_b.m ├── initialize.m ├── interp.m ├── laplacian.m ├── locate.m ├── refine.m ├── rsphere.m ├── sk.m ├── skew.m ├── tarea.m ├── triplot.m ├── trisph.m ├── vec_interp.m ├── vec_phi1.m ├── vec_phi2.m ├── vec_phi3.m ├── vec_spread.m └── vpoly.m /IB_matlab_2D/Force.m: -------------------------------------------------------------------------------- 1 | function F=Force(X) 2 | global kp km dtheta K; 3 | % elastic stretching force 4 | F=K*(X(kp,:)+X(km,:)-2*X)/(dtheta*dtheta); -------------------------------------------------------------------------------- /IB_matlab_2D/README: -------------------------------------------------------------------------------- 1 | # IB2D-MATLAB 2 | 3 | This directory contains code for running a 2D immersed boundary simulation of an elastic curve imbeded in a fluid. The code uses the Navier Stokes equations and periodic boundary conditions. 4 | 5 | The original code (https://www.math.nyu.edu/faculty/peskin/ib_lecture_notes/index.html) was written by Charlie Peskin and was vectorized by Tristan Goodwill 6 | 7 | # Scripts: 8 | 9 | ib2D Main script 10 | initialize Initialize boundary and fluid 11 | init_a Initialize Fourier domain solution operator used in fluid solver 12 | fluid Time step fluid 13 | Force Compute boundary forces 14 | laplacian Apply usual second order centered laplacian to u 15 | skew Get a nice discretization of (u. nabla)u 16 | sk Helper for skew 17 | 18 | vec_interp Interpolate value from grid to boundary 19 | vec_spread Spread value from boundary to grid 20 | vec_phi1 Evaluate 4-point regularized delta function in x 21 | vec_phi2 Evaluate 4-point regularized delta function in y -------------------------------------------------------------------------------- /IB_matlab_2D/fluid.m: -------------------------------------------------------------------------------- 1 | function [uuu,uu]=fluid(u,ff) 2 | % Time step the fluid 3 | global a dt rho mu; 4 | 5 | w=u-(dt/2)*skew(u)+(dt/(2*rho))*ff; % Get RHS 6 | w=fft(w,[],1); 7 | w=fft(w,[],2); 8 | uu(:,:,1)=a(:,:,1,1).*w(:,:,1)+a(:,:,1,2).*w(:,:,2); % Solve for LHS 9 | uu(:,:,2)=a(:,:,2,1).*w(:,:,1)+a(:,:,2,2).*w(:,:,2); 10 | uu=ifft(uu,[],2); 11 | uu=real(ifft(uu,[],1)); %Get u at midpoint in time 12 | 13 | 14 | w=u-dt*skew(uu)+(dt/rho)*ff+(dt/2)*(mu/rho)*laplacian(u);% Get RHS 15 | w=fft(w,[],1); 16 | w=fft(w,[],2); 17 | uuu(:,:,1)=a(:,:,1,1).*w(:,:,1)+a(:,:,1,2).*w(:,:,2);% Solve for LHS 18 | uuu(:,:,2)=a(:,:,2,1).*w(:,:,1)+a(:,:,2,2).*w(:,:,2); 19 | uuu=ifft(uuu,[],2); 20 | uuu=real(ifft(uuu,[],1)); % Get u at next timestep 21 | -------------------------------------------------------------------------------- /IB_matlab_2D/ib2D.m: -------------------------------------------------------------------------------- 1 | % ib2D.m 2 | % This script is the main program. 3 | % Original Code by Charlie Peskin: 4 | % https://www.math.nyu.edu/faculty/peskin/ib_lecture_notes/index.html 5 | % Vectorized and commented by Tristan Goodwill,2019.4 6 | %% Initialize simulation 7 | global dt Nb N h rho mu ip im a; 8 | global kp km dtheta K; 9 | initialize 10 | init_a 11 | 12 | %% Run simulation 13 | for clock=1:clockmax 14 | XX=X+(dt/2)*vec_interp(u,X); % Euler step to midpoint 15 | ff=vec_spread(Force(XX),XX); % Force at midpoint 16 | [u,uu]=fluid(u,ff); % Step Fluid Velocity 17 | X=X+dt*vec_interp(uu,XX); % full step using midpoint velocity 18 | 19 | %animation: 20 | vorticity=(u(ip,:,2)-u(im,:,2)-u(:,ip,1)+u(:,im,1))/(2*h); 21 | contour(xgrid,ygrid,vorticity,values) 22 | hold on 23 | plot(X(:,1),X(:,2),'ko') 24 | axis([0,L,0,L]) 25 | caxis(valminmax) 26 | axis equal 27 | axis manual 28 | drawnow 29 | hold off 30 | end 31 | 32 | -------------------------------------------------------------------------------- /IB_matlab_2D/init_a.m: -------------------------------------------------------------------------------- 1 | %init_a.m 2 | %This script initializes the array a 3 | %that is used in the fluid solver 4 | 5 | global a; 6 | a=zeros(N,N,2,2); 7 | for m1=0:(N-1) 8 | for m2=0:(N-1) 9 | a(m1+1,m2+1,1,1)=1; 10 | a(m1+1,m2+1,2,2)=1; 11 | end 12 | end 13 | 14 | for m1=0:(N-1) 15 | for m2=0:(N-1) 16 | if~(((m1==0)|(m1==N/2))&((m2==0)|(m2==N/2))) 17 | t=(2*pi/N)*[m1;m2]; 18 | s=sin(t); 19 | ss=(s*s')/(s'*s); 20 | % a(m1+1,m2+1,:,:)=a(m1+1,m2+1,:,:)-(s*s')/(s'*s); 21 | a(m1+1,m2+1,1,1)=a(m1+1,m2+1,1,1)-ss(1,1); 22 | a(m1+1,m2+1,1,2)=a(m1+1,m2+1,1,2)-ss(1,2); 23 | a(m1+1,m2+1,2,1)=a(m1+1,m2+1,2,1)-ss(2,1); 24 | a(m1+1,m2+1,2,2)=a(m1+1,m2+1,2,2)-ss(2,2); 25 | end 26 | end 27 | end 28 | 29 | for m1=0:(N-1) 30 | for m2=0:(N-1) 31 | t=(pi/N)*[m1;m2]; 32 | s=sin(t); 33 | a(m1+1,m2+1,:,:)=a(m1+1,m2+1,:,:)... 34 | /(1+(dt/2)*(mu/rho)*(4/(h*h))*(s'*s)); 35 | end 36 | end 37 | 38 | -------------------------------------------------------------------------------- /IB_matlab_2D/initialize.m: -------------------------------------------------------------------------------- 1 | %initialize.m 2 | %% Initialize Parameters and special indices 3 | 4 | L=1.0 % Box size 5 | N=64 % Number of grid cells 6 | h=L/N % Grid spacing 7 | ip=[(2:N),1] % Grid index shifted left 8 | im=[N,(1:(N-1))] % Grid index shifted right 9 | Nb=ceil(pi*(L/2)/(h/2)) % Number of IB points 10 | dtheta=2*pi/Nb % IB point spacing 11 | kp=[(2:Nb),1] % IB index shifted left 12 | km=[Nb,(1:(Nb-1))] % IB index shifted right 13 | K=1 % Elastic stiffness 14 | rho=1 % Fluid density 15 | mu=0.01 % viscosity 16 | tmax=1 % Run until time 17 | dt=0.01 % Time step 18 | clockmax=ceil(tmax/dt) 19 | 20 | %% Initialize boundary and velocity 21 | k=0:(Nb-1); 22 | theta = k'*dtheta; 23 | X = (L/2) + (L/4)*[cos(theta), sin(theta)]; 24 | 25 | u=zeros(N,N,2); 26 | j1=0:(N-1); % Initialize fluid velocity as (0,sin(2*pi*x/L)) 27 | x=j1'*h; 28 | u(j1+1,:,2)=sin(2*pi*x/L)*ones(1,N); 29 | 30 | %% Initialize animation 31 | vorticity=(u(ip,:,2)-u(im,:,2)-u(:,ip,1)+u(:,im,1))/(2*h); 32 | dvorticity=(max(max(vorticity))-min(min(vorticity)))/5; 33 | values= (-10*dvorticity):dvorticity:(10*dvorticity); % Get vorticity contours 34 | valminmax=[min(values),max(values)]; 35 | xgrid=zeros(N,N); 36 | ygrid=zeros(N,N); 37 | for j=0:(N-1) 38 | xgrid(j+1,:)=j*h; 39 | ygrid(:,j+1)=j*h; 40 | end 41 | 42 | set(gcf,'double','on') 43 | contour(xgrid,ygrid,vorticity,values) 44 | hold on 45 | plot(X(:,1),X(:,2),'ko') 46 | axis([0,L,0,L]) 47 | caxis(valminmax) 48 | axis equal 49 | axis manual 50 | drawnow 51 | hold off 52 | 53 | -------------------------------------------------------------------------------- /IB_matlab_2D/laplacian.m: -------------------------------------------------------------------------------- 1 | function w=laplacian(u) 2 | global im ip h; 3 | % Second order centered Laplacian 4 | w=(u(ip,:,:)+u(im,:,:)+u(:,ip,:)+u(:,im,:)-4*u)/(h*h); 5 | 6 | % im = [N,1:(N-1)] = circular version of i-1 7 | % ip = [2:N,1] = circular version of i+1 8 | % N = number of points in each space direction 9 | 10 | -------------------------------------------------------------------------------- /IB_matlab_2D/sk.m: -------------------------------------------------------------------------------- 1 | function f=sk(u,g) 2 | % Help skew.m get a disretized (u . nabla)u with nice symmetries 3 | global ip im h; 4 | f=((u(ip,:,1)+u(:,:,1)).*g(ip,:)... 5 | -(u(im,:,1)+u(:,:,1)).*g(im,:)... 6 | +(u(:,ip,2)+u(:,:,2)).*g(:,ip)... 7 | -(u(:,im,2)+u(:,:,2)).*g(:,im))/(4*h); 8 | -------------------------------------------------------------------------------- /IB_matlab_2D/skew.m: -------------------------------------------------------------------------------- 1 | function w=skew(u) 2 | % Get a disretized (u . nabla)u with nice symmetries 3 | w=u; %note that this is done only to make w the same size as u 4 | w(:,:,1)=sk(u,u(:,:,1)); 5 | w(:,:,2)=sk(u,u(:,:,2)); 6 | 7 | -------------------------------------------------------------------------------- /IB_matlab_2D/vec_interp.m: -------------------------------------------------------------------------------- 1 | function U=vec_interp(u,X) 2 | % interpolate fluid velocity to the body 3 | global Nb h; 4 | global N; 5 | U=zeros(Nb,2); 6 | s=X/h; % Get body position relative to grid 7 | i=floor(s); 8 | r=s-i; 9 | w=vec_phi1(r(:,1)).*vec_phi2(r(:,2)); %Evaluate delta function 10 | w = permute(w, [1,3,2]); %Reogranize, this is quite fast 11 | for k = 1:Nb 12 | i1=mod((i(k,1)-1):(i(k,1)+2),N)+1; % Find adjacent fluid cells 13 | i2=mod((i(k,2)-1):(i(k,2)+2),N)+1; 14 | 15 | %Interpolate fluid velocity, this is the costly part (65% of the time for 16 | %N=100) 17 | ww = w(:,:,k); 18 | UU = [sum(sum(ww.*u(i1,i2,1))), sum(sum(ww.*u(i1,i2,2)))]; %Interpolate 19 | U(k,:)= UU; 20 | end 21 | % for k=1:Nb 22 | % s=X(k,:)/h; 23 | % i=floor(s); 24 | % r=s-i; 25 | % i1=mod((i(1)-1):(i(1)+2),N)+1; 26 | % i2=mod((i(2)-1):(i(2)+2),N)+1; 27 | % w=phi1(r(1)).*phi2(r(2)); 28 | % UU = [sum(sum(w.*u(i1,i2,1))), sum(sum(w.*u(i1,i2,2)))]; 29 | % U(k,:)= UU; 30 | % end 31 | 32 | -------------------------------------------------------------------------------- /IB_matlab_2D/vec_phi1.m: -------------------------------------------------------------------------------- 1 | function w=vec_phi1(r) 2 | % 4 point delta function in y, vectorizing makes this 10x faster for Nb = 3 | % 100 4 | w=zeros(4,size(r,1),4); 5 | q=sqrt(1+4*r.*(1-r)); 6 | w(4,:,:)=repmat((1+2*r-q)/8,[1,1,4]); 7 | w(3,:,:)=repmat((1+2*r+q)/8,[1,1,4]); 8 | w(2,:,:)=repmat((3-2*r+q)/8,[1,1,4]); 9 | w(1,:,:)=repmat((3-2*r-q)/8,[1,1,4]); 10 | end 11 | 12 | %% The following are alternatives that are twice as slow 13 | % function w=vec_phi1(r) 14 | % % 4 point delta function in y 15 | % w=zeros(4,4,size(r,1)); 16 | % q=sqrt(1+4*r.*(1-r)); 17 | % for i = 1:4 18 | % w(4,i,:)=(1+2*r-q)/8; 19 | % w(3,i,:)=(1+2*r+q)/8; 20 | % w(2,i,:)=(3-2*r+q)/8; 21 | % w(1,i,:)=(3-2*r-q)/8; 22 | % end 23 | % 24 | % function w=vec_phi1(r) 25 | % % 4 point delta function in y 26 | % w=zeros(4,size(r,1),4); 27 | % q=sqrt(1+4*r.*(1-r)); 28 | % for i = 1:4 29 | % w(4,:,i)=(1+2*r-q)/8; 30 | % w(3,:,i)=(1+2*r+q)/8; 31 | % w(2,:,i)=(3-2*r+q)/8; 32 | % w(1,:,i)=(3-2*r-q)/8; 33 | % end -------------------------------------------------------------------------------- /IB_matlab_2D/vec_phi2.m: -------------------------------------------------------------------------------- 1 | function w=vec_phi2(r) 2 | % 4 point delta function in x, vectorizing makes this 15x faster for 3 | % Nb=100 4 | w=zeros(4,size(r,1),4); 5 | q=sqrt(1+4*r.*(1-r)); 6 | w(:,:,4)=repmat((1+2*r-q)'/8,[4,1]); 7 | w(:,:,3)=repmat((1+2*r+q)'/8,[4,1]); 8 | w(:,:,2)=repmat((3-2*r+q)'/8,[4,1]); 9 | w(:,:,1)=repmat((3-2*r-q)'/8,[4,1]); 10 | end 11 | %% The following is 50% slower 12 | % function w=vec_phi2(r) 13 | % % 4 point delta function in x 14 | % w=zeros(4,size(r,1),4); 15 | % q=sqrt(1+4*r.*(1-r)); 16 | % for i =1:4 17 | % w(i,:,4)=(1+2*r-q)'/8; 18 | % w(i,:,3)=(1+2*r+q)'/8; 19 | % w(i,:,2)=(3-2*r+q)'/8; 20 | % w(i,:,1)=(3-2*r-q)'/8; 21 | % end 22 | % end -------------------------------------------------------------------------------- /IB_matlab_2D/vec_spread.m: -------------------------------------------------------------------------------- 1 | function f=vec_spread(F,X) 2 | % spread F to grid 3 | global h N dtheta Nb; 4 | 5 | c=dtheta/(h*h); 6 | f=zeros(N,N,2); 7 | 8 | s=X/h; % Get body position relative to grid 9 | i=floor(s); 10 | r=s-i; 11 | w=vec_phi1(r(:,1)).*vec_phi2(r(:,2));%Evaluate delta function 12 | w = permute(w, [1,3,2]); %Reogranize, this is quite fast 13 | 14 | 15 | for k=1:Nb 16 | i1=mod((i(k,1)-1):(i(k,1)+2),N)+1; %Find affected cells 17 | i2=mod((i(k,2)-1):(i(k,2)+2),N)+1; 18 | 19 | %Spread force to fluid, this is the costly part (75% of the time for 20 | %N=100) 21 | ww = w(:,:,k); 22 | f(i1,i2,1)=f(i1,i2,1)+(c*F(k,1))*ww; 23 | f(i1,i2,2)=f(i1,i2,2)+(c*F(k,2))*ww; 24 | end 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IB-MATLAB 2 | 3 | This repository will contain 2D/3D matlab codes for the Immersed Boundary method. 4 | 5 | For Immersed Boundary method, see https://www.math.nyu.edu/faculty/peskin/. 6 | 7 | 8 | # Usage 9 | 10 | Play with it and see comments! 11 | 12 | ## Others 13 | 14 | This code orignates from Prof. Charles Peskin's class: "Advanced Topics In Numerical Analysis: Immersed Boundary Method For Fluid Structure Interaction" in Spring 2019, and coauthored by Guanhua Sun and Tristan Goodwill. 15 | -------------------------------------------------------------------------------- /ib_matlab_3D/.gitignore: -------------------------------------------------------------------------------- 1 | # Windows default autosave extension 2 | *.asv 3 | 4 | # OSX / *nix default autosave extension 5 | *.m~ 6 | 7 | # Compiled MEX binaries (all platforms) 8 | *.mex* 9 | 10 | # Packaged app and toolbox files 11 | *.mlappinstall 12 | *.mltbx 13 | 14 | # Generated helpsearch folders 15 | helpsearch*/ 16 | 17 | # Simulink code generation folders 18 | slprj/ 19 | sccprj/ 20 | 21 | # Matlab code generation folders 22 | codegen/ 23 | 24 | # Simulink autosave extension 25 | *.autosave 26 | 27 | # Octave session info 28 | octave-workspace 29 | -------------------------------------------------------------------------------- /ib_matlab_3D/Forcespr.m: -------------------------------------------------------------------------------- 1 | function F=Forcespr(X) 2 | %this force calculation uses the sum of the square of every edge's length as the energy function. 3 | global Nb K ed; 4 | F=zeros(Nb,3); 5 | numed=size(ed,1); 6 | for ei=1:numed 7 | A=X(ed(ei,1),:); 8 | B=X(ed(ei,2),:); 9 | F(ed(ei,1),:)=F(ed(ei,1),:)-K*(B-A); 10 | F(ed(ei,2),:)=F(ed(ei,2),:)-K*(A-B); 11 | end 12 | F=-F; 13 | -------------------------------------------------------------------------------- /ib_matlab_3D/Forcesurf.m: -------------------------------------------------------------------------------- 1 | function F=Forcesurf(X) 2 | %thi force calculation uses the surface energy(the area) as its energy function. 3 | global Nb v K; 4 | F=zeros(Nb,3); 5 | numtri=size(v,1); 6 | for ti=1:numtri 7 | A=X(v(ti,1),:); 8 | B=X(v(ti,2),:); 9 | C=X(v(ti,3),:); 10 | F(v(ti,1),:)=F(v(ti,1),:)+grad(A,B,C); 11 | F(v(ti,2),:)=F(v(ti,2),:)+grad(B,A,C); 12 | F(v(ti,3),:)=F(v(ti,3),:)+grad(C,A,B); 13 | end 14 | F=-F*K; 15 | -------------------------------------------------------------------------------- /ib_matlab_3D/README: -------------------------------------------------------------------------------- 1 | This 3D code contains a triangulation program that triangulates a sphere. The triangulation program was authored by Prof. Charles Peskin. 2 | ib3D.m is the main program. 3 | -------------------------------------------------------------------------------- /ib_matlab_3D/dodec.m: -------------------------------------------------------------------------------- 1 | %dodec.m constructs the vertices of a dodecahedron on the unit sphere 2 | global sr 3 | theta=2*pi/5 4 | z=cos(theta)/(1-cos(theta)) 5 | r=sqrt(1-z^2) 6 | 7 | x( 1,:)=[0,0, 1]; 8 | x(12,:)=[0,0,-1]; 9 | for j=1:5 10 | k=j-.5; 11 | x(1+j,:)=[r*cos(j*theta),r*sin(j*theta), z]; 12 | x(6+j,:)=[r*cos(k*theta),r*sin(k*theta),-z]; 13 | end 14 | 15 | nv=12 16 | x(1:nv,:) 17 | 18 | v(1,:)=[1,2,3]; 19 | v(2,:)=[1,3,4]; 20 | v(3,:)=[1,4,5]; 21 | v(4,:)=[1,5,6]; 22 | v(5,:)=[1,6,2]; 23 | 24 | v(6,:)=[2,8,3]; 25 | v(7,:)=[3,9,4]; 26 | v(8,:)=[4,10,5]; 27 | v(9,:)=[5,11,6]; 28 | v(10,:)=[6,7,2]; 29 | 30 | v(11,:)=[8,2,7]; 31 | v(12,:)=[9,3,8]; 32 | v(13,:)=[10,4,9]; 33 | v(14,:)=[11,5,10]; 34 | v(15,:)=[7,6,11]; 35 | 36 | v(16,:)=[7,12,8]; 37 | v(17,:)=[8,12,9]; 38 | v(18,:)=[9,12,10]; 39 | v(19,:)=[10,12,11]; 40 | v(20,:)=[11,12,7]; 41 | 42 | nt=20 43 | v(1:nt,:) 44 | 45 | clf 46 | %triplot 47 | 48 | -------------------------------------------------------------------------------- /ib_matlab_3D/fluid.m: -------------------------------------------------------------------------------- 1 | function [uuu,uu,ppp]=fluid(u,ff) 2 | %uuu outputs the final velocity, where uu is the output in between. 3 | %See notes on https://www.math.nyu.edu/faculty/peskin/ib_lecture_notes/index.html 4 | %ppp outputs the final pressure. 5 | global a dt rho mu b; 6 | w=u-(dt/2)*skew(u)+(dt/(2*rho))*ff; 7 | w=fft(w,[],1); 8 | w=fft(w,[],2); 9 | w=fft(w,[],3); 10 | 11 | uu(:,:,:,1)=a(:,:,:,1,1).*w(:,:,:,1)+a(:,:,:,1,2).*w(:,:,:,2)+a(:,:,:,1,3).*w(:,:,:,3); 12 | uu(:,:,:,2)=a(:,:,:,2,1).*w(:,:,:,1)+a(:,:,:,2,2).*w(:,:,:,2)+a(:,:,:,2,3).*w(:,:,:,3); 13 | uu(:,:,:,3)=a(:,:,:,3,1).*w(:,:,:,1)+a(:,:,:,3,2).*w(:,:,:,2)+a(:,:,:,3,3).*w(:,:,:,3); 14 | 15 | 16 | uu=ifft(uu,[],3); 17 | uu=ifft(uu,[],2); 18 | uu=real(ifft(uu,[],1)); 19 | w=u-dt*skew(uu)+(dt/rho)*ff+(dt/2)*(mu/rho)*laplacian(u); 20 | w=fft(w,[],1); 21 | w=fft(w,[],2); 22 | w=fft(w,[],3); 23 | 24 | 25 | uuu(:,:,:,1)=a(:,:,:,1,1).*w(:,:,:,1)+a(:,:,:,1,2).*w(:,:,:,2)+a(:,:,:,1,3).*w(:,:,:,3); 26 | uuu(:,:,:,2)=a(:,:,:,2,1).*w(:,:,:,1)+a(:,:,:,2,2).*w(:,:,:,2)+a(:,:,:,2,3).*w(:,:,:,3); 27 | uuu(:,:,:,3)=a(:,:,:,3,1).*w(:,:,:,1)+a(:,:,:,3,2).*w(:,:,:,2)+a(:,:,:,3,3).*w(:,:,:,3); 28 | 29 | ppp=b(:,:,:,1).*w(:,:,:,1)+b(:,:,:,2).*w(:,:,:,2)+b(:,:,:,3).*w(:,:,:,3); 30 | ppp=ifft(ppp,[],3); 31 | ppp=ifft(ppp,[],2); 32 | ppp=real(ifft(ppp,[],1)); 33 | %ppp is the pressure output 34 | uuu=ifft(uuu,[],3); 35 | uuu=ifft(uuu,[],2); 36 | uuu=real(ifft(uuu,[],1)); 37 | -------------------------------------------------------------------------------- /ib_matlab_3D/grad.m: -------------------------------------------------------------------------------- 1 | %grad2 2 | function [grad] =grad(A,B,C) 3 | base=sqrt(sum((B-C).^2)); 4 | n=cross(B-A,C-A); 5 | un=n/norm(n); 6 | dir=cross(B-C,un); 7 | dir=dir/norm(dir); 8 | grad=dir*base/2; 9 | end -------------------------------------------------------------------------------- /ib_matlab_3D/ib3D.m: -------------------------------------------------------------------------------- 1 | % ib3D.m 2 | % This script is the main program. 3 | %Coauthored by Guanhua Sun & Tristan Goodwill,2019.4 4 | %Original Code: 5 | %https://www.math.nyu.edu/faculty/peskin/ib_lecture_notes/index.html 6 | 7 | global dt Nb N h rho mu ip im a b tri v K triarea ed; 8 | 9 | initialize 10 | init_a 11 | init_b 12 | 13 | for clock=1:clockmax 14 | t=clock*dt 15 | XX=X+(dt/2)*vec_interp(u,X); 16 | ff=vec_spread(Forcespr(XX),XX); 17 | [u,uu,ppp]=fluid(u,ff); 18 | X=X+dt*vec_interp(uu,XX); 19 | 20 | tri=triangulation(v,X); 21 | trisurf(tri); 22 | 23 | hold on 24 | quiver3(xgrid,ygrid,zgrid,ff(:,:,:,1),ff(:,:,:,2),ff(:,:,:,3),3); 25 | %3plot the body force on the fluid 26 | hold off 27 | 28 | 29 | axis equal 30 | axis ([0,L,0,L,0,L]) 31 | title(["t=",t]) 32 | 33 | drawnow 34 | hold off 35 | 36 | end 37 | 38 | -------------------------------------------------------------------------------- /ib_matlab_3D/init_a.m: -------------------------------------------------------------------------------- 1 | %init_a.m 2 | %This script initializes the array a 3 | %that is used in the fluid solver 4 | 5 | global a; 6 | a=zeros(N,N,N,3,3); 7 | for m1=0:(N-1) 8 | for m2=0:(N-1) 9 | for m3=0:(N-1) 10 | a(m1+1,m2+1,m3+1,1,1)=1; 11 | a(m1+1,m2+1,m3+1,2,2)=1; 12 | a(m1+1,m2+1,m3+1,3,3)=1; 13 | end 14 | end 15 | end 16 | 17 | for m1=0:(N-1) 18 | for m2=0:(N-1) 19 | for m3=0:(N-1) 20 | if~(((m1==0)|(m1==N/2))&((m2==0)|(m2==N/2))&((m3==0)|(m3==N/2))) 21 | t=(2*pi/N)*[m1;m2;m3]; 22 | s=sin(t); 23 | ss=(s*s')/(s'*s); 24 | % a(m1+1,m2+1,:,:)=a(m1+1,m2+1,:,:)-(s*s')/(s'*s); 25 | a(m1+1,m2+1,m3+1,1,1)=a(m1+1,m2+1,m3+1,1,1)-ss(1,1); 26 | a(m1+1,m2+1,m3+1,1,2)=a(m1+1,m2+1,m3+1,1,2)-ss(1,2); 27 | a(m1+1,m2+1,m3+1,1,3)=a(m1+1,m2+1,m3+1,1,3)-ss(1,3); 28 | 29 | a(m1+1,m2+1,m3+1,2,1)=a(m1+1,m2+1,m3+1,2,1)-ss(2,1); 30 | a(m1+1,m2+1,m3+1,2,2)=a(m1+1,m2+1,m3+1,2,2)-ss(2,2); 31 | a(m1+1,m2+1,m3+1,2,3)=a(m1+1,m2+1,m3+1,2,3)-ss(2,3); 32 | 33 | a(m1+1,m2+1,m3+1,3,1)=a(m1+1,m2+1,m3+1,3,1)-ss(3,1); 34 | a(m1+1,m2+1,m3+1,3,2)=a(m1+1,m2+1,m3+1,3,2)-ss(3,2); 35 | a(m1+1,m2+1,m3+1,3,3)=a(m1+1,m2+1,m3+1,3,3)-ss(3,3); 36 | 37 | end 38 | end 39 | end 40 | end 41 | 42 | for m1=0:(N-1) 43 | for m2=0:(N-1) 44 | for m3=0:(N-1) 45 | t=(pi/N)*[m1;m2;m3]; 46 | s=sin(t); 47 | a(m1+1,m2+1,m3+1,:,:)=a(m1+1,m2+1,m3+1,:,:)... 48 | /(1+(dt/2)*(mu/rho)*(4/(h*h))*(s'*s)); 49 | 50 | end 51 | end 52 | end 53 | 54 | -------------------------------------------------------------------------------- /ib_matlab_3D/init_b.m: -------------------------------------------------------------------------------- 1 | %init_b.m 2 | %This script initializes the array b 3 | %that is used in the fluid solver to extract pressure output 4 | global b 5 | 6 | b=zeros(N,N,N,3); 7 | 8 | for m1=0:(N-1) 9 | for m2=0:(N-1) 10 | for m3=0:(N-1) 11 | if~(((m1==0)||(m1==N/2))&&((m2==0)||(m2==N/2))&&((m3==0)||(m3==N/2))) 12 | t=2*pi/N*[m1;m2;m3]; 13 | s=sin(t); 14 | c = - (1i*rho*h/dt)/(s(1)^2+s(2)^2+s(3)^2); 15 | b(m1+1,m2+1,m3+1,1) = c*s(1); 16 | b(m1+1,m2+1,m3+1,2) = c*s(2); 17 | b(m1+1,m2+1,m3+1,3) = c*s(3); 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /ib_matlab_3D/initialize.m: -------------------------------------------------------------------------------- 1 | %initialize.m 2 | 3 | L=1.0 %domain length 4 | N=32 %mesh number 5 | h=L/N %mesh width 6 | ip=[(2:N),1] 7 | im=[N,(1:(N-1))] 8 | 9 | 10 | K=0.1 %spring constant between boundary points 11 | rho=1 %density 12 | mu=0.01 %viscosity 13 | tmax=4 %simulation time 14 | dt=0.01 %timestep 15 | clockmax=ceil(tmax/dt) 16 | 17 | 18 | [X v]=trisph(1/3,1/2,4); %trisph(r,a,nref) creates a triangulated sphere of raidus r, centered at a and nref times refined. 19 | tri=triangulation(v,X); 20 | 21 | numtri=size(tri,1); 22 | 23 | Nb=size(X,1);%this is the right number of boundary points 24 | 25 | %reference area for each triangle 26 | triarea=zeros(numtri,1); 27 | for i=1:numtri 28 | triarea(i,1)=tarea(X(v(i,1),:),X(v(i,2),:),X(v(i,3),:)); 29 | end 30 | 31 | ed=edges(tri); 32 | numed=size(ed,1); 33 | elength=0; 34 | for ei=1:numed 35 | A=X(ed(ei,1),:); 36 | B=X(ed(ei,2),:); 37 | el=(sum((A-B).^2)); 38 | elength=elength+el; 39 | end 40 | u=zeros(N,N,N,3); 41 | % initial perturbation, here is a plane wave. 42 | au1=[0 0 1]; 43 | ku1=[0 1 0]; 44 | au2=[1 0 0]; 45 | ku2=[0 0 1]; 46 | 47 | 48 | for j1=0:(N-1) 49 | for j2=0:(N-1) 50 | for j3=0:(N-1) 51 | xu=[j1 j2 j3]*h; 52 | u(j1+1,j2+1,j3+1,:)=au1*sin(2*pi/L*xu(2))+au2*sin(2*pi/L*xu(3)); 53 | end 54 | end 55 | end 56 | 57 | vorticity=(u(:,ip,:,3)-u(:,im,:,3)-u(:,ip,:,2)+u(:,im,:,2)... 58 | -(u(ip,:,:,3)-u(im,:,:,3)-u(:,:,ip,1)+u(:,:,im,1))... 59 | +(u(ip,:,:,2)-u(im,:,:,2)-u(:,ip,:,1)+u(:,im,:,1)))/(2*h); 60 | 61 | 62 | 63 | xgrid=zeros(N,N,N); 64 | ygrid=zeros(N,N,N); 65 | zgrid=zeros(N,N,N); 66 | for j=0:(N-1) 67 | xgrid(j+1,:,:)=j*h; 68 | ygrid(:,j+1,:)=j*h; 69 | zgrid(:,:,j+1)=j*h; 70 | end 71 | 72 | trisurf(tri); 73 | axis equal 74 | axis([0,L,0,L,0,L]) 75 | drawnow 76 | 77 | -------------------------------------------------------------------------------- /ib_matlab_3D/interp.m: -------------------------------------------------------------------------------- 1 | function U=interp(u,X) 2 | global Nb h; 3 | global N; 4 | U=zeros(Nb,3); 5 | for k=1:Nb 6 | s=X(k,:,:)/h; 7 | i=floor(s); 8 | %i1=floor(s1); 9 | %i2=floor(s2); 10 | %i3=floor(s3); 11 | %r1=s1-i1; 12 | %r2=s2-i2; 13 | %r3=s3-i3; 14 | r=s-i; 15 | i1=mod((i(1)-1):(i(1)+2),N)+1; 16 | i2=mod((i(2)-1):(i(2)+2),N)+1; 17 | i3=mod((i(3)-1):(i(3)+2),N)+1; 18 | w=phi1(r(1)).*phi2(r(2)).*phi3(r(3)); 19 | U(k,1)=sum(sum(sum(w.*u(i1,i2,i3,1)))); 20 | U(k,2)=sum(sum(sum(w.*u(i1,i2,i3,2)))); 21 | U(k,3)=sum(sum(sum(w.*u(i1,i2,i3,3)))); 22 | end 23 | 24 | -------------------------------------------------------------------------------- /ib_matlab_3D/laplacian.m: -------------------------------------------------------------------------------- 1 | function w=laplacian(u) 2 | global im ip h; 3 | w=(u(ip,:,:,:)+u(im,:,:,:)+u(:,ip,:,:)+u(:,im,:,:)+... 4 | u(:,:,ip,:)+u(:,:,im,:)-6*u)/(h*h); 5 | 6 | % im = [N,1:(N-1)] = circular version of i-1 7 | % ip = [2:N,1] = circular version of i+1 8 | % N = number of points in each space direction 9 | 10 | -------------------------------------------------------------------------------- /ib_matlab_3D/locate.m: -------------------------------------------------------------------------------- 1 | function xout=locate(v1,v2,x) 2 | %locate the perpendicular bisector of the great circle joining 3 | %the points whose indices are stored in rows v1 and v2 of x 4 | xout=(x(v1,:)+x(v2,:))/2; 5 | r=sqrt(xout(1)^2+xout(2)^2+xout(3)^2); 6 | xout=xout/r; 7 | 8 | -------------------------------------------------------------------------------- /ib_matlab_3D/refine.m: -------------------------------------------------------------------------------- 1 | %refine.m script to refine triangulation of the sphere 2 | vnew=zeros(1,3); 3 | next3=[2,3,1]; 4 | a=zeros(nv,nv); 5 | for t=1:nt 6 | for j=1:3 7 | v1=v(t,next3(j)); 8 | v2=v(t,next3(next3(j))); 9 | if(a(v1,v2)==0) 10 | nv=nv+1; 11 | vnew(j)=nv; 12 | x(nv,:)=locate(v1,v2,x); 13 | a(v1,v2)=nv; 14 | a(v2,v1)=nv; 15 | else 16 | vnew(j)=a(v1,v2); 17 | end 18 | end 19 | v(1*nt+t,:)=[v(t,1),vnew(3),vnew(2)]; 20 | v(2*nt+t,:)=[v(t,2),vnew(1),vnew(3)]; 21 | v(3*nt+t,:)=[v(t,3),vnew(2),vnew(1)]; 22 | v(t,:)=vnew; 23 | end 24 | nt=nt*4; -------------------------------------------------------------------------------- /ib_matlab_3D/rsphere.m: -------------------------------------------------------------------------------- 1 | function x=rsphere(n) % find n random points on the unit sphere 2 | x=zeros(n,3); 3 | x(:,3)=2*(rand(n,1)-0.5); 4 | alpha=sqrt(1-x(:,3).^2); 5 | theta=2*pi*rand(n,1); 6 | x(:,1)=alpha.*cos(theta); 7 | x(:,2)=alpha.*sin(theta); 8 | plot3(x(:,1),x(:,2),x(:,3),'.') 9 | 10 | -------------------------------------------------------------------------------- /ib_matlab_3D/sk.m: -------------------------------------------------------------------------------- 1 | function f=sk(u,g) 2 | global ip im h; 3 | f=((u(ip,:,:,1)+u(:,:,:,1)).*g(ip,:,:)... 4 | -(u(im,:,:,1)+u(:,:,:,1)).*g(im,:,:)... 5 | +(u(:,ip,:,2)+u(:,:,:,2)).*g(:,ip,:)... 6 | -(u(:,im,:,2)+u(:,:,:,2)).*g(:,im,:)... 7 | +(u(:,:,ip,3)+u(:,:,:,3)).*g(:,:,ip)... 8 | -(u(:,:,im,3)+u(:,:,:,3)).*g(:,:,im))/(6*h); 9 | -------------------------------------------------------------------------------- /ib_matlab_3D/skew.m: -------------------------------------------------------------------------------- 1 | function w=skew(u) 2 | w=u; %note that this is done only to make w the same size as u 3 | w(:,:,:,1)=sk(u,u(:,:,:,1)); 4 | w(:,:,:,2)=sk(u,u(:,:,:,2)); 5 | w(:,:,:,3)=sk(u,u(:,:,:,3)); 6 | -------------------------------------------------------------------------------- /ib_matlab_3D/tarea.m: -------------------------------------------------------------------------------- 1 | function [s] = tarea(X,Y,Z) 2 | %calculate the area of a triangle, given three vertices:X Y Z 3 | x1=(Y-X); 4 | x2=(Z-X); 5 | s=1/2*norm(cross(x1,x2)); 6 | end 7 | 8 | -------------------------------------------------------------------------------- /ib_matlab_3D/triplot.m: -------------------------------------------------------------------------------- 1 | %triplot.m plots vertices and triangles 2 | 3 | figure 4 | 5 | hold on 6 | plot3(x(1:nv,1),x(1:nv,2),x(1:nv,3),'ko') 7 | 8 | xplot=zeros(4,3); 9 | 10 | for t=1:nt 11 | v1=v(t,1); 12 | v2=v(t,2); 13 | v3=v(t,3); 14 | xplot(1,:)=x(v1,:); 15 | xplot(2,:)=x(v2,:); 16 | xplot(3,:)=x(v3,:); 17 | xplot(4,:)=x(v1,:); 18 | plot3(xplot(:,1),xplot(:,2),xplot(:,3)) 19 | end 20 | 21 | view(0,0) 22 | 23 | hold off -------------------------------------------------------------------------------- /ib_matlab_3D/trisph.m: -------------------------------------------------------------------------------- 1 | %sphere.m main program 2 | 3 | function [x v]=trisph(rad,ctr,numr) 4 | 5 | nref=numr; 6 | nvmax=12*4^nref; 7 | ntmax=20*4^nref; 8 | x=zeros(nvmax,3); 9 | v=zeros(ntmax,3); 10 | dodec 11 | for nr=1:nref 12 | refine 13 | end 14 | x=x*rad+ctr; 15 | x=x(1:nv,:); 16 | 17 | %axis equal 18 | -------------------------------------------------------------------------------- /ib_matlab_3D/vec_interp.m: -------------------------------------------------------------------------------- 1 | function U=vec_interp(u,X) 2 | % interpolate fluid velocity to the body 3 | global Nb h; 4 | global N; 5 | U=zeros(Nb,3); 6 | s=X/h; % Get body position relative to grid 7 | i=floor(s); 8 | r=s-i; 9 | w=vec_phi1(r(:,1)).*vec_phi2(r(:,2)).*vec_phi3(r(:,3)); %Evaluate delta function 10 | w = permute(w, [1,3,4,2]); %Reogranize 11 | for k = 1:Nb 12 | i1=mod((i(k,1)-1):(i(k,1)+2),N)+1; % Find adjacent fluid cells 13 | i2=mod((i(k,2)-1):(i(k,2)+2),N)+1; 14 | i3=mod((i(k,3)-1):(i(k,3)+2),N)+1; 15 | 16 | ww = w(:,:,:,k); 17 | UU = [sum(sum(sum(ww.*u(i1,i2,i3,1)))), sum(sum(sum(ww.*u(i1,i2,i3,2)))),... 18 | sum(sum(sum(ww.*u(i1,i2,i3,3))))]; %Interpolate 19 | 20 | U(k,:,:)= UU(1,:); 21 | end 22 | % for k=1:Nb 23 | % s=X(k,:)/h; 24 | % i=floor(s); 25 | % r=s-i; 26 | % i1=mod((i(1)-1):(i(1)+2),N)+1; 27 | % i2=mod((i(2)-1):(i(2)+2),N)+1; 28 | % w=phi1(r(1)).*phi2(r(2)); 29 | % UU = [sum(sum(w.*u(i1,i2,1))), sum(sum(w.*u(i1,i2,2)))]; 30 | % U(k,:)= UU; 31 | % end 32 | 33 | -------------------------------------------------------------------------------- /ib_matlab_3D/vec_phi1.m: -------------------------------------------------------------------------------- 1 | function w=vec_phi1(r) 2 | % 4 point delta function in y, vectorizing makes this 10x faster for Nb = 3 | % 100 4 | w=zeros(4,size(r,1),4,4); 5 | q=sqrt(1+4*r.*(1-r)); 6 | w(4,:,:,:)=repmat((1+2*r-q)/8,[1,1,4,4]); 7 | w(3,:,:,:)=repmat((1+2*r+q)/8,[1,1,4,4]); 8 | w(2,:,:,:)=repmat((3-2*r+q)/8,[1,1,4,4]); 9 | w(1,:,:,:)=repmat((3-2*r-q)/8,[1,1,4,4]); 10 | end 11 | 12 | %% The following are alternatives that are twice as slow 13 | % function w=vec_phi1(r) 14 | % % 4 point delta function in y 15 | % w=zeros(4,4,size(r,1)); 16 | % q=sqrt(1+4*r.*(1-r)); 17 | % for i = 1:4 18 | % w(4,i,:)=(1+2*r-q)/8; 19 | % w(3,i,:)=(1+2*r+q)/8; 20 | % w(2,i,:)=(3-2*r+q)/8; 21 | % w(1,i,:)=(3-2*r-q)/8; 22 | % end 23 | % 24 | % function w=vec_phi1(r) 25 | % % 4 point delta function in y 26 | % w=zeros(4,size(r,1),4); 27 | % q=sqrt(1+4*r.*(1-r)); 28 | % for i = 1:4 29 | % w(4,:,i)=(1+2*r-q)/8; 30 | % w(3,:,i)=(1+2*r+q)/8; 31 | % w(2,:,i)=(3-2*r+q)/8; 32 | % w(1,:,i)=(3-2*r-q)/8; 33 | % end -------------------------------------------------------------------------------- /ib_matlab_3D/vec_phi2.m: -------------------------------------------------------------------------------- 1 | function w=vec_phi2(r) 2 | % 4 point delta function in x, vectorizing makes this 15x faster for 3 | % Nb=100 4 | w=zeros(4,size(r,1),4,4); 5 | q=sqrt(1+4*r.*(1-r)); 6 | w(:,:,4,:)=repmat((1+2*r-q)'/8,[4,1,4]); 7 | w(:,:,3,:)=repmat((1+2*r+q)'/8,[4,1,4]); 8 | w(:,:,2,:)=repmat((3-2*r+q)'/8,[4,1,4]); 9 | w(:,:,1,:)=repmat((3-2*r-q)'/8,[4,1,4]); 10 | end 11 | %% The following is 50% slower 12 | % function w=vec_phi2(r) 13 | % % 4 point delta function in x 14 | % w=zeros(4,size(r,1),4); 15 | % q=sqrt(1+4*r.*(1-r)); 16 | % for i =1:4 17 | % w(i,:,4)=(1+2*r-q)'/8; 18 | % w(i,:,3)=(1+2*r+q)'/8; 19 | % w(i,:,2)=(3-2*r+q)'/8; 20 | % w(i,:,1)=(3-2*r-q)'/8; 21 | % end 22 | % end -------------------------------------------------------------------------------- /ib_matlab_3D/vec_phi3.m: -------------------------------------------------------------------------------- 1 | function w=vec_phi3(r) 2 | % 4 point delta function in x, vectorizing makes this 15x faster for 3 | % Nb=100 4 | w=zeros(4,size(r,1),4,4); 5 | q=sqrt(1+4*r.*(1-r)); 6 | w(:,:,:,4)=repmat((1+2*r-q)'/8,[4,1,4]); 7 | w(:,:,:,3)=repmat((1+2*r+q)'/8,[4,1,4]); 8 | w(:,:,:,2)=repmat((3-2*r+q)'/8,[4,1,4]); 9 | w(:,:,:,1)=repmat((3-2*r-q)'/8,[4,1,4]); 10 | end -------------------------------------------------------------------------------- /ib_matlab_3D/vec_spread.m: -------------------------------------------------------------------------------- 1 | function f=vec_spread(F,X) 2 | % spread F to grid 3 | global h N Nb; 4 | 5 | c=1/(h*h*h); 6 | f=zeros(N,N,N,3); 7 | 8 | s=X/h; % Get body position relative to grid 9 | i=floor(s); 10 | r=s-i; 11 | w=vec_phi1(r(:,1)).*vec_phi2(r(:,2)).*vec_phi3(r(:,3));%Evaluate delta function 12 | w = permute(w, [1,3,4,2]); 13 | 14 | 15 | for k=1:Nb 16 | i1=mod((i(k,1)-1):(i(k,1)+2),N)+1; %Find affected cells 17 | i2=mod((i(k,2)-1):(i(k,2)+2),N)+1; 18 | i3=mod((i(k,3)-1):(i(k,3)+2),N)+1; 19 | ww = w(:,:,:,k); 20 | f(i1,i2,i3,1)=f(i1,i2,i3,1)+(c*F(k,1))*ww; %Spread force to fluid 21 | f(i1,i2,i3,2)=f(i1,i2,i3,2)+(c*F(k,2))*ww; 22 | f(i1,i2,i3,3)=f(i1,i2,i3,3)+(c*F(k,3))*ww; 23 | end 24 | 25 | -------------------------------------------------------------------------------- /ib_matlab_3D/vpoly.m: -------------------------------------------------------------------------------- 1 | function vsph=vpoly(X) 2 | %this function calculates the volume of a triangulted polyhedron whose points on every triangle is counterclockwise oriented. 3 | global v 4 | vsph=0; 5 | numtri=size(v,1); 6 | %vnorm=[0 0 1]; 7 | for ti =1:numtri 8 | A=X(v(ti,1),:); 9 | B=X(v(ti,2),:); 10 | C=X(v(ti,3),:); 11 | vol=1/6*dot(cross(A,B),C); 12 | vsph=vsph+vol; 13 | end 14 | 15 | --------------------------------------------------------------------------------