SIMPLE method with matlab
Hi,I wrote a Simple method by matlab.
However it's very POOR program and not smart. I hope it can help someone who need a matlab program. And I want to know,Why,When I solved out the pressure correction and correct the velocity,the mass is still highly unbalanced(still,the final result seems not bad!) clear all; %initialization nx=100; ny=30; %velcity field u=zeros(ny+2,nx+1,3); v=zeros(ny+1,nx+2,3); %pressure p=zeros(ny,nx,3); %co. for momentum equation aeu=zeros(ny+2,nx+1); awu=zeros(ny+2,nx+1); asu=zeros(ny+2,nx+1); anu=zeros(ny+2,nx+1); apu=zeros(ny+2,nx+1); aev=zeros(ny+1,nx+2); awv=zeros(ny+1,nx+2); asv=zeros(ny+1,nx+2); anv=zeros(ny+1,nx+2); apv=zeros(ny+1,nx+2); %co. for pressure correction equation pce=zeros(ny,nx); pcw=zeros(ny,nx); pcs=zeros(ny,nx); pcn=zeros(ny,nx); aep=zeros(ny,nx); awp=zeros(ny,nx); asp=zeros(ny,nx); anp=zeros(ny,nx); app=zeros(ny,nx); aepc=zeros(ny,nx); awpc=zeros(ny,nx); anpc=zeros(ny,nx); aspc=zeros(ny,nx); appc=zeros(ny,nx); pc=zeros(ny+2,nx+2,3); %mass unbalance mp=zeros(ny,nx); errp=zeros(ny,nx); raw=1000; dx=0.001/ny; dy=0.001/ny; d=0.001; u(2:ny+1,:,:)=0.01; for q=1:5000 %%%%%%%%%%%%%%%%%%%%%%%%%momentum equation%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for ll=1:10 for i=2:ny+1 for j=2:nx if i==2 aeu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))); awu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))); asu(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*v(i1,j+1,1)+0.25*v(i1,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))); anu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))); if j==nx aeu(i,j)=0; end apu(i,j)=aeu(i,j)+awu(i,j)+asu(i,j)+anu(i,j); u(i,j,1)=(aeu(i,j)*u(i,j+1,1)+awu(i,j)*u(i,j1,1)+anu(i,j)*u(i+1,j,1)+asu(i,j)*u(i1,j,1)+(p(i1,j1,1)p(i1,j,1))*dy)/apu(i,j); else if i==ny+1 aeu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))); awu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))); asu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))); anu(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*v(i,j+1,1)+0.25*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))); if j==nx aeu(i,j)=0; end apu(i,j)=aeu(i,j)+awu(i,j)+asu(i,j)+anu(i,j); u(i,j,1)=(aeu(i,j)*u(i,j+1,1)+awu(i,j)*u(i,j1,1)+anu(i,j)*u(i+1,j,1)+asu(i,j)*u(i1,j,1)+(p(i1,j1,1)p(i1,j,1))*dy)/apu(i,j); else aeu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))); awu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))); asu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))); anu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))); if j==nx aeu(i,j)=0; end apu(i,j)=aeu(i,j)+awu(i,j)+asu(i,j)+anu(i,j); u(i,j,1)=(aeu(i,j)*u(i,j+1,1)+awu(i,j)*u(i,j1,1)+anu(i,j)*u(i+1,j,1)+asu(i,j)*u(i1,j,1)+(p(i1,j1,1)p(i1,j,1))*dy)/apu(i,j); end end end end u(:,nx,1)=u(:,nx,1)*(sum(u(:,1,1))/sum(u(:,nx,1))); u(:,nx+1,1)=u(:,nx,1); for i=2:ny for j=2:nx+1 if j==2 aev(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))); awv(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*u(i,j1,1)+0.25*u(i+1,j1,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))); asv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))); anv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))); if j==nx+1 aev(i,j)=0; end apv(i,j)=aev(i,j)+awv(i,j)+asv(i,j)+anv(i,j); v(i,j,1)=(aev(i,j)*v(i,j+1,1)+awv(i,j)*v(i,j1,1)+anv(i,j)*v(i+1,j,1)+asv(i,j)*v(i1,j,1)+(p(i1,j1,1)p(i,j1,1))*dy)/apv(i,j); else if j==nx+1 aev(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*u(i,j,1)+0.25*u(i+1,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))); awv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))); asv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))); anv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))); if j==nx+1 aev(i,j)=0; end apv(i,j)=aev(i,j)+awv(i,j)+asv(i,j)+anv(i,j); v(i,j,1)=(aev(i,j)*v(i,j+1,1)+awv(i,j)*v(i,j1,1)+anv(i,j)*v(i+1,j,1)+asv(i,j)*v(i1,j,1)+(p(i1,j1,1)p(i,j1,1))*dy)/apv(i,j); else aev(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))); awv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))); asv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))); anv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))); if j==nx+1 aev(i,j)=0; end apv(i,j)=aev(i,j)+awv(i,j)+asv(i,j)+anv(i,j); v(i,j,1)=(aev(i,j)*v(i,j+1,1)+awv(i,j)*v(i,j1,1)+anv(i,j)*v(i+1,j,1)+asv(i,j)*v(i1,j,1)+(p(i1,j1,1)p(i,j1,1))*dy)/apv(i,j); end end end end end %%%%%%%%%%%%%%%%%%%pressure correction%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %co. for pressure correction for i=2:ny+1 for j=2:nx if i==2 aeu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))); awu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))); asu(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*v(i1,j+1,1)+0.25*v(i1,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))); anu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))); if j==nx aeu(i,j)=0; end apu(i,j)=aeu(i,j)+awu(i,j)+asu(i,j)+anu(i,j); else if i==ny+1 aeu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))); awu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))); asu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))); anu(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*v(i,j+1,1)+0.25*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))); if j==nx aeu(i,j)=0; end apu(i,j)=aeu(i,j)+awu(i,j)+asu(i,j)+anu(i,j); else aeu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j+1,1)+0.5*u(i,j,1))); awu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i,j,1))); asu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j+1,1)+0.5*v(i1,j,1))); anu(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i,j+1,1)+0.5*v(i,j,1))); if j==nx aeu(i,j)=0; end apu(i,j)=aeu(i,j)+awu(i,j)+asu(i,j)+anu(i,j); end end end end for i=2:ny for j=2:nx+1 if j==2 aev(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))); awv(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*u(i,j1,1)+0.25*u(i+1,j1,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))); asv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))); anv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))); apv(i,j)=aev(i,j)+awv(i,j)+asv(i,j)+anv(i,j); else if j==nx+1 aev(i,j)=2*d*max(0,(10.1*abs(raw*dy*(0.25*u(i,j,1)+0.25*u(i+1,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))); awv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))); asv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))); anv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))); apv(i,j)=aev(i,j)+awv(i,j)+asv(i,j)+anv(i,j); else aev(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j,1)+0.5*u(i+1,j,1))); awv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))/d))^5)+max(0,raw*dy*(0.5*u(i,j1,1)+0.5*u(i+1,j1,1))); asv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i1,j,1)+0.5*v(i,j,1))); anv(i,j)=d*max(0,(10.1*abs(raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))/d))^5)+max(0,raw*dy*(0.5*v(i+1,j,1)+0.5*v(i,j,1))); apv(i,j)=aev(i,j)+awv(i,j)+asv(i,j)+anv(i,j); end end end end for i=1:ny for j=2:nx1 aepc(i,j)=raw*dy^2/apu(i+1,j+1); awpc(i,j)=raw*dy^2/apu(i+1,j); end end for i=2:ny1 for j=1:nx anpc(i,j)=raw*dx^2/apv(i+1,j+1); aspc(i,j)=raw*dx^2/apv(i,j+1); end end for i=1:ny awpc(i,1)=0; aepc(i,1)=raw*dy^2/apu(i+1,2); awpc(i,nx)=raw*dy^2/apu(i+1,nx); aepc(i,nx)=0; end for j=1:nx anpc(1,j)=raw*dx^2/apv(2,j+1); aspc(1,j)=0; anpc(ny,j)=0; aspc(ny,j)=raw*dx^2/apv(ny,j+1); end for i=1:ny for j=1:nx appc(i,j)=aepc(i,j)+awpc(i,j)+anpc(i,j)+aspc(i,j); end end for i=1:ny for j=1:nx mp(i,j)=raw*dx*((u(i+1,j+1,1)u(i+1,j,1))+(v(i+1,j+1,1)v(i,j+1,1))); end end for ll=1:1000 for i=2:ny+1 for j=2:nx+1 pc(i,j,1)=(pc(i,j+1,1)*aepc(i1,j1)+pc(i,j1,1)*awpc(i1,j1)+pc(i+1,j,1)*anpc(i1,j1)+pc(i1,j,1)*aspc(i1,j1)mp(i1,j1))/appc(i1,j1); end end end ref=pc(2,2,1); for i=2:ny+1 for j=2:nx+1 pc(i,j,1)=pc(i,j,1)ref; end end for i=1:ny for j=1:nx p(i,j,1)=p(i,j,1)+0.01*pc(i+1,j+1,1); end end for i=2:ny+1 for j=2:nx u(i,j,1)=u(i,j,1)+dx/apu(i,j)*(pc(i,j,1)pc(i,j+1,1)); end end for i=2:ny for j=2:nx v(i,j,1)=v(i,j,1)+dy/apv(i,j)*(pc(i,j,1)pc(i+1,j,1)); end end err=norm(mp(:,:)) if err<10^5 break end for i=2:ny1 for j=2:nx1 mp(i,j)=raw*dx*((u(i,j+1,1)u(i,j,1))+(v(i+1,j,1)v(i,j,1))); end end end contourf(u(2:31,:,1),30);axis equal 
hi
Can you explain SIMPLE ? 
If you want to improve your code you should make more use of matrices. Matrix calculation is what matlab does best (MATrix LABoratory).
For instance let's say we want to take a second derivative of our velocity field U (2D). In formula form: (U(i+1,j)2*U(i,j)+U(i1,j))/dx^2 We could also write this down in matrix form, namely: [ 2 1 0 ; 1 2 1 ; 0 1 2 ] or to create a nxn matrix of this type we can write in matlab A = diag(ones(n1,1),1) E = 2*eye(n)  A A' Where E is now our desired second difference matrix. Multiply U*E will give our second derivate at each location (but beware of correctly imposing BCs). You should check the speed increase, it's huge (Matlabs for loops are very slow). And whats even better it is easier to use and gives more compact coding. A next step could be to use the spare matrix identity. If you let matlab know if a matrix is spare (like a large nxn difference matrix) it will result in quicker computation and less memory use. As for your question: A well posed pressure correction should make your solution divergence free. If this is not the case then something must be off. I would advice to write down (on a piece of paper) the mathematical equations and see for yourself how you want to pressurecorrection scheme to work. Using a staggered grid (defining velocity on cell faces, pressure in the center) is the way to go for a proper pressurevelocity coupling. Good luck! 
Quote:
As for the pressure correction,yes,I studied it again and I notice BECAUSE in SIMPLE algorithm,it usually drop the temporary mass unbalance when doing the velocity correction,thus,even I get a perfect solution for pressure correction equation,it will not totally make the velocity field to be divergence free.Am I right?? 
The whole idea of solving the pressure correction equation is to make the velocity divergence free. After solving the pressure correction equation and correcting the velocities, theoretically speaking continuity equation should be exaclty satisfied i.e. velocity field should be exactly divergence free (enough though momentum equation is not). But usually, the velocity corrections (after pressure correction equation is solved) use approximate formulas. Hence, there is small residual error in the continuity equation. However, usually we iterate over momentum and pressurecorrection equations and eventually the residual errors can be reduced to machine zero.

