Main Page   Data Structures   File List   Data Fields   Globals  

vmg.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 *irhs, *ip, *iap, *ierr;
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 |= ((ip = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00076   err |= ((iap = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00077   err |= ((ic0 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00078   err |= ((ic1 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00079   err |= ((ic2 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00080   err |= ((ic3 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00081   err |= ((ic4 = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00082   err |= ((ierr = (real2D *) malloc((ng + 1) * sizeof(real2D))) == NULL);
00083 
00084   if ( err ) return MEMERROR;
00085 
00086   err |= ((sxp = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00087   err |= ((syp = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00088 
00089   err |= ((syu = (real2D)mymalloc(sizeof(real), n1 + 1, n2)) == NULL); 
00090   err |= ((au = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00091   err |= ((cu = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00092 
00093   err |= ((sxv = (real2D)mymalloc(sizeof(real), n1, n2 + 1)) == NULL);
00094   err |= ((av = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00095   err |= ((cv = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00096 
00097   err |= ((rz1dr = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00098   err |= ((rz2dr = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00099   err |= ((rr1dz = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00100   err |= ((rr2dz = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00101 
00102   err |= ((w1 = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00103   err |= ((w2 = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00104   err |= ((dummy = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00105 
00106   err |= ((ierr[ng] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL); 
00107   err |= ((irhs[ng] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00108 
00109   n1 = n1 / 2 + 1;
00110   n2 = n2 / 2 + 1;
00111 
00112   for (j = ng - 1; j >= 1; j--) {
00113     err |= ((irhs[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     err |= ((ierr[j] = (real2D)mymalloc(sizeof(real), n1, n2)) == NULL);
00122     
00123     if ( err ) return MEMERROR;
00124     
00125     n1 = n1 / 2 + 1;
00126     n2 = n2 / 2 + 1;
00127   }
00128 
00129   return 0;
00130 } /* end initpressure() */
00131 
00132 /* --------------------------------------------------------------------- */
00133 
00134 int mgsolve(real2D u, real2D p, real2D ap,
00135             real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00136             interface in, real lredis, real maxdiv,
00137             int n1, int n2, int ng) 
00138 {
00139   int ngrid, nn1, nn2, i, j;
00140   interface intemp;
00141   interface_cut cutp, cutu, cutv;
00142   real scale = 1.0;
00143   int ncycle = 0;
00144 
00145   resid(irhs[ng], p, u, ap, c0, c1, c2, c3, c4, n1, n2);
00146   bc_scalar(irhs[ng], n1, n2, NUL);
00147   if (rdivmax(irhs[ng], n1, n2, &i, &j) <= maxdiv)
00148     return 0;
00149 
00150   ip[ng] = p;
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   copy(w1, p, n1, n2);
00212   while (rdivmax(irhs[ng], n1, n2, &i, &j) > maxdiv && ncycle < NCYCLEMAX) {
00213     fill0(ip[ng], n1, n2);
00214     mgvcycle(ng, n1, n2, 1, 1);
00215     printf("ncycle: %d rdivmax: %g\n", 
00216            ncycle + 1, rdivmax(irhs[ng], n1, n2, &i, &j));
00217     add(w1, p, n1, n2);
00218     ncycle++;
00219   }
00220   copy(p, w1, n1, n2);  
00221 
00222   return ncycle;
00223 } /* end mginit() */
00224 
00225 /* --------------------------------------------------------------------- */
00226 
00227 void mgvcycle(int n, int nx, int ny, int npre, int npost)
00228 {
00229   int count;
00230   int ncx = nx/2 + 1, ncy = ny/2 + 1;
00231 char s[256];
00232 
00233   /* solve exactly on the coarsest grid */
00234   if (n == COARSEST) {
00235     slvsml(ip[COARSEST], irhs[COARSEST], iap[COARSEST], 
00236            ic0[COARSEST], ic1[COARSEST], ic2[COARSEST], ic3[COARSEST], 
00237            ic4[COARSEST],
00238            nx, ny);
00239     return;
00240   }
00241   
00242   /* do prerelaxation */
00243   for (count = 0; count < npre; count++) {
00244     relax(ip[n], irhs[n], iap[n], 
00245           ic0[n], ic1[n], ic2[n], ic3[n], ic4[n], nx, ny);
00246     bc_scalar(ip[n], nx, ny, NULGRAD2);
00247   }
00248 
00249   /* compute defect */
00250   resid(irhs[n], ip[n], irhs[n], iap[n],
00251         ic0[n], ic1[n], ic2[n], ic3[n], ic4[n], 
00252         nx, ny);
00253   bc_scalar(irhs[n], nx, ny, NUL);
00254 
00255   /* compute r.h.s. on the coarser grid using defect */
00256   rstrct(irhs[n-1], irhs[n], ncx, ncy, - 4.0);
00257 
00258   /* use zero as initial guess on the coarser grid */
00259   fill0(ip[n-1], ncx, ncy);
00260 
00261   /* solve on the coarser grid */
00262   mgvcycle(n - 1, ncx, ncy, npre + 1, npost + 1);
00263 
00264   /* interpolate the error from coarse to fine grid */
00265   interp(ierr[n], ip[n-1], nx, ny);
00266 
00267   /* new residual res(new) = res(old)-A*error */
00268   resid(irhs[n], ierr[n], irhs[n], iap[n], 
00269         ic0[n], ic1[n], ic2[n], ic3[n], ic4[n],
00270         nx, ny);
00271   bc_scalar(irhs[n], nx, ny, NUL);
00272 
00273   /* correct e(ngrid) with error = interp(e(ngrid-1)) */
00274   add(ip[n], ierr[n], nx, ny);
00275 
00276   /* do post relaxation with initial guess = 0 */
00277   fill0(ierr[n], nx, ny);
00278   for (count = 0; count < npost; count++) {
00279     relax(ierr[n], irhs[n], iap[n], 
00280           ic0[n], ic1[n], ic2[n], ic3[n], ic4[n], nx, ny);
00281     bc_scalar(ierr[n], nx, ny, NULGRAD);
00282   }
00283 
00284   /* add correction to correction to solution */
00285   add(ip[n], ierr[n], nx, ny);
00286 
00287   /* compute residual */
00288   resid(irhs[n], ierr[n], irhs[n], iap[n],
00289         ic0[n], ic1[n], ic2[n], ic3[n], ic4[n],
00290         nx, ny);
00291   bc_scalar(irhs[n], nx, ny, NUL);
00292 /*
00293   sprintf(s, "ip%d", n);
00294   datbarray(ip[n], nx, ny, s);
00295   sprintf(s, "ipc%d", n);
00296   sprintf(s, "iap%d", n);
00297   datbarray(iap[n], nx, ny, s);
00298 */
00299 }
00300 
00301 /* --------------------------------------------------------------------- */
00302 
00303 static void rstrct(real2D uc, real2D uf, int ncx, int ncy, real scaling)
00304 {
00305   int ic, iff, jc, jf;
00306   
00307   scaling *= 0.5;
00308   for (jc = 2; jc <= ncx - 1; jc++)
00309     {
00310       jf = 2 * jc - 2;
00311       for (ic = 2; ic <= ncy - 1; ic++)
00312         {
00313           iff = 2 * ic - 2;
00314 #if 0
00315           uc[jc][ic] = (uf[jf][iff] + 
00316                         0.25 * (uf[jf][iff+1] + uf[jf][iff-1] + 
00317                                 uf[jf+1][iff] + uf[jf-1][iff])) * scaling;
00318 #else
00319           uc[jc][ic] = .5 * scaling * (uf[jf][iff] + uf[jf + 1][iff] 
00320                                        + uf[jf][iff+1] + uf[jf + 1][iff+1]);
00321 #endif
00322         }
00323     }
00324   bc_scalar(uc, ncx, ncy, NULGRAD);
00325 }
00326 
00327 /* --------------------------------------------------------------------- */
00328 
00329 static void interp(real2D uf, real2D uc, int nfx, int nfy)
00330 {
00331   int ic, iif, jc, jf, ncx, ncy;
00332 
00333   ncx = nfx / 2 + 1;
00334   ncy = nfy / 2 + 1;
00335 #if 0
00336   for (jc = 1, jf = 1; jc < ncy; jc++, jf += 2)
00337     for (ic = 1; ic < ncx; ic++)
00338       uf[2*ic-1][jf] = uc[ic][jc];
00339   for (jf = 1; jf < nfy; jf += 2)
00340     for (iif = 2; iif < nfx; iif += 2)
00341       uf[iif][jf] = 0.5 * (uf[iif+1][jf] + uf[iif-1][jf]);
00342   for (jf = 2; jf < nfy; jf += 2)
00343     for (iif = 1; iif < nfx; iif++)
00344       uf[iif][jf] = 0.5 * (uf[iif][jf+1] + uf[iif][jf-1]);
00345 #else
00346   for (ic = 2; ic <= ncx - 1; ic++) {
00347     iif = 2 * ic - 2;
00348     for (jc = 2; jc <= ncy - 1; jc++) {
00349       jf = 2 * jc - 2;
00350       uf[iif][jf] =
00351       uf[iif][jf+1] =
00352       uf[iif + 1][jf] =
00353       uf[iif + 1][jf+1] = uc[ic][jc];
00354     }
00355   }
00356 #endif
00357 
00358   bc_scalar(uf, nfx, nfy, NULGRAD);
00359 }
00360 
00361 /* --------------------------------------------------------------------- */
00362 
00363 static void addint(real2D uf, real2D uc, real2D res, real2D ap, 
00364                    int nfx, int nfy)
00365 {
00366   int i, j;
00367   
00368   interp(res, uc, nfx, nfy); 
00369   for (i = 2; i < nfx; i++)
00370     for (j = 2; j < nfy; j++)
00371       if (INP(i,j))
00372         uf[i][j] += res[i][j];
00373 }
00374 
00375 /* --------------------------------------------------------------------- */
00376 
00377 static void slvsml(real2D u, real2D rhs, real2D ap, 
00378                    real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00379                    int nfx, int nfy)
00380 {
00381   int count;
00382   
00383   for (count = 1; count <= COARSERELAX; count++) {
00384     relax(u, rhs, ap, c0, c1, c2, c3, c4, nfx, nfy);
00385     bc_scalar(u, nfx, nfy, NULGRAD2);
00386   }
00387 }
00388 
00389 /* --------------------------------------------------------------------- */
00390 
00391 void resid(real2D res, real2D p, real2D rhs, real2D ap, 
00392            real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00393            int nx, int ny)
00394 {
00395   int i, j;
00396   
00397   for (i = 2; i < nx; i++)
00398     for (j = 2; j < ny; j++)
00399       if (INP(i,j))
00400         res[i][j] = c1[i][j]*p[i+1][j] + c2[i][j]*p[i][j+1] 
00401           + c3[i][j]*p[i-1][j] + c4[i][j]*p[i][j-1] - c0[i][j]*p[i][j]
00402           - rhs[i][j];
00403       else
00404         res[i][j] = 0.0;
00405 }
00406 
00407 /* --------------------------------------------------------------------- */
00408 
00409 void relax(real2D p, real2D rhs, real2D ap,
00410            real2D c0, real2D c1, real2D c2, real2D c3, real2D c4,
00411            int nx, int ny)
00412 {
00413   int i, j, isw, jsw;
00414 
00415   for (jsw = 1; jsw <= 2; jsw++) {
00416     isw = jsw;
00417     for (i = 2; i < nx; i++, isw = 3 - isw)
00418       for (j = isw + 1; j < ny; j += 2)
00419         if (INP(i,j))
00420           p[i][j] = (c1[i][j]*p[i+1][j] + c2[i][j]*p[i][j+1] +
00421                      c3[i][j]*p[i-1][j] + c4[i][j]*p[i][j-1] 
00422                      - rhs[i][j])/c0[i][j];
00423   }
00424 }

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