00001
00002
00003
00004
00005
00006
00007 #include "utilf.h"
00008 #include "mymalloc.h"
00009 #include "make_bc.h"
00010 #include "fas.h"
00011
00012
00013
00014 #define COARSEST 1
00015 #define COARSERELAX 4
00016
00017 static real2D *itau, *irhs, *irho, *ip, *ia, *ib, *iei, *itemp, *icc;
00018
00019 static void abfromab(real2D a, real2D b, real2D ei, real2D a2, real2D c2,
00020 int n1, int n2);
00021
00022 static void rstrct(real2D uc, real2D uf, int ncx, int ncy);
00023
00024 static void interp(real2D uf, real2D uc, int nfx, int nfy);
00025
00026 static void slvsml(real2D u, real2D rhs,
00027 real2D a, real2D b, real2D ei,
00028 int nfx, int nfy);
00029
00030 void lop(real2D out, real2D u, real2D a, real2D b,
00031 int n1, int n2);
00032
00033
00034
00035 int computeng(int n1, int n2)
00036 {
00037 int nmin, n, nn, j;
00038
00039 nmin = min(n1, n2);
00040
00041 j = nmin - 2; n = 1;
00042 while (j > 2)
00043 { j /= 2; n++; }
00044
00045 nn = 1;
00046 for (j = 1; j <= n; j++)
00047 nn *= 2;
00048 if((nn + 2) != nmin)
00049 return NGERROR;
00050
00051 if ((n1 - 2) % (nmin - 2) != 0)
00052 return NXERROR;
00053 if ((n2 - 2) % (nmin - 2) != 0)
00054 return NYERROR;
00055
00056 return n;
00057 }
00058
00059
00060
00061 int initpressure(int n1, int n2, int ng)
00062 {
00063 int j;
00064
00065 irhs = (real2D *) malloc((ng + 1) * sizeof(real2D));
00066 irho = (real2D *) malloc((ng + 1) * sizeof(real2D));
00067 itau = (real2D *) malloc((ng + 1) * sizeof(real2D));
00068 ip = (real2D *) malloc((ng + 1) * sizeof(real2D));
00069 ia = (real2D *) malloc((ng + 1) * sizeof(real2D));
00070 ib = (real2D *) malloc((ng + 1) * sizeof(real2D));
00071 iei = (real2D *) malloc((ng + 1) * sizeof(real2D));
00072 itemp = (real2D *) malloc((ng + 1) * sizeof(real2D));
00073 icc = (real2D *) malloc((ng + 1) * sizeof(real2D));
00074
00075 if (icc EQUALS NULL)
00076 return MEMERROR;
00077
00078 irhs[ng] = (real2D)mymalloc(sizeof(real), n1, n2);
00079 itau[ng] = (real2D)mymalloc(sizeof(real), n1, n2);
00080 itemp[ng] = (real2D)mymalloc(sizeof(real), n1, n2);
00081
00082 n1 = n1 / 2 + 1;
00083 n2 = n2 / 2 + 1;
00084
00085 for (j = ng - 1; j >= 1; j--)
00086 {
00087 irhs[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00088 irho[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00089 itau[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00090 ip[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00091 ia[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00092 ib[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00093 iei[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00094 icc[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00095 itemp[j] = (real2D)mymalloc(sizeof(real), n1, n2);
00096
00097 if (itemp[j] EQUALS NULL)
00098 return MEMERROR;
00099
00100 n1 = n1 / 2 + 1;
00101 n2 = n2 / 2 + 1;
00102 }
00103
00104 return 0;
00105 }
00106
00107
00108
00109 void mginit(real2D u, real2D p, real2D a, real2D b, real2D ei, real2D cc,
00110 int n1, int n2, int ng)
00111 {
00112 int ngrid, nn1, nn2;
00113
00114 ip[ng] = p;
00115 irho[ng] = u;
00116 ia[ng] = a;
00117 ib[ng] = b;
00118 iei[ng] = ei;
00119 icc[ng] = cc;
00120
00121 nn1 = n1 / 2 + 1;
00122 nn2 = n2 / 2 + 1;
00123 ngrid = ng - 1;
00124
00125 bc_scalar(u, n1, n2, NULGRAD);
00126
00127 rstrct(irho[ngrid], u, nn1, nn2);
00128 rstrct(icc[ngrid], p, nn1, nn2);
00129 abfromab(ia[ngrid], ib[ngrid], iei[ngrid],
00130 ia[ngrid+1], ib[ngrid+1], nn1, nn2);
00131 while ((nn1 > 4) && (nn2 > 4))
00132 {
00133 nn1 = nn1 / 2 + 1;
00134 nn2 = nn2 / 2 + 1;
00135 ngrid = ngrid - 1;
00136 rstrct(irho[ngrid], irho[ngrid+1], nn1, nn2);
00137 rstrct(icc[ngrid], icc[ngrid+1], nn1, nn2);
00138 abfromab(ia[ngrid], ib[ngrid], iei[ngrid], ia[ngrid+1], ib[ngrid+1],
00139 nn1, nn2);
00140 }
00141 }
00142
00143 void mgfas(real2D u, real2D p, real2D a, real2D b, real2D ei,
00144 int n1, int n2, int ng, int npre, int npost, int ncycle)
00145 {
00146 int i, j, jj, jcycle, jpre, jpost, ngrid, nfx, nfy, nn1, nn2;
00147
00148 ip[ng] = p;
00149 irho[ng] = u;
00150 ia[ng] = a;
00151 ib[ng] = b;
00152 iei[ng] = ei;
00153 icc[ng] = cc;
00154
00155 nn1 = n1 / 2 + 1;
00156 nn2 = n2 / 2 + 1;
00157 ngrid = ng - 1;
00158
00159 bc_scalar(u, n1, n2, NULGRAD);
00160
00161 rstrct(irho[ngrid], u, nn1, nn2);
00162 rstrct(icc[ngrid], cc, nn1, nn2);
00163 abfromab(ia[ngrid], ib[ngrid], iei[ngrid],
00164 ia[ngrid+1], ib[ngrid+1], nn1, nn2);
00165 while ((nn1 > 4) && (nn2 > 4))
00166 {
00167 nn1 = nn1 / 2 + 1;
00168 nn2 = nn2 / 2 + 1;
00169 ngrid = ngrid - 1;
00170 rstrct(irho[ngrid], irho[ngrid+1], nn1, nn2);
00171 rstrct(icc[ngrid], icc[ngrid+1], nn1, nn2);
00172 abfromab(ia[ngrid], ib[ngrid], iei[ngrid], ia[ngrid+1], ib[ngrid+1],
00173 nn1, nn2);
00174 }
00175
00176 ngrid = ng;
00177 for (j = 2; j <= ngrid; j++)
00178 {
00179 nn1 = 2 * nn1 - 2;
00180 nn2 = 2 * nn2 - 2;
00181 interp(ip[j], ip[j-1], nn1, nn2);
00182 copy(irhs[j], irho[j], nn1, nn2);
00183 for (jcycle = 1; jcycle <= ncycle; jcycle++)
00184 {
00185 nfx = nn1;
00186 nfy = nn2;
00187 for (jj = j; jj >= 2; jj--)
00188 {
00189 for (jpre = 1; jpre <= npre; jpre++)
00190 {
00191 relax(ip[jj], irhs[jj], ia[jj], ib[jj], iei[jj], icc[jj],
00192 nfx, nfy);
00193 bc_scalar(ip[jj], nfx, nfy, NULGRAD);
00194 }
00195 lop(itemp[jj], ip[jj], ia[jj], ib[jj], icc[jj], nfx, nfy);
00196 bc_scalar(itemp[jj], nfx, nfy, NULGRAD);
00197 nfx = nfx / 2 + 1;
00198 nfy = nfy / 2 + 1;
00199 rstrct(itemp[jj-1], itemp[jj], nfx, nfy);
00200 rstrct(ip[jj-1], ip[jj], nfx, nfy);
00201 lop(itau[jj-1], ip[jj-1], ia[jj-1], ib[jj-1], icc[jj-1], nfx, nfy);
00202 bc_scalar(itau[jj-1], nfx, nfy, NULGRAD);
00203 matsub(itau[jj-1], itemp[jj-1], itau[jj-1], nfx, nfy);
00204 rstrct(irhs[jj-1], irhs[jj], nfx, nfy);
00205 matadd(irhs[jj-1], itau[jj-1], irhs[jj-1], nfx, nfy);
00206 }
00207
00208 slvsml(ip[1], irhs[1],
00209 ia[1], ib[1], iei[1], icc[1], nfx, nfy);
00210
00211 for (jj = 2; jj <= j; jj++)
00212 {
00213 rstrct(itemp[jj-1], ip[jj], nfx, nfy);
00214 matsub(ip[jj-1], itemp[jj-1], itemp[jj-1], nfx, nfy);
00215 nfx = 2 * nfx - 2;
00216 nfy = 2 * nfy - 2;
00217 interp(itau[jj], itemp[jj-1], nfx, nfy);
00218 matadd(ip[jj], itau[jj], ip[jj], nfx, nfy);
00219 for (jpost = 1; jpost <= npost; jpost++)
00220 {
00221 relax(ip[jj], irhs[jj], ia[jj], ib[jj], iei[jj], icc[jj],
00222 nfx, nfy);
00223 bc_scalar(ip[jj], nfx, nfy, NULGRAD);
00224 }
00225 }
00226 }
00227 }
00228 }
00229 #if 0
00230
00231
00232 void mgvcycle(int n, int nx, int ny, int npre, int npost)
00233 {
00234 int count;
00235 int ncx = nx / 2 + 1, ncy = ny / 2 + 1;
00236
00237
00238 if (n EQUALS COARSEST)
00239 {
00240 slvsml(ip[COARSEST], irhs[COARSEST],
00241 ia[COARSEST], ib[COARSEST], iei[COARSEST], icc[COARSEST},
00242 nx, ny);
00243 return;
00244 }
00245
00246
00247 for (count = 0; count < npre; count++)
00248 {
00249 relax(ip[n], irhs[n], ia[n], ib[n], iei[n], icc[n], nx, ny);
00250 bc_scalar(ip[n], nx, ny, NULGRAD);
00251 }
00252
00253
00254 lop(itemp[n], ip[n], ia[n], ib[n], icc[n], nx, ny);
00255 bc_scalar(itemp[n], nx, ny, NULGRAD);
00256 rstrct(itemp[n-1], itemp[n], ncx, ncy);
00257 rstrct(ip[n-1], ip[n], ncx, ncy);
00258 lop(itau[n-1], ip[n-1], ia[n-1], ib[n-1], icc[n-1], ncx, ncy);
00259 bc_scalar(itau[n-1], ncx, ncy, NULGRAD);
00260 matsub(itau[n-1], itemp[n-1], itau[n-1], ncx, ncy);
00261
00262
00263 rstrct(irhs[n-1], irhs[n], ncx, ncy);
00264 matadd(irhs[n-1], itau[n-1], irhs[n-1], ncx, ncy);
00265
00266
00267 mgvcycle(n - 1, ncx, ncy, npre, npost);
00268
00269
00270 rstrct(itemp[n-1], ip[n], ncx, ncy);
00271 matsub(ip[n-1], itemp[n-1], itemp[n-1], ncx, ncy);
00272 printf("--------------------itemp[%d]--------------------\n", n-1);
00273 matprint(itemp[n-1], ncx, ncy);
00274 interp(itau[n], itemp[n-1], nx, ny);
00275 printf("--------------------itau[%d]------------------\n", n);
00276 matprint(itau[n], nx, ny);
00277
00278
00279 printf("--------------------ip[%d]--------------------\n", n);
00280 matprint(ip[n], nx, ny);
00281 matadd(ip[n], itau[n], ip[n], nx, ny);
00282
00283
00284 for (count = 0; count < npost; count++)
00285 {
00286 relax(ip[n], irhs[n], ia[n], ib[n], iei[n], icc[n], nx, ny);
00287 bc_scalar(ip[n], nx, ny, NULGRAD);
00288 }
00289 }
00290 #endif
00291
00292
00293 static void abfromab(real2D a, real2D b, real2D ei, real2D a2, real2D c2,
00294 int n1, int n2)
00295 {
00296 int i, j;
00297
00298 for (i = 1; i <= n1 - 1; i++)
00299 for (j = 2; j <= n2 - 1; j++)
00300 a[i][j] = 0.5 * (a2[2*i-1][2*j-2] + a2[2*i-1][2*j-1]);
00301 for (i = 2; i <= n1 - 1; i++)
00302 for (j = 1; j <= n2 - 1; j++)
00303 b[i][j] = 0.5 * (c2[2*i-2][2*j-1] + c2[2*i-1][2*j-1]);
00304 for (i = 2; i <= n1 - 1; i++)
00305 for (j = 2; j <= n2 - 1; j++)
00306 ei[i][j] = 1.0 / (a[i-1][j] + a[i][j] + b[i][j-1] + b[i][j]);
00307 }
00308
00309
00310
00311 static void rstrct(real2D uc, real2D uf, int ncx, int ncy)
00312 {
00313 int ic, iff, jc, jf;
00314
00315 for (jc = 2; jc <= ncx - 1; jc++)
00316 {
00317 jf = 2 * jc - 2;
00318 for (ic = 2; ic <= ncy - 1; ic++)
00319 {
00320 iff = 2 * ic - 2;
00321 uc[jc][ic] = 0.5 * uf[jf][iff] +
00322 0.125 * (uf[jf][iff+1] + uf[jf][iff-1] +
00323 uf[jf+1][iff] + uf[jf-1][iff]);
00324 }
00325 }
00326 bc_scalar(uc, ncx, ncy, NULGRAD);
00327 }
00328
00329
00330 #if 0
00331 static void interp(real2D uf, real2D uc, int nfx, int nfy)
00332 {
00333 int ic, iif, jc, jf, ncx = nfx / 2 + 1, ncy = nfy / 2 + 1;
00334
00335 for (jc = 1, jf = 1; jc <= ncy; jc++, jf += 2)
00336 for (ic = 1; ic < ncx; ic++)
00337 uf[2*ic-1][jf] = uc[ic][jc];
00338
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
00343 for (jf = 2; jf < nfy; jf += 2)
00344 for (iif = 1; iif <= nfx; iif++)
00345 uf[iif][jf] = 0.5 * (uf[iif][jf+1] + uf[iif][jf-1]);
00346
00347 bc_scalar(uf, nfx, nfy, NULGRAD);
00348 }
00349 #endif
00350
00351 static void interp(real2D uf, real2D uc, int nfx, int nfy)
00352 {
00353 int ic, iff, jc, jf, ncx, ncy;
00354
00355 ncx = nfx / 2 + 1;
00356 ncy = nfy / 2 + 1;
00357 for (ic = 2; ic <= ncx - 1; ic++)
00358 {
00359 iff = 2 * ic - 2;
00360 for (jc = 2; jc <= ncy - 1; jc++)
00361 {
00362 jf = 2 * jc - 2;
00363 uf[iff][jf] =
00364 uf[iff][jf+1] =
00365 uf[iff+1][jf] =
00366 uf[iff+1][jf+1] = uc[ic][jc];
00367 }
00368 }
00369
00370 bc_scalar(uf, nfx, nfy, NULGRAD);
00371 }
00372
00373 #if 0
00374 static void interp(real2D uf, real2D uc, int nfx, int nfy)
00375 {
00376 int ic, iff, jc, jf, ncx, ncy;
00377
00378 ncx = nfx / 2 + 1;
00379 ncy = nfy / 2 + 1;
00380
00381 for (ic = 2; ic <= ncx - 1; ic++)
00382 {
00383 iff = 2 * ic - 2;
00384 for (jc = 2; jc <= ncy - 1; jc++)
00385 {
00386 jf = 2 * jc - 2;
00387 uf[iff][jf] = uc[ic][jc];
00388 }
00389 }
00390
00391 for (jf = 1; jf <= nfy; jf += 2)
00392 for (iff = 2; iff < nfx; iff += 2)
00393 uf[iff][jf] = 0.5 * (uf[iff+1][jf] + uf[iff-1][jf]);
00394 for (jf = 2; jf < nfy; jf += 2)
00395 for (iff = 1; iff <= nfx; iff++)
00396 uf[iff][jf] = 0.5 * (uf[iff][jf+1] + uf[iff][jf-1]);
00397
00398 bc_scalar(uf, nfx, nfy, NULGRAD);
00399 }
00400 #endif
00401
00402
00403
00404 static void slvsml(real2D u, real2D rhs, real2D a, real2D b, real2D ei,
00405 int nfx, int nfy)
00406 {
00407 int count;
00408
00409 for (count = 1; count <= COARSERELAX; count++)
00410 {
00411 relax(u, rhs, a, b, ei, nfx, nfy);
00412 bc_scalar(u, nfx, nfy, NULGRAD);
00413 }
00414 }
00415
00416
00417
00418 void relax(real2D u, real2D rhs,
00419 real2D a, real2D b, real2D ei, real2D cc,
00420 int n1, int n2)
00421 {
00422 real h2, h, res;
00423 int i, j, isw, jsw;
00424
00425 h = 1.0 / (n2 - 2);
00426 h2 = h * h;
00427 for (jsw = 1; jsw <= 2; jsw++)
00428 {
00429 isw = jsw;
00430 for (i = 2; i <= n1 - 1; i++, isw = 3 - isw)
00431 for (j = isw + 1; j <= n2 - 1; j += 2)
00432 if (cc[i][j] == 1.0)
00433 u[i][j] = (a[i][j] * u[i+1][j] +
00434 a[i-1][j] * u[i-1][j] +
00435 b[i][j] * u[i][j+1] +
00436 b[i][j-1] * u[i][j-1]
00437 - h2 * rhs[i][j])
00438 * ei[i][j];
00439 }
00440 }
00441
00442
00443
00444
00445 void lop(real2D out, real2D u, real2D a, real2D b, real2D cc,
00446 int n1, int n2)
00447 {
00448 int i, j;
00449 real hi2;
00450
00451 hi2 = (real) (n2 - 2) * (n2 - 2);
00452 for (i = 2; i <= n1 - 1; i++)
00453 for (j = 2; j <= n2 - 1; j++)
00454 if (cc[i][j] == 1.0)
00455 out[i][j] = hi2 * (a[i][j] * (u[i+1][j] - u[i][j]) +
00456 a[i-1][j] * (u[i-1][j] - u[i][j]) +
00457 b[i][j] * (u[i][j+1] - u[i][j]) +
00458 b[i][j-1] * (u[i][j-1] - u[i][j]));
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468