IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
SortedList_dh.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 "SortedList_dh.h"
00044 #include "Mem_dh.h"
00045 #include "Parser_dh.h"
00046 #include "Hash_i_dh.h"
00047 #include "SubdomainGraph_dh.h"
00048 
00049 
00050 struct _sortedList_dh
00051 {
00052   int m;            /* number of local rows */
00053   int row;          /* local number of row being factored */
00054   int beg_row;          /* global number of first locally owned row, wrt A */
00055   int beg_rowP;         /* global number of first locally owned row, wrt F */
00056   int count;            /* number of items entered in the list, 
00057                    plus 1 (for header node) 
00058                  */
00059   int countMax;         /* same as count, but includes number of items that my have
00060                    been deleted from calling SortedList_dhEnforceConstraint()
00061                  */
00062   int *o2n_local;       /* not owned! */
00063   Hash_i_dh o2n_external;   /* not owned! */
00064 
00065   SRecord *list;        /* the sorted list */
00066   int alloc;            /* allocated length of list */
00067   int getLower;         /* index used for returning lower tri elts */
00068   int get;          /* index of returning all elts; */
00069 
00070   bool debug;
00071 };
00072 
00073 static void lengthen_list_private (SortedList_dh sList);
00074 
00075 
00076 #undef __FUNC__
00077 #define __FUNC__ "SortedList_dhCreate"
00078 void
00079 SortedList_dhCreate (SortedList_dh * sList)
00080 {
00081   START_FUNC_DH
00082     struct _sortedList_dh *tmp =
00083     (struct _sortedList_dh *) MALLOC_DH (sizeof (struct _sortedList_dh));
00084   CHECK_V_ERROR;
00085   *sList = tmp;
00086   tmp->m = 0;
00087   tmp->row = -1;
00088   tmp->beg_row = 0;
00089   tmp->count = 1;
00090   tmp->countMax = 1;
00091   tmp->o2n_external = NULL;
00092   tmp->o2n_local = NULL;
00093 
00094   tmp->get = 0;
00095   tmp->getLower = 0;
00096   tmp->alloc = 0;
00097   tmp->list = NULL;
00098   tmp->debug = Parser_dhHasSwitch (parser_dh, "-debug_SortedList");
00099 END_FUNC_DH}
00100 
00101 
00102 #undef __FUNC__
00103 #define __FUNC__ "SortedList_dhDestroy"
00104 void
00105 SortedList_dhDestroy (SortedList_dh sList)
00106 {
00107   START_FUNC_DH if (sList->list != NULL)
00108     {
00109       FREE_DH (sList->list);
00110       CHECK_V_ERROR;
00111     }
00112   FREE_DH (sList);
00113   CHECK_V_ERROR;
00114 END_FUNC_DH}
00115 
00116 
00117 #undef __FUNC__
00118 #define __FUNC__ "SortedList_dhInit"
00119 void
00120 SortedList_dhInit (SortedList_dh sList, SubdomainGraph_dh sg)
00121 {
00122   START_FUNC_DH sList->o2n_local = sg->o2n_col;
00123   sList->m = sg->m;
00124   sList->beg_row = sg->beg_row[myid_dh];
00125   sList->beg_rowP = sg->beg_rowP[myid_dh];
00126   sList->count = 1;     /* "1" is for the header node */
00127   sList->countMax = 1;      /* "1" is for the header node */
00128   sList->o2n_external = sg->o2n_ext;
00129 
00130   /* heuristic: "m" should be a good number of nodes */
00131   sList->alloc = sList->m + 5;
00132   sList->list = (SRecord *) MALLOC_DH (sList->alloc * sizeof (SRecord));
00133   sList->list[0].col = INT_MAX;
00134   sList->list[0].next = 0;
00135 END_FUNC_DH}
00136 
00137 
00138 #undef __FUNC__
00139 #define __FUNC__ "SortedList_dhReset"
00140 void
00141 SortedList_dhReset (SortedList_dh sList, int row)
00142 {
00143   START_FUNC_DH sList->row = row;
00144   sList->count = 1;
00145   sList->countMax = 1;
00146   sList->get = 0;
00147   sList->getLower = 0;
00148   sList->list[0].next = 0;
00149 END_FUNC_DH}
00150 
00151 
00152 #undef __FUNC__
00153 #define __FUNC__ "SortedList_dhReadCount"
00154 int
00155 SortedList_dhReadCount (SortedList_dh sList)
00156 {
00157 START_FUNC_DH END_FUNC_VAL (sList->count - 1)}
00158 
00159 #undef __FUNC__
00160 #define __FUNC__ "SortedList_dhResetGetSmallest"
00161 void
00162 SortedList_dhResetGetSmallest (SortedList_dh sList)
00163 {
00164   START_FUNC_DH sList->getLower = 0;
00165   sList->get = 0;
00166 END_FUNC_DH}
00167 
00168 #undef __FUNC__
00169 #define __FUNC__ "SortedList_dhGetSmallest"
00170 SRecord *
00171 SortedList_dhGetSmallest (SortedList_dh sList)
00172 {
00173   START_FUNC_DH SRecord * node = NULL;
00174   SRecord *list = sList->list;
00175   int get = sList->get;
00176 
00177   get = list[get].next;
00178 
00179   if (list[get].col < INT_MAX)
00180     {
00181       node = &(list[get]);
00182       sList->get = get;
00183     }
00184 END_FUNC_VAL (node)}
00185 
00186 #undef __FUNC__
00187 #define __FUNC__ "SortedList_dhGetSmallestLowerTri"
00188 SRecord *
00189 SortedList_dhGetSmallestLowerTri (SortedList_dh sList)
00190 {
00191   START_FUNC_DH SRecord * node = NULL;
00192   SRecord *list = sList->list;
00193   int getLower = sList->getLower;
00194   int globalRow = sList->row + sList->beg_rowP;
00195 
00196   getLower = list[getLower].next;
00197 
00198   if (list[getLower].col < globalRow)
00199     {
00200       node = &(list[getLower]);
00201       sList->getLower = getLower;
00202     }
00203 END_FUNC_VAL (node)}
00204 
00205 
00206 #undef __FUNC__
00207 #define __FUNC__ "SortedList_dhPermuteAndInsert"
00208 bool
00209 SortedList_dhPermuteAndInsert (SortedList_dh sList, SRecord * sr,
00210                    double thresh)
00211 {
00212   START_FUNC_DH bool wasInserted = false;
00213   int col = sr->col;
00214   double testVal = fabs (sr->val);
00215   int beg_row = sList->beg_row, end_row = beg_row + sList->m;
00216   int beg_rowP = sList->beg_rowP;
00217 
00218   /* insertion of local indices */
00219   if (col >= beg_row && col < end_row)
00220     {
00221       /* convert to local indexing  and permute */
00222       col -= beg_row;
00223       col = sList->o2n_local[col];
00224 
00225       /* sparsification */
00226       if (testVal > thresh || col == sList->row)
00227     {
00228       col += beg_rowP;
00229     }
00230       else
00231     {
00232       col = -1;
00233 /*
00234 fprintf(logFile, "local row: %i  DROPPED: col= %i  val= %g (thresh= %g)\n",
00235                            sList->row+1, sr->col+1, testVal, thresh);
00236 */
00237     }
00238     }
00239 
00240 
00241   /* insertion of external indices */
00242   else
00243     {
00244       /* sparsification for external indices */
00245       if (testVal < thresh)
00246     goto END_OF_FUNCTION;
00247 
00248       /* permute column index */
00249       if (sList->o2n_external == NULL)
00250     {
00251       col = -1;
00252     }
00253       else
00254     {
00255       int tmp = Hash_i_dhLookup (sList->o2n_external, col);
00256       CHECK_ERROR (-1);
00257       if (tmp == -1)
00258         {
00259           col = -1;
00260         }
00261       else
00262         {
00263           col = tmp;
00264         }
00265     }
00266     }
00267 
00268   if (col != -1)
00269     {
00270       sr->col = col;
00271       SortedList_dhInsert (sList, sr);
00272       CHECK_ERROR (-1);
00273       wasInserted = true;
00274     }
00275 
00276 END_OF_FUNCTION:;
00277 
00278 END_FUNC_VAL (wasInserted)}
00279 
00280 
00281 #undef __FUNC__
00282 #define __FUNC__ "SortedList_dhInsertOrUpdate"
00283 void
00284 SortedList_dhInsertOrUpdate (SortedList_dh sList, SRecord * sr)
00285 {
00286   START_FUNC_DH SRecord * node = SortedList_dhFind (sList, sr);
00287   CHECK_V_ERROR;
00288 
00289   if (node == NULL)
00290     {
00291       SortedList_dhInsert (sList, sr);
00292       CHECK_V_ERROR;
00293     }
00294   else
00295     {
00296       node->level = MIN (sr->level, node->level);
00297     }
00298 END_FUNC_DH}
00299 
00300 
00301 /* note: this does NOT check to see if item was already inserted! */
00302 #undef __FUNC__
00303 #define __FUNC__ "SortedList_dhInsert"
00304 void
00305 SortedList_dhInsert (SortedList_dh sList, SRecord * sr)
00306 {
00307   START_FUNC_DH int prev, next;
00308   int ct, col = sr->col;
00309   SRecord *list = sList->list;
00310 
00311   /* lengthen list if out of space */
00312   if (sList->countMax == sList->alloc)
00313     {
00314       lengthen_list_private (sList);
00315       CHECK_V_ERROR;
00316       list = sList->list;
00317     }
00318 
00319   /* add new node to end of list */
00320   ct = sList->countMax;
00321   sList->countMax += 1;
00322   sList->count += 1;
00323 
00324   list[ct].col = col;
00325   list[ct].level = sr->level;
00326   list[ct].val = sr->val;
00327 
00328   /* splice new node into list */
00329   prev = 0;
00330   next = list[0].next;
00331   while (col > list[next].col)
00332     {
00333       prev = next;
00334       next = list[next].next;
00335     }
00336   list[prev].next = ct;
00337   list[ct].next = next;
00338 END_FUNC_DH}
00339 
00340 
00341 #undef __FUNC__
00342 #define __FUNC__ "SortedList_dhFind"
00343 SRecord *
00344 SortedList_dhFind (SortedList_dh sList, SRecord * sr)
00345 {
00346   START_FUNC_DH int i, count = sList->countMax;
00347   int c = sr->col;
00348   SRecord *s = sList->list;
00349   SRecord *node = NULL;
00350 
00351   /* no need to traverse list in sorted order */
00352   for (i = 1; i < count; ++i)
00353     {               /* start at i=1, since i=0 would be header node */
00354 
00355       if (s[i].col == c)
00356     {
00357       node = &(s[i]);
00358       break;
00359     }
00360     }
00361 
00362 END_FUNC_VAL (node)}
00363 
00364 #undef __FUNC__
00365 #define __FUNC__ "lengthen_list_private"
00366 void
00367 lengthen_list_private (SortedList_dh sList)
00368 {
00369   START_FUNC_DH SRecord * tmp = sList->list;
00370   int size = sList->alloc = 2 * sList->alloc;
00371 
00372   SET_INFO ("lengthening list");
00373 
00374   sList->list = (SRecord *) MALLOC_DH (size * sizeof (SRecord));
00375   memcpy (sList->list, tmp, sList->countMax * sizeof (SRecord));
00376   SET_INFO ("doubling size of sList->list");
00377   FREE_DH (tmp);
00378   CHECK_V_ERROR;
00379 END_FUNC_DH}
00380 
00381 
00382 /*=====================================================================
00383  * functions for enforcing subdomain constraint 
00384  *=====================================================================*/
00385 
00386 
00387 static bool check_constraint_private (SubdomainGraph_dh sg,
00388                       int thisSubdomain, int col);
00389 void delete_private (SortedList_dh sList, int col);
00390 
00391 #undef __FUNC__
00392 #define __FUNC__ "SortedList_dhEnforceConstraint"
00393 void
00394 SortedList_dhEnforceConstraint (SortedList_dh sList, SubdomainGraph_dh sg)
00395 {
00396   START_FUNC_DH int thisSubdomain = myid_dh;
00397   int col, count;
00398   int beg_rowP = sList->beg_rowP;
00399   int end_rowP = beg_rowP + sList->m;
00400   bool debug = false;
00401 
00402   if (Parser_dhHasSwitch (parser_dh, "-debug_SortedList"))
00403     debug = true;
00404 
00405   if (debug)
00406     {
00407       fprintf (logFile, "SLIST ======= enforcing constraint for row= %i\n",
00408            1 + sList->row);
00409 
00410       fprintf (logFile, "\nSLIST ---- before checking: ");
00411       count = SortedList_dhReadCount (sList);
00412       CHECK_V_ERROR;
00413       while (count--)
00414     {
00415       SRecord *sr = SortedList_dhGetSmallest (sList);
00416       CHECK_V_ERROR;
00417       fprintf (logFile, "%i ", sr->col + 1);
00418     }
00419       fprintf (logFile, "\n");
00420       sList->get = 0;
00421     }
00422 
00423   /* for each column index in the list */
00424   count = SortedList_dhReadCount (sList);
00425   CHECK_V_ERROR;
00426 
00427   while (count--)
00428     {
00429       SRecord *sr = SortedList_dhGetSmallest (sList);
00430       CHECK_V_ERROR;
00431       col = sr->col;
00432 
00433       if (debug)
00434     {
00435       fprintf (logFile, "SLIST  next col= %i\n", col + 1);
00436     }
00437 
00438 
00439       /* if corresponding row is nonlocal */
00440       if (col < beg_rowP || col >= end_rowP)
00441     {
00442 
00443       if (debug)
00444         {
00445           fprintf (logFile, "SLIST     external col: %i ; ", 1 + col);
00446         }
00447 
00448       /* if entry would violate subdomain constraint, discard it
00449          (snip it out of the list)
00450        */
00451       if (check_constraint_private (sg, thisSubdomain, col))
00452         {
00453           delete_private (sList, col);
00454           CHECK_V_ERROR;
00455           sList->count -= 1;
00456 
00457           if (debug)
00458         {
00459           fprintf (logFile, " deleted\n");
00460         }
00461         }
00462       else
00463         {
00464           if (debug)
00465         {
00466           fprintf (logFile, " kept\n");
00467         }
00468         }
00469     }
00470     }
00471   sList->get = 0;
00472 
00473   if (debug)
00474     {
00475       fprintf (logFile, "SLIST---- after checking: ");
00476       count = SortedList_dhReadCount (sList);
00477       CHECK_V_ERROR;
00478       while (count--)
00479     {
00480       SRecord *sr = SortedList_dhGetSmallest (sList);
00481       CHECK_V_ERROR;
00482       fprintf (logFile, "%i ", sr->col + 1);
00483     }
00484       fprintf (logFile, "\n");
00485       fflush (logFile);
00486       sList->get = 0;
00487     }
00488 
00489 END_FUNC_DH}
00490 
00491 
00492 /* this is similar to a function in ilu_seq.c */
00493 #undef __FUNC__
00494 #define __FUNC__ "check_constraint_private"
00495 bool
00496 check_constraint_private (SubdomainGraph_dh sg, int p1, int j)
00497 {
00498   START_FUNC_DH bool retval = false;
00499   int i, p2;
00500   int *nabors, count;
00501 
00502   p2 = SubdomainGraph_dhFindOwner (sg, j, true);
00503 
00504   nabors = sg->adj + sg->ptrs[p1];
00505   count = sg->ptrs[p1 + 1] - sg->ptrs[p1];
00506 
00507   for (i = 0; i < count; ++i)
00508     {
00509       if (nabors[i] == p2)
00510     {
00511       retval = true;
00512       break;
00513     }
00514     }
00515 
00516 END_FUNC_VAL (!retval)}
00517 
00518 #undef __FUNC__
00519 #define __FUNC__ "delete_private"
00520 void
00521 delete_private (SortedList_dh sList, int col)
00522 {
00523   START_FUNC_DH int curNode = 0;
00524   SRecord *list = sList->list;
00525   int next;
00526 
00527   /* find node preceeding the node to be snipped out */
00528   /* 'list[curNode].next' is array index of the next node in the list */
00529 
00530   while (list[list[curNode].next].col != col)
00531     {
00532       curNode = list[curNode].next;
00533     }
00534 
00535   /* mark node to be deleted as inactive (needed for Find()) */
00536   next = list[curNode].next;
00537   list[next].col = -1;
00538 
00539   /* snip */
00540   next = list[next].next;
00541   list[curNode].next = next;
00542 END_FUNC_DH}
 All Classes Files Functions Variables Enumerations Friends