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 *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 }
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
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 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 }
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
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
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
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
00250 rstrct(irhs[n-1], ires[n], ncx, ncy, - 4.0);
00251
00252
00253 fill0(ip[n-1], ncx, ncy);
00254
00255
00256 mgvcycle(n - 1, ncx, ncy, npre + 1, npost + 1);
00257
00258
00259 addint(ip[n], ip[n-1], ires[n], iap[n], nx, ny);
00260
00261
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
00269
00270
00271
00272
00273
00274
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 }