Main Page   Data Structures   File List   Data Fields   Globals  

mg.c

Go to the documentation of this file.
00001 /* --------------------------------------------------------------------- */
00002 /* 
00003    SCCS information: %W% %G%
00004 */
00005 /* --------------------------------------------------------------------- */
00006 
00007 #include "utilf.h"
00008 #include "mymalloc.h"
00009 #include "markers.h"
00010 #include "surfaces.h"
00011 #include "extra.h"
00012 #include "make_bc.h"
00013 #include "momentum.h"
00014 #include "mg.h"
00015 #include "inout.h"
00016 
00017 /* --------------------------------------------------------------------- */
00018 
00019 #define COARSEST     3
00020 #define COARSERELAX  20
00021 
00022 static real2D *ires, *irhs, *ip, *iap;
00023 static real2D *ic0, *ic1, *ic2, *ic3, *ic4;
00024 static real2D sxp, syp, syu, au, cu, sxv, av, cv;
00025 static real2D rz1dr, rz2dr, rr1dz, rr2dz;
00026 static real2D w1, w2, dummy;
00027 static int Ngrid;
00028 
00029 static void rstrct(real2D uc, real2D uf, int ncx, int ncy, real scaling);
00030 
00031 static void interp(real2D uf, real2D uc, int nfx, int nfy);
00032 
00033 static void addint(real2D uf, real2D uc, real2D res, real2D ap,
00034                    int nfx, int nfy);
00035 
00036 static void slvsml(real2D u, real2D rhs, real2D cc, 
00037                    real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00038                    int nfx, int nfy);
00039 
00040 /* --------------------------------------------------------------------- */
00041 
00042 int computeng(int n1, int n2)
00043 {
00044   int nmin, n, nn, j;
00045 
00046   nmin = MIN(n1, n2);
00047   
00048   j = nmin - 2;  n = 1;
00049   while (j > 2) 
00050   {  j /= 2;   n++;  }
00051   
00052   nn = 1;  
00053   for (j = 1; j <= n; j++) 
00054     nn *= 2;       
00055   if((nn + 2) != nmin)
00056      return NGERROR;
00057 
00058   if ((n1 - 2) % (nmin - 2) != 0)
00059      return NXERROR;
00060   if ((n2 - 2) % (nmin - 2) != 0)
00061      return NYERROR;
00062 
00063   Ngrid = n;
00064   return n;
00065 }
00066 
00067 /* --------------------------------------------------------------------- */
00068 
00069 int initpressure(int n1, int n2, int ng)
00070 {
00071   int j;
00072   int err = 0;
00073 
00074   err |= ((irhs = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00075   err |= ((ires = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00076   err |= ((ip = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00077   err |= ((iap = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00078   err |= ((ic0 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00079   err |= ((ic1 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00080   err |= ((ic2 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00081   err |= ((ic3 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00082   err |= ((ic4 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00083 
00084   if ( err ) return MEMERROR;
00085 
00086   err |= ((ires[ng] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00087 
00088   err |= ((sxp = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00089   err |= ((syp = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00090 
00091   err |= ((syu = (real2D)mymalloc(sizeof(real), n1 + 1, n2)) == NULL); 
00092   err |= ((au = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00093   err |= ((cu = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00094 
00095   err |= ((sxv = (real2D)mymalloc(sizeof(real), n1, n2 + 1)) == NULL);
00096   err |= ((av = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00097   err |= ((cv = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00098 
00099   err |= ((rz1dr = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00100   err |= ((rz2dr = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00101   err |= ((rr1dz = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00102   err |= ((rr2dz = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00103 
00104   err |= ((w1 = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00105   err |= ((w2 = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00106   err |= ((dummy = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00107 
00108   n1 = n1 / 2 + 1;
00109   n2 = n2 / 2 + 1;
00110 
00111   for (j = ng - 1; j >= 1; j--) {
00112     err |= ((irhs[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00113     err |= ((ires[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00114     err |= ((ip[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00115     err |= ((iap[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00116     err |= ((ic0[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00117     err |= ((ic1[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00118     err |= ((ic2[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00119     err |= ((ic3[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00120     err |= ((ic4[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00121     
00122     if ( err ) return MEMERROR;
00123     
00124     n1 = n1 / 2 + 1;
00125     n2 = n2 / 2 + 1;
00126   }
00127 
00128   return 0;
00129 } /* end initpressure() */
00130 
00131 /* --------------------------------------------------------------------- */
00132 
00133 int mgsolve(real2D u, real2D p, real2D ap,
00134             real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00135             interface in, real lredis, real maxdiv,
00136             int n1, int n2, int ng) 
00137 {
00138   int ngrid, nn1, nn2, i, j;
00139   interface intemp;
00140   interface_cut cutp, cutu, cutv;
00141   real scale = 1.0;
00142   int ncycle = 0;
00143 
00144   resid(ires[ng], p, u, ap, c0, c1, c2, c3, c4, n1, n2);
00145   bc_scalar(ires[ng], n1, n2, NUL);
00146   if (rdivmax(ires[ng], n1, n2, &i, &j) <= maxdiv)
00147     return 0;
00148 
00149   ip[ng] = p;
00150   irhs[ng] = u;
00151   iap[ng] = ap;
00152   ic0[ng] = c0; ic1[ng] = c1; ic2[ng] = c2; ic3[ng] = c3; ic4[ng] = c4;
00153   interface_init(&intemp);
00154   intemp.bc = in.bc;
00155   cutp.list = cutu.list = cutv.list = NULL;
00156 
00157   nn1 = n1;
00158   nn2 = n2;
00159   ngrid = ng;
00160   while (ngrid > COARSEST) {
00161     nn1 = nn1 / 2 + 1;
00162     nn2 = nn2 / 2 + 1;
00163     ngrid--;
00164     scale *= 2.0;
00165     lredis *= 2.0;
00166     /* rescale the interface */
00167     interface_redis_scale(&intemp, in, lredis, 1./scale);
00168     interface_splines(intemp, nn1, nn2);
00169     /* compute volume fraction */
00170     rstrct(iap[ngrid], iap[ngrid+1], nn1, nn2, 1.0);
00171 
00172     cut_interface(intemp, &cutp, 0.0, 0.0);
00173     cut_interface(intemp, &cutu, -0.5, 0.0);
00174     cut_interface(intemp, &cutv, 0.0, -0.5);
00175 
00176     interface_surfaces(intemp, cutp, sxp, syp, iap[ngrid], dummy,
00177                        w1, w2, nn1, nn2);
00178     for (i = 2; i <= nn1; i++)
00179       for (j = 2; j <= nn2; j++) {
00180         au[i][j] = 0.5*(iap[ngrid][i][j] + iap[ngrid][i-1][j]);
00181         av[i][j] = 0.5*(iap[ngrid][i][j] + iap[ngrid][i][j-1]);
00182       } 
00183     interface_surfaces(intemp, cutu, dummy, syu, au, cu,
00184                        w1, w2, nn1, nn2);
00185     interface_surfaces(intemp, cutv, sxv, dummy, av, cv,
00186                        w1, w2, nn1, nn2);
00187     sx_fill(sxp, iap[ngrid], 0.0, 0.0, intemp, nn1, nn2);
00188     sy_fill(syp, iap[ngrid], 0.0, 0.0, intemp, nn1, nn2);
00189     sy_fill(syu, au, -0.5, 0.0, intemp, nn1, nn2);
00190     for (j = 2; j <= nn2; j++)
00191       syu[nn1+1][j] = (real)j - 1.5;
00192     sx_fill(sxv, av, 0.0, -0.5, intemp, nn1, nn2);
00193     for (i = 2; i <= nn1; i++)
00194       sxv[i][nn2+1] = (real)nn2 - 1.5;
00195 
00196     interface_rzdr(intemp, cutp, -0.5, rz1dr, nn1, nn2);
00197     interface_rzdr(intemp, cutp, 0.5, rz2dr, nn1, nn2);
00198     interface_rrdz(intemp, cutp, -0.5, rr1dz, nn1, nn2);
00199     interface_rrdz(intemp, cutp, 0.5, rr2dz, nn1, nn2);
00200     
00201     coli(sxp, syp, syu, sxv, cu, cv, iap[ngrid], av, 
00202          rz1dr, rz2dr, rr1dz, rr2dz,
00203          ic0[ngrid], ic1[ngrid], ic2[ngrid], ic3[ngrid], ic4[ngrid], 
00204          nn1, nn2, scale);
00205   }  
00206   interface_free(intemp);
00207   if (cutp.list) free(cutp.list);
00208   if (cutu.list) free(cutu.list);
00209   if (cutv.list) free(cutv.list);
00210 
00211   while (rdivmax(ires[ng], n1, n2, &i, &j) > maxdiv && ncycle < NCYCLEMAX) {
00212     mgvcycle(ng, n1, n2, 4, 4);
00213     resid(ires[ng], p, u, ap, c0, c1, c2, c3, c4, n1, n2);
00214     bc_scalar(ires[ng], n1, n2, NUL);
00215     ncycle++;
00216   }
00217   return ncycle;
00218 } /* end mgsolve() */
00219 
00220 /* --------------------------------------------------------------------- */
00221 
00222 void mgvcycle(int n, int nx, int ny, int npre, int npost)
00223 {
00224   int count;
00225   int ncx = nx/2 + 1, ncy = ny/2 + 1;
00226 
00227   /* solve exactly on the coarsest grid */
00228   if (n == COARSEST) {
00229     slvsml(ip[COARSEST], irhs[COARSEST], iap[COARSEST], 
00230            ic0[COARSEST], ic1[COARSEST], ic2[COARSEST], ic3[COARSEST], 
00231            ic4[COARSEST],
00232            nx, ny);
00233     return;
00234   }
00235   
00236   /* do prerelaxation */
00237   for (count = 0; count < npre; count++) {
00238     relax(ip[n], irhs[n], iap[n], 
00239           ic0[n], ic1[n], ic2[n], ic3[n], ic4[n], nx, ny);
00240     bc_scalar(ip[n], nx, ny, NULGRAD2);
00241   }
00242 
00243   /* compute defect */
00244   resid(ires[n], ip[n], irhs[n], iap[n],
00245         ic0[n], ic1[n], ic2[n], ic3[n], ic4[n], 
00246         nx, ny);
00247   bc_scalar(ires[n], nx, ny, NUL);
00248 
00249   /* compute r.h.s. on the coarser grid using defect */
00250   rstrct(irhs[n-1], ires[n], ncx, ncy, - 4.0);
00251 
00252   /* use zero as initial guess on the coarser grid */
00253   fill0(ip[n-1], ncx, ncy);
00254 
00255   /* solve on the coarser grid */
00256   mgvcycle(n - 1, ncx, ncy, npre + 1, npost + 1);
00257 
00258   /* correct on the fine grid (use ires as temporary storage) */
00259   addint(ip[n], ip[n-1], ires[n], iap[n], nx, ny);
00260 
00261   /* do post relaxation */
00262   for (count = 0; count < npost; count++) {
00263     relax(ip[n], irhs[n], iap[n], 
00264           ic0[n], ic1[n], ic2[n], ic3[n], ic4[n], nx, ny);
00265     bc_scalar(ip[n], nx, ny, NULGRAD2);
00266   }
00267   /*
00268   sprintf(s, "ip%d", n);
00269   datbarray(ip[n], nx, ny, s);
00270   sprintf(s, "ipc%d", n);
00271   interp(ires[n], ip[n-1], nx, ny);
00272   datbarray(ires[n], nx, ny, s);
00273   sprintf(s, "iap%d", n);
00274   datbarray(iap[n], nx, ny, s);
00275   */
00276 }
00277 
00278 /* --------------------------------------------------------------------- */
00279 
00280 static void rstrct(real2D uc, real2D uf, int ncx, int ncy, real scaling)
00281 {
00282   int ic, iff, jc, jf;
00283   
00284   scaling *= 0.5;
00285   for (jc = 2; jc <= ncx - 1; jc++)
00286     {
00287       jf = 2 * jc - 2;
00288       for (ic = 2; ic <= ncy - 1; ic++)
00289         {
00290           iff = 2 * ic - 2;
00291 #if 0
00292           uc[jc][ic] = (uf[jf][iff] + 
00293                         0.25 * (uf[jf][iff+1] + uf[jf][iff-1] + 
00294                                 uf[jf+1][iff] + uf[jf-1][iff])) * scaling;
00295 #else
00296           uc[jc][ic] = .5 * scaling * (uf[jf][iff] + uf[jf + 1][iff] 
00297                                        + uf[jf][iff+1] + uf[jf + 1][iff+1]);
00298 #endif
00299         }
00300     }
00301   bc_scalar(uc, ncx, ncy, NULGRAD);
00302 }
00303 
00304 /* --------------------------------------------------------------------- */
00305 
00306 static void interp(real2D uf, real2D uc, int nfx, int nfy)
00307 {
00308   int ic, iif, jc, jf, ncx, ncy;
00309 
00310   ncx = nfx / 2 + 1;
00311   ncy = nfy / 2 + 1;
00312 #if 0
00313   for (jc = 1, jf = 1; jc < ncy; jc++, jf += 2)
00314     for (ic = 1; ic < ncx; ic++)
00315       uf[2*ic-1][jf] = uc[ic][jc];
00316   for (jf = 1; jf < nfy; jf += 2)
00317     for (iif = 2; iif < nfx; iif += 2)
00318       uf[iif][jf] = 0.5 * (uf[iif+1][jf] + uf[iif-1][jf]);
00319   for (jf = 2; jf < nfy; jf += 2)
00320     for (iif = 1; iif < nfx; iif++)
00321       uf[iif][jf] = 0.5 * (uf[iif][jf+1] + uf[iif][jf-1]);
00322 #else
00323   for (ic = 2; ic <= ncx - 1; ic++) {
00324     iif = 2 * ic - 2;
00325     for (jc = 2; jc <= ncy - 1; jc++) {
00326       jf = 2 * jc - 2;
00327       uf[iif][jf] =
00328       uf[iif][jf+1] =
00329       uf[iif + 1][jf] =
00330       uf[iif + 1][jf+1] = uc[ic][jc];
00331     }
00332   }
00333 #endif
00334 
00335   bc_scalar(uf, nfx, nfy, NULGRAD);
00336 }
00337 
00338 /* --------------------------------------------------------------------- */
00339 
00340 static void addint(real2D uf, real2D uc, real2D res, real2D ap, 
00341                    int nfx, int nfy)
00342 {
00343   int i, j;
00344   
00345   interp(res, uc, nfx, nfy); 
00346   for (i = 2; i < nfx; i++)
00347     for (j = 2; j < nfy; j++)
00348       if (INP(i,j))
00349         uf[i][j] += res[i][j];
00350 }
00351 
00352 /* --------------------------------------------------------------------- */
00353 
00354 static void slvsml(real2D u, real2D rhs, real2D ap, 
00355                    real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00356                    int nfx, int nfy)
00357 {
00358   int count;
00359   
00360   for (count = 1; count <= COARSERELAX; count++) {
00361     relax(u, rhs, ap, c0, c1, c2, c3, c4, nfx, nfy);
00362     bc_scalar(u, nfx, nfy, NULGRAD2);
00363   }
00364 }
00365 
00366 /* --------------------------------------------------------------------- */
00367 
00368 void resid(real2D res, real2D p, real2D rhs, real2D ap, 
00369            real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00370            int nx, int ny)
00371 {
00372   int i, j;
00373   
00374   for (i = 2; i < nx; i++)
00375     for (j = 2; j < ny; j++)
00376       if (INP(i,j))
00377         res[i][j] = c1[i][j]*p[i+1][j] + c2[i][j]*p[i][j+1] 
00378           + c3[i][j]*p[i-1][j] + c4[i][j]*p[i][j-1] - c0[i][j]*p[i][j]
00379           - rhs[i][j];
00380       else
00381         res[i][j] = 0.0;
00382 }
00383 
00384 /* --------------------------------------------------------------------- */
00385 
00386 void relax(real2D p, real2D rhs, real2D ap,
00387            real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00388            int nx, int ny)
00389 {
00390   int i, j, isw, jsw;
00391 
00392   for (jsw = 1; jsw <= 2; jsw++) {
00393     isw = jsw;
00394     for (i = 2; i < nx; i++, isw = 3 - isw)
00395       for (j = isw + 1; j < ny; j += 2)
00396         if (INP(i,j))
00397           p[i][j] = (c1[i][j]*p[i+1][j] + c2[i][j]*p[i][j+1] +
00398                      c3[i][j]*p[i-1][j] + c4[i][j]*p[i][j-1] 
00399                      - rhs[i][j])/c0[i][j];
00400   }
00401 }

Generated on Wed Feb 19 22:26:50 2003 for Markers by doxygen1.2.18