00001
00002
00003
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 }
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
00167 interface_redis_scale(&intemp, in, lredis, 1./scale);
00168 interface_splines(intemp, nn1, nn2);
00169
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 }
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
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
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
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
00256 rstrct(irhs[n-1], irhs[n], ncx, ncy, - 4.0);
00257
00258
00259 fill0(ip[n-1], ncx, ncy);
00260
00261
00262 mgvcycle(n - 1, ncx, ncy, npre + 1, npost + 1);
00263
00264
00265 interp(ierr[n], ip[n-1], nx, ny);
00266
00267
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
00274 add(ip[n], ierr[n], nx, ny);
00275
00276
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
00285 add(ip[n], ierr[n], nx, ny);
00286
00287
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
00294
00295
00296
00297
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 }