00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
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
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
00236
00237
00238
00239 rcv_ext_storage_private (er);
00240 CHECK_V_ERROR;
00241
00242
00243
00244
00245
00246
00247 allocate_ext_row_storage_private (er);
00248 CHECK_V_ERROR;
00249
00250
00251
00252
00253
00254
00255 build_hash_table_private (er);
00256 CHECK_V_ERROR;
00257
00258
00259
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
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
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
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
00355 for (i = 0; i < loCount; ++i)
00356 nz += rcv_nz_counts[i];
00357
00358
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
00383 for (i = 0; i < loCount; ++i)
00384 rowCt += rcv_row_counts[i];
00385
00386
00387 Hash_dhCreate (&table, rowCt);
00388 CHECK_V_ERROR;
00389 er->rowLookup = table;
00390 offset = 0;
00391
00392
00393 for (i = 0; i < loCount; ++i)
00394 {
00395
00396
00397 int rowCount = rcv_row_counts[i];
00398
00399
00400 for (j = 0; j < rowCount; ++j)
00401 {
00402
00403
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
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
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
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
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
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
00538
00539
00540 send_ext_storage_private (er);
00541 CHECK_V_ERROR;
00542
00543
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;
00565 int first_bdry = er->F->first_bdry;
00566 bool debug = false;
00567
00568 if (logFile != NULL && er->debug)
00569 debug = true;
00570
00571
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
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
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
00605 for (i = 0, j = first_bdry; j < m; ++i, ++j)
00606 {
00607 nzNumbers[i] = j + beg_row;
00608 }
00609
00610
00611
00612
00613
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
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
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
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}