IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
ilu_mpi_pilu.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 "Euclid_dh.h"
00044 #include "Factor_dh.h"
00045 #include "Mat_dh.h"
00046 #include "ilu_dh.h"
00047 #include "Mem_dh.h"
00048 #include "Parser_dh.h"
00049 #include "Hash_dh.h"
00050 #include "getRow_dh.h"
00051 #include "SortedList_dh.h"
00052 #include "ExternalRows_dh.h"
00053 #include "SubdomainGraph_dh.h"
00054 
00055 
00056 static void iluk_symbolic_row_private (int localRow, int len, int *CVAL,
00057                        double *AVAL, ExternalRows_dh extRows,
00058                        SortedList_dh sList, Euclid_dh ctx,
00059                        bool debug);
00060 
00061 static void iluk_numeric_row_private (int new_row, ExternalRows_dh extRows,
00062                       SortedList_dh slist, Euclid_dh ctx,
00063                       bool debug);
00064 
00065 #undef __FUNC__
00066 #define __FUNC__ "iluk_mpi_pilu"
00067 void
00068 iluk_mpi_pilu (Euclid_dh ctx)
00069 {
00070   START_FUNC_DH int from = ctx->from, to = ctx->to;
00071   int i, m;
00072   int *n2o_row;         /* *o2n_col; */
00073   int *rp, *cval, *diag, *fill;
00074   int beg_row, beg_rowP, end_rowP;
00075   SubdomainGraph_dh sg = ctx->sg;
00076   int *CVAL, len, idx = 0, count;
00077   double *AVAL;
00078   REAL_DH *aval;
00079   Factor_dh F = ctx->F;
00080   SortedList_dh slist = ctx->slist;
00081   ExternalRows_dh extRows = ctx->extRows;
00082   bool bj, noValues, debug = false;
00083 
00084   /* for debugging */
00085   if (logFile != NULL && Parser_dhHasSwitch (parser_dh, "-debug_ilu"))
00086     debug = true;
00087   noValues = Parser_dhHasSwitch (parser_dh, "-noValues");
00088   bj = ctx->F->blockJacobi;
00089 
00090   m = F->m;
00091   rp = F->rp;
00092   cval = F->cval;
00093   fill = F->fill;
00094   diag = F->diag;
00095   aval = F->aval;
00096   /* work = ctx->work; */
00097 
00098   n2o_row = sg->n2o_row;
00099   /* o2n_col = sg->o2n_col; */
00100 
00101   if (from != 0)
00102     idx = rp[from];
00103 
00104   /* global numbers of first and last locally owned rows,
00105      with respect to A 
00106    */
00107   beg_row = sg->beg_row[myid_dh];
00108   /* end_row  = beg_row + sg->row_count[myid_dh]; */
00109 
00110   /* global number or first locally owned row, after reordering */
00111   beg_rowP = sg->beg_rowP[myid_dh];
00112   end_rowP = beg_rowP + sg->row_count[myid_dh];
00113 
00114 
00115   /* loop over rows to be factored (i references local rows) */
00116   for (i = from; i < to; ++i)
00117     {
00118 
00119       int row = n2o_row[i]; /* local row number */
00120       int globalRow = row + beg_row;    /* global row number */
00121 
00122       if (debug)
00123     {
00124       fprintf (logFile,
00125            "\nILU_pilu global: %i  old_Local: %i =========================================================\n",
00126            i + 1 + beg_rowP, row + 1);
00127     }
00128 
00129       EuclidGetRow (ctx->A, globalRow, &len, &CVAL, &AVAL);
00130       CHECK_V_ERROR;
00131 
00132       if (debug)
00133     {
00134       int h;
00135       fprintf (logFile, "ILU_pilu  EuclidGetRow:\n");
00136       for (h = 0; h < len; ++h)
00137         fprintf (logFile, "    %i   %g\n", 1 + CVAL[h], AVAL[h]);
00138     }
00139 
00140 
00141       /* compute scaling value for row(i) */
00142       if (ctx->isScaled)
00143     {
00144       compute_scaling_private (i, len, AVAL, ctx);
00145       CHECK_V_ERROR;
00146     }
00147 
00148       SortedList_dhReset (slist, i);
00149       CHECK_V_ERROR;
00150 
00151       /* Compute symbolic factor for row(i);
00152          this also performs sparsification
00153        */
00154       iluk_symbolic_row_private (i, len, CVAL, AVAL,
00155                  extRows, slist, ctx, debug);
00156       CHECK_V_ERROR;
00157 
00158       /* enforce subdomain constraint */
00159       SortedList_dhEnforceConstraint (slist, sg);
00160 
00161       /* compute numeric factor for row */
00162       if (!noValues)
00163     {
00164       iluk_numeric_row_private (i, extRows, slist, ctx, debug);
00165       CHECK_V_ERROR;
00166     }
00167 
00168       EuclidRestoreRow (ctx->A, globalRow, &len, &CVAL, &AVAL);
00169       CHECK_V_ERROR;
00170 
00171       /* Ensure adequate storage; reallocate, if necessary. */
00172       count = SortedList_dhReadCount (slist);
00173       CHECK_V_ERROR;
00174 
00175       /* Ensure adequate storage; reallocate, if necessary. */
00176       if (idx + count > F->alloc)
00177     {
00178       Factor_dhReallocate (F, idx, count);
00179       CHECK_V_ERROR;
00180       SET_INFO ("REALLOCATED from ilu_mpi_pilu");
00181       cval = F->cval;
00182       fill = F->fill;
00183       aval = F->aval;
00184     }
00185 
00186       /* Copy factor to permanent storage */
00187       if (bj)
00188     {           /* for debugging: blockJacobi case */
00189       int col;
00190       while (count--)
00191         {
00192           SRecord *sr = SortedList_dhGetSmallest (slist);
00193           CHECK_V_ERROR;
00194           col = sr->col;
00195           if (col >= beg_rowP && col < end_rowP)
00196         {
00197           cval[idx] = col;
00198           if (noValues)
00199             {
00200               aval[idx] = 0.0;
00201             }
00202           else
00203             {
00204               aval[idx] = sr->val;
00205             }
00206           fill[idx] = sr->level;
00207           ++idx;
00208         }
00209         }
00210     }
00211 
00212       if (debug)
00213     {
00214       fprintf (logFile, "ILU_pilu  ");
00215       while (count--)
00216         {
00217           SRecord *sr = SortedList_dhGetSmallest (slist);
00218           CHECK_V_ERROR;
00219           cval[idx] = sr->col;
00220           aval[idx] = sr->val;
00221           fill[idx] = sr->level;
00222           fprintf (logFile, "%i,%i,%g ; ", 1 + cval[idx], fill[idx],
00223                aval[idx]);
00224           ++idx;
00225         }
00226       fprintf (logFile, "\n");
00227     }
00228 
00229       else
00230     {
00231       while (count--)
00232         {
00233           SRecord *sr = SortedList_dhGetSmallest (slist);
00234           CHECK_V_ERROR;
00235           cval[idx] = sr->col;
00236           aval[idx] = sr->val;
00237           fill[idx] = sr->level;
00238           ++idx;
00239         }
00240     }
00241 
00242       /* add row-pointer to start of next row. */
00243       rp[i + 1] = idx;
00244 
00245       /* Insert pointer to diagonal */
00246       {
00247     int temp = rp[i];
00248     bool flag = true;
00249     while (temp < idx)
00250       {
00251         if (cval[temp] == i + beg_rowP)
00252           {
00253         diag[i] = temp;
00254         flag = false;
00255         break;
00256           }
00257         ++temp;
00258       }
00259     if (flag)
00260       {
00261         if (logFile != NULL)
00262           {
00263         int k;
00264         fprintf (logFile,
00265              "Failed to find diag in localRow %i (globalRow %i; ct= %i)\n   ",
00266              1 + i, i + 1 + beg_rowP, rp[i + 1] - rp[i]);
00267         for (k = rp[i]; k < rp[i + 1]; ++k)
00268           {
00269             fprintf (logFile, "%i ", cval[i] + 1);
00270           }
00271         fprintf (logFile, "\n\n");
00272           }
00273         sprintf (msgBuf_dh, "failed to find diagonal for localRow: %i",
00274              1 + i);
00275         SET_V_ERROR (msgBuf_dh);
00276       }
00277       }
00278 /*
00279     { int temp = rp[i]; 
00280       while (cval[temp] != i+beg_row) ++temp;
00281       diag[i] = temp;
00282     }
00283 */
00284 
00285       /* check for zero diagonal */
00286       if (!aval[diag[i]])
00287     {
00288       sprintf (msgBuf_dh, "zero diagonal in local row %i", i + 1);
00289       SET_V_ERROR (msgBuf_dh);
00290     }
00291 
00292     }
00293 
00294   /* adjust to local (zero) based, if block jacobi factorization */
00295   if (bj)
00296     {
00297       int nz = rp[m];
00298       for (i = 0; i < nz; ++i)
00299     cval[i] -= beg_rowP;
00300     }
00301 
00302 END_FUNC_DH}
00303 
00304 
00305 #undef __FUNC__
00306 #define __FUNC__ "iluk_symbolic_row_private"
00307 void
00308 iluk_symbolic_row_private (int localRow, int len, int *CVAL,
00309                double *AVAL, ExternalRows_dh extRows,
00310                SortedList_dh slist, Euclid_dh ctx, bool debug)
00311 {
00312   START_FUNC_DH int level = ctx->level, m = ctx->m;
00313   int beg_row = ctx->sg->beg_row[myid_dh];
00314   int beg_rowP = ctx->sg->beg_rowP[myid_dh];
00315   int *cval = ctx->F->cval, *diag = ctx->F->diag;
00316   int *rp = ctx->F->rp, *fill = ctx->F->fill;
00317   int j, node, col;
00318   int end_rowP = beg_rowP + m;
00319   int level_1, level_2;
00320   int *cvalPtr, *fillPtr;
00321   SRecord sr, *srPtr;
00322   REAL_DH scale, *avalPtr;
00323   double thresh = ctx->sparseTolA;
00324   bool wasInserted;
00325   int count = 0;
00326 
00327   scale = ctx->scale[localRow];
00328   ctx->stats[NZA_STATS] += (double) len;
00329 
00330   /* insert col indices in sorted linked list */
00331   sr.level = 0;
00332   for (j = 0; j < len; ++j)
00333     {
00334       sr.col = CVAL[j];
00335       sr.val = scale * AVAL[j];
00336 /*    if (fabs(sr.val) > thresh) { */
00337       wasInserted = SortedList_dhPermuteAndInsert (slist, &sr, thresh);
00338       CHECK_V_ERROR;
00339       if (wasInserted)
00340     ++count;
00341 /*    } */
00342       if (debug)
00343     {
00344       fprintf (logFile, "ILU_pilu   inserted from A: col= %i  val= %g\n",
00345            1 + CVAL[j], sr.val);
00346     }
00347     }
00348 
00349   /* ensure diagonal entry is inserted */
00350   sr.val = 0.0;
00351   sr.col = localRow + beg_rowP;
00352   srPtr = SortedList_dhFind (slist, &sr);
00353   CHECK_V_ERROR;
00354   if (srPtr == NULL)
00355     {
00356       SortedList_dhInsert (slist, &sr);
00357       CHECK_V_ERROR;
00358       ++count;
00359       if (debug)
00360     {
00361       fprintf (logFile, "ILU_pilu   inserted missing diagonal: %i\n",
00362            1 + localRow + beg_row);
00363     }
00364     }
00365   ctx->stats[NZA_USED_STATS] += (double) count;
00366 
00367   /* update row from previously factored rows */
00368   sr.val = 0.0;
00369   if (level > 0)
00370     {
00371       while (1)
00372     {
00373       srPtr = SortedList_dhGetSmallestLowerTri (slist);
00374       CHECK_V_ERROR;
00375       if (srPtr == NULL)
00376         break;
00377 
00378       node = srPtr->col;
00379 
00380       if (debug)
00381         {
00382           fprintf (logFile, "ILU_pilu   sf updating from row: %i\n",
00383                1 + srPtr->col);
00384         }
00385 
00386       level_1 = srPtr->level;
00387       if (level_1 < level)
00388         {
00389 
00390           /* case 1: locally owned row */
00391           if (node >= beg_rowP && node < end_rowP)
00392         {
00393           node -= beg_rowP;
00394           len = rp[node + 1] - diag[node] - 1;
00395           cvalPtr = cval + diag[node] + 1;
00396           fillPtr = fill + diag[node] + 1;
00397         }
00398 
00399           /* case 2: external row */
00400           else
00401         {
00402           len = 0;
00403           ExternalRows_dhGetRow (extRows, node, &len, &cvalPtr,
00404                      &fillPtr, &avalPtr);
00405           CHECK_V_ERROR;
00406           if (debug && len == 0)
00407             {
00408               fprintf (stderr,
00409                    "ILU_pilu  sf failed to get extern row: %i\n",
00410                    1 + node);
00411             }
00412         }
00413 
00414 
00415           /* merge in strict upper triangular portion of row */
00416           for (j = 0; j < len; ++j)
00417         {
00418           col = *cvalPtr++;
00419           level_2 = 1 + level_1 + *fillPtr++;
00420           if (level_2 <= level)
00421             {
00422               /* Insert new element, or update level if already inserted. */
00423               sr.col = col;
00424               sr.level = level_2;
00425               sr.val = 0.0;
00426               SortedList_dhInsertOrUpdate (slist, &sr);
00427               CHECK_V_ERROR;
00428             }
00429         }
00430         }
00431     }
00432     }
00433 END_FUNC_DH}
00434 
00435 
00436 #undef __FUNC__
00437 #define __FUNC__ "iluk_numeric_row_private"
00438 void
00439 iluk_numeric_row_private (int new_row, ExternalRows_dh extRows,
00440               SortedList_dh slist, Euclid_dh ctx, bool debug)
00441 {
00442   START_FUNC_DH int m = ctx->m;
00443   int beg_rowP = ctx->sg->beg_rowP[myid_dh];
00444   int end_rowP = beg_rowP + m;
00445   int len, row;
00446   int *rp = ctx->F->rp, *cval = ctx->F->cval, *diag = ctx->F->diag;
00447   REAL_DH *avalPtr, *aval = ctx->F->aval;
00448   int *cvalPtr;
00449   double multiplier, pc, pv;
00450   SRecord sr, *srPtr;
00451 
00452   /* note: non-zero entries from A were inserted in list during iluk_symbolic_row_private */
00453 
00454   SortedList_dhResetGetSmallest (slist);
00455   CHECK_V_ERROR;
00456   while (1)
00457     {
00458       srPtr = SortedList_dhGetSmallestLowerTri (slist);
00459       CHECK_V_ERROR;
00460       if (srPtr == NULL)
00461     break;
00462 
00463       /* update new_row's values from upper triangular portion of previously
00464          factored row
00465        */
00466       row = srPtr->col;
00467 
00468       if (row >= beg_rowP && row < end_rowP)
00469     {
00470       int local_row = row - beg_rowP;
00471 
00472       len = rp[local_row + 1] - diag[local_row];
00473       cvalPtr = cval + diag[local_row];
00474       avalPtr = aval + diag[local_row];
00475     }
00476       else
00477     {
00478       len = 0;
00479       ExternalRows_dhGetRow (extRows, row, &len, &cvalPtr,
00480                  NULL, &avalPtr);
00481       CHECK_V_ERROR;
00482       if (debug && len == 0)
00483         {
00484           fprintf (stderr, "ILU_pilu  failed to get extern row: %i\n",
00485                1 + row);
00486         }
00487 
00488     }
00489 
00490       if (len)
00491     {
00492       /* first, form and store pivot */
00493       sr.col = row;
00494       srPtr = SortedList_dhFind (slist, &sr);
00495       CHECK_V_ERROR;
00496       if (srPtr == NULL)
00497         {
00498           sprintf (msgBuf_dh,
00499                "find failed for sr.col = %i while factoring local row= %i \n",
00500                1 + sr.col, new_row + 1);
00501           SET_V_ERROR (msgBuf_dh);
00502         }
00503 
00504       pc = srPtr->val;
00505 
00506       if (pc != 0.0)
00507         {
00508           pv = *avalPtr++;
00509           --len;
00510           ++cvalPtr;
00511           multiplier = pc / pv;
00512           srPtr->val = multiplier;
00513 
00514           if (debug)
00515         {
00516           fprintf (logFile,
00517                "ILU_pilu   nf updating from row: %i; multiplier = %g\n",
00518                1 + srPtr->col, multiplier);
00519         }
00520 
00521           /* second, update from strict upper triangular portion of row */
00522           while (len--)
00523         {
00524           sr.col = *cvalPtr++;
00525           sr.val = *avalPtr++;
00526           srPtr = SortedList_dhFind (slist, &sr);
00527           CHECK_V_ERROR;
00528           if (srPtr != NULL)
00529             {
00530               srPtr->val -= (multiplier * sr.val);
00531             }
00532         }
00533         }
00534 
00535       else
00536         {
00537           if (debug)
00538         {
00539           fprintf (logFile,
00540                "ILU_pilu   NO UPDATE from row: %i; srPtr->val = 0.0\n",
00541                1 + srPtr->col);
00542         }
00543         }
00544 
00545     }
00546     }
00547 END_FUNC_DH}
 All Classes Files Functions Variables Enumerations Friends