IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
ExternalRows_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 "ExternalRows_dh.h"
00044 #include "Factor_dh.h"
00045 #include "Euclid_dh.h"
00046 #include "SubdomainGraph_dh.h"
00047 #include "Mem_dh.h"
00048 #include "Parser_dh.h"
00049 #include "Hash_dh.h"
00050 
00051  /* tags for MPI comms */
00052 enum
00053 { ROW_CT_TAG, NZ_CT_TAG, ROW_LENGTH_TAG, ROW_NUMBER_TAG,
00054   CVAL_TAG, FILL_TAG, AVAL_TAG
00055 };
00056 
00057 #undef __FUNC__
00058 #define __FUNC__ "ExternalRows_dhCreate"
00059 void
00060 ExternalRows_dhCreate (ExternalRows_dh * er)
00061 {
00062   START_FUNC_DH
00063     struct _extrows_dh *tmp =
00064     (struct _extrows_dh *) MALLOC_DH (sizeof (struct _extrows_dh));
00065   CHECK_V_ERROR;
00066   *er = tmp;
00067 
00068   if (MAX_MPI_TASKS < np_dh)
00069     {
00070       SET_V_ERROR ("MAX_MPI_TASKS is too small; change, then recompile!");
00071     }
00072 
00073   {
00074     int i;
00075     for (i = 0; i < MAX_MPI_TASKS; ++i)
00076       {
00077     tmp->rcv_row_lengths[i] = NULL;
00078     tmp->rcv_row_numbers[i] = NULL;
00079       }
00080   }
00081 
00082   tmp->cvalExt = NULL;
00083   tmp->fillExt = NULL;
00084   tmp->avalExt = NULL;
00085   tmp->my_row_counts = NULL;
00086   tmp->my_row_numbers = NULL;
00087   tmp->cvalSend = NULL;
00088   tmp->fillSend = NULL;
00089   tmp->avalSend = NULL;
00090   tmp->rowLookup = NULL;
00091   tmp->sg = NULL;
00092   tmp->F = NULL;
00093   tmp->debug = Parser_dhHasSwitch (parser_dh, "-debug_ExtRows");
00094 END_FUNC_DH}
00095 
00096 #undef __FUNC__
00097 #define __FUNC__ "ExternalRows_dhDestroy"
00098 void
00099 ExternalRows_dhDestroy (ExternalRows_dh er)
00100 {
00101   START_FUNC_DH int i;
00102 
00103   for (i = 0; i < MAX_MPI_TASKS; ++i)
00104     {
00105       if (er->rcv_row_lengths[i] != NULL)
00106     {
00107       FREE_DH (er->rcv_row_lengths[i]);
00108       CHECK_V_ERROR;
00109     }
00110       if (er->rcv_row_numbers[i] != NULL)
00111     {
00112       FREE_DH (er->rcv_row_numbers[i]);
00113       CHECK_V_ERROR;
00114     }
00115     }
00116 
00117   if (er->cvalExt != NULL)
00118     {
00119       FREE_DH (er->cvalExt);
00120       CHECK_V_ERROR;
00121     }
00122   if (er->fillExt != NULL)
00123     {
00124       FREE_DH (er->fillExt);
00125       CHECK_V_ERROR;
00126     }
00127   if (er->avalExt != NULL)
00128     {
00129       FREE_DH (er->avalExt);
00130       CHECK_V_ERROR;
00131     }
00132 
00133   if (er->my_row_counts != NULL)
00134     {
00135       FREE_DH (er->my_row_counts);
00136       CHECK_V_ERROR;
00137     }
00138   if (er->my_row_numbers != NULL)
00139     {
00140       FREE_DH (er->my_row_numbers);
00141       CHECK_V_ERROR;
00142     }
00143 
00144   if (er->cvalSend != NULL)
00145     {
00146       FREE_DH (er->cvalSend);
00147       CHECK_V_ERROR;
00148     }
00149   if (er->fillSend != NULL)
00150     {
00151       FREE_DH (er->fillSend);
00152       CHECK_V_ERROR;
00153     }
00154   if (er->avalSend != NULL)
00155     {
00156       FREE_DH (er->avalSend);
00157       CHECK_V_ERROR;
00158     }
00159 
00160   if (er->rowLookup != NULL)
00161     {
00162       Hash_dhDestroy (er->rowLookup);
00163       CHECK_V_ERROR;
00164     }
00165   FREE_DH (er);
00166   CHECK_V_ERROR;
00167 END_FUNC_DH}
00168 
00169 #undef __FUNC__
00170 #define __FUNC__ "ExternalRows_dhInit"
00171 void
00172 ExternalRows_dhInit (ExternalRows_dh er, Euclid_dh ctx)
00173 {
00174   START_FUNC_DH er->sg = ctx->sg;
00175   er->F = ctx->F;
00176 END_FUNC_DH}
00177 
00178 /*=====================================================================
00179  * method for accessing external rows
00180  *=====================================================================*/
00181 
00182 #undef __FUNC__
00183 #define __FUNC__ "ExternalRows_dhGetRow"
00184 void
00185 ExternalRows_dhGetRow (ExternalRows_dh er, int globalRow,
00186                int *len, int **cval, int **fill, REAL_DH ** aval)
00187 {
00188   START_FUNC_DH if (er->rowLookup == NULL)
00189     {
00190       *len = 0;
00191     }
00192 
00193   else
00194     {
00195       HashData *r = NULL;
00196       r = Hash_dhLookup (er->rowLookup, globalRow);
00197       CHECK_V_ERROR;
00198       if (r != NULL)
00199     {
00200       *len = r->iData;
00201       if (cval != NULL)
00202         *cval = r->iDataPtr;
00203       if (fill != NULL)
00204         *fill = r->iDataPtr2;
00205       if (aval != NULL)
00206         *aval = r->fDataPtr;
00207     }
00208       else
00209     {
00210       *len = 0;
00211     }
00212     }
00213 END_FUNC_DH}
00214 
00215 /*=====================================================================
00216  * methods for receiving  external rows from lower-ordered subdomains
00217  *=====================================================================*/
00218 static void rcv_ext_storage_private (ExternalRows_dh extRows);
00219 static void build_hash_table_private (ExternalRows_dh er);
00220 static void rcv_external_rows_private (ExternalRows_dh er);
00221 static void allocate_ext_row_storage_private (ExternalRows_dh er);
00222 static void print_received_rows_private (ExternalRows_dh er);
00223 
00224 #undef __FUNC__
00225 #define __FUNC__ "ExternalRows_dhRecvRows"
00226 void
00227 ExternalRows_dhRecvRows (ExternalRows_dh er)
00228 {
00229   START_FUNC_DH bool debug = false;
00230   if (logFile != NULL && er->debug)
00231     debug = true;
00232 
00233   if (er->sg->loCount > 0)
00234     {
00235       /* get number of rows and length of each row to be received
00236          from each lower ordered nabor.
00237          (allocates: *rcv_row_lengths[], *rcv_row_numbers[])
00238        */
00239       rcv_ext_storage_private (er);
00240       CHECK_V_ERROR;
00241 
00242 
00243       /* allocate data structures for receiving the rows (no comms) 
00244          (allocates: cvalExt, fillExt, avalExt)
00245          (no communications)
00246        */
00247       allocate_ext_row_storage_private (er);
00248       CHECK_V_ERROR;
00249 
00250 
00251       /* construct hash table for  external row lookup (no comms) 
00252          (Creates/allocates: rowLookup)
00253          (no communications)
00254        */
00255       build_hash_table_private (er);
00256       CHECK_V_ERROR;
00257 
00258       /* receive the actual row structures and values 
00259          from lower ordered neighbors 
00260        */
00261       rcv_external_rows_private (er);
00262       CHECK_V_ERROR;
00263 
00264       if (debug)
00265     {
00266       print_received_rows_private (er);
00267       CHECK_V_ERROR;
00268     }
00269     }
00270 END_FUNC_DH}
00271 
00272 #undef __FUNC__
00273 #define __FUNC__ "rcv_ext_storage_private"
00274 void
00275 rcv_ext_storage_private (ExternalRows_dh er)
00276 {
00277   START_FUNC_DH int i;
00278   int loCount = er->sg->loCount, *loNabors = er->sg->loNabors;
00279   int *rcv_row_counts = er->rcv_row_counts;
00280   int *rcv_nz_counts = er->rcv_nz_counts;
00281   int **lengths = er->rcv_row_lengths, **numbers = er->rcv_row_numbers;
00282   bool debug = false;
00283 
00284   if (logFile != NULL && er->debug)
00285     debug = true;
00286 
00287   /* get number of rows, and total nonzeros, that each lo-nabor will send */
00288   for (i = 0; i < loCount; ++i)
00289     {
00290       int nabor = loNabors[i];
00291       MPI_Irecv (rcv_row_counts + i, 1, MPI_INT, nabor, ROW_CT_TAG, comm_dh,
00292          er->req1 + i);
00293       MPI_Irecv (rcv_nz_counts + i, 1, MPI_INT, nabor, NZ_CT_TAG, comm_dh,
00294          er->req2 + i);
00295     }
00296   MPI_Waitall (loCount, er->req1, er->status);
00297   MPI_Waitall (loCount, er->req2, er->status);
00298 
00299   if (debug)
00300     {
00301       fprintf (logFile,
00302            "\nEXR rcv_ext_storage_private:: <nabor,rowCount,nzCount>\nEXR ");
00303       for (i = 0; i < loCount; ++i)
00304     {
00305       fprintf (logFile, "<%i,%i,%i> ", loNabors[i], rcv_row_counts[i],
00306            rcv_nz_counts[i]);
00307     }
00308     }
00309 
00310   /* get lengths and global number of each row to be received */
00311   for (i = 0; i < loCount; ++i)
00312     {
00313       int nz = rcv_nz_counts[i];
00314       int nabor = loNabors[i];
00315       lengths[i] = (int *) MALLOC_DH (nz * sizeof (int));
00316       CHECK_V_ERROR;
00317       numbers[i] = (int *) MALLOC_DH (nz * sizeof (int));
00318       CHECK_V_ERROR;
00319       MPI_Irecv (lengths[i], nz, MPI_INT, nabor, ROW_LENGTH_TAG, comm_dh,
00320          er->req1 + i);
00321       MPI_Irecv (numbers[i], nz, MPI_INT, nabor, ROW_NUMBER_TAG, comm_dh,
00322          er->req2 + i);
00323     }
00324   MPI_Waitall (loCount, er->req1, er->status);
00325   MPI_Waitall (loCount, er->req2, er->status);
00326 
00327   if (debug)
00328     {
00329       int j, nz;
00330       for (i = 0; i < loCount; ++i)
00331     {
00332       fprintf (logFile,
00333            "\nEXR rows <number,length> to be received from P_%i\nEXR ",
00334            loNabors[i]);
00335       nz = rcv_row_counts[i];
00336       for (j = 0; j < nz; ++j)
00337         fprintf (logFile, "<%i,%i> ", numbers[i][j], lengths[i][j]);
00338       fprintf (logFile, "\n");
00339     }
00340     }
00341 
00342 END_FUNC_DH}
00343 
00344 /* allocates: cvalExt, fillExt, avalExt */
00345 #undef __FUNC__
00346 #define __FUNC__ "allocate_ext_row_storage_private"
00347 void
00348 allocate_ext_row_storage_private (ExternalRows_dh er)
00349 {
00350   START_FUNC_DH int i, nz = 0;
00351   int loCount = er->sg->loCount;
00352   int *rcv_nz_counts = er->rcv_nz_counts;
00353 
00354   /* count total number of nonzeros to be received */
00355   for (i = 0; i < loCount; ++i)
00356     nz += rcv_nz_counts[i];
00357 
00358   /* allocate buffers */
00359   er->cvalExt = (int *) MALLOC_DH (nz * sizeof (int));
00360   CHECK_V_ERROR;
00361   er->fillExt = (int *) MALLOC_DH (nz * sizeof (int));
00362   CHECK_V_ERROR;
00363   er->avalExt = (REAL_DH *) MALLOC_DH (nz * sizeof (REAL_DH));
00364   CHECK_V_ERROR;
00365 END_FUNC_DH}
00366 
00367 #undef __FUNC__
00368 #define __FUNC__ "build_hash_table_private"
00369 void
00370 build_hash_table_private (ExternalRows_dh er)
00371 {
00372   START_FUNC_DH int loCount = er->sg->loCount;
00373   int i, j, offset, rowCt = 0;
00374   Hash_dh table;
00375   HashData record;
00376   int *extRowCval = er->cvalExt, *extRowFill = er->fillExt;
00377   REAL_DH *extRowAval = er->avalExt;
00378   int *rcv_row_counts = er->rcv_row_counts;
00379   int **rcv_row_numbers = er->rcv_row_numbers;
00380   int **rcv_row_lengths = er->rcv_row_lengths;
00381 
00382   /* count total number of rows to be received */
00383   for (i = 0; i < loCount; ++i)
00384     rowCt += rcv_row_counts[i];
00385 
00386   /* build table for looking up external rows */
00387   Hash_dhCreate (&table, rowCt);
00388   CHECK_V_ERROR;
00389   er->rowLookup = table;
00390   offset = 0;
00391 
00392   /* loop over lower ordered nabors in subdomain graph */
00393   for (i = 0; i < loCount; ++i)
00394     {
00395 
00396       /* number of rows to be received from nabor(i) */
00397       int rowCount = rcv_row_counts[i];
00398 
00399       /* loop over rows to be received from nabor(i) */
00400       for (j = 0; j < rowCount; ++j)
00401     {
00402 
00403       /* insert a record to locate row(j) in the hash table */
00404       int row = rcv_row_numbers[i][j];
00405       int rowLength = rcv_row_lengths[i][j];
00406       record.iData = rowLength;
00407       record.iDataPtr = extRowCval + offset;
00408       record.iDataPtr2 = extRowFill + offset;
00409       record.fDataPtr = extRowAval + offset;
00410       Hash_dhInsert (table, row, &record);
00411       CHECK_V_ERROR;
00412       offset += rowLength;
00413     }
00414     }
00415 END_FUNC_DH}
00416 
00417 #undef __FUNC__
00418 #define __FUNC__ "rcv_external_rows_private"
00419 void
00420 rcv_external_rows_private (ExternalRows_dh er)
00421 {
00422   START_FUNC_DH int *rcv_nz_counts = er->rcv_nz_counts;
00423   int i, loCount = er->sg->loCount, *loNabors = er->sg->loNabors;
00424   int nabor, nz = 0, offset = 0;
00425   int *extRowCval = er->cvalExt, *extRowFill = er->fillExt;
00426   double *extRowAval = er->avalExt;
00427 
00428   /* start receives of external rows */
00429   nz = 0;
00430   for (i = 0; i < loCount; ++i)
00431     {
00432       nabor = loNabors[i];
00433       nz = rcv_nz_counts[i];
00434       MPI_Irecv (extRowCval + offset, nz, MPI_INT, nabor, CVAL_TAG, comm_dh,
00435          er->req1 + i);
00436       MPI_Irecv (extRowFill + offset, nz, MPI_INT, nabor, FILL_TAG, comm_dh,
00437          er->req2 + i);
00438       MPI_Irecv (extRowAval + offset, nz, MPI_DOUBLE, nabor, AVAL_TAG,
00439          comm_dh, er->req3 + i);
00440       offset += nz;
00441     }
00442 
00443   /* wait for external rows to arrive */
00444   MPI_Waitall (loCount, er->req1, er->status);
00445   MPI_Waitall (loCount, er->req2, er->status);
00446   MPI_Waitall (loCount, er->req3, er->status);
00447 END_FUNC_DH}
00448 
00449 
00450 #undef __FUNC__
00451 #define __FUNC__ "print_received_rows_private"
00452 void
00453 print_received_rows_private (ExternalRows_dh er)
00454 {
00455   START_FUNC_DH bool noValues = (Parser_dhHasSwitch (parser_dh, "-noValues"));
00456   int i, j, k, rwCt, idx = 0, nabor;
00457   int loCount = er->sg->loCount, *loNabors = er->sg->loNabors;
00458   int n = er->F->n;
00459 
00460   fprintf (logFile,
00461        "\nEXR ================= received rows, printed from buffers ==============\n");
00462 
00463   /* loop over nabors from whom we received rows */
00464   for (i = 0; i < loCount; ++i)
00465     {
00466       rwCt = er->rcv_row_counts[i];
00467       nabor = loNabors[i];
00468       fprintf (logFile, "\nEXR Rows received from P_%i:\n", nabor);
00469 
00470       /* loop over each row to be received from this nabor */
00471       for (j = 0; j < rwCt; ++j)
00472     {
00473       int rowNum = er->rcv_row_numbers[i][j];
00474       int rowLen = er->rcv_row_lengths[i][j];
00475       fprintf (logFile, "EXR %i :: ", 1 + rowNum);
00476       for (k = 0; k < rowLen; ++k)
00477         {
00478           if (noValues)
00479         {
00480           fprintf (logFile, "%i,%i ; ", er->cvalExt[idx],
00481                er->fillExt[idx]);
00482         }
00483           else
00484         {
00485           fprintf (logFile, "%i,%i,%g ; ", er->cvalExt[idx],
00486                er->fillExt[idx], er->avalExt[idx]);
00487         }
00488           ++idx;
00489         }
00490       fprintf (logFile, "\n");
00491     }
00492     }
00493 
00494   fprintf (logFile,
00495        "\nEXR =============== received rows, printed from hash table =============\n");
00496   for (i = 0; i < n; ++i)
00497     {
00498       int len, *cval, *fill;
00499       REAL_DH *aval;
00500       ExternalRows_dhGetRow (er, i, &len, &cval, &fill, &aval);
00501       CHECK_V_ERROR;
00502       if (len > 0)
00503     {
00504       fprintf (logFile, "EXR %i :: ", i + 1);
00505       for (j = 0; j < len; ++j)
00506         {
00507           if (noValues)
00508         {
00509           fprintf (logFile, "%i,%i ; ", cval[j], fill[j]);
00510         }
00511           else
00512         {
00513           fprintf (logFile, "%i,%i,%g ; ", cval[j], fill[j], aval[j]);
00514         }
00515         }
00516       fprintf (logFile, "\n");
00517     }
00518     }
00519 
00520 END_FUNC_DH}
00521 
00522 /*=====================================================================
00523  * methods for sending rows to higher ordered nabors in subdomain graph
00524  *=====================================================================*/
00525 
00526 static void send_ext_storage_private (ExternalRows_dh er);
00527 static void send_external_rows_private (ExternalRows_dh er);
00528 static void waitfor_sends_private (ExternalRows_dh er);
00529 
00530 #undef __FUNC__
00531 #define __FUNC__ "ExternalRows_dhSendRows"
00532 void
00533 ExternalRows_dhSendRows (ExternalRows_dh er)
00534 {
00535   START_FUNC_DH if (er->sg->hiCount > 0)
00536     {
00537       /* send number of rows and length of each row to be sent
00538          to each higher ordered nabor.
00539        */
00540       send_ext_storage_private (er);
00541       CHECK_V_ERROR;
00542 
00543       /* send the row's colum indices, fill levels, and values */
00544       send_external_rows_private (er);
00545       CHECK_V_ERROR;
00546 
00547       waitfor_sends_private (er);
00548       CHECK_V_ERROR;
00549     }
00550 END_FUNC_DH}
00551 
00552 
00553 #undef __FUNC__
00554 #define __FUNC__ "send_ext_storage_private"
00555 void
00556 send_ext_storage_private (ExternalRows_dh er)
00557 {
00558   START_FUNC_DH int nz, i, j;
00559   int *nzCounts, *nzNumbers;
00560   int hiCount = er->sg->hiCount, *hiNabors = er->sg->hiNabors;
00561   int *rp = er->F->rp, *diag = er->F->diag;
00562   int m = er->F->m;
00563   int beg_row = er->F->beg_row;
00564   int rowCount = er->F->bdry_count; /* number of boundary rows */
00565   int first_bdry = er->F->first_bdry;
00566   bool debug = false;
00567 
00568   if (logFile != NULL && er->debug)
00569     debug = true;
00570 
00571   /* allocate storage to hold nz counts for each row */
00572   nzCounts = er->my_row_counts = (int *) MALLOC_DH (rowCount * sizeof (int));
00573   CHECK_V_ERROR;
00574   nzNumbers = er->my_row_numbers =
00575     (int *) MALLOC_DH (rowCount * sizeof (int));
00576   CHECK_V_ERROR;
00577 
00578   /* count nonzeros in upper triangular portion of each boundary row */
00579   nz = 0;
00580   for (i = first_bdry, j = 0; i < m; ++i, ++j)
00581     {
00582       int tmp = (rp[i + 1] - diag[i]);
00583       nz += tmp;
00584       nzCounts[j] = tmp;
00585     }
00586   er->nzSend = nz;
00587 
00588   if (debug)
00589     {
00590       fprintf (logFile, "EXR send_ext_storage_private:: rowCount = %i\n",
00591            rowCount);
00592       fprintf (logFile, "EXR send_ext_storage_private:: nz Count = %i\n", nz);
00593     }
00594 
00595   /* send  number of rows, and total nonzeros, to higher ordered nabors */
00596   for (i = 0; i < hiCount; ++i)
00597     {
00598       int nabor = hiNabors[i];
00599       MPI_Isend (&rowCount, 1, MPI_INT, nabor, ROW_CT_TAG, comm_dh,
00600          er->req1 + i);
00601       MPI_Isend (&nz, 1, MPI_INT, nabor, NZ_CT_TAG, comm_dh, er->req2 + i);
00602     }
00603 
00604   /* set up array for global row numbers */
00605   for (i = 0, j = first_bdry; j < m; ++i, ++j)
00606     {
00607       nzNumbers[i] = j + beg_row;
00608     }
00609 
00610   /* start sends of length and global number of each of this processor's
00611      boundary row to higher ordered nabors; the receiving processor will
00612      use this information to allocate storage buffers for the actual
00613      row structures and values.
00614    */
00615   for (i = 0; i < hiCount; ++i)
00616     {
00617       int nabor = hiNabors[i];
00618       MPI_Isend (nzNumbers, rowCount, MPI_INT, nabor, ROW_NUMBER_TAG, comm_dh,
00619          er->req3 + i);
00620       MPI_Isend (nzCounts, rowCount, MPI_INT, nabor, ROW_LENGTH_TAG, comm_dh,
00621          er->req4 + i);
00622     }
00623 
00624 END_FUNC_DH}
00625 
00626 
00627 #undef __FUNC__
00628 #define __FUNC__ "send_external_rows_private"
00629 void
00630 send_external_rows_private (ExternalRows_dh er)
00631 {
00632   START_FUNC_DH
00633     int i, j, hiCount = er->sg->hiCount, *hiNabors = er->sg->hiNabors;
00634   int offset, nz = er->nzSend;
00635   int *cvalSend, *fillSend;
00636   REAL_DH *avalSend;
00637   int *cval = er->F->cval, *fill = er->F->fill;
00638   int m = er->F->m;
00639   int *rp = er->F->rp, *diag = er->F->diag;
00640   int first_bdry = er->F->first_bdry;
00641   REAL_DH *aval = er->F->aval;
00642   bool debug = false;
00643 
00644   if (logFile != NULL && er->debug)
00645     debug = true;
00646 
00647   /* allocate buffers to hold upper triangular portion of boundary rows */
00648   cvalSend = er->cvalSend = (int *) MALLOC_DH (nz * sizeof (int));
00649   CHECK_V_ERROR;
00650   fillSend = er->fillSend = (int *) MALLOC_DH (nz * sizeof (int));
00651   CHECK_V_ERROR;
00652   avalSend = er->avalSend = (double *) MALLOC_DH (nz * sizeof (double));
00653   CHECK_V_ERROR;
00654 
00655   /* copy upper triangular portion of boundary rows int send buffers */
00656   offset = 0;
00657   for (i = first_bdry, j = 0; i < m; ++i, ++j)
00658     {
00659       int tmp = (rp[i + 1] - diag[i]);
00660 
00661       memcpy (cvalSend + offset, cval + diag[i], tmp * sizeof (int));
00662       memcpy (fillSend + offset, fill + diag[i], tmp * sizeof (int));
00663       memcpy (avalSend + offset, aval + diag[i], tmp * sizeof (double));
00664       offset += tmp;
00665     }
00666 
00667   if (debug)
00668     {
00669       int beg_row = er->F->beg_row;
00670       int idx = 0;
00671       bool noValues = (Parser_dhHasSwitch (parser_dh, "-noValues"));
00672 
00673       fprintf (logFile,
00674            "\nEXR ======================= send buffers ======================\n");
00675 
00676       for (i = first_bdry, j = 0; i < m; ++i, ++j)
00677     {
00678       int tmp = (rp[i + 1] - diag[i]);
00679       fprintf (logFile, "EXR %i :: ", i + beg_row);
00680 
00681       for (j = 0; j < tmp; ++j)
00682         {
00683           if (noValues)
00684         {
00685           fprintf (logFile, "%i,%i ; ", cvalSend[idx], fillSend[idx]);
00686         }
00687           else
00688         {
00689           fprintf (logFile, "%i,%i,%g ; ", cvalSend[idx],
00690                fillSend[idx], avalSend[idx]);
00691         }
00692           ++idx;
00693         }
00694       fprintf (logFile, "\n");
00695     }
00696     }
00697 
00698   /* start sends to higher-ordred nabors */
00699   for (i = 0; i < hiCount; ++i)
00700     {
00701       int nabor = hiNabors[i];
00702       MPI_Isend (cvalSend, nz, MPI_INT, nabor, CVAL_TAG, comm_dh,
00703          er->cval_req + i);
00704       MPI_Isend (fillSend, nz, MPI_INT, nabor, FILL_TAG, comm_dh,
00705          er->fill_req + i);
00706       MPI_Isend (avalSend, nz, MPI_DOUBLE, nabor, AVAL_TAG, comm_dh,
00707          er->aval_req + i);
00708     }
00709 END_FUNC_DH}
00710 
00711 
00712 #undef __FUNC__
00713 #define __FUNC__ "waitfor_sends_private"
00714 void
00715 waitfor_sends_private (ExternalRows_dh er)
00716 {
00717   START_FUNC_DH MPI_Status * status = er->status;
00718   int hiCount = er->sg->hiCount;
00719 
00720   if (hiCount)
00721     {
00722       MPI_Waitall (hiCount, er->req1, status);
00723       MPI_Waitall (hiCount, er->req2, status);
00724       MPI_Waitall (hiCount, er->req3, status);
00725       MPI_Waitall (hiCount, er->req4, status);
00726       MPI_Waitall (hiCount, er->cval_req, status);
00727       MPI_Waitall (hiCount, er->fill_req, status);
00728       MPI_Waitall (hiCount, er->aval_req, status);
00729     }
00730 END_FUNC_DH}
 All Classes Files Functions Variables Enumerations Friends