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 "Mat_dh.h"
00044 #include "getRow_dh.h"
00045 #include "SubdomainGraph_dh.h"
00046 #include "TimeLog_dh.h"
00047 #include "Mem_dh.h"
00048 #include "Numbering_dh.h"
00049 #include "Parser_dh.h"
00050 #include "mat_dh_private.h"
00051 #include "io_dh.h"
00052 #include "Hash_i_dh.h"
00053
00054 static void setup_matvec_sends_private (Mat_dh mat, int *inlist);
00055 static void setup_matvec_receives_private (Mat_dh mat, int *beg_rows,
00056 int *end_rows, int reqlen,
00057 int *reqind, int *outlist);
00058
00059 #if 0
00060
00061 partial (?)
00062 implementation below;
00063 not used anyplace, I think;
00064 for future
00065 expansion ?[mar 21, 2 K + 1]
00066 static void Mat_dhAllocate_getRow_private (Mat_dh A);
00067 #endif
00068
00069 static bool commsOnly = false;
00070
00071 #undef __FUNC__
00072 #define __FUNC__ "Mat_dhCreate"
00073 void Mat_dhCreate (Mat_dh * mat)
00074 {
00075 START_FUNC_DH
00076 struct _mat_dh *tmp =
00077 (struct _mat_dh *) MALLOC_DH (sizeof (struct _mat_dh));
00078 CHECK_V_ERROR;
00079 *mat = tmp;
00080
00081 commsOnly = Parser_dhHasSwitch (parser_dh, "-commsOnly");
00082 if (myid_dh == 0 && commsOnly == true)
00083 {
00084
00085 fflush (stdout);
00086 }
00087
00088 tmp->m = 0;
00089 tmp->n = 0;
00090 tmp->beg_row = 0;
00091 tmp->bs = 1;
00092
00093 tmp->rp = NULL;
00094 tmp->len = NULL;
00095 tmp->cval = NULL;
00096 tmp->aval = NULL;
00097 tmp->diag = NULL;
00098 tmp->fill = NULL;
00099 tmp->owner = true;
00100
00101 tmp->len_private = 0;
00102 tmp->rowCheckedOut = -1;
00103 tmp->cval_private = NULL;
00104 tmp->aval_private = NULL;
00105
00106 tmp->row_perm = NULL;
00107
00108 tmp->num_recv = 0;
00109 tmp->num_send = 0;
00110 tmp->recv_req = NULL;
00111 tmp->send_req = NULL;
00112 tmp->status = NULL;
00113 tmp->recvbuf = NULL;
00114 tmp->sendbuf = NULL;
00115 tmp->sendind = NULL;
00116 tmp->sendlen = 0;
00117 tmp->recvlen = 0;
00118 tmp->numb = NULL;
00119 tmp->matvecIsSetup = false;
00120
00121 Mat_dhZeroTiming (tmp);
00122 CHECK_V_ERROR;
00123 tmp->matvec_timing = true;
00124
00125 tmp->debug = Parser_dhHasSwitch (parser_dh, "-debug_Mat");
00126 END_FUNC_DH}
00127
00128 #undef __FUNC__
00129 #define __FUNC__ "Mat_dhDestroy"
00130 void
00131 Mat_dhDestroy (Mat_dh mat)
00132 {
00133 START_FUNC_DH int i;
00134
00135 if (mat->owner)
00136 {
00137 if (mat->rp != NULL)
00138 {
00139 FREE_DH (mat->rp);
00140 CHECK_V_ERROR;
00141 }
00142 if (mat->len != NULL)
00143 {
00144 FREE_DH (mat->len);
00145 CHECK_V_ERROR;
00146 }
00147 if (mat->cval != NULL)
00148 {
00149 FREE_DH (mat->cval);
00150 CHECK_V_ERROR;
00151 }
00152 if (mat->aval != NULL)
00153 {
00154 FREE_DH (mat->aval);
00155 CHECK_V_ERROR;
00156 }
00157 if (mat->diag != NULL)
00158 {
00159 FREE_DH (mat->diag);
00160 CHECK_V_ERROR;
00161 }
00162 if (mat->fill != NULL)
00163 {
00164 FREE_DH (mat->fill);
00165 CHECK_V_ERROR;
00166 }
00167 if (mat->cval_private != NULL)
00168 {
00169 FREE_DH (mat->cval_private);
00170 CHECK_V_ERROR;
00171 }
00172 if (mat->aval_private != NULL)
00173 {
00174 FREE_DH (mat->aval_private);
00175 CHECK_V_ERROR;
00176 }
00177 if (mat->row_perm != NULL)
00178 {
00179 FREE_DH (mat->row_perm);
00180 CHECK_V_ERROR;
00181 }
00182 }
00183
00184 for (i = 0; i < mat->num_recv; i++)
00185 MPI_Request_free (&mat->recv_req[i]);
00186 for (i = 0; i < mat->num_send; i++)
00187 MPI_Request_free (&mat->send_req[i]);
00188 if (mat->recv_req != NULL)
00189 {
00190 FREE_DH (mat->recv_req);
00191 CHECK_V_ERROR;
00192 }
00193 if (mat->send_req != NULL)
00194 {
00195 FREE_DH (mat->send_req);
00196 CHECK_V_ERROR;
00197 }
00198 if (mat->status != NULL)
00199 {
00200 FREE_DH (mat->status);
00201 CHECK_V_ERROR;
00202 }
00203 if (mat->recvbuf != NULL)
00204 {
00205 FREE_DH (mat->recvbuf);
00206 CHECK_V_ERROR;
00207 }
00208 if (mat->sendbuf != NULL)
00209 {
00210 FREE_DH (mat->sendbuf);
00211 CHECK_V_ERROR;
00212 }
00213 if (mat->sendind != NULL)
00214 {
00215 FREE_DH (mat->sendind);
00216 CHECK_V_ERROR;
00217 }
00218
00219 if (mat->matvecIsSetup)
00220 {
00221 Mat_dhMatVecSetdown (mat);
00222 CHECK_V_ERROR;
00223 }
00224 if (mat->numb != NULL)
00225 {
00226 Numbering_dhDestroy (mat->numb);
00227 CHECK_V_ERROR;
00228 }
00229 FREE_DH (mat);
00230 CHECK_V_ERROR;
00231 END_FUNC_DH}
00232
00233
00234
00235 #undef __FUNC__
00236 #define __FUNC__ "Mat_dhMatVecSetDown"
00237 void
00238 Mat_dhMatVecSetdown (Mat_dh mat)
00239 {
00240 START_FUNC_DH if (ignoreMe)
00241 SET_V_ERROR ("not implemented");
00242 END_FUNC_DH}
00243
00244
00245
00246 #undef __FUNC__
00247 #define __FUNC__ "Mat_dhMatVecSetup"
00248 void
00249 Mat_dhMatVecSetup (Mat_dh mat)
00250 {
00251 START_FUNC_DH if (np_dh == 1)
00252 {
00253 goto DO_NOTHING;
00254 }
00255
00256 else
00257 {
00258 int *outlist, *inlist;
00259 int ierr, i, row, *rp = mat->rp, *cval = mat->cval;
00260 Numbering_dh numb;
00261 int m = mat->m;
00262 int firstLocal = mat->beg_row;
00263 int lastLocal = firstLocal + m;
00264 int *beg_rows, *end_rows;
00265
00266 mat->recv_req =
00267 (MPI_Request *) MALLOC_DH (np_dh * sizeof (MPI_Request));
00268 CHECK_V_ERROR;
00269 mat->send_req =
00270 (MPI_Request *) MALLOC_DH (np_dh * sizeof (MPI_Request));
00271 CHECK_V_ERROR;
00272 mat->status = (MPI_Status *) MALLOC_DH (np_dh * sizeof (MPI_Status));
00273 CHECK_V_ERROR;
00274 beg_rows = (int *) MALLOC_DH (np_dh * sizeof (int));
00275 CHECK_V_ERROR;
00276 end_rows = (int *) MALLOC_DH (np_dh * sizeof (int));
00277 CHECK_V_ERROR;
00278
00279 if (np_dh == 1)
00280 {
00281 beg_rows[0] = 0;
00282 end_rows[0] = m;
00283 }
00284 else
00285 {
00286 ierr =
00287 MPI_Allgather (&firstLocal, 1, MPI_INT, beg_rows, 1, MPI_INT,
00288 comm_dh);
00289
00290 CHECK_MPI_V_ERROR (ierr);
00291
00292 ierr =
00293 MPI_Allgather (&lastLocal, 1, MPI_INT, end_rows, 1, MPI_INT,
00294 comm_dh);
00295 CHECK_MPI_V_ERROR (ierr);
00296 }
00297
00298 outlist = (int *) MALLOC_DH (np_dh * sizeof (int));
00299 CHECK_V_ERROR;
00300 inlist = (int *) MALLOC_DH (np_dh * sizeof (int));
00301 CHECK_V_ERROR;
00302 for (i = 0; i < np_dh; ++i)
00303 {
00304 outlist[i] = 0;
00305 inlist[i] = 0;
00306 }
00307
00308
00309 Numbering_dhCreate (&(mat->numb));
00310 CHECK_V_ERROR;
00311 numb = mat->numb;
00312 Numbering_dhSetup (numb, mat);
00313 CHECK_V_ERROR;
00314
00315 setup_matvec_receives_private (mat, beg_rows, end_rows, numb->num_ext,
00316 numb->idx_ext, outlist);
00317 CHECK_V_ERROR;
00318
00319 if (np_dh == 1)
00320 {
00321 inlist[0] = outlist[0];
00322 }
00323 else
00324 {
00325 ierr =
00326 MPI_Alltoall (outlist, 1, MPI_INT, inlist, 1, MPI_INT, comm_dh);
00327 CHECK_MPI_V_ERROR (ierr);
00328 }
00329
00330 setup_matvec_sends_private (mat, inlist);
00331 CHECK_V_ERROR;
00332
00333
00334 for (row = 0; row < m; row++)
00335 {
00336 int len = rp[row + 1] - rp[row];
00337 int *ind = cval + rp[row];
00338 Numbering_dhGlobalToLocal (numb, len, ind, ind);
00339 CHECK_V_ERROR;
00340 }
00341
00342 FREE_DH (outlist);
00343 CHECK_V_ERROR;
00344 FREE_DH (inlist);
00345 CHECK_V_ERROR;
00346 FREE_DH (beg_rows);
00347 CHECK_V_ERROR;
00348 FREE_DH (end_rows);
00349 CHECK_V_ERROR;
00350 }
00351
00352 DO_NOTHING:;
00353
00354 END_FUNC_DH}
00355
00356
00357 #undef __FUNC__
00358 #define __FUNC__ "setup_matvec_receives_private"
00359 void
00360 setup_matvec_receives_private (Mat_dh mat, int *beg_rows, int *end_rows,
00361 int reqlen, int *reqind, int *outlist)
00362 {
00363 START_FUNC_DH int ierr, i, j, this_pe;
00364 MPI_Request request;
00365 int m = mat->m;
00366
00367 mat->num_recv = 0;
00368
00369
00370
00371 mat->recvbuf = (double *) MALLOC_DH ((reqlen + m) * sizeof (double));
00372
00373 for (i = 0; i < reqlen; i = j)
00374 {
00375
00376 this_pe = mat_find_owner (beg_rows, end_rows, reqind[i]);
00377 CHECK_V_ERROR;
00378
00379
00380 for (j = i + 1; j < reqlen; j++)
00381 {
00382
00383 if (reqind[j] < beg_rows[this_pe] || reqind[j] > end_rows[this_pe])
00384 break;
00385 }
00386
00387
00388 ierr =
00389 MPI_Isend (&reqind[i], j - i, MPI_INT, this_pe, 444, comm_dh,
00390 &request);
00391 CHECK_MPI_V_ERROR (ierr);
00392 ierr = MPI_Request_free (&request);
00393 CHECK_MPI_V_ERROR (ierr);
00394
00395
00396 outlist[this_pe] = j - i;
00397
00398 ierr =
00399 MPI_Recv_init (&mat->recvbuf[i + m], j - i, MPI_DOUBLE, this_pe, 555,
00400 comm_dh, &mat->recv_req[mat->num_recv]);
00401 CHECK_MPI_V_ERROR (ierr);
00402
00403 mat->num_recv++;
00404 mat->recvlen += j - i;
00405 }
00406 END_FUNC_DH}
00407
00408
00409
00410 #undef __FUNC__
00411 #define __FUNC__ "setup_matvec_sends_private"
00412 void
00413 setup_matvec_sends_private (Mat_dh mat, int *inlist)
00414 {
00415 START_FUNC_DH int ierr, i, j, sendlen, first = mat->beg_row;
00416 MPI_Request *requests;
00417 MPI_Status *statuses;
00418
00419 requests = (MPI_Request *) MALLOC_DH (np_dh * sizeof (MPI_Request));
00420 CHECK_V_ERROR;
00421 statuses = (MPI_Status *) MALLOC_DH (np_dh * sizeof (MPI_Status));
00422 CHECK_V_ERROR;
00423
00424
00425 sendlen = 0;
00426 for (i = 0; i < np_dh; i++)
00427 sendlen += inlist[i];
00428 mat->sendlen = sendlen;
00429 mat->sendbuf = (double *) MALLOC_DH (sendlen * sizeof (double));
00430 CHECK_V_ERROR;
00431 mat->sendind = (int *) MALLOC_DH (sendlen * sizeof (int));
00432 CHECK_V_ERROR;
00433
00434 j = 0;
00435 mat->num_send = 0;
00436 for (i = 0; i < np_dh; i++)
00437 {
00438 if (inlist[i] != 0)
00439 {
00440
00441 ierr =
00442 MPI_Irecv (&mat->sendind[j], inlist[i], MPI_INT, i, 444, comm_dh,
00443 &requests[mat->num_send]);
00444 CHECK_MPI_V_ERROR (ierr);
00445
00446 ierr =
00447 MPI_Send_init (&mat->sendbuf[j], inlist[i], MPI_DOUBLE, i, 555,
00448 comm_dh, &mat->send_req[mat->num_send]);
00449 CHECK_MPI_V_ERROR (ierr);
00450
00451 mat->num_send++;
00452 j += inlist[i];
00453 }
00454 }
00455
00456
00457 mat->time[MATVEC_WORDS] = j;
00458
00459
00460 ierr = MPI_Waitall (mat->num_send, requests, statuses);
00461 CHECK_MPI_V_ERROR (ierr);
00462
00463
00464 for (i = 0; i < mat->sendlen; i++)
00465 mat->sendind[i] -= first;
00466
00467 FREE_DH (requests);
00468 FREE_DH (statuses);
00469 END_FUNC_DH}
00470
00471
00472
00473 #undef __FUNC__
00474 #define __FUNC__ "Mat_dhMatVec"
00475 void
00476 Mat_dhMatVec (Mat_dh mat, double *x, double *b)
00477 {
00478 START_FUNC_DH if (np_dh == 1)
00479 {
00480 Mat_dhMatVec_uni (mat, x, b);
00481 CHECK_V_ERROR;
00482 }
00483
00484 else
00485 {
00486 int ierr, i, row, m = mat->m;
00487 int *rp = mat->rp, *cval = mat->cval;
00488 double *aval = mat->aval;
00489 int *sendind = mat->sendind;
00490 int sendlen = mat->sendlen;
00491 double *sendbuf = mat->sendbuf;
00492 double *recvbuf = mat->recvbuf;
00493 double t1 = 0, t2 = 0, t3 = 0, t4 = 0;
00494 bool timeFlag = mat->matvec_timing;
00495
00496
00497 if (timeFlag)
00498 t1 = MPI_Wtime ();
00499
00500
00501 if (!commsOnly)
00502 {
00503 for (i = 0; i < sendlen; i++)
00504 sendbuf[i] = x[sendind[i]];
00505 }
00506
00507 if (timeFlag)
00508 {
00509 t2 = MPI_Wtime ();
00510 mat->time[MATVEC_TIME] += (t2 - t1);
00511
00512 }
00513
00514 ierr = MPI_Startall (mat->num_recv, mat->recv_req);
00515 CHECK_MPI_V_ERROR (ierr);
00516 ierr = MPI_Startall (mat->num_send, mat->send_req);
00517 CHECK_MPI_V_ERROR (ierr);
00518 ierr = MPI_Waitall (mat->num_recv, mat->recv_req, mat->status);
00519 CHECK_MPI_V_ERROR (ierr);
00520 ierr = MPI_Waitall (mat->num_send, mat->send_req, mat->status);
00521 CHECK_MPI_V_ERROR (ierr);
00522
00523
00524 if (timeFlag)
00525 {
00526 t3 = MPI_Wtime ();
00527 mat->time[MATVEC_MPI_TIME] += (t3 - t2);
00528 }
00529
00530
00531 if (!commsOnly)
00532 {
00533 for (i = 0; i < m; i++)
00534 recvbuf[i] = x[i];
00535
00536
00537 for (row = 0; row < m; row++)
00538 {
00539 int len = rp[row + 1] - rp[row];
00540 int *ind = cval + rp[row];
00541 double *val = aval + rp[row];
00542 double temp = 0.0;
00543 for (i = 0; i < len; i++)
00544 {
00545 temp += (val[i] * recvbuf[ind[i]]);
00546 }
00547 b[row] = temp;
00548 }
00549 }
00550
00551 if (timeFlag)
00552 {
00553 t4 = MPI_Wtime ();
00554 mat->time[MATVEC_TOTAL_TIME] += (t4 - t1);
00555 mat->time[MATVEC_TIME] += (t4 - t3);
00556 }
00557 }
00558 END_FUNC_DH}
00559
00560
00561 #undef __FUNC__
00562 #define __FUNC__ "Mat_dhMatVec_omp"
00563 void
00564 Mat_dhMatVec_omp (Mat_dh mat, double *x, double *b)
00565 {
00566 START_FUNC_DH int ierr, i, row, m = mat->m;
00567 int *rp = mat->rp, *cval = mat->cval;
00568 double *aval = mat->aval;
00569 int *sendind = mat->sendind;
00570 int sendlen = mat->sendlen;
00571 double *sendbuf = mat->sendbuf;
00572 double *recvbuf = mat->recvbuf;
00573 double t1 = 0, t2 = 0, t3 = 0, t4 = 0, tx = 0;
00574 double *val, temp;
00575 int len, *ind;
00576 bool timeFlag = mat->matvec_timing;
00577
00578 if (timeFlag)
00579 t1 = MPI_Wtime ();
00580
00581
00582 for (i = 0; i < sendlen; i++)
00583 sendbuf[i] = x[sendind[i]];
00584
00585 if (timeFlag)
00586 {
00587 t2 = MPI_Wtime ();
00588 mat->time[MATVEC_TIME] += (t2 - t1);
00589 }
00590
00591 ierr = MPI_Startall (mat->num_recv, mat->recv_req);
00592 CHECK_MPI_V_ERROR (ierr);
00593 ierr = MPI_Startall (mat->num_send, mat->send_req);
00594 CHECK_MPI_V_ERROR (ierr);
00595 ierr = MPI_Waitall (mat->num_recv, mat->recv_req, mat->status);
00596 CHECK_MPI_V_ERROR (ierr);
00597 ierr = MPI_Waitall (mat->num_send, mat->send_req, mat->status);
00598 CHECK_MPI_V_ERROR (ierr);
00599
00600 if (timeFlag)
00601 {
00602 t3 = MPI_Wtime ();
00603 mat->time[MATVEC_MPI_TIME] += (t3 - t2);
00604 }
00605
00606
00607 for (i = 0; i < m; i++)
00608 recvbuf[i] = x[i];
00609
00610 if (timeFlag)
00611 {
00612 tx = MPI_Wtime ();
00613 mat->time[MATVEC_MPI_TIME2] += (tx - t1);
00614 }
00615
00616
00617
00618 for (row = 0; row < m; row++)
00619 {
00620 len = rp[row + 1] - rp[row];
00621 ind = cval + rp[row];
00622 val = aval + rp[row];
00623 temp = 0.0;
00624 for (i = 0; i < len; i++)
00625 {
00626 temp += (val[i] * recvbuf[ind[i]]);
00627 }
00628 b[row] = temp;
00629 }
00630
00631 if (timeFlag)
00632 {
00633 t4 = MPI_Wtime ();
00634 mat->time[MATVEC_TOTAL_TIME] += (t4 - t1);
00635 mat->time[MATVEC_TIME] += (t4 - t3);
00636 }
00637
00638 END_FUNC_DH}
00639
00640
00641
00642 #undef __FUNC__
00643 #define __FUNC__ "Mat_dhMatVec_uni_omp"
00644 void
00645 Mat_dhMatVec_uni_omp (Mat_dh mat, double *x, double *b)
00646 {
00647 START_FUNC_DH int i, row, m = mat->m;
00648 int *rp = mat->rp, *cval = mat->cval;
00649 double *aval = mat->aval;
00650 double t1 = 0, t2 = 0;
00651 bool timeFlag = mat->matvec_timing;
00652
00653 if (timeFlag)
00654 {
00655 t1 = MPI_Wtime ();
00656 }
00657
00658
00659 for (row = 0; row < m; row++)
00660 {
00661 int len = rp[row + 1] - rp[row];
00662 int *ind = cval + rp[row];
00663 double *val = aval + rp[row];
00664 double temp = 0.0;
00665 for (i = 0; i < len; i++)
00666 {
00667 temp += (val[i] * x[ind[i]]);
00668 }
00669 b[row] = temp;
00670 }
00671
00672 if (timeFlag)
00673 {
00674 t2 = MPI_Wtime ();
00675 mat->time[MATVEC_TIME] += (t2 - t1);
00676 mat->time[MATVEC_TOTAL_TIME] += (t2 - t1);
00677 }
00678
00679 END_FUNC_DH}
00680
00681
00682
00683 #undef __FUNC__
00684 #define __FUNC__ "Mat_dhMatVec_uni"
00685 void
00686 Mat_dhMatVec_uni (Mat_dh mat, double *x, double *b)
00687 {
00688 START_FUNC_DH int i, row, m = mat->m;
00689 int *rp = mat->rp, *cval = mat->cval;
00690 double *aval = mat->aval;
00691 double t1 = 0, t2 = 0;
00692 bool timeFlag = mat->matvec_timing;
00693
00694 if (timeFlag)
00695 t1 = MPI_Wtime ();
00696
00697 for (row = 0; row < m; row++)
00698 {
00699 int len = rp[row + 1] - rp[row];
00700 int *ind = cval + rp[row];
00701 double *val = aval + rp[row];
00702 double temp = 0.0;
00703 for (i = 0; i < len; i++)
00704 {
00705 temp += (val[i] * x[ind[i]]);
00706 }
00707 b[row] = temp;
00708 }
00709
00710 if (timeFlag)
00711 {
00712 t2 = MPI_Wtime ();
00713 mat->time[MATVEC_TIME] += (t2 - t1);
00714 mat->time[MATVEC_TOTAL_TIME] += (t2 - t1);
00715 }
00716
00717 END_FUNC_DH}
00718
00719
00720 #undef __FUNC__
00721 #define __FUNC__ "Mat_dhReadNz"
00722 int
00723 Mat_dhReadNz (Mat_dh mat)
00724 {
00725 START_FUNC_DH int ierr, retval = mat->rp[mat->m];
00726 int nz = retval;
00727 ierr = MPI_Allreduce (&nz, &retval, 1, MPI_INT, MPI_SUM, comm_dh);
00728 CHECK_MPI_ERROR (ierr);
00729 END_FUNC_VAL (retval)}
00730
00731
00732
00733 #if 0
00734
00735 #undef __FUNC__
00736 #define __FUNC__ "Mat_dhAllocate_getRow_private"
00737 void
00738 Mat_dhAllocate_getRow_private (Mat_dh A)
00739 {
00740 START_FUNC_DH int i, *rp = A->rp, len = 0;
00741 int m = A->m;
00742
00743
00744 for (i = 0; i < m; ++i)
00745 len = MAX (len, rp[i + 1] - rp[i]);
00746 len *= A->bs;
00747
00748
00749 if (len > A->len_private)
00750 {
00751 if (A->cval_private != NULL)
00752 {
00753 FREE_DH (A->cval_private);
00754 CHECK_V_ERROR;
00755 }
00756 if (A->aval_private != NULL)
00757 {
00758 FREE_DH (A->aval_private);
00759 CHECK_V_ERROR;
00760 }
00761 }
00762
00763
00764 A->cval_private = (int *) MALLOC_DH (len * sizeof (int));
00765 CHECK_V_ERROR;
00766 A->aval_private = (double *) MALLOC_DH (len * sizeof (double));
00767 CHECK_V_ERROR;
00768 A->len_private = len;
00769 END_FUNC_DH}
00770
00771 #endif
00772
00773 #undef __FUNC__
00774 #define __FUNC__ "Mat_dhZeroTiming"
00775 void
00776 Mat_dhZeroTiming (Mat_dh mat)
00777 {
00778 START_FUNC_DH int i;
00779
00780 for (i = 0; i < MAT_DH_BINS; ++i)
00781 {
00782 mat->time[i] = 0;
00783 mat->time_max[i] = 0;
00784 mat->time_min[i] = 0;
00785 }
00786 END_FUNC_DH}
00787
00788 #undef __FUNC__
00789 #define __FUNC__ "Mat_dhReduceTiming"
00790 void
00791 Mat_dhReduceTiming (Mat_dh mat)
00792 {
00793 START_FUNC_DH if (mat->time[MATVEC_MPI_TIME])
00794 {
00795 mat->time[MATVEC_RATIO] =
00796 mat->time[MATVEC_TIME] / mat->time[MATVEC_MPI_TIME];
00797 }
00798 MPI_Allreduce (mat->time, mat->time_min, MAT_DH_BINS, MPI_DOUBLE, MPI_MIN,
00799 comm_dh);
00800 MPI_Allreduce (mat->time, mat->time_max, MAT_DH_BINS, MPI_DOUBLE, MPI_MAX,
00801 comm_dh);
00802 END_FUNC_DH}
00803
00804 #undef __FUNC__
00805 #define __FUNC__ "Mat_dhPermute"
00806 void
00807 Mat_dhPermute (Mat_dh A, int *n2o, Mat_dh * Bout)
00808 {
00809 START_FUNC_DH Mat_dh B;
00810 int i, j, *RP = A->rp, *CVAL = A->cval;
00811 int *o2n, *rp, *cval, m = A->m, nz = RP[m];
00812 double *aval, *AVAL = A->aval;
00813
00814 Mat_dhCreate (&B);
00815 CHECK_V_ERROR;
00816 B->m = B->n = m;
00817 *Bout = B;
00818
00819
00820 o2n = (int *) MALLOC_DH (m * sizeof (int));
00821 CHECK_V_ERROR;
00822 for (i = 0; i < m; ++i)
00823 o2n[n2o[i]] = i;
00824
00825
00826 rp = B->rp = (int *) MALLOC_DH ((m + 1) * sizeof (int));
00827 CHECK_V_ERROR;
00828 cval = B->cval = (int *) MALLOC_DH (nz * sizeof (int));
00829 CHECK_V_ERROR;
00830 aval = B->aval = (double *) MALLOC_DH (nz * sizeof (double));
00831 CHECK_V_ERROR;
00832
00833
00834 rp[0] = 0;
00835 for (i = 0; i < m; ++i)
00836 {
00837 int oldRow = n2o[i];
00838 rp[i + 1] = RP[oldRow + 1] - RP[oldRow];
00839 }
00840 for (i = 1; i <= m; ++i)
00841 rp[i] = rp[i] + rp[i - 1];
00842
00843 for (i = 0; i < m; ++i)
00844 {
00845 int oldRow = n2o[i];
00846 int idx = rp[i];
00847 for (j = RP[oldRow]; j < RP[oldRow + 1]; ++j)
00848 {
00849 cval[idx] = o2n[CVAL[j]];
00850 aval[idx] = AVAL[j];
00851 ++idx;
00852 }
00853 }
00854
00855 FREE_DH (o2n);
00856 CHECK_V_ERROR;
00857 END_FUNC_DH}
00858
00859
00860
00861
00862
00863
00864
00865 #undef __FUNC__
00866 #define __FUNC__ "Mat_dhPrintGraph"
00867 void
00868 Mat_dhPrintGraph (Mat_dh A, SubdomainGraph_dh sg, FILE * fp)
00869 {
00870 START_FUNC_DH int pe, id = myid_dh;
00871 int ierr;
00872
00873 if (sg != NULL)
00874 {
00875 id = sg->o2n_sub[id];
00876 }
00877
00878 for (pe = 0; pe < np_dh; ++pe)
00879 {
00880 ierr = MPI_Barrier (comm_dh);
00881 CHECK_MPI_V_ERROR (ierr);
00882 if (id == pe)
00883 {
00884 if (sg == NULL)
00885 {
00886 mat_dh_print_graph_private (A->m, A->beg_row, A->rp, A->cval,
00887 A->aval, NULL, NULL, NULL, fp);
00888 CHECK_V_ERROR;
00889 }
00890 else
00891 {
00892 int beg_row = sg->beg_rowP[myid_dh];
00893 mat_dh_print_graph_private (A->m, beg_row, A->rp, A->cval,
00894 A->aval, sg->n2o_row, sg->o2n_col,
00895 sg->o2n_ext, fp);
00896 CHECK_V_ERROR;
00897 }
00898 }
00899 }
00900 END_FUNC_DH}
00901
00902
00903 #undef __FUNC__
00904 #define __FUNC__ "Mat_dhPrintRows"
00905 void
00906 Mat_dhPrintRows (Mat_dh A, SubdomainGraph_dh sg, FILE * fp)
00907 {
00908 START_FUNC_DH bool noValues;
00909 int m = A->m, *rp = A->rp, *cval = A->cval;
00910 double *aval = A->aval;
00911
00912 noValues = (Parser_dhHasSwitch (parser_dh, "-noValues"));
00913 if (noValues)
00914 aval = NULL;
00915
00916
00917
00918
00919 if (sg == NULL)
00920 {
00921 int i, j;
00922 int beg_row = A->beg_row;
00923
00924 fprintf (fp,
00925 "\n----- A, unpermuted ------------------------------------\n");
00926 for (i = 0; i < m; ++i)
00927 {
00928 fprintf (fp, "%i :: ", 1 + i + beg_row);
00929 for (j = rp[i]; j < rp[i + 1]; ++j)
00930 {
00931 if (noValues)
00932 {
00933 fprintf (fp, "%i ", 1 + cval[j]);
00934 }
00935 else
00936 {
00937 fprintf (fp, "%i,%g ; ", 1 + cval[j], aval[j]);
00938 }
00939 }
00940 fprintf (fp, "\n");
00941 }
00942 }
00943
00944
00945
00946
00947 else if (np_dh == 1)
00948 {
00949 int i, k, idx = 1;
00950 int oldRow;
00951
00952 for (i = 0; i < sg->blocks; ++i)
00953 {
00954 int oldBlock = sg->n2o_sub[i];
00955
00956
00957
00958
00959 int beg_row = sg->beg_row[oldBlock];
00960 int end_row = beg_row + sg->row_count[oldBlock];
00961
00962 fprintf (fp, "\n");
00963 fprintf (fp,
00964 "\n----- A, permuted, single mpi task ------------------\n");
00965 fprintf (fp, "---- new subdomain: %i; old subdomain: %i\n", i,
00966 oldBlock);
00967 fprintf (fp, " old beg_row: %i; new beg_row: %i\n",
00968 sg->beg_row[oldBlock], sg->beg_rowP[oldBlock]);
00969 fprintf (fp, " local rows in this block: %i\n",
00970 sg->row_count[oldBlock]);
00971 fprintf (fp, " bdry rows in this block: %i\n",
00972 sg->bdry_count[oldBlock]);
00973 fprintf (fp, " 1st bdry row= %i \n",
00974 1 + end_row - sg->bdry_count[oldBlock]);
00975
00976 for (oldRow = beg_row; oldRow < end_row; ++oldRow)
00977 {
00978 int len = 0, *cval;
00979 double *aval;
00980
00981 fprintf (fp, "%3i (old= %3i) :: ", idx, 1 + oldRow);
00982 ++idx;
00983 Mat_dhGetRow (A, oldRow, &len, &cval, &aval);
00984 CHECK_V_ERROR;
00985
00986 for (k = 0; k < len; ++k)
00987 {
00988 if (noValues)
00989 {
00990 fprintf (fp, "%i ", 1 + sg->o2n_col[cval[k]]);
00991 }
00992 else
00993 {
00994 fprintf (fp, "%i,%g ; ", 1 + sg->o2n_col[cval[k]],
00995 aval[k]);
00996 }
00997 }
00998
00999 fprintf (fp, "\n");
01000 Mat_dhRestoreRow (A, oldRow, &len, &cval, &aval);
01001 CHECK_V_ERROR;
01002 }
01003 }
01004 }
01005
01006
01007
01008
01009 else
01010 {
01011 Hash_i_dh hash = sg->o2n_ext;
01012 int *o2n_col = sg->o2n_col, *n2o_row = sg->n2o_row;
01013 int beg_row = sg->beg_row[myid_dh];
01014 int beg_rowP = sg->beg_rowP[myid_dh];
01015 int i, j;
01016
01017 for (i = 0; i < m; ++i)
01018 {
01019 int row = n2o_row[i];
01020 fprintf (fp, "%3i (old= %3i) :: ", 1 + i + beg_rowP,
01021 1 + row + beg_row);
01022 for (j = rp[row]; j < rp[row + 1]; ++j)
01023 {
01024 int col = cval[j];
01025
01026
01027
01028 if (col >= beg_row && col < beg_row + m)
01029 {
01030 col = o2n_col[col - beg_row] + beg_rowP;
01031 }
01032
01033
01034 else
01035 {
01036 int tmp = col;
01037 tmp = Hash_i_dhLookup (hash, col);
01038 CHECK_V_ERROR;
01039 if (tmp == -1)
01040 {
01041 sprintf (msgBuf_dh,
01042 "nonlocal column= %i not in hash table",
01043 1 + col);
01044 SET_V_ERROR (msgBuf_dh);
01045 }
01046 else
01047 {
01048 col = tmp;
01049 }
01050 }
01051
01052 if (noValues)
01053 {
01054 fprintf (fp, "%i ", 1 + col);
01055 }
01056 else
01057 {
01058 fprintf (fp, "%i,%g ; ", 1 + col, aval[j]);
01059 }
01060 }
01061 fprintf (fp, "\n");
01062 }
01063 }
01064 END_FUNC_DH}
01065
01066
01067
01068 #undef __FUNC__
01069 #define __FUNC__ "Mat_dhPrintTriples"
01070 void
01071 Mat_dhPrintTriples (Mat_dh A, SubdomainGraph_dh sg, char *filename)
01072 {
01073 START_FUNC_DH int m = A->m, *rp = A->rp, *cval = A->cval;
01074 double *aval = A->aval;
01075 bool noValues;
01076 bool matlab;
01077 FILE *fp;
01078
01079 noValues = (Parser_dhHasSwitch (parser_dh, "-noValues"));
01080 if (noValues)
01081 aval = NULL;
01082 matlab = (Parser_dhHasSwitch (parser_dh, "-matlab"));
01083
01084
01085
01086
01087 if (sg == NULL)
01088 {
01089 int i, j, pe;
01090 int beg_row = A->beg_row;
01091 double val;
01092
01093 for (pe = 0; pe < np_dh; ++pe)
01094 {
01095 MPI_Barrier (comm_dh);
01096 if (pe == myid_dh)
01097 {
01098 if (pe == 0)
01099 {
01100 fp = openFile_dh (filename, "w");
01101 CHECK_V_ERROR;
01102 }
01103 else
01104 {
01105 fp = openFile_dh (filename, "a");
01106 CHECK_V_ERROR;
01107 }
01108
01109 for (i = 0; i < m; ++i)
01110 {
01111 for (j = rp[i]; j < rp[i + 1]; ++j)
01112 {
01113 if (noValues)
01114 {
01115 fprintf (fp, "%i %i\n", 1 + i + beg_row,
01116 1 + cval[j]);
01117 }
01118 else
01119 {
01120 val = aval[j];
01121 if (val == 0.0 && matlab)
01122 val = _MATLAB_ZERO_;
01123 fprintf (fp, TRIPLES_FORMAT, 1 + i + beg_row,
01124 1 + cval[j], val);
01125 }
01126 }
01127 }
01128 closeFile_dh (fp);
01129 CHECK_V_ERROR;
01130 }
01131 }
01132 }
01133
01134
01135
01136
01137 else if (np_dh == 1)
01138 {
01139 int i, j, k, idx = 1;
01140
01141 fp = openFile_dh (filename, "w");
01142 CHECK_V_ERROR;
01143
01144 for (i = 0; i < sg->blocks; ++i)
01145 {
01146 int oldBlock = sg->n2o_sub[i];
01147 int beg_row = sg->beg_rowP[oldBlock];
01148 int end_row = beg_row + sg->row_count[oldBlock];
01149
01150 for (j = beg_row; j < end_row; ++j)
01151 {
01152 int len = 0, *cval;
01153 double *aval;
01154 int oldRow = sg->n2o_row[j];
01155
01156 Mat_dhGetRow (A, oldRow, &len, &cval, &aval);
01157 CHECK_V_ERROR;
01158
01159 if (noValues)
01160 {
01161 for (k = 0; k < len; ++k)
01162 {
01163 fprintf (fp, "%i %i\n", idx, 1 + sg->o2n_col[cval[k]]);
01164 }
01165 ++idx;
01166 }
01167
01168 else
01169 {
01170 for (k = 0; k < len; ++k)
01171 {
01172 double val = aval[k];
01173 if (val == 0.0 && matlab)
01174 val = _MATLAB_ZERO_;
01175 fprintf (fp, TRIPLES_FORMAT, idx,
01176 1 + sg->o2n_col[cval[k]], val);
01177 }
01178 ++idx;
01179 }
01180 Mat_dhRestoreRow (A, oldRow, &len, &cval, &aval);
01181 CHECK_V_ERROR;
01182 }
01183 }
01184 }
01185
01186
01187
01188
01189 else
01190 {
01191 Hash_i_dh hash = sg->o2n_ext;
01192 int *o2n_col = sg->o2n_col, *n2o_row = sg->n2o_row;
01193 int beg_row = sg->beg_row[myid_dh];
01194 int beg_rowP = sg->beg_rowP[myid_dh];
01195 int i, j, pe;
01196 int id = sg->o2n_sub[myid_dh];
01197
01198 for (pe = 0; pe < np_dh; ++pe)
01199 {
01200 MPI_Barrier (comm_dh);
01201 if (id == pe)
01202 {
01203 if (pe == 0)
01204 {
01205 fp = openFile_dh (filename, "w");
01206 CHECK_V_ERROR;
01207 }
01208 else
01209 {
01210 fp = openFile_dh (filename, "a");
01211 CHECK_V_ERROR;
01212 }
01213
01214 for (i = 0; i < m; ++i)
01215 {
01216 int row = n2o_row[i];
01217 for (j = rp[row]; j < rp[row + 1]; ++j)
01218 {
01219 int col = cval[j];
01220 double val = 0.0;
01221
01222 if (aval != NULL)
01223 val = aval[j];
01224 if (val == 0.0 && matlab)
01225 val = _MATLAB_ZERO_;
01226
01227
01228
01229 if (col >= beg_row && col < beg_row + m)
01230 {
01231 col = o2n_col[col - beg_row] + beg_rowP;
01232 }
01233
01234
01235 else
01236 {
01237 int tmp = col;
01238 tmp = Hash_i_dhLookup (hash, col);
01239 CHECK_V_ERROR;
01240 if (tmp == -1)
01241 {
01242 sprintf (msgBuf_dh,
01243 "nonlocal column= %i not in hash table",
01244 1 + col);
01245 SET_V_ERROR (msgBuf_dh);
01246 }
01247 else
01248 {
01249 col = tmp;
01250 }
01251 }
01252
01253 if (noValues)
01254 {
01255 fprintf (fp, "%i %i\n", 1 + i + beg_rowP, 1 + col);
01256 }
01257 else
01258 {
01259 fprintf (fp, TRIPLES_FORMAT, 1 + i + beg_rowP,
01260 1 + col, val);
01261 }
01262 }
01263 }
01264 closeFile_dh (fp);
01265 CHECK_V_ERROR;
01266 }
01267 }
01268 }
01269 END_FUNC_DH}
01270
01271
01272
01273 #undef __FUNC__
01274 #define __FUNC__ "Mat_dhPrintCSR"
01275 void
01276 Mat_dhPrintCSR (Mat_dh A, SubdomainGraph_dh sg, char *filename)
01277 {
01278 START_FUNC_DH FILE * fp;
01279
01280 if (np_dh > 1)
01281 {
01282 SET_V_ERROR ("only implemented for a single mpi task");
01283 }
01284 if (sg != NULL)
01285 {
01286 SET_V_ERROR
01287 ("not implemented for reordered matrix (SubdomainGraph_dh should be NULL)");
01288 }
01289
01290 fp = openFile_dh (filename, "w");
01291 CHECK_V_ERROR;
01292
01293 if (sg == NULL)
01294 {
01295 mat_dh_print_csr_private (A->m, A->rp, A->cval, A->aval, fp);
01296 CHECK_V_ERROR;
01297 }
01298 else
01299 {
01300 mat_dh_print_csr_private (A->m, A->rp, A->cval, A->aval, fp);
01301 CHECK_V_ERROR;
01302 }
01303 closeFile_dh (fp);
01304 CHECK_V_ERROR;
01305 END_FUNC_DH}
01306
01307
01308
01309 #undef __FUNC__
01310 #define __FUNC__ "Mat_dhPrintBIN"
01311 void
01312 Mat_dhPrintBIN (Mat_dh A, SubdomainGraph_dh sg, char *filename)
01313 {
01314 START_FUNC_DH if (np_dh > 1)
01315 {
01316 SET_V_ERROR ("only implemented for a single MPI task");
01317 }
01318
01319
01320 if (sg != NULL)
01321 {
01322 SET_V_ERROR ("not implemented for reordering; ensure sg=NULL");
01323 }
01324
01325 io_dh_print_ebin_mat_private (A->m, A->beg_row, A->rp, A->cval, A->aval,
01326 NULL, NULL, NULL, filename);
01327 CHECK_V_ERROR;
01328 END_FUNC_DH}
01329
01330
01331
01332
01333
01334
01335 #undef __FUNC__
01336 #define __FUNC__ "Mat_dhReadCSR"
01337 void
01338 Mat_dhReadCSR (Mat_dh * mat, char *filename)
01339 {
01340 START_FUNC_DH Mat_dh A;
01341 FILE *fp;
01342
01343 if (np_dh > 1)
01344 {
01345 SET_V_ERROR ("only implemented for a single MPI task");
01346 }
01347
01348 fp = openFile_dh (filename, "r");
01349 CHECK_V_ERROR;
01350
01351 Mat_dhCreate (&A);
01352 CHECK_V_ERROR;
01353 mat_dh_read_csr_private (&A->m, &A->rp, &A->cval, &A->aval, fp);
01354 CHECK_V_ERROR;
01355 A->n = A->m;
01356 *mat = A;
01357
01358 closeFile_dh (fp);
01359 CHECK_V_ERROR;
01360 END_FUNC_DH}
01361
01362
01363 #undef __FUNC__
01364 #define __FUNC__ "Mat_dhReadTriples"
01365 void
01366 Mat_dhReadTriples (Mat_dh * mat, int ignore, char *filename)
01367 {
01368 START_FUNC_DH FILE * fp = NULL;
01369 Mat_dh A = NULL;
01370
01371 if (np_dh > 1)
01372 {
01373 SET_V_ERROR ("only implemented for a single MPI task");
01374 }
01375
01376 fp = openFile_dh (filename, "r");
01377 CHECK_V_ERROR;
01378
01379 Mat_dhCreate (&A);
01380 CHECK_V_ERROR;
01381 mat_dh_read_triples_private (ignore, &A->m, &A->rp, &A->cval, &A->aval, fp);
01382 CHECK_V_ERROR;
01383 A->n = A->m;
01384 *mat = A;
01385
01386 closeFile_dh (fp);
01387 CHECK_V_ERROR;
01388 END_FUNC_DH}
01389
01390
01391
01392
01393
01394 #undef __FUNC__
01395 #define __FUNC__ "Mat_dhReadBIN"
01396 void
01397 Mat_dhReadBIN (Mat_dh * mat, char *filename)
01398 {
01399 START_FUNC_DH Mat_dh A;
01400
01401 if (np_dh > 1)
01402 {
01403 SET_V_ERROR ("only implemented for a single MPI task");
01404 }
01405
01406 Mat_dhCreate (&A);
01407 CHECK_V_ERROR;
01408 io_dh_read_ebin_mat_private (&A->m, &A->rp, &A->cval, &A->aval, filename);
01409 CHECK_V_ERROR;
01410 A->n = A->m;
01411 *mat = A;
01412 END_FUNC_DH}
01413
01414 #undef __FUNC__
01415 #define __FUNC__ "Mat_dhTranspose"
01416 void
01417 Mat_dhTranspose (Mat_dh A, Mat_dh * Bout)
01418 {
01419 START_FUNC_DH Mat_dh B;
01420
01421 if (np_dh > 1)
01422 {
01423 SET_V_ERROR ("only for sequential");
01424 }
01425
01426 Mat_dhCreate (&B);
01427 CHECK_V_ERROR;
01428 *Bout = B;
01429 B->m = B->n = A->m;
01430 mat_dh_transpose_private (A->m, A->rp, &B->rp, A->cval, &B->cval,
01431 A->aval, &B->aval);
01432 CHECK_V_ERROR;
01433 END_FUNC_DH}
01434
01435 #undef __FUNC__
01436 #define __FUNC__ "Mat_dhMakeStructurallySymmetric"
01437 void
01438 Mat_dhMakeStructurallySymmetric (Mat_dh A)
01439 {
01440 START_FUNC_DH if (np_dh > 1)
01441 {
01442 SET_V_ERROR ("only for sequential");
01443 }
01444 make_symmetric_private (A->m, &A->rp, &A->cval, &A->aval);
01445 CHECK_V_ERROR;
01446 END_FUNC_DH}
01447
01448 void insert_diags_private (Mat_dh A, int ct);
01449
01450
01451
01452
01453
01454 #undef __FUNC__
01455 #define __FUNC__ "Mat_dhFixDiags"
01456 void
01457 Mat_dhFixDiags (Mat_dh A)
01458 {
01459 START_FUNC_DH int i, j;
01460 int *rp = A->rp, *cval = A->cval, m = A->m;
01461 bool ct = 0;
01462 double *aval = A->aval;
01463
01464
01465 for (i = 0; i < m; ++i)
01466 {
01467 bool flag = true;
01468 for (j = rp[i]; j < rp[i + 1]; ++j)
01469 {
01470 int col = cval[j];
01471 if (col == i)
01472 {
01473 flag = false;
01474 break;
01475 }
01476 }
01477 if (flag)
01478 ++ct;
01479 }
01480
01481
01482 if (ct)
01483 {
01484 printf
01485 ("\nMat_dhFixDiags:: %i diags not explicitly present; inserting!\n",
01486 ct);
01487 insert_diags_private (A, ct);
01488 CHECK_V_ERROR;
01489 rp = A->rp;
01490 cval = A->cval;
01491 aval = A->aval;
01492 }
01493
01494
01495 for (i = 0; i < m; ++i)
01496 {
01497 double sum = 0.0;
01498 for (j = rp[i]; j < rp[i + 1]; ++j)
01499 {
01500 sum += fabs (aval[j]);
01501 }
01502 for (j = rp[i]; j < rp[i + 1]; ++j)
01503 {
01504 if (cval[j] == i)
01505 {
01506 aval[j] = sum;
01507 }
01508 }
01509 }
01510 END_FUNC_DH}
01511
01512
01513 #undef __FUNC__
01514 #define __FUNC__ "insert_diags_private"
01515 void
01516 insert_diags_private (Mat_dh A, int ct)
01517 {
01518 START_FUNC_DH int *RP = A->rp, *CVAL = A->cval;
01519 int *rp, *cval, m = A->m;
01520 double *aval, *AVAL = A->aval;
01521 int nz = RP[m] + ct;
01522 int i, j, idx = 0;
01523
01524 rp = A->rp = (int *) MALLOC_DH ((m + 1) * sizeof (int));
01525 CHECK_V_ERROR;
01526 cval = A->cval = (int *) MALLOC_DH (nz * sizeof (int));
01527 CHECK_V_ERROR;
01528 aval = A->aval = (double *) MALLOC_DH (nz * sizeof (double));
01529 CHECK_V_ERROR;
01530 rp[0] = 0;
01531
01532 for (i = 0; i < m; ++i)
01533 {
01534 bool flag = true;
01535 for (j = RP[i]; j < RP[i + 1]; ++j)
01536 {
01537 cval[idx] = CVAL[j];
01538 aval[idx] = AVAL[j];
01539 ++idx;
01540 if (CVAL[j] == i)
01541 flag = false;
01542 }
01543
01544 if (flag)
01545 {
01546 cval[idx] = i;
01547 aval[idx] = 0.0;
01548 ++idx;
01549 }
01550 rp[i + 1] = idx;
01551 }
01552
01553 FREE_DH (RP);
01554 CHECK_V_ERROR;
01555 FREE_DH (CVAL);
01556 CHECK_V_ERROR;
01557 FREE_DH (AVAL);
01558 CHECK_V_ERROR;
01559
01560 END_FUNC_DH}
01561
01562 #undef __FUNC__
01563 #define __FUNC__ "Mat_dhPrintDiags"
01564 void
01565 Mat_dhPrintDiags (Mat_dh A, FILE * fp)
01566 {
01567 START_FUNC_DH int i, j, m = A->m;
01568 int *rp = A->rp, *cval = A->cval;
01569 double *aval = A->aval;
01570
01571 fprintf (fp,
01572 "=================== diagonal elements ====================\n");
01573 for (i = 0; i < m; ++i)
01574 {
01575 bool flag = true;
01576 for (j = rp[i]; j < rp[i + 1]; ++j)
01577 {
01578 if (cval[j] == i)
01579 {
01580 fprintf (fp, "%i %g\n", i + 1, aval[j]);
01581 flag = false;
01582 break;
01583 }
01584 }
01585 if (flag)
01586 {
01587 fprintf (fp, "%i ---------- missing\n", i + 1);
01588 }
01589 }
01590 END_FUNC_DH}
01591
01592
01593 #undef __FUNC__
01594 #define __FUNC__ "Mat_dhGetRow"
01595 void
01596 Mat_dhGetRow (Mat_dh B, int globalRow, int *len, int **ind, double **val)
01597 {
01598 START_FUNC_DH int row = globalRow - B->beg_row;
01599 if (row > B->m)
01600 {
01601 sprintf (msgBuf_dh,
01602 "requested globalRow= %i, which is local row= %i, but only have %i rows!",
01603 globalRow, row, B->m);
01604 SET_V_ERROR (msgBuf_dh);
01605 }
01606 *len = B->rp[row + 1] - B->rp[row];
01607 if (ind != NULL)
01608 *ind = B->cval + B->rp[row];
01609 if (val != NULL)
01610 *val = B->aval + B->rp[row];
01611 END_FUNC_DH}
01612
01613 #undef __FUNC__
01614 #define __FUNC__ "Mat_dhRestoreRow"
01615 void
01616 Mat_dhRestoreRow (Mat_dh B, int row, int *len, int **ind, double **val)
01617 {
01618 START_FUNC_DH END_FUNC_DH}
01619
01620 #undef __FUNC__
01621 #define __FUNC__ "Mat_dhRowPermute"
01622 void
01623 Mat_dhRowPermute (Mat_dh mat)
01624 {
01625 START_FUNC_DH if (ignoreMe)
01626 SET_V_ERROR ("turned off; compilation problem on blue");
01627
01628 #if 0
01629 int i, j, m = mat->m, nz = mat->rp[m];
01630 int *o2n, *cval;
01631 int algo = 1;
01632 double *r1, *c1;
01633 bool debug = mat->debug;
01634 bool isNatural;
01635 Mat_dh B;
01636
01637 #if 0
01638 * = 1:Compute a row permutation of the matrix so that the
01639 * permuted matrix has as many entries on its diagonal as
01640 * possible.The values on the diagonal are of arbitrary size.
01641 * HSL subroutine MC21A / AD is used for this
01642 . * = 2: Compute a row permutation of the matrix so that the smallest * value on the diagonal of the permuted matrix is maximized. * = 3:Compute a row permutation of the matrix so that the smallest
01643 * value on the diagonal of the permuted matrix is maximized.
01644 * The algorithm differs from the one used for JOB
01645 = 2 and may * have quite a different performance. * = 4: Compute a row permutation of the matrix so that the sum * of the diagonal entries of the permuted matrix is maximized. * = 5:Compute a row permutation of the matrix so that the product
01646 * of the diagonal entries of the permuted matrix is maximized
01647 * and vectors to scale the matrix so that the nonzero diagonal
01648 * entries of the permuted matrix are one in absolute value and
01649 * all the off - diagonal entries are less than or equal to one in
01650 * absolute value.
01651 #endif
01652 Parser_dhReadInt (parser_dh, "-rowPermute", &algo);
01653 CHECK_V_ERROR;
01654 if (algo < 1)
01655 algo = 1;
01656 if (algo > 5)
01657 algo = 1;
01658 sprintf (msgBuf_dh, "calling row permutation with algo= %i", algo);
01659 SET_INFO (msgBuf_dh);
01660
01661 r1 = (double *) MALLOC_DH (m * sizeof (double));
01662 CHECK_V_ERROR;
01663 c1 = (double *) MALLOC_DH (m * sizeof (double));
01664 CHECK_V_ERROR;
01665 if (mat->row_perm == NULL)
01666 {
01667 mat->row_perm = o2n = (int *) MALLOC_DH (m * sizeof (int));
01668 CHECK_V_ERROR;
01669 }
01670 else
01671 {
01672 o2n = mat->row_perm;
01673 }
01674
01675 Mat_dhTranspose (mat, &B);
01676 CHECK_V_ERROR;
01677
01678
01679 dldperm (algo, m, nz, B->rp, B->cval, B->aval, o2n, r1, c1);
01680
01681
01682 cval = B->cval;
01683 for (i = 0; i < nz; ++i)
01684 cval[i] = o2n[cval[i]];
01685
01686
01687 if (debug && logFile != NULL)
01688 {
01689 fprintf (logFile, "\n-------- row permutation vector --------\n");
01690 for (i = 0; i < m; ++i)
01691 fprintf (logFile, "%i ", 1 + o2n[i]);
01692 fprintf (logFile, "\n");
01693
01694 if (myid_dh == 0)
01695 {
01696 printf ("\n-------- row permutation vector --------\n");
01697 for (i = 0; i < m; ++i)
01698 printf ("%i ", 1 + o2n[i]);
01699 printf ("\n");
01700 }
01701 }
01702
01703
01704 isNatural = true;
01705 for (i = 0; i < m; ++i)
01706 {
01707 if (o2n[i] != i)
01708 {
01709 isNatural = false;
01710 break;
01711 }
01712 }
01713
01714 if (isNatural)
01715 {
01716 printf ("@@@ [%i] Mat_dhRowPermute :: got natural ordering!\n",
01717 myid_dh);
01718 }
01719 else
01720 {
01721 int *rp = B->rp, *cval = B->cval;
01722 double *aval = B->aval;
01723
01724 if (algo == 5)
01725 {
01726 printf
01727 ("@@@ [%i] Mat_dhRowPermute :: scaling matrix rows and columns!\n",
01728 myid_dh);
01729
01730
01731 for (i = 0; i < m; i++)
01732 {
01733 r1[i] = exp (r1[i]);
01734 c1[i] = exp (c1[i]);
01735 }
01736 for (i = 0; i < m; i++)
01737 for (j = rp[i]; j < rp[i + 1]; j++)
01738 aval[j] *= r1[cval[j]] * c1[i];
01739 }
01740
01741 mat_dh_transpose_reuse_private (B->m, B->rp, B->cval, B->aval,
01742 mat->rp, mat->cval, mat->aval);
01743 CHECK_V_ERROR;
01744 }
01745
01746
01747 Mat_dhDestroy (B);
01748 CHECK_V_ERROR;
01749 FREE_DH (r1);
01750 CHECK_V_ERROR;
01751 FREE_DH (c1);
01752 CHECK_V_ERROR;
01753
01754 #endif
01755 END_FUNC_DH}
01756
01757
01758
01759 #undef __FUNC__
01760 #define __FUNC__ "Mat_dhPartition"
01761 void
01762 build_adj_lists_private (Mat_dh mat, int **rpOUT, int **cvalOUT)
01763 {
01764 START_FUNC_DH int m = mat->m;
01765 int *RP = mat->rp, *CVAL = mat->cval;
01766 int nz = RP[m];
01767 int i, j, *rp, *cval, idx = 0;
01768
01769 rp = *rpOUT = (int *) MALLOC_DH ((m + 1) * sizeof (int));
01770 CHECK_V_ERROR;
01771 cval = *cvalOUT = (int *) MALLOC_DH (nz * sizeof (int));
01772 CHECK_V_ERROR;
01773 rp[0] = 0;
01774
01775
01776 for (i = 0; i < m; ++i)
01777 {
01778 for (j = RP[i]; j < RP[i + 1]; ++j)
01779 {
01780 int col = CVAL[j];
01781 if (col != i)
01782 {
01783 cval[idx++] = col;
01784 }
01785 }
01786 rp[i + 1] = idx;
01787 }
01788 END_FUNC_DH}
01789
01790
01791 #undef __FUNC__
01792 #define __FUNC__ "Mat_dhPartition"
01793 void
01794 Mat_dhPartition (Mat_dh mat, int blocks,
01795 int **beg_rowOUT, int **row_countOUT, int **n2oOUT,
01796 int **o2nOUT)
01797 {
01798 START_FUNC_DH
01799 #ifndef HAVE_METIS_DH
01800 if (ignoreMe)
01801 SET_V_ERROR ("not compiled for metis!");
01802
01803 #else
01804 int *beg_row, *row_count, *n2o, *o2n, bk, new, *part;
01805 int m = mat->m;
01806 int i, cutEdgeCount;
01807 double zero = 0.0;
01808 int metisOpts[5] = { 0, 0, 0, 0, 0 };
01809 int *rp, *cval;
01810
01811
01812 beg_row = *beg_rowOUT = (int *) MALLOC_DH (blocks * sizeof (int));
01813 CHECK_V_ERROR;
01814 row_count = *row_countOUT = (int *) MALLOC_DH (blocks * sizeof (int));
01815 CHECK_V_ERROR;
01816 *n2oOUT = n2o = (int *) MALLOC_DH (m * sizeof (int));
01817 CHECK_V_ERROR;
01818 *o2nOUT = o2n = (int *) MALLOC_DH (m * sizeof (int));
01819 CHECK_V_ERROR;
01820
01821 #if 0
01822 == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == = Metis arguments:
01823
01824 n - number of nodes rp[], cval[]NULL, NULL, 0
01825 0
01826 blocksIN, options[5] = 0::0 / 1 use defauls;
01827 use uptions 1. .4
01828 1::
01829 edgecutOUT,
01830 part[]
01831 == == == == == == == == == == == == == == == == == == == == == == == == ==
01832 == == == == == =
01833 #endif
01834
01835 build_adj_lists_private (mat, &rp, &cval);
01836 CHECK_V_ERROR;
01837 part = (int *) MALLOC_DH (m * sizeof (int));
01838 CHECK_V_ERROR;
01839
01840
01841 METIS_PartGraphKway (&m, rp, cval, NULL, NULL,
01842 &zero, &zero, &blocks, metisOpts, &cutEdgeCount, part);
01843
01844 FREE_DH (rp);
01845 CHECK_V_ERROR;
01846 FREE_DH (cval);
01847 CHECK_V_ERROR;
01848
01849 if (mat->debug)
01850 {
01851 printf_dh ("\nmetis partitioning vector; blocks= %i\n", blocks);
01852 for (i = 0; i < m; ++i)
01853 printf_dh (" %i %i\n", i + 1, part[i]);
01854 }
01855
01856
01857 for (i = 0; i < blocks; ++i)
01858 row_count[i] = 0;
01859 for (i = 0; i < m; ++i)
01860 {
01861 bk = part[i];
01862 row_count[bk] += 1;
01863 }
01864 beg_row[0] = 0;
01865 for (i = 1; i < blocks; ++i)
01866 beg_row[i] = beg_row[i - 1] + row_count[i - 1];
01867
01868 if (mat->debug)
01869 {
01870 printf_dh ("\nrow_counts: ");
01871 for (i = 0; i < blocks; ++i)
01872 printf_dh (" %i", row_count[i]);
01873 printf_dh ("\nbeg_row: ");
01874 for (i = 0; i < blocks; ++i)
01875 printf_dh (" %i", beg_row[i] + 1);
01876 printf_dh ("\n");
01877 }
01878
01879
01880 {
01881 int *tmp = (int *) MALLOC_DH (blocks * sizeof (int));
01882 CHECK_V_ERROR;
01883 memcpy (tmp, beg_row, blocks * sizeof (int));
01884 for (i = 0; i < m; ++i)
01885 {
01886 bk = part[i];
01887 new = tmp[bk];
01888 tmp[bk] += 1;
01889 o2n[i] = new;
01890 n2o[new] = i;
01891 }
01892 FREE_DH (tmp);
01893 }
01894
01895 FREE_DH (part);
01896 CHECK_V_ERROR;
01897
01898 #endif
01899
01900 END_FUNC_DH}