Quote:

I will explain how steps to take when running the SIMPLE method and also what could be the problem.
1. We guess an initial pressure field p* 2. Use the momentum equations to determine the velocity field u*,v* This field does not correctly represent the flow field since it's not divergence free. Our pressure field is bound to be the wrong guess. 3. We take the following correction the the velocity and pressure: u** = u* + u' v** = v* + v' p** = p* + p' where ue' = dy/ae*(PpPe) (Pp is pressure in center cell, Pe is pressure in ajacent cell, ae is the cell coefficient). 4. Substituting these corrected velocity into a continuity equation yields us our pressure correction. 5. This process is repeated untill convergence For stability a underrelaxation coefficient is introduced. p** = p* + A*p' This coefficient depends on reynolds number and the pressure correction should be small in respect to the original pressure. So a couple of questions: Are you indeed using a staggered grid?  Otherwise a phenomena know as checkerboarding can occur. Did you try changing the value of your relaxation coefficient? Are you positive your solution is converged? Good luck! 
Quote:
Can you please explain how you got from your equation for the 2nd derivative of U to the 3x3 matrix? You have me pretty stumped here! Cheers, 
Quote:
(U(i+1,j)2*U(i,j)+U(i1,j))/dx^2 is the 2nd derivative If we want to write this as a matrix multiplication we need to build a matrix so that A*U = (U(i+1,j)2*U(i,j)+U(i1,j))/dx^2 In order to do so we need 2's on the diagonal and 1's on the offdiagonals (I switched the sign before, sorry!). Using a function like the one below we actaully build this matrix: function A = K1(n,h,a11,a22) % a11,a22: Neumann=1, Dirichlet=2, Dirichlet mid=3; A = spdiags([1 a11 0;ones(n2,1)*[1 2 1];0 a22 1],1:1,n,n)'/h^2; Here n is equal to the size of our matrix U and h is the delta x. In order to properly enforce the boundary conditions of our system we need to use the correct values at the points (1,1) and (n,n). It might be insightfull to type: A = spdiags([1 1 0;ones(52,1)*[1 2 1];0 1 1],1:1,5,5)' B = full(A) Then you have a nice picture of what happens in case of 1 values at the side (1,1 and n,n). The 2nd difference for the first cell will be equal to U(i,j) +U(i+1,j), which is the same as taking U(i,j)=U(i1,j) so du/dx=0 (Neumann) boundary condition. Good luck! 
Hi,
I could not figure out your grid system. Did you use staggered grid or something else? What are your boundary conditions? I am working on 2D simulation of the flow inside a heat pipe and there is something wrong with my code (most probably in the implementation of the BCs) so I am stucked and have been trying to figure out whats wrong for a long while. Moreover why did you recalculate the same coefficients in pressure correction equation? Thanks in advance for the response. 
All times are GMT 4. The time now is 14:10. 