/* 2d multigrid simple test From More C Tools for Scientists and Engineers by L. Baker*/ /* dimension to 2(n+1)**2 where n is a power of 2 */ float x[2000],v[2000],u[2000],f[2000]; /* x=grid v=answer f=drive A for Laplacian, i.e Poisson Ay=f */ #include /*problem size, coarsest grid allowed*/ #define n 16 #define ncoarsest 2 #define INDEX(I,J) [J+(I)*maxj] #define INDX(I,J,k) [J+(I)*((k)+1)] /*relaxtion parameters*/ #define n0 1 #define n1 2 #define n2 2 #define dx .1 float bc0=1.,bc1=2.,mult;/*boundary conditions*/ float av(i,j,m,y) int i,j,m; float *y; {/* evaluate Av. use Av-f for residual*/ int maxj; maxj=m+1; /* boundary conditions residuals*/ if(!i||!j||i==(m)||j==(m))return y INDEX(i,j); return (y INDEX(i,j+1)+y INDEX(i,j-1)+ y INDEX(i+1,j)+y INDEX(i-1,j)-4.*y INDEX(i,j) )/dx*dx; } float residual(i,j,m,f,v) int i,j,m;float *f,*v; { int maxj; float av(); maxj=m+1; return f INDEX(i,j)-av(i,j,m,v); } correct(m,v,v2h) int m; float *v,*v2h; {/*coarse to fine red points only */ int i,j,mfine,maxj;float save; mfine=m<<1; maxj=m+1;/*coarse*/ /*printf(" correcting coarse=%d\n",m);*/ for(j=0;j<=m;j++) for(i=0;i<=m;i++)/*don't touch boundary points*/ {/* i=0 set v 0,1 from v2h 0,1. i=m-1, set 2m-1*/ if(i!=(m) && i && j && j!=(m) ) { /* prevent correction of i==0 boundary here*/ if(i) /* agrees with comment, but not actual usage in MULTIG*/ { save= v INDEX(2*i,2*j+1); /* multiply correction by 2 to account for no corr. of black*/ v INDX(2*i,2*j+1,mfine)+=.5*mult*(v2h INDEX(i,j)+v2h INDEX(i,j-1)); /*printf("v %d %d was %f now %f\n",2*i,2*j+1,save,v INDX(2*i,2*j+1,mfine));*/ } /*add correction term*/ save= v INDEX(2*i+1,2*j); v INDX(2*i+1,2*j,mfine)+=.5*mult*(v2h INDEX(i,j)+v2h INDEX(i-1,j)); /*printf("v %d %d was %f now %f\n",2*i+1,2*j,save,v INDX(2*i+1,2*j,mfine));*/ } /* if i==m but 2*i+1 would not be boundary- don't correct! /* else {; if(!i) { v INDX(0,2*j+1,k)+=.5*(v2h INDEX(i,j)+v2h INDEX(i,j-1)); } else if(!j) { v INDX(2*i+1,j,k)+=.5*(v2h INDEX(i,j)+v2h INDEX(i-1,j)); } else if (i==(m)) { v INDX(2*i+1,2*j,k)+=.5*(v2h INDEX(i,j)+v2h INDEX(i,j-1)); } else { v INDX(2*i,2*j+1,k)+=.5*(v2h INDEX(i,j)+v2h INDEX(i-1,j)); } } */ } } restrict(m,coarsef,finef,v) int m; float *finef,*coarsef,*v; {/*fine to coarse f*/ int i,mfine,j,k,l,finetop,maxj; float coef,residp,residm,residc,residq,residr; float residual(); maxj=m+1;/*coarse*/ mfine=m<<1; finetop=mfine; coef=dx*dx; for(j=1;j>=1; msq=(m+1)*(m+1); h<<=1; restrict(m,nextgridf,f,v); for(i=0;i>1; h<<=1; msq=(nn+1)*(nn+1); nextgridf= &(f[msq]); nextgridv= &(v[msq]); restrict(m,nextgridf,f,v); msq=(m+1)*(m+1); for(i=0;i