IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
MatGenFD.c
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack: Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2002) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 //@HEADER
00041 */
00042 
00043 #include "MatGenFD.h"
00044 #include "Mat_dh.h"
00045 #include "Vec_dh.h"
00046 #include "Parser_dh.h"
00047 #include "Mem_dh.h"
00048 /* #include "graphColor_dh.h" */
00049 
00050 static bool isThreeD;
00051 
00052   /* handles for values in the 5-point (2D) or 7-point (for 3D) stencil */
00053 #define FRONT(a)  a[5]
00054 #define SOUTH(a)  a[3]
00055 #define WEST(a)   a[1]
00056 #define CENTER(a) a[0]
00057 #define EAST(a)   a[2]
00058 #define NORTH(a)  a[4]
00059 #define BACK(a)   a[6]
00060 #define RHS(a)    a[7]
00061 
00062 static void setBoundary_private (int node, int *cval, double *aval, int len,
00063                  double *rhs, double bc, double coeff,
00064                  double ctr, int nabor);
00065 static void generateStriped (MatGenFD mg, int *rp, int *cval, double *aval,
00066                  Mat_dh A, Vec_dh b);
00067 static void generateBlocked (MatGenFD mg, int *rp, int *cval, double *aval,
00068                  Mat_dh A, Vec_dh b);
00069 static void getstencil (MatGenFD g, int ix, int iy, int iz);
00070 
00071 #if 0
00072 static void fdaddbc (int nx, int ny, int nz, int *rp, int *cval,
00073              int *diag, double *aval, double *rhs, double h,
00074              MatGenFD mg);
00075 #endif
00076 
00077 #undef __FUNC__
00078 #define __FUNC__ "MatGenFDCreate"
00079 void
00080 MatGenFD_Create (MatGenFD * mg)
00081 {
00082   START_FUNC_DH
00083     struct _matgenfd *tmp =
00084     (struct _matgenfd *) MALLOC_DH (sizeof (struct _matgenfd));
00085   CHECK_V_ERROR;
00086   *mg = tmp;
00087 
00088   tmp->debug = Parser_dhHasSwitch (parser_dh, "-debug_matgen");
00089 
00090   tmp->m = 9;
00091   tmp->px = tmp->py = 1;
00092   tmp->pz = 0;
00093   Parser_dhReadInt (parser_dh, "-m", &tmp->m);
00094   Parser_dhReadInt (parser_dh, "-px", &tmp->px);
00095   Parser_dhReadInt (parser_dh, "-py", &tmp->py);
00096   Parser_dhReadInt (parser_dh, "-pz", &tmp->pz);
00097 
00098   if (tmp->px < 1)
00099     tmp->px = 1;
00100   if (tmp->py < 1)
00101     tmp->py = 1;
00102   if (tmp->pz < 0)
00103     tmp->pz = 0;
00104   tmp->threeD = false;
00105   if (tmp->pz)
00106     {
00107       tmp->threeD = true;
00108     }
00109   else
00110     {
00111       tmp->pz = 1;
00112     }
00113   if (Parser_dhHasSwitch (parser_dh, "-threeD"))
00114     tmp->threeD = true;
00115 
00116   tmp->a = tmp->b = tmp->c = 1.0;
00117   tmp->d = tmp->e = tmp->f = 0.0;
00118   tmp->g = tmp->h = 0.0;
00119 
00120   Parser_dhReadDouble (parser_dh, "-dx", &tmp->a);
00121   Parser_dhReadDouble (parser_dh, "-dy", &tmp->b);
00122   Parser_dhReadDouble (parser_dh, "-dz", &tmp->c);
00123   Parser_dhReadDouble (parser_dh, "-cx", &tmp->d);
00124   Parser_dhReadDouble (parser_dh, "-cy", &tmp->e);
00125   Parser_dhReadDouble (parser_dh, "-cz", &tmp->f);
00126 
00127   tmp->a = -1 * fabs (tmp->a);
00128   tmp->b = -1 * fabs (tmp->b);
00129   tmp->c = -1 * fabs (tmp->c);
00130 
00131   tmp->allocateMem = true;
00132 
00133   tmp->A = tmp->B = tmp->C = tmp->D = tmp->E
00134     = tmp->F = tmp->G = tmp->H = konstant;
00135 
00136   tmp->bcX1 = tmp->bcX2 = tmp->bcY1 = tmp->bcY2 = tmp->bcZ1 = tmp->bcZ2 = 0.0;
00137   Parser_dhReadDouble (parser_dh, "-bcx1", &tmp->bcX1);
00138   Parser_dhReadDouble (parser_dh, "-bcx2", &tmp->bcX2);
00139   Parser_dhReadDouble (parser_dh, "-bcy1", &tmp->bcY1);
00140   Parser_dhReadDouble (parser_dh, "-bcy2", &tmp->bcY2);
00141   Parser_dhReadDouble (parser_dh, "-bcz1", &tmp->bcZ1);
00142   Parser_dhReadDouble (parser_dh, "-bcz2", &tmp->bcZ2);
00143 END_FUNC_DH}
00144 
00145 
00146 #undef __FUNC__
00147 #define __FUNC__ "MatGenFD_Destroy"
00148 void
00149 MatGenFD_Destroy (MatGenFD mg)
00150 {
00151   START_FUNC_DH FREE_DH (mg);
00152   CHECK_V_ERROR;
00153 END_FUNC_DH}
00154 
00155 
00156 #undef __FUNC__
00157 #define __FUNC__ "MatGenFD_Run"
00158 void
00159 MatGenFD_Run (MatGenFD mg, int id, int np, Mat_dh * AOut, Vec_dh * rhsOut)
00160 {
00161 /* What this function does:
00162  *   0. creates return objects (A and rhs)
00163  *   1. computes "nice to have" values;
00164  *   2. allocates storage, if required;
00165  *   3. calls generateBlocked() or generateStriped().
00166  *   4. initializes variable in A and rhs.
00167  */
00168 
00169   START_FUNC_DH Mat_dh A;
00170   Vec_dh rhs;
00171   bool threeD = mg->threeD;
00172   int nnz;
00173   int m = mg->m;        /* local unknowns */
00174   bool debug = false, striped;
00175 
00176   if (mg->debug && logFile != NULL)
00177     debug = true;
00178   striped = Parser_dhHasSwitch (parser_dh, "-striped");
00179 
00180   /* 0. create objects */
00181   Mat_dhCreate (AOut);
00182   CHECK_V_ERROR;
00183   Vec_dhCreate (rhsOut);
00184   CHECK_V_ERROR;
00185   A = *AOut;
00186   rhs = *rhsOut;
00187 
00188   /* ensure that processor grid contains the same number of
00189      nodes as there are processors.
00190    */
00191   if (!Parser_dhHasSwitch (parser_dh, "-noChecks"))
00192     {
00193       if (!striped)
00194     {
00195       int npTest = mg->px * mg->py;
00196       if (threeD)
00197         npTest *= mg->pz;
00198       if (npTest != np)
00199         {
00200           sprintf (msgBuf_dh,
00201                "numbers don't match: np_dh = %i, px*py*pz = %i", np,
00202                npTest);
00203           SET_V_ERROR (msgBuf_dh);
00204         }
00205     }
00206     }
00207 
00208   /* 1. compute "nice to have" values */
00209   /* each proc's subgrid dimension */
00210   mg->cc = m;
00211   if (threeD)
00212     {
00213       m = mg->m = m * m * m;
00214     }
00215   else
00216     {
00217       m = mg->m = m * m;
00218     }
00219 
00220   mg->first = id * m;
00221   mg->hh = 1.0 / (mg->px * mg->cc - 1);
00222 
00223   if (debug)
00224     {
00225       sprintf (msgBuf_dh, "cc (local grid dimension) = %i", mg->cc);
00226       SET_INFO (msgBuf_dh);
00227       if (threeD)
00228     {
00229       sprintf (msgBuf_dh, "threeD = true");
00230     }
00231       else
00232     {
00233       sprintf (msgBuf_dh, "threeD = false");
00234     }
00235       SET_INFO (msgBuf_dh);
00236       sprintf (msgBuf_dh, "np= %i  id= %i", np, id);
00237       SET_INFO (msgBuf_dh);
00238     }
00239 
00240   mg->id = id;
00241   mg->np = np;
00242   nnz = threeD ? m * 7 : m * 5;
00243 
00244   /* 2. allocate storage */
00245   if (mg->allocateMem)
00246     {
00247       A->rp = (int *) MALLOC_DH ((m + 1) * sizeof (int));
00248       CHECK_V_ERROR;
00249       A->rp[0] = 0;
00250       A->cval = (int *) MALLOC_DH (nnz * sizeof (int));
00251       CHECK_V_ERROR A->aval = (double *) MALLOC_DH (nnz * sizeof (double));
00252       CHECK_V_ERROR;
00253       /* rhs->vals = (double*)MALLOC_DH(m*sizeof(double)); CHECK_V_ERROR; */
00254     }
00255 
00256   /* 4. initialize variables in A and rhs */
00257   rhs->n = m;
00258   A->m = m;
00259   A->n = m * mg->np;
00260   A->beg_row = mg->first;
00261 
00262   /* 3. generate matrix */
00263   isThreeD = threeD;        /* yuck!  used in box_XX() */
00264   if (Parser_dhHasSwitch (parser_dh, "-striped"))
00265     {
00266       generateStriped (mg, A->rp, A->cval, A->aval, A, rhs);
00267       CHECK_V_ERROR;
00268     }
00269   else
00270     {
00271       generateBlocked (mg, A->rp, A->cval, A->aval, A, rhs);
00272       CHECK_V_ERROR;
00273     }
00274 
00275   /* add in bdry conditions */
00276   /* only implemented for 2D mats! */
00277   if (!threeD)
00278     {
00279 /*  fdaddbc(nx, ny, nz, rp, cval, diag, aval, rhs, h, mg); */
00280     }
00281 
00282 END_FUNC_DH}
00283 
00284 
00285 #undef __FUNC__
00286 #define __FUNC__ "generateStriped"
00287 void
00288 generateStriped (MatGenFD mg, int *rp, int *cval, double *aval, Mat_dh A,
00289          Vec_dh b)
00290 {
00291   START_FUNC_DH int mGlobal;
00292   int m = mg->m;
00293   int beg_row, end_row;
00294   int i, j, k, row;
00295   bool threeD = mg->threeD;
00296   int idx = 0;
00297   double *stencil = mg->stencil;
00298   bool debug = false;
00299   int plane, nodeRemainder;
00300   int naborx1, naborx2, nabory1, nabory2;
00301   double *rhs;
00302 
00303   bool applyBdry = true;
00304   double hhalf;
00305   double bcx1 = mg->bcX1;
00306   double bcx2 = mg->bcX2;
00307   double bcy1 = mg->bcY1;
00308   double bcy2 = mg->bcY2;
00309   /* double bcz1 = mg->bcZ1; */
00310   /* double bcz2 = mg->bcZ2; */
00311   int nx, ny;
00312 
00313   printf_dh ("@@@ using striped partitioning\n");
00314 
00315   if (mg->debug && logFile != NULL)
00316     debug = true;
00317 
00318   /* recompute values (yuck!) */
00319   m = 9;
00320   Parser_dhReadInt (parser_dh, "-m", &m);   /* global grid dimension */
00321   mGlobal = m * m;      /* global unkknowns */
00322   if (threeD)
00323     mGlobal *= m;
00324   i = mGlobal / mg->np;     /* unknowns per processor */
00325   beg_row = i * mg->id;     /* global number of 1st local row */
00326   end_row = beg_row + i;
00327   if (mg->id == mg->np - 1)
00328     end_row = mGlobal;
00329   nx = ny = m;
00330 
00331   mg->hh = 1.0 / (m - 1);
00332   hhalf = 0.5 * mg->hh;
00333 
00334   A->n = m * m;
00335   A->m = end_row - beg_row;
00336   A->beg_row = beg_row;
00337 
00338   Vec_dhInit (b, A->m);
00339   CHECK_V_ERROR;
00340   rhs = b->vals;
00341 
00342   plane = m * m;
00343 
00344   if (debug)
00345     {
00346       fprintf (logFile, "generateStriped: beg_row= %i; end_row= %i; m= %i\n",
00347            beg_row + 1, end_row + 1, m);
00348     }
00349 
00350   for (row = beg_row; row < end_row; ++row)
00351     {
00352       int localRow = row - beg_row;
00353 
00354       /* compute current node's position in grid */
00355       k = (row / plane);
00356       nodeRemainder = row - (k * plane);    /* map row to 1st plane */
00357       j = nodeRemainder / m;
00358       i = nodeRemainder % m;
00359 
00360       if (debug)
00361     {
00362       fprintf (logFile, "row= %i  x= %i  y= %i  z= %i\n", row + 1, i, j,
00363            k);
00364     }
00365 
00366       /* compute column values and rhs entry for the current node */
00367       getstencil (mg, i, j, k);
00368 
00369       /* only homogenous Dirichlet boundary conditions presently supported */
00370 
00371       /* down plane */
00372       if (threeD)
00373     {
00374       if (k > 0)
00375         {
00376           cval[idx] = row - plane;
00377           aval[idx++] = BACK (stencil);
00378         }
00379     }
00380 
00381       /* south */
00382       if (j > 0)
00383     {
00384       nabory1 = cval[idx] = row - m;
00385       aval[idx++] = SOUTH (stencil);
00386     }
00387 
00388       /* west */
00389       if (i > 0)
00390     {
00391       naborx1 = cval[idx] = row - 1;
00392       aval[idx++] = WEST (stencil);
00393     }
00394 
00395       /* center node */
00396       cval[idx] = row;
00397       aval[idx++] = CENTER (stencil);
00398 
00399       /* east */
00400       if (i < m - 1)
00401     {
00402       naborx2 = cval[idx] = row + 1;
00403       aval[idx++] = EAST (stencil);
00404     }
00405 
00406       /* north */
00407       if (j < m - 1)
00408     {
00409       nabory2 = cval[idx] = row + m;
00410       aval[idx++] = NORTH (stencil);
00411     }
00412 
00413       /* up plane */
00414       if (threeD)
00415     {
00416       if (k < m - 1)
00417         {
00418           cval[idx] = row + plane;
00419           aval[idx++] = FRONT (stencil);
00420         }
00421     }
00422       rhs[localRow] = 0.0;
00423       ++localRow;
00424       rp[localRow] = idx;
00425 
00426       /* apply boundary conditions; only for 2D! */
00427       if (!threeD && applyBdry)
00428     {
00429       int offset = rp[localRow - 1];
00430       int len = rp[localRow] - rp[localRow - 1];
00431       double ctr, coeff;
00432 
00433 /* fprintf(logFile, "globalRow = %i; naborx2 = %i\n", row+1, row); */
00434 
00435       if (i == 0)
00436         {           /* if x1 */
00437           coeff = mg->A (mg->a, i + hhalf, j, k);
00438           ctr = mg->A (mg->a, i - hhalf, j, k);
00439           setBoundary_private (row, cval + offset, aval + offset, len,
00440                    &(rhs[localRow - 1]), bcx1, coeff, ctr,
00441                    naborx2);
00442         }
00443       else if (i == nx - 1)
00444         {           /* if x2 */
00445           coeff = mg->A (mg->a, i - hhalf, j, k);
00446           ctr = mg->A (mg->a, i + hhalf, j, k);
00447           setBoundary_private (row, cval + offset, aval + offset, len,
00448                    &(rhs[localRow - 1]), bcx2, coeff, ctr,
00449                    naborx1);
00450         }
00451       else if (j == 0)
00452         {           /* if y1 */
00453           coeff = mg->B (mg->b, i, j + hhalf, k);
00454           ctr = mg->B (mg->b, i, j - hhalf, k);
00455           setBoundary_private (row, cval + offset, aval + offset, len,
00456                    &(rhs[localRow - 1]), bcy1, coeff, ctr,
00457                    nabory2);
00458         }
00459       else if (j == ny - 1)
00460         {           /* if y2 */
00461           coeff = mg->B (mg->b, i, j - hhalf, k);
00462           ctr = mg->B (mg->b, i, j + hhalf, k);
00463           setBoundary_private (row, cval + offset, aval + offset, len,
00464                    &(rhs[localRow - 1]), bcy2, coeff, ctr,
00465                    nabory1);
00466         }
00467     }
00468     }
00469 END_FUNC_DH}
00470 
00471 
00472 /* zero-based 
00473    (from Edmond Chow)
00474 */
00475 /* 
00476    x,y,z       -  coordinates of row, wrt naturally ordered grid
00477    nz, ny, nz  -  local grid dimensions, wrt 0
00478    P, Q        -  subdomain grid dimensions in x and y directions
00479 */
00480 int
00481 rownum (const bool threeD, const int x, const int y, const int z,
00482     const int nx, const int ny, const int nz, int P, int Q)
00483 {
00484   int p, q, r;
00485   int lowerx, lowery, lowerz;
00486   int id, startrow;
00487 
00488 
00489   /* compute x,y,z coordinates of subdomain to which
00490      this row belongs.
00491    */
00492   p = x / nx;
00493   q = y / ny;
00494   r = z / nz;
00495 
00496 /*
00497 if (myid_dh == 0) printf("nx= %i  ny= %i  nz= %i\n", nx, ny, nz);
00498 if (myid_dh == 0) printf("x= %i y= %i z= %i  threeD= %i  p= %i q= %i r= %i\n",
00499               x,y,z,threeD, p,q,r);
00500 */
00501 
00502   /* compute the subdomain (processor) of the subdomain to which
00503      this row belongs.
00504    */
00505   if (threeD)
00506     {
00507       id = r * P * Q + q * P + p;
00508     }
00509   else
00510     {
00511       id = q * P + p;
00512     }
00513 
00514 /*  if (myid_dh == 0) printf(" id= %i\n", id);
00515 */
00516 
00517   /* smallest row in the subdomain */
00518   startrow = id * (nx * ny * nz);
00519 
00520   /* x,y, and z coordinates of local grid of unknowns */
00521   lowerx = nx * p;
00522   lowery = ny * q;
00523   lowerz = nz * r;
00524 
00525   if (threeD)
00526     {
00527       return startrow + nx * ny * (z - lowerz) + nx * (y - lowery) + (x -
00528                                       lowerx);
00529     }
00530   else
00531     {
00532       return startrow + nx * (y - lowery) + (x - lowerx);
00533     }
00534 }
00535 
00536 
00537 
00538 void
00539 getstencil (MatGenFD g, int ix, int iy, int iz)
00540 {
00541   int k;
00542   double h = g->hh;
00543   double hhalf = h * 0.5;
00544   double x = h * ix;
00545   double y = h * iy;
00546   double z = h * iz;
00547   double cntr = 0.0;
00548   double *stencil = g->stencil;
00549   double coeff;
00550   bool threeD = g->threeD;
00551 
00552   for (k = 0; k < 8; ++k)
00553     stencil[k] = 0.0;
00554 
00555   /* differentiation wrt x */
00556   coeff = g->A (g->a, x + hhalf, y, z);
00557   EAST (stencil) += coeff;
00558   cntr += coeff;
00559 
00560   coeff = g->A (g->a, x - hhalf, y, z);
00561   WEST (stencil) += coeff;
00562   cntr += coeff;
00563 
00564   coeff = g->D (g->d, x, y, z) * hhalf;
00565   EAST (stencil) += coeff;
00566   WEST (stencil) -= coeff;
00567 
00568   /* differentiation wrt y */
00569   coeff = g->B (g->b, x, y + hhalf, z);
00570   NORTH (stencil) += coeff;
00571   cntr += coeff;
00572 
00573   coeff = g->B (g->b, x, y - hhalf, z);
00574   SOUTH (stencil) += coeff;
00575   cntr += coeff;
00576 
00577   coeff = g->E (g->e, x, y, z) * hhalf;
00578   NORTH (stencil) += coeff;
00579   SOUTH (stencil) -= coeff;
00580 
00581   /* differentiation wrt z */
00582   if (threeD)
00583     {
00584       coeff = g->C (g->c, x, y, z + hhalf);
00585       BACK (stencil) += coeff;
00586       cntr += coeff;
00587 
00588       coeff = g->C (g->c, x, y, z - hhalf);
00589       FRONT (stencil) += coeff;
00590       cntr += coeff;
00591 
00592       coeff = g->F (g->f, x, y, z) * hhalf;
00593       BACK (stencil) += coeff;
00594       FRONT (stencil) -= coeff;
00595     }
00596 
00597   /* contribution from function G: */
00598   coeff = g->G (g->g, x, y, z);
00599   CENTER (stencil) = h * h * coeff - cntr;
00600 
00601   RHS (stencil) = h * h * g->H (g->h, x, y, z);
00602 }
00603 
00604 
00605 double
00606 konstant (double coeff, double x, double y, double z)
00607 {
00608   return coeff;
00609 }
00610 
00611 double
00612 e2_xy (double coeff, double x, double y, double z)
00613 {
00614   return exp (coeff * x * y);
00615 }
00616 
00617 double boxThreeD (double coeff, double x, double y, double z);
00618 
00619 /* returns diffusivity constant -bd1 if the point
00620    (x,y,z) is inside the box whose upper left and
00621    lower right points are (-bx1,-by1), (-bx2,-by2);
00622    else, returns diffusivity constant -bd2
00623 */
00624 double
00625 box_1 (double coeff, double x, double y, double z)
00626 {
00627   static bool setup = false;
00628   double retval = coeff;
00629 
00630   /* dffusivity constants */
00631   static double dd1 = BOX1_DD;
00632   static double dd2 = BOX2_DD;
00633   static double dd3 = BOX3_DD;
00634 
00635   /* boxes */
00636   static double ax1 = BOX1_X1, ay1 = BOX1_Y1;
00637   static double ax2 = BOX1_X2, ay2 = BOX1_Y2;
00638   static double bx1 = BOX2_X1, by1 = BOX2_Y1;
00639   static double bx2 = BOX2_X2, by2 = BOX2_Y2;
00640   static double cx1 = BOX3_X1, cy1 = BOX3_Y1;
00641   static double cx2 = BOX3_X2, cy2 = BOX3_Y2;
00642 
00643   if (isThreeD)
00644     {
00645       return (boxThreeD (coeff, x, y, z));
00646     }
00647 
00648 
00649   /* 1st time through, parse for dffusivity constants */
00650   if (!setup)
00651     {
00652       dd1 = 0.1;
00653       dd2 = 0.1;
00654       dd3 = 10;
00655       Parser_dhReadDouble (parser_dh, "-dd1", &dd1);
00656       Parser_dhReadDouble (parser_dh, "-dd2", &dd2);
00657       Parser_dhReadDouble (parser_dh, "-dd3", &dd3);
00658       Parser_dhReadDouble (parser_dh, "-box1x1", &cx1);
00659       Parser_dhReadDouble (parser_dh, "-box1x2", &cx2);
00660       setup = true;
00661     }
00662 
00663   /* determine if point is inside box a */
00664   if (x > ax1 && x < ax2 && y > ay1 && y < ay2)
00665     {
00666       retval = dd1 * coeff;
00667     }
00668 
00669   /* determine if point is inside box b */
00670   if (x > bx1 && x < bx2 && y > by1 && y < by2)
00671     {
00672       retval = dd2 * coeff;
00673     }
00674 
00675   /* determine if point is inside box c */
00676   if (x > cx1 && x < cx2 && y > cy1 && y < cy2)
00677     {
00678       retval = dd3 * coeff;
00679     }
00680 
00681   return retval;
00682 }
00683 
00684 double
00685 boxThreeD (double coeff, double x, double y, double z)
00686 {
00687   static bool setup = false;
00688   double retval = coeff;
00689 
00690   /* dffusivity constants */
00691   static double dd1 = 100;
00692 
00693   /* boxes */
00694   static double x1 = .2, x2 = .8;
00695   static double y1 = .3, y2 = .7;
00696   static double z1 = .4, z2 = .6;
00697 
00698   /* 1st time through, parse for diffusivity constants */
00699   if (!setup)
00700     {
00701       Parser_dhReadDouble (parser_dh, "-dd1", &dd1);
00702       setup = true;
00703     }
00704 
00705   /* determine if point is inside the box */
00706   if (x > x1 && x < x2 && y > y1 && y < y2 && z > z1 && z < z2)
00707     {
00708       retval = dd1 * coeff;
00709     }
00710 
00711   return retval;
00712 }
00713 
00714 #if 0
00715 double
00716 box_1 (double coeff, double x, double y, double z)
00717 {
00718   static double x1, x2, y1, y2;
00719   static double d1, d2;
00720   bool setup = false;
00721   double retval;
00722 
00723   /* 1st time through, parse for constants and
00724      bounding box definition
00725    */
00726   if (!setup)
00727     {
00728       x1 = .25;
00729       x2 = .75;
00730       y1 = .25;
00731       y2 = .75;
00732       d1 = 1;
00733       d2 = 2;
00734       Parser_dhReadDouble (parser_dh, "-bx1", &x1);
00735       Parser_dhReadDouble (parser_dh, "-bx2", &x2);
00736       Parser_dhReadDouble (parser_dh, "-by1", &y1);
00737       Parser_dhReadDouble (parser_dh, "-by2", &y2);
00738       Parser_dhReadDouble (parser_dh, "-bd1", &d1);
00739       Parser_dhReadDouble (parser_dh, "-bd2", &d2);
00740       setup = true;
00741     }
00742 
00743   retval = d2;
00744 
00745   /* determine if point is inside box */
00746   if (x > x1 && x < x2 && y > y1 && y < y2)
00747     {
00748       retval = d1;
00749     }
00750 
00751   return -1 * retval;
00752 }
00753 #endif
00754 
00755 /* divide square into 4 quadrants; return one of
00756    2 constants depending on the quadrant (checkerboard)
00757 */
00758 double
00759 box_2 (double coeff, double x, double y, double z)
00760 {
00761   bool setup = false;
00762   static double d1, d2;
00763   double retval;
00764 
00765   if (!setup)
00766     {
00767       d1 = 1;
00768       d2 = 2;
00769       Parser_dhReadDouble (parser_dh, "-bd1", &d1);
00770       Parser_dhReadDouble (parser_dh, "-bd2", &d2);
00771     }
00772 
00773   retval = d2;
00774 
00775   if (x < .5 && y < .5)
00776     retval = d1;
00777   if (x > .5 && y > .5)
00778     retval = d1;
00779 
00780   return -1 * retval;
00781 }
00782 
00783 
00784 #undef __FUNC__
00785 #define __FUNC__ "generateBlocked"
00786 void
00787 generateBlocked (MatGenFD mg, int *rp, int *cval, double *aval, Mat_dh A,
00788          Vec_dh b)
00789 {
00790   START_FUNC_DH bool applyBdry = true;
00791   double *stencil = mg->stencil;
00792   int id = mg->id;
00793   bool threeD = mg->threeD;
00794   int px = mg->px, py = mg->py, pz = mg->pz;    /* processor grid dimensions */
00795   int p, q, r;          /* this proc's position in processor grid */
00796   int cc = mg->cc;      /* local grid dimension (grid of unknowns) */
00797   int nx = cc, ny = cc, nz = cc;
00798   int lowerx, upperx, lowery, uppery, lowerz, upperz;
00799   int startRow;
00800   int x, y, z;
00801   bool debug = false;
00802   int idx = 0, localRow = 0;    /* nabor; */
00803   int naborx1, naborx2, nabory1, nabory2, naborz1, naborz2;
00804   double *rhs;
00805 
00806   double hhalf = 0.5 * mg->hh;
00807   double bcx1 = mg->bcX1;
00808   double bcx2 = mg->bcX2;
00809   double bcy1 = mg->bcY1;
00810   double bcy2 = mg->bcY2;
00811   /* double bcz1 = mg->bcZ1; */
00812   /* double bcz2 = mg->bcZ2; */
00813 
00814   Vec_dhInit (b, A->m);
00815   CHECK_V_ERROR;
00816   rhs = b->vals;
00817 
00818   if (mg->debug && logFile != NULL)
00819     debug = true;
00820   if (!threeD)
00821     nz = 1;
00822 
00823   /* compute p,q,r from P,Q,R and myid */
00824   p = id % px;
00825   q = ((id - p) / px) % py;
00826   r = (id - p - px * q) / (px * py);
00827 
00828   if (debug)
00829     {
00830       sprintf (msgBuf_dh,
00831            "this proc's position in subdomain grid: p= %i  q= %i  r= %i",
00832            p, q, r);
00833       SET_INFO (msgBuf_dh);
00834     }
00835 
00836   /* compute ilower and iupper from p,q,r and nx,ny,nz */
00837   /* zero-based */
00838 
00839   lowerx = nx * p;
00840   upperx = lowerx + nx;
00841   lowery = ny * q;
00842   uppery = lowery + ny;
00843   lowerz = nz * r;
00844   upperz = lowerz + nz;
00845 
00846   if (debug)
00847     {
00848       sprintf (msgBuf_dh, "local grid parameters: lowerx= %i  upperx= %i",
00849            lowerx, upperx);
00850       SET_INFO (msgBuf_dh);
00851       sprintf (msgBuf_dh, "local grid parameters: lowery= %i  uppery= %i",
00852            lowery, uppery);
00853       SET_INFO (msgBuf_dh);
00854       sprintf (msgBuf_dh, "local grid parameters: lowerz= %i  upperz= %i",
00855            lowerz, upperz);
00856       SET_INFO (msgBuf_dh);
00857     }
00858 
00859   startRow = mg->first;
00860   rp[0] = 0;
00861 
00862   for (z = lowerz; z < upperz; z++)
00863     {
00864       for (y = lowery; y < uppery; y++)
00865     {
00866       for (x = lowerx; x < upperx; x++)
00867         {
00868 
00869           if (debug)
00870         {
00871           fprintf (logFile, "row= %i  x= %i  y= %i  z= %i\n",
00872                localRow + startRow + 1, x, y, z);
00873         }
00874 
00875           /* compute row values and rhs, at the current node */
00876           getstencil (mg, x, y, z);
00877 
00878           /* down plane */
00879           if (threeD)
00880         {
00881           if (z > 0)
00882             {
00883               naborz1 =
00884             rownum (threeD, x, y, z - 1, nx, ny, nz, px, py);
00885               cval[idx] = naborz1;
00886               aval[idx++] = FRONT (stencil);
00887             }
00888         }
00889 
00890           /* south */
00891           if (y > 0)
00892         {
00893           nabory1 = rownum (threeD, x, y - 1, z, nx, ny, nz, px, py);
00894           cval[idx] = nabory1;
00895           aval[idx++] = SOUTH (stencil);
00896         }
00897 
00898           /* west */
00899           if (x > 0)
00900         {
00901           naborx1 = rownum (threeD, x - 1, y, z, nx, ny, nz, px, py);
00902           cval[idx] = naborx1;
00903           aval[idx++] = WEST (stencil);
00904 /*fprintf(logFile, "--- row: %i;  naborx1= %i\n", localRow+startRow+1, 1+naborx1);
00905 */
00906         }
00907 /*
00908 else {
00909 fprintf(logFile, "--- row: %i;  x >= nx*px-1; naborx1 has old value: %i\n", localRow+startRow+1,1+naborx1);
00910 }
00911 */
00912 
00913           /* center node */
00914           cval[idx] = localRow + startRow;
00915           aval[idx++] = CENTER (stencil);
00916 
00917 
00918           /* east */
00919           if (x < nx * px - 1)
00920         {
00921           naborx2 = rownum (threeD, x + 1, y, z, nx, ny, nz, px, py);
00922           cval[idx] = naborx2;
00923           aval[idx++] = EAST (stencil);
00924         }
00925 /*
00926 else {
00927 fprintf(logFile, "--- row: %i;  x >= nx*px-1; nobors2 has old value: %i\n", localRow+startRow,1+naborx2);
00928 }
00929 */
00930 
00931           /* north */
00932           if (y < ny * py - 1)
00933         {
00934           nabory2 = rownum (threeD, x, y + 1, z, nx, ny, nz, px, py);
00935           cval[idx] = nabory2;
00936           aval[idx++] = NORTH (stencil);
00937         }
00938 
00939           /* up plane */
00940           if (threeD)
00941         {
00942           if (z < nz * pz - 1)
00943             {
00944               naborz2 =
00945             rownum (threeD, x, y, z + 1, nx, ny, nz, px, py);
00946               cval[idx] = naborz2;
00947               aval[idx++] = BACK (stencil);
00948             }
00949         }
00950 
00951           /* rhs[rhsIdx++] = RHS(stencil); */
00952           rhs[localRow] = 0.0;
00953 
00954           ++localRow;
00955           rp[localRow] = idx;
00956 
00957           /* apply boundary conditions; only for 2D! */
00958           if (!threeD && applyBdry)
00959         {
00960           int globalRow = localRow + startRow - 1;
00961           int offset = rp[localRow - 1];
00962           int len = rp[localRow] - rp[localRow - 1];
00963           double ctr, coeff;
00964 
00965 /* fprintf(logFile, "globalRow = %i; naborx2 = %i\n", globalRow+1, naborx2+1); */
00966 
00967           if (x == 0)
00968             {       /* if x1 */
00969               coeff = mg->A (mg->a, x + hhalf, y, z);
00970               ctr = mg->A (mg->a, x - hhalf, y, z);
00971               setBoundary_private (globalRow, cval + offset,
00972                        aval + offset, len,
00973                        &(rhs[localRow - 1]), bcx1, coeff,
00974                        ctr, naborx2);
00975             }
00976           else if (x == nx * px - 1)
00977             {       /* if x2 */
00978               coeff = mg->A (mg->a, x - hhalf, y, z);
00979               ctr = mg->A (mg->a, x + hhalf, y, z);
00980               setBoundary_private (globalRow, cval + offset,
00981                        aval + offset, len,
00982                        &(rhs[localRow - 1]), bcx2, coeff,
00983                        ctr, naborx1);
00984             }
00985           else if (y == 0)
00986             {       /* if y1 */
00987               coeff = mg->B (mg->b, x, y + hhalf, z);
00988               ctr = mg->B (mg->b, x, y - hhalf, z);
00989               setBoundary_private (globalRow, cval + offset,
00990                        aval + offset, len,
00991                        &(rhs[localRow - 1]), bcy1, coeff,
00992                        ctr, nabory2);
00993             }
00994           else if (y == ny * py - 1)
00995             {       /* if y2 */
00996               coeff = mg->B (mg->b, x, y - hhalf, z);
00997               ctr = mg->B (mg->b, x, y + hhalf, z);
00998               setBoundary_private (globalRow, cval + offset,
00999                        aval + offset, len,
01000                        &(rhs[localRow - 1]), bcy2, coeff,
01001                        ctr, nabory1);
01002             }
01003           else if (threeD)
01004             {
01005               if (z == 0)
01006             {
01007               coeff = mg->B (mg->b, x, y, z + hhalf);
01008               ctr = mg->B (mg->b, x, y, z - hhalf);
01009               setBoundary_private (globalRow, cval + offset,
01010                            aval + offset, len,
01011                            &(rhs[localRow - 1]), bcy1,
01012                            coeff, ctr, naborz2);
01013             }
01014               else if (z == nz * nx - 1)
01015             {
01016               coeff = mg->B (mg->b, x, y, z - hhalf);
01017               ctr = mg->B (mg->b, x, y, z + hhalf);
01018               setBoundary_private (globalRow, cval + offset,
01019                            aval + offset, len,
01020                            &(rhs[localRow - 1]), bcy1,
01021                            coeff, ctr, naborz1);
01022             }
01023             }
01024         }
01025         }
01026     }
01027     }
01028 END_FUNC_DH}
01029 
01030 
01031 #undef __FUNC__
01032 #define __FUNC__ "setBoundary_private"
01033 void
01034 setBoundary_private (int node, int *cval, double *aval, int len,
01035              double *rhs, double bc, double coeff, double ctr,
01036              int nabor)
01037 {
01038   START_FUNC_DH int i;
01039 
01040   /* case 1: Dirichlet Boundary condition  */
01041   if (bc >= 0)
01042     {
01043       /* set all values to zero, set the diagonal to 1.0, set rhs to "bc" */
01044       *rhs = bc;
01045       for (i = 0; i < len; ++i)
01046     {
01047       if (cval[i] == node)
01048         {
01049           aval[i] = 1.0;
01050         }
01051       else
01052         {
01053           aval[i] = 0;
01054         }
01055     }
01056     }
01057 
01058   /* case 2: neuman */
01059   else
01060     {
01061 /* fprintf(logFile, "node= %i  nabor= %i  coeff= %g\n", node+1, nabor+1, coeff); */
01062       /* adjust row values */
01063       for (i = 0; i < len; ++i)
01064     {
01065       /* adjust diagonal */
01066       if (cval[i] == node)
01067         {
01068           aval[i] += (ctr - coeff);
01069           /* adust node's right neighbor */
01070         }
01071       else if (cval[i] == nabor)
01072         {
01073           aval[i] = 2.0 * coeff;
01074         }
01075     }
01076     }
01077 END_FUNC_DH}
 All Classes Files Functions Variables Enumerations Friends