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 17c4762a1bSJed Brown int main(int argc,char **args) 18c4762a1bSJed Brown { 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 31*327415f7SBarry 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