1c4762a1bSJed Brown 2c4762a1bSJed Brown static char help[] = "Reads a PETSc matrix from a file partitions it\n\n"; 3c4762a1bSJed Brown 4c4762a1bSJed Brown /* 5c4762a1bSJed Brown Include "petscmat.h" so that we can use matrices. Note that this file 6c4762a1bSJed Brown automatically includes: 7c4762a1bSJed Brown petscsys.h - base PETSc routines petscvec.h - vectors 8c4762a1bSJed Brown petscmat.h - matrices 9c4762a1bSJed Brown petscis.h - index sets 10c4762a1bSJed Brown petscviewer.h - viewers 11c4762a1bSJed Brown 12c4762a1bSJed Brown Example of usage: 13c4762a1bSJed Brown mpiexec -n 3 ex73 -f <matfile> -mat_partitioning_type parmetis/scotch -viewer_binary_skip_info -nox 14c4762a1bSJed Brown */ 15c4762a1bSJed Brown #include <petscmat.h> 16c4762a1bSJed Brown 17*d71ae5a4SJacob Faibussowitsch int main(int argc, char **args) 18*d71ae5a4SJacob Faibussowitsch { 19c4762a1bSJed Brown MatType mtype = MATMPIAIJ; /* matrix format */ 20c4762a1bSJed Brown Mat A, B; /* matrix */ 21c4762a1bSJed Brown PetscViewer fd; /* viewer */ 22c4762a1bSJed Brown char file[PETSC_MAX_PATH_LEN]; /* input file name */ 23c4762a1bSJed Brown PetscBool flg, viewMats, viewIS, viewVecs, useND, noVecLoad = PETSC_FALSE; 24b122ec5aSJacob Faibussowitsch PetscInt *nlocal, m, n; 25c4762a1bSJed Brown PetscMPIInt rank, size; 26c4762a1bSJed Brown MatPartitioning part; 27c4762a1bSJed Brown IS is, isn; 28c4762a1bSJed Brown Vec xin, xout; 29c4762a1bSJed Brown VecScatter scat; 30c4762a1bSJed Brown 31327415f7SBarry Smith PetscFunctionBeginUser; 329566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &args, (char *)0, help)); 339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); 349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 359566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-view_mats", &viewMats)); 369566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-view_is", &viewIS)); 379566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-view_vecs", &viewVecs)); 389566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-use_nd", &useND)); 399566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(NULL, NULL, "-novec_load", &noVecLoad)); 40c4762a1bSJed Brown 41c4762a1bSJed Brown /* 42c4762a1bSJed Brown Determine file from which we read the matrix 43c4762a1bSJed Brown */ 449566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-f", file, sizeof(file), &flg)); 45c4762a1bSJed Brown 46c4762a1bSJed Brown /* 47c4762a1bSJed Brown Open binary file. Note that we use FILE_MODE_READ to indicate 48c4762a1bSJed Brown reading from this file. 49c4762a1bSJed Brown */ 509566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, file, FILE_MODE_READ, &fd)); 51c4762a1bSJed Brown 52c4762a1bSJed Brown /* 53c4762a1bSJed Brown Load the matrix and vector; then destroy the viewer. 54c4762a1bSJed Brown */ 559566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &A)); 569566063dSJacob Faibussowitsch PetscCall(MatSetType(A, mtype)); 579566063dSJacob Faibussowitsch PetscCall(MatLoad(A, fd)); 58c4762a1bSJed Brown if (!noVecLoad) { 599566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &xin)); 609566063dSJacob Faibussowitsch PetscCall(VecLoad(xin, fd)); 61c4762a1bSJed Brown } else { 629566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &xin, NULL)); 639566063dSJacob Faibussowitsch PetscCall(VecSetRandom(xin, NULL)); 64c4762a1bSJed Brown } 659566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&fd)); 66c4762a1bSJed Brown if (viewMats) { 679566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Original matrix:\n")); 689566063dSJacob Faibussowitsch PetscCall(MatView(A, PETSC_VIEWER_DRAW_WORLD)); 69c4762a1bSJed Brown } 70c4762a1bSJed Brown if (viewVecs) { 719566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Original vector:\n")); 729566063dSJacob Faibussowitsch PetscCall(VecView(xin, PETSC_VIEWER_STDOUT_WORLD)); 73c4762a1bSJed Brown } 74c4762a1bSJed Brown 75c4762a1bSJed Brown /* Partition the graph of the matrix */ 769566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(PETSC_COMM_WORLD, &part)); 779566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(part, A)); 789566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(part)); 79c4762a1bSJed Brown 80c4762a1bSJed Brown /* get new processor owner number of each vertex */ 81c4762a1bSJed Brown if (useND) { 829566063dSJacob Faibussowitsch PetscCall(MatPartitioningApplyND(part, &is)); 83c4762a1bSJed Brown } else { 849566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(part, &is)); 85c4762a1bSJed Brown } 86c4762a1bSJed Brown if (viewIS) { 879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "IS1 - new processor ownership:\n")); 889566063dSJacob Faibussowitsch PetscCall(ISView(is, PETSC_VIEWER_STDOUT_WORLD)); 89c4762a1bSJed Brown } 90c4762a1bSJed Brown 91c4762a1bSJed Brown /* get new global number of each old global number */ 929566063dSJacob Faibussowitsch PetscCall(ISPartitioningToNumbering(is, &isn)); 93c4762a1bSJed Brown if (viewIS) { 949566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "IS2 - new global numbering:\n")); 959566063dSJacob Faibussowitsch PetscCall(ISView(isn, PETSC_VIEWER_STDOUT_WORLD)); 96c4762a1bSJed Brown } 97c4762a1bSJed Brown 98c4762a1bSJed Brown /* get number of new vertices for each processor */ 999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &nlocal)); 1009566063dSJacob Faibussowitsch PetscCall(ISPartitioningCount(is, size, nlocal)); 1019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 102c4762a1bSJed Brown 103c4762a1bSJed Brown /* get old global number of each new global number */ 1049566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(isn, useND ? PETSC_DECIDE : nlocal[rank], &is)); 105c4762a1bSJed Brown if (viewIS) { 1069566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "IS3=inv(IS2) - old global number of each new global number:\n")); 1079566063dSJacob Faibussowitsch PetscCall(ISView(is, PETSC_VIEWER_STDOUT_WORLD)); 108c4762a1bSJed Brown } 109c4762a1bSJed Brown 110c4762a1bSJed Brown /* move the matrix rows to the new processes they have been assigned to by the permutation */ 1119566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, is, is, MAT_INITIAL_MATRIX, &B)); 1129566063dSJacob Faibussowitsch PetscCall(PetscFree(nlocal)); 1139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isn)); 1149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 1159566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&part)); 116c4762a1bSJed Brown if (viewMats) { 1179566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Partitioned matrix:\n")); 1189566063dSJacob Faibussowitsch PetscCall(MatView(B, PETSC_VIEWER_DRAW_WORLD)); 119c4762a1bSJed Brown } 120c4762a1bSJed Brown 121c4762a1bSJed Brown /* move the vector rows to the new processes they have been assigned to */ 1229566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B, &m, &n)); 1239566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(PETSC_COMM_WORLD, m, PETSC_DECIDE, &xout)); 1249566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(xin, is, xout, NULL, &scat)); 1259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat, xin, xout, INSERT_VALUES, SCATTER_FORWARD)); 1269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat, xin, xout, INSERT_VALUES, SCATTER_FORWARD)); 1279566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&scat)); 128c4762a1bSJed Brown if (viewVecs) { 1299566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Mapped vector:\n")); 1309566063dSJacob Faibussowitsch PetscCall(VecView(xout, PETSC_VIEWER_STDOUT_WORLD)); 131c4762a1bSJed Brown } 1329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xout)); 1339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 134c4762a1bSJed Brown 135c4762a1bSJed Brown { 136c4762a1bSJed Brown PetscInt rstart, i, *nzd, *nzo, nzl, nzmax = 0, *ncols, nrow, j; 137c4762a1bSJed Brown Mat J; 138c4762a1bSJed Brown const PetscInt *cols; 139c4762a1bSJed Brown const PetscScalar *vals; 140c4762a1bSJed Brown PetscScalar *nvals; 141c4762a1bSJed Brown 1429566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, NULL)); 1439566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(2 * m, &nzd, 2 * m, &nzo)); 144c4762a1bSJed Brown for (i = 0; i < m; i++) { 1459566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i + rstart, &nzl, &cols, NULL)); 146c4762a1bSJed Brown for (j = 0; j < nzl; j++) { 147c4762a1bSJed Brown if (cols[j] >= rstart && cols[j] < rstart + n) { 148c4762a1bSJed Brown nzd[2 * i] += 2; 149c4762a1bSJed Brown nzd[2 * i + 1] += 2; 150c4762a1bSJed Brown } else { 151c4762a1bSJed Brown nzo[2 * i] += 2; 152c4762a1bSJed Brown nzo[2 * i + 1] += 2; 153c4762a1bSJed Brown } 154c4762a1bSJed Brown } 155c4762a1bSJed Brown nzmax = PetscMax(nzmax, nzd[2 * i] + nzo[2 * i]); 1569566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i + rstart, &nzl, &cols, NULL)); 157c4762a1bSJed Brown } 1589566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_WORLD, 2 * m, 2 * m, PETSC_DECIDE, PETSC_DECIDE, 0, nzd, 0, nzo, &J)); 1599566063dSJacob Faibussowitsch PetscCall(PetscInfo(0, "Created empty Jacobian matrix\n")); 1609566063dSJacob Faibussowitsch PetscCall(PetscFree2(nzd, nzo)); 1619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nzmax, &ncols, nzmax, &nvals)); 1629566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(nvals, nzmax)); 163c4762a1bSJed Brown for (i = 0; i < m; i++) { 1649566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i + rstart, &nzl, &cols, &vals)); 165c4762a1bSJed Brown for (j = 0; j < nzl; j++) { 166c4762a1bSJed Brown ncols[2 * j] = 2 * cols[j]; 167c4762a1bSJed Brown ncols[2 * j + 1] = 2 * cols[j] + 1; 168c4762a1bSJed Brown } 169c4762a1bSJed Brown nrow = 2 * (i + rstart); 1709566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &nrow, 2 * nzl, ncols, nvals, INSERT_VALUES)); 171c4762a1bSJed Brown nrow = 2 * (i + rstart) + 1; 1729566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &nrow, 2 * nzl, ncols, nvals, INSERT_VALUES)); 1739566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i + rstart, &nzl, &cols, &vals)); 174c4762a1bSJed Brown } 1759566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 1769566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 177c4762a1bSJed Brown if (viewMats) { 1789566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Jacobian matrix structure:\n")); 1799566063dSJacob Faibussowitsch PetscCall(MatView(J, PETSC_VIEWER_DRAW_WORLD)); 180c4762a1bSJed Brown } 1819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J)); 1829566063dSJacob Faibussowitsch PetscCall(PetscFree2(ncols, nvals)); 183c4762a1bSJed Brown } 184c4762a1bSJed Brown 185c4762a1bSJed Brown /* 186c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they 187c4762a1bSJed Brown are no longer needed. 188c4762a1bSJed Brown */ 1899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 1909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xin)); 1919566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 192b122ec5aSJacob Faibussowitsch return 0; 193c4762a1bSJed Brown } 194c4762a1bSJed Brown 195c4762a1bSJed Brown /*TEST 196c4762a1bSJed Brown 197c4762a1bSJed Brown test: 198c4762a1bSJed Brown nsize: 3 199dfd57a17SPierre Jolivet requires: parmetis datafilespath !complex double !defined(PETSC_USE_64BIT_INDICES) 200c4762a1bSJed Brown args: -nox -f ${DATAFILESPATH}/matrices/arco1 -mat_partitioning_type parmetis -viewer_binary_skip_info -novec_load 201c4762a1bSJed Brown 202c4762a1bSJed Brown test: 203dfd57a17SPierre Jolivet requires: parmetis !complex double !defined(PETSC_USE_64BIT_INDICES) 204c4762a1bSJed Brown output_file: output/ex73_1.out 205c4762a1bSJed Brown suffix: parmetis_nd_32 206c4762a1bSJed Brown nsize: 3 207c4762a1bSJed Brown args: -nox -f ${wPETSC_DIR}/share/petsc/datafiles/matrices/spd-real-int32-float64 -mat_partitioning_type parmetis -viewer_binary_skip_info -use_nd -novec_load 208c4762a1bSJed Brown 209c4762a1bSJed Brown test: 210dfd57a17SPierre Jolivet requires: parmetis !complex double defined(PETSC_USE_64BIT_INDICES) 211c4762a1bSJed Brown output_file: output/ex73_1.out 212c4762a1bSJed Brown suffix: parmetis_nd_64 213c4762a1bSJed Brown nsize: 3 214c4762a1bSJed Brown args: -nox -f ${wPETSC_DIR}/share/petsc/datafiles/matrices/spd-real-int64-float64 -mat_partitioning_type parmetis -viewer_binary_skip_info -use_nd -novec_load 215c4762a1bSJed Brown 216c4762a1bSJed Brown test: 217dfd57a17SPierre Jolivet requires: ptscotch !complex double !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_SCOTCH_PARMETIS_V3_NODEND) 218c4762a1bSJed Brown output_file: output/ex73_1.out 219c4762a1bSJed Brown suffix: ptscotch_nd_32 220c4762a1bSJed Brown nsize: 4 221c4762a1bSJed Brown args: -nox -f ${wPETSC_DIR}/share/petsc/datafiles/matrices/spd-real-int32-float64 -mat_partitioning_type ptscotch -viewer_binary_skip_info -use_nd -novec_load 222c4762a1bSJed Brown 223c4762a1bSJed Brown test: 224dfd57a17SPierre Jolivet requires: ptscotch !complex double defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_SCOTCH_PARMETIS_V3_NODEND) 225c4762a1bSJed Brown output_file: output/ex73_1.out 226c4762a1bSJed Brown suffix: ptscotch_nd_64 227c4762a1bSJed Brown nsize: 4 228c4762a1bSJed Brown args: -nox -f ${wPETSC_DIR}/share/petsc/datafiles/matrices/spd-real-int64-float64 -mat_partitioning_type ptscotch -viewer_binary_skip_info -use_nd -novec_load 229c4762a1bSJed Brown 230c4762a1bSJed Brown TEST*/ 231