1be1d678aSKris Buschelman 2b97cf49bSBarry Smith /* 3b97cf49bSBarry Smith Defines the basic matrix operations for the ADJ adjacency list matrix data-structure. 4b97cf49bSBarry Smith */ 5e37d9405SJed Brown #include <../src/mat/impls/adj/mpi/mpiadj.h> /*I "petscmat.h" I*/ 6841d17a1SFande Kong #include <petscsf.h> 7b97cf49bSBarry Smith 840244768SBarry Smith /* 97dae84e0SHong Zhang * The interface should be easy to use for both MatCreateSubMatrix (parallel sub-matrix) and MatCreateSubMatrices (sequential sub-matrices) 1040244768SBarry Smith * */ 117dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_MPIAdj_data(Mat adj,IS irows, IS icols, PetscInt **sadj_xadj,PetscInt **sadj_adjncy,PetscInt **sadj_values) 1240244768SBarry Smith { 13131c27b5Sprj- PetscInt nlrows_is,icols_n,i,j,nroots,nleaves,rlocalindex,*ncols_send,*ncols_recv; 1440244768SBarry Smith PetscInt nlrows_mat,*adjncy_recv,Ncols_recv,Ncols_send,*xadj_recv,*values_recv; 15e895ccc0SFande Kong PetscInt *ncols_recv_offsets,loc,rnclos,*sadjncy,*sxadj,*svalues; 1640244768SBarry Smith const PetscInt *irows_indices,*icols_indices,*xadj, *adjncy; 17131c27b5Sprj- PetscMPIInt owner; 1840244768SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)adj->data; 1940244768SBarry Smith PetscLayout rmap; 2040244768SBarry Smith MPI_Comm comm; 2140244768SBarry Smith PetscSF sf; 2240244768SBarry Smith PetscSFNode *iremote; 2340244768SBarry Smith PetscBool done; 2440244768SBarry Smith PetscErrorCode ierr; 2540244768SBarry Smith 2640244768SBarry Smith PetscFunctionBegin; 2740244768SBarry Smith ierr = PetscObjectGetComm((PetscObject)adj,&comm);CHKERRQ(ierr); 28390e1bf2SBarry Smith ierr = MatGetLayouts(adj,&rmap,NULL);CHKERRQ(ierr); 2940244768SBarry Smith ierr = ISGetLocalSize(irows,&nlrows_is);CHKERRQ(ierr); 3040244768SBarry Smith ierr = ISGetIndices(irows,&irows_indices);CHKERRQ(ierr); 31071fcb05SBarry Smith ierr = PetscMalloc1(nlrows_is,&iremote);CHKERRQ(ierr); 3240244768SBarry Smith /* construct sf graph*/ 3340244768SBarry Smith nleaves = nlrows_is; 3440244768SBarry Smith for (i=0; i<nlrows_is; i++) { 3540244768SBarry Smith owner = -1; 3640244768SBarry Smith rlocalindex = -1; 3740244768SBarry Smith ierr = PetscLayoutFindOwnerIndex(rmap,irows_indices[i],&owner,&rlocalindex);CHKERRQ(ierr); 3840244768SBarry Smith iremote[i].rank = owner; 3940244768SBarry Smith iremote[i].index = rlocalindex; 4040244768SBarry Smith } 4140244768SBarry Smith ierr = MatGetRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done);CHKERRQ(ierr); 4240244768SBarry Smith ierr = PetscCalloc4(nlrows_mat,&ncols_send,nlrows_is,&xadj_recv,nlrows_is+1,&ncols_recv_offsets,nlrows_is,&ncols_recv);CHKERRQ(ierr); 4340244768SBarry Smith nroots = nlrows_mat; 4440244768SBarry Smith for (i=0; i<nlrows_mat; i++) { 4540244768SBarry Smith ncols_send[i] = xadj[i+1]-xadj[i]; 4640244768SBarry Smith } 4740244768SBarry Smith ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); 48390e1bf2SBarry Smith ierr = PetscSFSetGraph(sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 4940244768SBarry Smith ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); 5040244768SBarry Smith ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 51ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf,MPIU_INT,ncols_send,ncols_recv,MPI_REPLACE);CHKERRQ(ierr); 52ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf,MPIU_INT,ncols_send,ncols_recv,MPI_REPLACE);CHKERRQ(ierr); 53ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf,MPIU_INT,xadj,xadj_recv,MPI_REPLACE);CHKERRQ(ierr); 54ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf,MPIU_INT,xadj,xadj_recv,MPI_REPLACE);CHKERRQ(ierr); 5540244768SBarry Smith ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 5640244768SBarry Smith Ncols_recv =0; 5740244768SBarry Smith for (i=0; i<nlrows_is; i++) { 5840244768SBarry Smith Ncols_recv += ncols_recv[i]; 5940244768SBarry Smith ncols_recv_offsets[i+1] = ncols_recv[i]+ncols_recv_offsets[i]; 6040244768SBarry Smith } 6140244768SBarry Smith Ncols_send = 0; 6240244768SBarry Smith for (i=0; i<nlrows_mat; i++) { 6340244768SBarry Smith Ncols_send += ncols_send[i]; 6440244768SBarry Smith } 6540244768SBarry Smith ierr = PetscCalloc1(Ncols_recv,&iremote);CHKERRQ(ierr); 6640244768SBarry Smith ierr = PetscCalloc1(Ncols_recv,&adjncy_recv);CHKERRQ(ierr); 6740244768SBarry Smith nleaves = Ncols_recv; 6840244768SBarry Smith Ncols_recv = 0; 6940244768SBarry Smith for (i=0; i<nlrows_is; i++) { 7040244768SBarry Smith ierr = PetscLayoutFindOwner(rmap,irows_indices[i],&owner);CHKERRQ(ierr); 7140244768SBarry Smith for (j=0; j<ncols_recv[i]; j++) { 7240244768SBarry Smith iremote[Ncols_recv].rank = owner; 7340244768SBarry Smith iremote[Ncols_recv++].index = xadj_recv[i]+j; 7440244768SBarry Smith } 7540244768SBarry Smith } 7640244768SBarry Smith ierr = ISRestoreIndices(irows,&irows_indices);CHKERRQ(ierr); 7740244768SBarry Smith /*if we need to deal with edge weights ???*/ 78e895ccc0SFande Kong if (a->useedgeweights) {ierr = PetscCalloc1(Ncols_recv,&values_recv);CHKERRQ(ierr);} 7940244768SBarry Smith nroots = Ncols_send; 8040244768SBarry Smith ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); 81390e1bf2SBarry Smith ierr = PetscSFSetGraph(sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 8240244768SBarry Smith ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); 8340244768SBarry Smith ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 84ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf,MPIU_INT,adjncy,adjncy_recv,MPI_REPLACE);CHKERRQ(ierr); 85ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf,MPIU_INT,adjncy,adjncy_recv,MPI_REPLACE);CHKERRQ(ierr); 86e895ccc0SFande Kong if (a->useedgeweights) { 87ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf,MPIU_INT,a->values,values_recv,MPI_REPLACE);CHKERRQ(ierr); 88ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf,MPIU_INT,a->values,values_recv,MPI_REPLACE);CHKERRQ(ierr); 8940244768SBarry Smith } 9040244768SBarry Smith ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 9140244768SBarry Smith ierr = MatRestoreRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done);CHKERRQ(ierr); 9240244768SBarry Smith ierr = ISGetLocalSize(icols,&icols_n);CHKERRQ(ierr); 9340244768SBarry Smith ierr = ISGetIndices(icols,&icols_indices);CHKERRQ(ierr); 9440244768SBarry Smith rnclos = 0; 9540244768SBarry Smith for (i=0; i<nlrows_is; i++) { 9640244768SBarry Smith for (j=ncols_recv_offsets[i]; j<ncols_recv_offsets[i+1]; j++) { 9740244768SBarry Smith ierr = PetscFindInt(adjncy_recv[j], icols_n, icols_indices, &loc);CHKERRQ(ierr); 9840244768SBarry Smith if (loc<0) { 9940244768SBarry Smith adjncy_recv[j] = -1; 100e895ccc0SFande Kong if (a->useedgeweights) values_recv[j] = -1; 10140244768SBarry Smith ncols_recv[i]--; 10240244768SBarry Smith } else { 10340244768SBarry Smith rnclos++; 10440244768SBarry Smith } 10540244768SBarry Smith } 10640244768SBarry Smith } 10740244768SBarry Smith ierr = ISRestoreIndices(icols,&icols_indices);CHKERRQ(ierr); 10840244768SBarry Smith ierr = PetscCalloc1(rnclos,&sadjncy);CHKERRQ(ierr); 109e895ccc0SFande Kong if (a->useedgeweights) {ierr = PetscCalloc1(rnclos,&svalues);CHKERRQ(ierr);} 11040244768SBarry Smith ierr = PetscCalloc1(nlrows_is+1,&sxadj);CHKERRQ(ierr); 11140244768SBarry Smith rnclos = 0; 11240244768SBarry Smith for (i=0; i<nlrows_is; i++) { 11340244768SBarry Smith for (j=ncols_recv_offsets[i]; j<ncols_recv_offsets[i+1]; j++) { 11440244768SBarry Smith if (adjncy_recv[j]<0) continue; 11540244768SBarry Smith sadjncy[rnclos] = adjncy_recv[j]; 116e895ccc0SFande Kong if (a->useedgeweights) svalues[rnclos] = values_recv[j]; 11740244768SBarry Smith rnclos++; 11840244768SBarry Smith } 11940244768SBarry Smith } 12040244768SBarry Smith for (i=0; i<nlrows_is; i++) { 12140244768SBarry Smith sxadj[i+1] = sxadj[i]+ncols_recv[i]; 12240244768SBarry Smith } 12340244768SBarry Smith if (sadj_xadj) { *sadj_xadj = sxadj;} else { ierr = PetscFree(sxadj);CHKERRQ(ierr);} 12440244768SBarry Smith if (sadj_adjncy) { *sadj_adjncy = sadjncy;} else { ierr = PetscFree(sadjncy);CHKERRQ(ierr);} 12540244768SBarry Smith if (sadj_values) { 126f4259b30SLisandro Dalcin if (a->useedgeweights) *sadj_values = svalues; else *sadj_values=NULL; 12740244768SBarry Smith } else { 128e895ccc0SFande Kong if (a->useedgeweights) {ierr = PetscFree(svalues);CHKERRQ(ierr);} 12940244768SBarry Smith } 13040244768SBarry Smith ierr = PetscFree4(ncols_send,xadj_recv,ncols_recv_offsets,ncols_recv);CHKERRQ(ierr); 13140244768SBarry Smith ierr = PetscFree(adjncy_recv);CHKERRQ(ierr); 132e895ccc0SFande Kong if (a->useedgeweights) {ierr = PetscFree(values_recv);CHKERRQ(ierr);} 13340244768SBarry Smith PetscFunctionReturn(0); 13440244768SBarry Smith } 13540244768SBarry Smith 1367dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrices_MPIAdj_Private(Mat mat,PetscInt n,const IS irow[],const IS icol[],PetscBool subcomm,MatReuse scall,Mat *submat[]) 13740244768SBarry Smith { 13840244768SBarry Smith PetscInt i,irow_n,icol_n,*sxadj,*sadjncy,*svalues; 13940244768SBarry Smith PetscInt *indices,nindx,j,k,loc; 14040244768SBarry Smith PetscMPIInt issame; 14140244768SBarry Smith const PetscInt *irow_indices,*icol_indices; 14240244768SBarry Smith MPI_Comm scomm_row,scomm_col,scomm_mat; 14340244768SBarry Smith PetscErrorCode ierr; 14440244768SBarry Smith 14540244768SBarry Smith PetscFunctionBegin; 14640244768SBarry Smith nindx = 0; 14740244768SBarry Smith /* 14840244768SBarry Smith * Estimate a maximum number for allocating memory 14940244768SBarry Smith */ 15040244768SBarry Smith for (i=0; i<n; i++) { 15140244768SBarry Smith ierr = ISGetLocalSize(irow[i],&irow_n);CHKERRQ(ierr); 15240244768SBarry Smith ierr = ISGetLocalSize(icol[i],&icol_n);CHKERRQ(ierr); 15340244768SBarry Smith nindx = nindx>(irow_n+icol_n)? nindx:(irow_n+icol_n); 15440244768SBarry Smith } 155071fcb05SBarry Smith ierr = PetscMalloc1(nindx,&indices);CHKERRQ(ierr); 15640244768SBarry Smith /* construct a submat */ 15740244768SBarry Smith for (i=0; i<n; i++) { 15840244768SBarry Smith if (subcomm) { 15940244768SBarry Smith ierr = PetscObjectGetComm((PetscObject)irow[i],&scomm_row);CHKERRQ(ierr); 16040244768SBarry Smith ierr = PetscObjectGetComm((PetscObject)icol[i],&scomm_col);CHKERRQ(ierr); 161ffc4695bSBarry Smith ierr = MPI_Comm_compare(scomm_row,scomm_col,&issame);CHKERRMPI(ierr); 162*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(issame != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"row index set must have the same comm as the col index set"); 163ffc4695bSBarry Smith ierr = MPI_Comm_compare(scomm_row,PETSC_COMM_SELF,&issame);CHKERRMPI(ierr); 164*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(issame == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP," can not use PETSC_COMM_SELF as comm when extracting a parallel submatrix"); 16540244768SBarry Smith } else { 16640244768SBarry Smith scomm_row = PETSC_COMM_SELF; 16740244768SBarry Smith } 16840244768SBarry Smith /*get sub-matrix data*/ 169f4259b30SLisandro Dalcin sxadj=NULL; sadjncy=NULL; svalues=NULL; 1707dae84e0SHong Zhang ierr = MatCreateSubMatrix_MPIAdj_data(mat,irow[i],icol[i],&sxadj,&sadjncy,&svalues);CHKERRQ(ierr); 17140244768SBarry Smith ierr = ISGetLocalSize(irow[i],&irow_n);CHKERRQ(ierr); 17240244768SBarry Smith ierr = ISGetLocalSize(icol[i],&icol_n);CHKERRQ(ierr); 17340244768SBarry Smith ierr = ISGetIndices(irow[i],&irow_indices);CHKERRQ(ierr); 174580bdb30SBarry Smith ierr = PetscArraycpy(indices,irow_indices,irow_n);CHKERRQ(ierr); 17540244768SBarry Smith ierr = ISRestoreIndices(irow[i],&irow_indices);CHKERRQ(ierr); 17640244768SBarry Smith ierr = ISGetIndices(icol[i],&icol_indices);CHKERRQ(ierr); 177580bdb30SBarry Smith ierr = PetscArraycpy(indices+irow_n,icol_indices,icol_n);CHKERRQ(ierr); 17840244768SBarry Smith ierr = ISRestoreIndices(icol[i],&icol_indices);CHKERRQ(ierr); 17940244768SBarry Smith nindx = irow_n+icol_n; 18040244768SBarry Smith ierr = PetscSortRemoveDupsInt(&nindx,indices);CHKERRQ(ierr); 18140244768SBarry Smith /* renumber columns */ 18240244768SBarry Smith for (j=0; j<irow_n; j++) { 18340244768SBarry Smith for (k=sxadj[j]; k<sxadj[j+1]; k++) { 18440244768SBarry Smith ierr = PetscFindInt(sadjncy[k],nindx,indices,&loc);CHKERRQ(ierr); 185*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(loc<0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"can not find col %" PetscInt_FMT,sadjncy[k]); 18640244768SBarry Smith sadjncy[k] = loc; 18740244768SBarry Smith } 18840244768SBarry Smith } 18940244768SBarry Smith if (scall==MAT_INITIAL_MATRIX) { 19040244768SBarry Smith ierr = MatCreateMPIAdj(scomm_row,irow_n,icol_n,sxadj,sadjncy,svalues,submat[i]);CHKERRQ(ierr); 19140244768SBarry Smith } else { 19240244768SBarry Smith Mat sadj = *(submat[i]); 19340244768SBarry Smith Mat_MPIAdj *sa = (Mat_MPIAdj*)((sadj)->data); 19440244768SBarry Smith ierr = PetscObjectGetComm((PetscObject)sadj,&scomm_mat);CHKERRQ(ierr); 195ffc4695bSBarry Smith ierr = MPI_Comm_compare(scomm_row,scomm_mat,&issame);CHKERRMPI(ierr); 196*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(issame != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"submatrix must have the same comm as the col index set"); 197580bdb30SBarry Smith ierr = PetscArraycpy(sa->i,sxadj,irow_n+1);CHKERRQ(ierr); 198580bdb30SBarry Smith ierr = PetscArraycpy(sa->j,sadjncy,sxadj[irow_n]);CHKERRQ(ierr); 199580bdb30SBarry Smith if (svalues) {ierr = PetscArraycpy(sa->values,svalues,sxadj[irow_n]);CHKERRQ(ierr);} 20040244768SBarry Smith ierr = PetscFree(sxadj);CHKERRQ(ierr); 20140244768SBarry Smith ierr = PetscFree(sadjncy);CHKERRQ(ierr); 20240244768SBarry Smith if (svalues) {ierr = PetscFree(svalues);CHKERRQ(ierr);} 20340244768SBarry Smith } 20440244768SBarry Smith } 20540244768SBarry Smith ierr = PetscFree(indices);CHKERRQ(ierr); 20640244768SBarry Smith PetscFunctionReturn(0); 20740244768SBarry Smith } 20840244768SBarry Smith 2097dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatricesMPI_MPIAdj(Mat mat,PetscInt n, const IS irow[],const IS icol[],MatReuse scall,Mat *submat[]) 21040244768SBarry Smith { 21140244768SBarry Smith PetscErrorCode ierr; 21240244768SBarry Smith /*get sub-matrices across a sub communicator */ 21340244768SBarry Smith PetscFunctionBegin; 2147dae84e0SHong Zhang ierr = MatCreateSubMatrices_MPIAdj_Private(mat,n,irow,icol,PETSC_TRUE,scall,submat);CHKERRQ(ierr); 21540244768SBarry Smith PetscFunctionReturn(0); 21640244768SBarry Smith } 21740244768SBarry Smith 2187dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrices_MPIAdj(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[]) 21940244768SBarry Smith { 22040244768SBarry Smith PetscErrorCode ierr; 22140244768SBarry Smith 22240244768SBarry Smith PetscFunctionBegin; 22340244768SBarry Smith /*get sub-matrices based on PETSC_COMM_SELF */ 2247dae84e0SHong Zhang ierr = MatCreateSubMatrices_MPIAdj_Private(mat,n,irow,icol,PETSC_FALSE,scall,submat);CHKERRQ(ierr); 22540244768SBarry Smith PetscFunctionReturn(0); 22640244768SBarry Smith } 22740244768SBarry Smith 22840244768SBarry Smith static PetscErrorCode MatView_MPIAdj_ASCII(Mat A,PetscViewer viewer) 229b97cf49bSBarry Smith { 2303eda8832SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)A->data; 231dfbe8321SBarry Smith PetscErrorCode ierr; 232d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n; 2332dcb1b2aSMatthew Knepley const char *name; 234ce1411ecSBarry Smith PetscViewerFormat format; 235b97cf49bSBarry Smith 236433994e6SBarry Smith PetscFunctionBegin; 2373a7fca6bSBarry Smith ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr); 238b0a32e0cSBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 239fb9695e5SSatish Balay if (format == PETSC_VIEWER_ASCII_INFO) { 2403a40ed3dSBarry Smith PetscFunctionReturn(0); 241*2c71b3e2SJacob Faibussowitsch } else PetscCheckFalse(format == PETSC_VIEWER_ASCII_MATLAB,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MATLAB format not supported"); 2426c4ed002SBarry Smith else { 243d00279f6SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 244c5e4d11fSDmitry Karpeev ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 245b97cf49bSBarry Smith for (i=0; i<m; i++) { 246c0aa6a63SJacob Faibussowitsch ierr = PetscViewerASCIISynchronizedPrintf(viewer,"row %" PetscInt_FMT ":",i+A->rmap->rstart);CHKERRQ(ierr); 247b97cf49bSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 2480170919eSFande Kong if (a->values) { 249c0aa6a63SJacob Faibussowitsch ierr = PetscViewerASCIISynchronizedPrintf(viewer," (%" PetscInt_FMT ", %" PetscInt_FMT ") ",a->j[j], a->values[j]);CHKERRQ(ierr); 2500170919eSFande Kong } else { 251c0aa6a63SJacob Faibussowitsch ierr = PetscViewerASCIISynchronizedPrintf(viewer," %" PetscInt_FMT " ",a->j[j]);CHKERRQ(ierr); 2520752156aSBarry Smith } 2530170919eSFande Kong } 254b0a32e0cSBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); 255b97cf49bSBarry Smith } 256d00279f6SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 257b0a32e0cSBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 258c5e4d11fSDmitry Karpeev ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 2597b23a99aSBarry Smith } 2603a40ed3dSBarry Smith PetscFunctionReturn(0); 261b97cf49bSBarry Smith } 262b97cf49bSBarry Smith 26340244768SBarry Smith static PetscErrorCode MatView_MPIAdj(Mat A,PetscViewer viewer) 264b97cf49bSBarry Smith { 265dfbe8321SBarry Smith PetscErrorCode ierr; 266ace3abfcSBarry Smith PetscBool iascii; 267b97cf49bSBarry Smith 268433994e6SBarry Smith PetscFunctionBegin; 269251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 27032077d6dSBarry Smith if (iascii) { 2713eda8832SBarry Smith ierr = MatView_MPIAdj_ASCII(A,viewer);CHKERRQ(ierr); 272b97cf49bSBarry Smith } 2733a40ed3dSBarry Smith PetscFunctionReturn(0); 274b97cf49bSBarry Smith } 275b97cf49bSBarry Smith 27640244768SBarry Smith static PetscErrorCode MatDestroy_MPIAdj(Mat mat) 277b97cf49bSBarry Smith { 2783eda8832SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)mat->data; 279dfbe8321SBarry Smith PetscErrorCode ierr; 28094d884c6SBarry Smith 28194d884c6SBarry Smith PetscFunctionBegin; 282aa482453SBarry Smith #if defined(PETSC_USE_LOG) 283c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)mat,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,mat->rmap->n,mat->cmap->n,a->nz); 284b97cf49bSBarry Smith #endif 28505b42c5fSBarry Smith ierr = PetscFree(a->diag);CHKERRQ(ierr); 2860400557aSBarry Smith if (a->freeaij) { 28714196391SBarry Smith if (a->freeaijwithfree) { 28814196391SBarry Smith if (a->i) free(a->i); 28914196391SBarry Smith if (a->j) free(a->j); 29014196391SBarry Smith } else { 291606d414cSSatish Balay ierr = PetscFree(a->i);CHKERRQ(ierr); 292606d414cSSatish Balay ierr = PetscFree(a->j);CHKERRQ(ierr); 29305b42c5fSBarry Smith ierr = PetscFree(a->values);CHKERRQ(ierr); 29414196391SBarry Smith } 2950400557aSBarry Smith } 2962b1d8763SJed Brown ierr = PetscFree(a->rowvalues);CHKERRQ(ierr); 297bf0cc555SLisandro Dalcin ierr = PetscFree(mat->data);CHKERRQ(ierr); 298f4259b30SLisandro Dalcin ierr = PetscObjectChangeTypeName((PetscObject)mat,NULL);CHKERRQ(ierr); 299bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjSetPreallocation_C",NULL);CHKERRQ(ierr); 300bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjCreateNonemptySubcommMat_C",NULL);CHKERRQ(ierr); 3013a40ed3dSBarry Smith PetscFunctionReturn(0); 302b97cf49bSBarry Smith } 303b97cf49bSBarry Smith 30440244768SBarry Smith static PetscErrorCode MatSetOption_MPIAdj(Mat A,MatOption op,PetscBool flg) 305b97cf49bSBarry Smith { 3063eda8832SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)A->data; 30763ba0a88SBarry Smith PetscErrorCode ierr; 308b97cf49bSBarry Smith 309433994e6SBarry Smith PetscFunctionBegin; 31012c028f9SKris Buschelman switch (op) { 31177e54ba9SKris Buschelman case MAT_SYMMETRIC: 31212c028f9SKris Buschelman case MAT_STRUCTURALLY_SYMMETRIC: 3139a4540c5SBarry Smith case MAT_HERMITIAN: 3144e0d8c25SBarry Smith a->symmetric = flg; 3159a4540c5SBarry Smith break; 3169a4540c5SBarry Smith case MAT_SYMMETRY_ETERNAL: 3179a4540c5SBarry Smith break; 31812c028f9SKris Buschelman default: 3197d3de750SJacob Faibussowitsch ierr = PetscInfo(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 32012c028f9SKris Buschelman break; 321b97cf49bSBarry Smith } 3223a40ed3dSBarry Smith PetscFunctionReturn(0); 323b97cf49bSBarry Smith } 324b97cf49bSBarry Smith 32540244768SBarry Smith static PetscErrorCode MatGetRow_MPIAdj(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 326b97cf49bSBarry Smith { 3273eda8832SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)A->data; 3282b1d8763SJed Brown PetscErrorCode ierr; 329b97cf49bSBarry Smith 330433994e6SBarry Smith PetscFunctionBegin; 331d0f46423SBarry Smith row -= A->rmap->rstart; 332*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(row < 0 || row >= A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row out of range"); 333b97cf49bSBarry Smith *nz = a->i[row+1] - a->i[row]; 3342b1d8763SJed Brown if (v) { 3352b1d8763SJed Brown PetscInt j; 3362b1d8763SJed Brown if (a->rowvalues_alloc < *nz) { 3372b1d8763SJed Brown ierr = PetscFree(a->rowvalues);CHKERRQ(ierr); 3382b1d8763SJed Brown a->rowvalues_alloc = PetscMax(a->rowvalues_alloc*2, *nz); 339785e854fSJed Brown ierr = PetscMalloc1(a->rowvalues_alloc,&a->rowvalues);CHKERRQ(ierr); 340b97cf49bSBarry Smith } 34191f8cafeSFande Kong for (j=0; j<*nz; j++) { 34291f8cafeSFande Kong a->rowvalues[j] = a->values ? a->values[a->i[row]+j]:1.0; 34391f8cafeSFande Kong } 3442b1d8763SJed Brown *v = (*nz) ? a->rowvalues : NULL; 345b97cf49bSBarry Smith } 34692b6f2a0SJed Brown if (idx) *idx = (*nz) ? a->j + a->i[row] : NULL; 3473a40ed3dSBarry Smith PetscFunctionReturn(0); 348b97cf49bSBarry Smith } 349b97cf49bSBarry Smith 35040244768SBarry Smith static PetscErrorCode MatRestoreRow_MPIAdj(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 351b97cf49bSBarry Smith { 352433994e6SBarry Smith PetscFunctionBegin; 3533a40ed3dSBarry Smith PetscFunctionReturn(0); 354b97cf49bSBarry Smith } 355b97cf49bSBarry Smith 35640244768SBarry Smith static PetscErrorCode MatEqual_MPIAdj(Mat A,Mat B,PetscBool * flg) 357b97cf49bSBarry Smith { 3583eda8832SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)A->data,*b = (Mat_MPIAdj*)B->data; 359dfbe8321SBarry Smith PetscErrorCode ierr; 360ace3abfcSBarry Smith PetscBool flag; 361b97cf49bSBarry Smith 362433994e6SBarry Smith PetscFunctionBegin; 363b97cf49bSBarry Smith /* If the matrix dimensions are not equal,or no of nonzeros */ 364d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) ||(a->nz != b->nz)) { 3650f5bd95cSBarry Smith flag = PETSC_FALSE; 366b97cf49bSBarry Smith } 367b97cf49bSBarry Smith 368b97cf49bSBarry Smith /* if the a->i are the same */ 369580bdb30SBarry Smith ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,&flag);CHKERRQ(ierr); 370b97cf49bSBarry Smith 371b97cf49bSBarry Smith /* if a->j are the same */ 372b24ad042SBarry Smith ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),&flag);CHKERRQ(ierr); 373b97cf49bSBarry Smith 374820f2d46SBarry Smith ierr = MPIU_Allreduce(&flag,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 3753a40ed3dSBarry Smith PetscFunctionReturn(0); 376b97cf49bSBarry Smith } 377b97cf49bSBarry Smith 37840244768SBarry Smith static PetscErrorCode MatGetRowIJ_MPIAdj(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt *m,const PetscInt *inia[],const PetscInt *inja[],PetscBool *done) 3796cd91f64SBarry Smith { 380b24ad042SBarry Smith PetscInt i; 3816cd91f64SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)A->data; 3821a83f524SJed Brown PetscInt **ia = (PetscInt**)inia,**ja = (PetscInt**)inja; 3836cd91f64SBarry Smith 3846cd91f64SBarry Smith PetscFunctionBegin; 385d0f46423SBarry Smith *m = A->rmap->n; 3866cd91f64SBarry Smith *ia = a->i; 3876cd91f64SBarry Smith *ja = a->j; 3886cd91f64SBarry Smith *done = PETSC_TRUE; 389d42735a1SBarry Smith if (oshift) { 390d42735a1SBarry Smith for (i=0; i<(*ia)[*m]; i++) { 391d42735a1SBarry Smith (*ja)[i]++; 392d42735a1SBarry Smith } 393d42735a1SBarry Smith for (i=0; i<=(*m); i++) (*ia)[i]++; 394d42735a1SBarry Smith } 395d42735a1SBarry Smith PetscFunctionReturn(0); 396d42735a1SBarry Smith } 397d42735a1SBarry Smith 39840244768SBarry Smith static PetscErrorCode MatRestoreRowIJ_MPIAdj(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt *m,const PetscInt *inia[],const PetscInt *inja[],PetscBool *done) 399d42735a1SBarry Smith { 400b24ad042SBarry Smith PetscInt i; 401d42735a1SBarry Smith Mat_MPIAdj *a = (Mat_MPIAdj*)A->data; 4021a83f524SJed Brown PetscInt **ia = (PetscInt**)inia,**ja = (PetscInt**)inja; 403d42735a1SBarry Smith 404d42735a1SBarry Smith PetscFunctionBegin; 405*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ia && a->i != *ia,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"ia passed back is not one obtained with MatGetRowIJ()"); 406*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ja && a->j != *ja,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"ja passed back is not one obtained with MatGetRowIJ()"); 407d42735a1SBarry Smith if (oshift) { 408*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!ia,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"If oshift then you must passed in inia[] argument"); 409*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!ja,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"If oshift then you must passed in inja[] argument"); 410d42735a1SBarry Smith for (i=0; i<=(*m); i++) (*ia)[i]--; 411d42735a1SBarry Smith for (i=0; i<(*ia)[*m]; i++) { 412d42735a1SBarry Smith (*ja)[i]--; 413d42735a1SBarry Smith } 414d42735a1SBarry Smith } 4156cd91f64SBarry Smith PetscFunctionReturn(0); 4166cd91f64SBarry Smith } 417b97cf49bSBarry Smith 41819fd82e9SBarry Smith PetscErrorCode MatConvertFrom_MPIAdj(Mat A,MatType type,MatReuse reuse,Mat *newmat) 41917667f90SBarry Smith { 42017667f90SBarry Smith Mat B; 42117667f90SBarry Smith PetscErrorCode ierr; 42217667f90SBarry Smith PetscInt i,m,N,nzeros = 0,*ia,*ja,len,rstart,cnt,j,*a; 42317667f90SBarry Smith const PetscInt *rj; 42417667f90SBarry Smith const PetscScalar *ra; 42517667f90SBarry Smith MPI_Comm comm; 42617667f90SBarry Smith 42717667f90SBarry Smith PetscFunctionBegin; 4280298fd71SBarry Smith ierr = MatGetSize(A,NULL,&N);CHKERRQ(ierr); 4290298fd71SBarry Smith ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr); 4300298fd71SBarry Smith ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 43117667f90SBarry Smith 43217667f90SBarry Smith /* count the number of nonzeros per row */ 43317667f90SBarry Smith for (i=0; i<m; i++) { 4340298fd71SBarry Smith ierr = MatGetRow(A,i+rstart,&len,&rj,NULL);CHKERRQ(ierr); 4355ee9ba1cSJed Brown for (j=0; j<len; j++) { 4365ee9ba1cSJed Brown if (rj[j] == i+rstart) {len--; break;} /* don't count diagonal */ 4375ee9ba1cSJed Brown } 43817667f90SBarry Smith nzeros += len; 4390f2063bfSTobin Isaac ierr = MatRestoreRow(A,i+rstart,&len,&rj,NULL);CHKERRQ(ierr); 44017667f90SBarry Smith } 44117667f90SBarry Smith 44217667f90SBarry Smith /* malloc space for nonzeros */ 443854ce69bSBarry Smith ierr = PetscMalloc1(nzeros+1,&a);CHKERRQ(ierr); 444854ce69bSBarry Smith ierr = PetscMalloc1(N+1,&ia);CHKERRQ(ierr); 445854ce69bSBarry Smith ierr = PetscMalloc1(nzeros+1,&ja);CHKERRQ(ierr); 44617667f90SBarry Smith 44717667f90SBarry Smith nzeros = 0; 44817667f90SBarry Smith ia[0] = 0; 44917667f90SBarry Smith for (i=0; i<m; i++) { 45017667f90SBarry Smith ierr = MatGetRow(A,i+rstart,&len,&rj,&ra);CHKERRQ(ierr); 45117667f90SBarry Smith cnt = 0; 45217667f90SBarry Smith for (j=0; j<len; j++) { 4535ee9ba1cSJed Brown if (rj[j] != i+rstart) { /* if not diagonal */ 45417667f90SBarry Smith a[nzeros+cnt] = (PetscInt) PetscAbsScalar(ra[j]); 45517667f90SBarry Smith ja[nzeros+cnt++] = rj[j]; 45617667f90SBarry Smith } 4575ee9ba1cSJed Brown } 45817667f90SBarry Smith ierr = MatRestoreRow(A,i+rstart,&len,&rj,&ra);CHKERRQ(ierr); 45917667f90SBarry Smith nzeros += cnt; 46017667f90SBarry Smith ia[i+1] = nzeros; 46117667f90SBarry Smith } 46217667f90SBarry Smith 46317667f90SBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 46417667f90SBarry Smith ierr = MatCreate(comm,&B);CHKERRQ(ierr); 46558ec18a5SLisandro Dalcin ierr = MatSetSizes(B,m,PETSC_DETERMINE,PETSC_DETERMINE,N);CHKERRQ(ierr); 46617667f90SBarry Smith ierr = MatSetType(B,type);CHKERRQ(ierr); 46717667f90SBarry Smith ierr = MatMPIAdjSetPreallocation(B,ia,ja,a);CHKERRQ(ierr); 46817667f90SBarry Smith 469511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 47028be2f97SBarry Smith ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 47117667f90SBarry Smith } else { 47217667f90SBarry Smith *newmat = B; 47317667f90SBarry Smith } 47417667f90SBarry Smith PetscFunctionReturn(0); 47517667f90SBarry Smith } 47617667f90SBarry Smith 477b97cf49bSBarry Smith /* -------------------------------------------------------------------*/ 478f4259b30SLisandro Dalcin static struct _MatOps MatOps_Values = {NULL, 4793eda8832SBarry Smith MatGetRow_MPIAdj, 4803eda8832SBarry Smith MatRestoreRow_MPIAdj, 481f4259b30SLisandro Dalcin NULL, 482f4259b30SLisandro Dalcin /* 4*/ NULL, 483f4259b30SLisandro Dalcin NULL, 484f4259b30SLisandro Dalcin NULL, 485f4259b30SLisandro Dalcin NULL, 486f4259b30SLisandro Dalcin NULL, 487f4259b30SLisandro Dalcin NULL, 488f4259b30SLisandro Dalcin /*10*/ NULL, 489f4259b30SLisandro Dalcin NULL, 490f4259b30SLisandro Dalcin NULL, 491f4259b30SLisandro Dalcin NULL, 492f4259b30SLisandro Dalcin NULL, 493f4259b30SLisandro Dalcin /*15*/ NULL, 4943eda8832SBarry Smith MatEqual_MPIAdj, 495f4259b30SLisandro Dalcin NULL, 496f4259b30SLisandro Dalcin NULL, 497f4259b30SLisandro Dalcin NULL, 498f4259b30SLisandro Dalcin /*20*/ NULL, 499f4259b30SLisandro Dalcin NULL, 5003eda8832SBarry Smith MatSetOption_MPIAdj, 501f4259b30SLisandro Dalcin NULL, 502f4259b30SLisandro Dalcin /*24*/ NULL, 503f4259b30SLisandro Dalcin NULL, 504f4259b30SLisandro Dalcin NULL, 505f4259b30SLisandro Dalcin NULL, 506f4259b30SLisandro Dalcin NULL, 507f4259b30SLisandro Dalcin /*29*/ NULL, 508f4259b30SLisandro Dalcin NULL, 509f4259b30SLisandro Dalcin NULL, 510f4259b30SLisandro Dalcin NULL, 511f4259b30SLisandro Dalcin NULL, 512f4259b30SLisandro Dalcin /*34*/ NULL, 513f4259b30SLisandro Dalcin NULL, 514f4259b30SLisandro Dalcin NULL, 515f4259b30SLisandro Dalcin NULL, 516f4259b30SLisandro Dalcin NULL, 517f4259b30SLisandro Dalcin /*39*/ NULL, 5187dae84e0SHong Zhang MatCreateSubMatrices_MPIAdj, 519f4259b30SLisandro Dalcin NULL, 520f4259b30SLisandro Dalcin NULL, 521f4259b30SLisandro Dalcin NULL, 522f4259b30SLisandro Dalcin /*44*/ NULL, 523f4259b30SLisandro Dalcin NULL, 5247d68702bSBarry Smith MatShift_Basic, 525f4259b30SLisandro Dalcin NULL, 526f4259b30SLisandro Dalcin NULL, 527f4259b30SLisandro Dalcin /*49*/ NULL, 5286cd91f64SBarry Smith MatGetRowIJ_MPIAdj, 529d42735a1SBarry Smith MatRestoreRowIJ_MPIAdj, 530f4259b30SLisandro Dalcin NULL, 531f4259b30SLisandro Dalcin NULL, 532f4259b30SLisandro Dalcin /*54*/ NULL, 533f4259b30SLisandro Dalcin NULL, 534f4259b30SLisandro Dalcin NULL, 535f4259b30SLisandro Dalcin NULL, 536f4259b30SLisandro Dalcin NULL, 537f4259b30SLisandro Dalcin /*59*/ NULL, 538b9b97703SBarry Smith MatDestroy_MPIAdj, 539b9b97703SBarry Smith MatView_MPIAdj, 54017667f90SBarry Smith MatConvertFrom_MPIAdj, 541f4259b30SLisandro Dalcin NULL, 542f4259b30SLisandro Dalcin /*64*/ NULL, 543f4259b30SLisandro Dalcin NULL, 544f4259b30SLisandro Dalcin NULL, 545f4259b30SLisandro Dalcin NULL, 546f4259b30SLisandro Dalcin NULL, 547f4259b30SLisandro Dalcin /*69*/ NULL, 548f4259b30SLisandro Dalcin NULL, 549f4259b30SLisandro Dalcin NULL, 550f4259b30SLisandro Dalcin NULL, 551f4259b30SLisandro Dalcin NULL, 552f4259b30SLisandro Dalcin /*74*/ NULL, 553f4259b30SLisandro Dalcin NULL, 554f4259b30SLisandro Dalcin NULL, 555f4259b30SLisandro Dalcin NULL, 556f4259b30SLisandro Dalcin NULL, 557f4259b30SLisandro Dalcin /*79*/ NULL, 558f4259b30SLisandro Dalcin NULL, 559f4259b30SLisandro Dalcin NULL, 560f4259b30SLisandro Dalcin NULL, 561f4259b30SLisandro Dalcin NULL, 562f4259b30SLisandro Dalcin /*84*/ NULL, 563f4259b30SLisandro Dalcin NULL, 564f4259b30SLisandro Dalcin NULL, 565f4259b30SLisandro Dalcin NULL, 566f4259b30SLisandro Dalcin NULL, 567f4259b30SLisandro Dalcin /*89*/ NULL, 568f4259b30SLisandro Dalcin NULL, 569f4259b30SLisandro Dalcin NULL, 570f4259b30SLisandro Dalcin NULL, 571f4259b30SLisandro Dalcin NULL, 572f4259b30SLisandro Dalcin /*94*/ NULL, 573f4259b30SLisandro Dalcin NULL, 574f4259b30SLisandro Dalcin NULL, 575f4259b30SLisandro Dalcin NULL, 576f4259b30SLisandro Dalcin NULL, 577f4259b30SLisandro Dalcin /*99*/ NULL, 578f4259b30SLisandro Dalcin NULL, 579f4259b30SLisandro Dalcin NULL, 580f4259b30SLisandro Dalcin NULL, 581f4259b30SLisandro Dalcin NULL, 582f4259b30SLisandro Dalcin /*104*/ NULL, 583f4259b30SLisandro Dalcin NULL, 584f4259b30SLisandro Dalcin NULL, 585f4259b30SLisandro Dalcin NULL, 586f4259b30SLisandro Dalcin NULL, 587f4259b30SLisandro Dalcin /*109*/ NULL, 588f4259b30SLisandro Dalcin NULL, 589f4259b30SLisandro Dalcin NULL, 590f4259b30SLisandro Dalcin NULL, 591f4259b30SLisandro Dalcin NULL, 592f4259b30SLisandro Dalcin /*114*/ NULL, 593f4259b30SLisandro Dalcin NULL, 594f4259b30SLisandro Dalcin NULL, 595f4259b30SLisandro Dalcin NULL, 596f4259b30SLisandro Dalcin NULL, 597f4259b30SLisandro Dalcin /*119*/ NULL, 598f4259b30SLisandro Dalcin NULL, 599f4259b30SLisandro Dalcin NULL, 600f4259b30SLisandro Dalcin NULL, 601f4259b30SLisandro Dalcin NULL, 602f4259b30SLisandro Dalcin /*124*/ NULL, 603f4259b30SLisandro Dalcin NULL, 604f4259b30SLisandro Dalcin NULL, 605f4259b30SLisandro Dalcin NULL, 6067dae84e0SHong Zhang MatCreateSubMatricesMPI_MPIAdj, 607f4259b30SLisandro Dalcin /*129*/ NULL, 608f4259b30SLisandro Dalcin NULL, 609f4259b30SLisandro Dalcin NULL, 610f4259b30SLisandro Dalcin NULL, 611f4259b30SLisandro Dalcin NULL, 612f4259b30SLisandro Dalcin /*134*/ NULL, 613f4259b30SLisandro Dalcin NULL, 614f4259b30SLisandro Dalcin NULL, 615f4259b30SLisandro Dalcin NULL, 616f4259b30SLisandro Dalcin NULL, 617f4259b30SLisandro Dalcin /*139*/ NULL, 618f4259b30SLisandro Dalcin NULL, 619f4259b30SLisandro Dalcin NULL 6203964eb88SJed Brown }; 621b97cf49bSBarry Smith 622f7a08781SBarry Smith static PetscErrorCode MatMPIAdjSetPreallocation_MPIAdj(Mat B,PetscInt *i,PetscInt *j,PetscInt *values) 623a23d5eceSKris Buschelman { 624a23d5eceSKris Buschelman Mat_MPIAdj *b = (Mat_MPIAdj*)B->data; 625e895ccc0SFande Kong PetscBool useedgeweights; 626dfbe8321SBarry Smith PetscErrorCode ierr; 627a23d5eceSKris Buschelman 628a23d5eceSKris Buschelman PetscFunctionBegin; 62926283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 63026283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 631e895ccc0SFande Kong if (values) useedgeweights = PETSC_TRUE; else useedgeweights = PETSC_FALSE; 632e895ccc0SFande Kong /* Make everybody knows if they are using edge weights or not */ 633820f2d46SBarry Smith ierr = MPIU_Allreduce((int*)&useedgeweights,(int*)&b->useedgeweights,1,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)B));CHKERRMPI(ierr); 63458ec18a5SLisandro Dalcin 63576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 63676bd3646SJed Brown PetscInt ii; 63776bd3646SJed Brown 638*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i[0] != 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"First i[] index must be zero, instead it is %" PetscInt_FMT,i[0]); 639d0f46423SBarry Smith for (ii=1; ii<B->rmap->n; ii++) { 640*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i[ii] < 0 || i[ii] < i[ii-1],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i[%" PetscInt_FMT "]=%" PetscInt_FMT " index is out of range: i[%" PetscInt_FMT "]=%" PetscInt_FMT,ii,i[ii],ii-1,i[ii-1]); 641a23d5eceSKris Buschelman } 642d0f46423SBarry Smith for (ii=0; ii<i[B->rmap->n]; ii++) { 643*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j[ii] < 0 || j[ii] >= B->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index %" PetscInt_FMT " out of range %" PetscInt_FMT,ii,j[ii]); 644a23d5eceSKris Buschelman } 64576bd3646SJed Brown } 64658ec18a5SLisandro Dalcin B->preallocated = PETSC_TRUE; 647a23d5eceSKris Buschelman 648a23d5eceSKris Buschelman b->j = j; 649a23d5eceSKris Buschelman b->i = i; 650a23d5eceSKris Buschelman b->values = values; 651a23d5eceSKris Buschelman 652d0f46423SBarry Smith b->nz = i[B->rmap->n]; 653f4259b30SLisandro Dalcin b->diag = NULL; 654a23d5eceSKris Buschelman b->symmetric = PETSC_FALSE; 655a23d5eceSKris Buschelman b->freeaij = PETSC_TRUE; 656a23d5eceSKris Buschelman 657a23d5eceSKris Buschelman ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 658a23d5eceSKris Buschelman ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 659a23d5eceSKris Buschelman PetscFunctionReturn(0); 660a23d5eceSKris Buschelman } 661b97cf49bSBarry Smith 662f7a08781SBarry Smith static PetscErrorCode MatMPIAdjCreateNonemptySubcommMat_MPIAdj(Mat A,Mat *B) 6639a3665c6SJed Brown { 6649a3665c6SJed Brown Mat_MPIAdj *a = (Mat_MPIAdj*)A->data; 6659a3665c6SJed Brown PetscErrorCode ierr; 6669a3665c6SJed Brown const PetscInt *ranges; 6679a3665c6SJed Brown MPI_Comm acomm,bcomm; 6689a3665c6SJed Brown MPI_Group agroup,bgroup; 6699a3665c6SJed Brown PetscMPIInt i,rank,size,nranks,*ranks; 6709a3665c6SJed Brown 6719a3665c6SJed Brown PetscFunctionBegin; 6720298fd71SBarry Smith *B = NULL; 673ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&acomm);CHKERRQ(ierr); 67455b25c41SPierre Jolivet ierr = MPI_Comm_size(acomm,&size);CHKERRMPI(ierr); 67555b25c41SPierre Jolivet ierr = MPI_Comm_size(acomm,&rank);CHKERRMPI(ierr); 6769a3665c6SJed Brown ierr = MatGetOwnershipRanges(A,&ranges);CHKERRQ(ierr); 6779a3665c6SJed Brown for (i=0,nranks=0; i<size; i++) { 6789a3665c6SJed Brown if (ranges[i+1] - ranges[i] > 0) nranks++; 6799a3665c6SJed Brown } 6809a3665c6SJed Brown if (nranks == size) { /* All ranks have a positive number of rows, so we do not need to create a subcomm; */ 6819a3665c6SJed Brown ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 6829a3665c6SJed Brown *B = A; 6839a3665c6SJed Brown PetscFunctionReturn(0); 6849a3665c6SJed Brown } 6859a3665c6SJed Brown 686785e854fSJed Brown ierr = PetscMalloc1(nranks,&ranks);CHKERRQ(ierr); 6879a3665c6SJed Brown for (i=0,nranks=0; i<size; i++) { 6889a3665c6SJed Brown if (ranges[i+1] - ranges[i] > 0) ranks[nranks++] = i; 6899a3665c6SJed Brown } 690ffc4695bSBarry Smith ierr = MPI_Comm_group(acomm,&agroup);CHKERRMPI(ierr); 691ffc4695bSBarry Smith ierr = MPI_Group_incl(agroup,nranks,ranks,&bgroup);CHKERRMPI(ierr); 6929a3665c6SJed Brown ierr = PetscFree(ranks);CHKERRQ(ierr); 693ffc4695bSBarry Smith ierr = MPI_Comm_create(acomm,bgroup,&bcomm);CHKERRMPI(ierr); 694ffc4695bSBarry Smith ierr = MPI_Group_free(&agroup);CHKERRMPI(ierr); 695ffc4695bSBarry Smith ierr = MPI_Group_free(&bgroup);CHKERRMPI(ierr); 6969a3665c6SJed Brown if (bcomm != MPI_COMM_NULL) { 6979a3665c6SJed Brown PetscInt m,N; 6989a3665c6SJed Brown Mat_MPIAdj *b; 6990298fd71SBarry Smith ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr); 7000298fd71SBarry Smith ierr = MatGetSize(A,NULL,&N);CHKERRQ(ierr); 7019a3665c6SJed Brown ierr = MatCreateMPIAdj(bcomm,m,N,a->i,a->j,a->values,B);CHKERRQ(ierr); 7029a3665c6SJed Brown b = (Mat_MPIAdj*)(*B)->data; 7039a3665c6SJed Brown b->freeaij = PETSC_FALSE; 70455b25c41SPierre Jolivet ierr = MPI_Comm_free(&bcomm);CHKERRMPI(ierr); 7059a3665c6SJed Brown } 7069a3665c6SJed Brown PetscFunctionReturn(0); 7079a3665c6SJed Brown } 7089a3665c6SJed Brown 709b44e7856SBarry Smith PetscErrorCode MatMPIAdjToSeq_MPIAdj(Mat A,Mat *B) 710b44e7856SBarry Smith { 711b44e7856SBarry Smith PetscErrorCode ierr; 712b44e7856SBarry Smith PetscInt M,N,*II,*J,NZ,nz,m,nzstart,i; 713b44e7856SBarry Smith PetscInt *Values = NULL; 714b44e7856SBarry Smith Mat_MPIAdj *adj = (Mat_MPIAdj*)A->data; 715b44e7856SBarry Smith PetscMPIInt mnz,mm,*allnz,*allm,size,*dispnz,*dispm; 716b44e7856SBarry Smith 717b44e7856SBarry Smith PetscFunctionBegin; 718ffc4695bSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRMPI(ierr); 719b44e7856SBarry Smith ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 720b44e7856SBarry Smith ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr); 721b44e7856SBarry Smith nz = adj->nz; 722*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(adj->i[m] != nz,PETSC_COMM_SELF,PETSC_ERR_PLIB,"nz %" PetscInt_FMT " not correct i[m] %" PetscInt_FMT,nz,adj->i[m]); 723ffc4695bSBarry Smith ierr = MPI_Allreduce(&nz,&NZ,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 724d4e69552SBarry Smith 725b44e7856SBarry Smith ierr = PetscMPIIntCast(nz,&mnz);CHKERRQ(ierr); 726071fcb05SBarry Smith ierr = PetscMalloc2(size,&allnz,size,&dispnz);CHKERRQ(ierr); 727ffc4695bSBarry Smith ierr = MPI_Allgather(&mnz,1,MPI_INT,allnz,1,MPI_INT,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 728b44e7856SBarry Smith dispnz[0] = 0; for (i=1; i<size; i++) dispnz[i] = dispnz[i-1]+ allnz[i-1]; 729b44e7856SBarry Smith if (adj->values) { 730b44e7856SBarry Smith ierr = PetscMalloc1(NZ,&Values);CHKERRQ(ierr); 731ffc4695bSBarry Smith ierr = MPI_Allgatherv(adj->values,mnz,MPIU_INT,Values,allnz,dispnz,MPIU_INT,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 732b44e7856SBarry Smith } 733b44e7856SBarry Smith ierr = PetscMalloc1(NZ,&J);CHKERRQ(ierr); 734ffc4695bSBarry Smith ierr = MPI_Allgatherv(adj->j,mnz,MPIU_INT,J,allnz,dispnz,MPIU_INT,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 735b44e7856SBarry Smith ierr = PetscFree2(allnz,dispnz);CHKERRQ(ierr); 736ffc4695bSBarry Smith ierr = MPI_Scan(&nz,&nzstart,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 737b44e7856SBarry Smith nzstart -= nz; 738b44e7856SBarry Smith /* shift the i[] values so they will be correct after being received */ 739b44e7856SBarry Smith for (i=0; i<m; i++) adj->i[i] += nzstart; 740b44e7856SBarry Smith ierr = PetscMalloc1(M+1,&II);CHKERRQ(ierr); 741b44e7856SBarry Smith ierr = PetscMPIIntCast(m,&mm);CHKERRQ(ierr); 742b44e7856SBarry Smith ierr = PetscMalloc2(size,&allm,size,&dispm);CHKERRQ(ierr); 743ffc4695bSBarry Smith ierr = MPI_Allgather(&mm,1,MPI_INT,allm,1,MPI_INT,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 744b44e7856SBarry Smith dispm[0] = 0; for (i=1; i<size; i++) dispm[i] = dispm[i-1]+ allm[i-1]; 745ffc4695bSBarry Smith ierr = MPI_Allgatherv(adj->i,mm,MPIU_INT,II,allm,dispm,MPIU_INT,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 746b44e7856SBarry Smith ierr = PetscFree2(allm,dispm);CHKERRQ(ierr); 747b44e7856SBarry Smith II[M] = NZ; 748b44e7856SBarry Smith /* shift the i[] values back */ 749b44e7856SBarry Smith for (i=0; i<m; i++) adj->i[i] -= nzstart; 750b44e7856SBarry Smith ierr = MatCreateMPIAdj(PETSC_COMM_SELF,M,N,II,J,Values,B);CHKERRQ(ierr); 751b44e7856SBarry Smith PetscFunctionReturn(0); 752b44e7856SBarry Smith } 753b44e7856SBarry Smith 7549a3665c6SJed Brown /*@ 7559a3665c6SJed Brown MatMPIAdjCreateNonemptySubcommMat - create the same MPIAdj matrix on a subcommunicator containing only processes owning a positive number of rows 7569a3665c6SJed Brown 7579a3665c6SJed Brown Collective 7589a3665c6SJed Brown 7594165533cSJose E. Roman Input Parameter: 7609a3665c6SJed Brown . A - original MPIAdj matrix 7619a3665c6SJed Brown 7624165533cSJose E. Roman Output Parameter: 7630298fd71SBarry Smith . B - matrix on subcommunicator, NULL on ranks that owned zero rows of A 7649a3665c6SJed Brown 7659a3665c6SJed Brown Level: developer 7669a3665c6SJed Brown 7679a3665c6SJed Brown Note: 7689a3665c6SJed Brown This function is mostly useful for internal use by mesh partitioning packages that require that every process owns at least one row. 7699a3665c6SJed Brown 7709a3665c6SJed Brown The matrix B should be destroyed with MatDestroy(). The arrays are not copied, so B should be destroyed before A is destroyed. 7719a3665c6SJed Brown 7729a3665c6SJed Brown .seealso: MatCreateMPIAdj() 7739a3665c6SJed Brown @*/ 7749a3665c6SJed Brown PetscErrorCode MatMPIAdjCreateNonemptySubcommMat(Mat A,Mat *B) 7759a3665c6SJed Brown { 7769a3665c6SJed Brown PetscErrorCode ierr; 7779a3665c6SJed Brown 7789a3665c6SJed Brown PetscFunctionBegin; 7799a3665c6SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 7809a3665c6SJed Brown ierr = PetscUseMethod(A,"MatMPIAdjCreateNonemptySubcommMat_C",(Mat,Mat*),(A,B));CHKERRQ(ierr); 7819a3665c6SJed Brown PetscFunctionReturn(0); 7829a3665c6SJed Brown } 7839a3665c6SJed Brown 7840bad9183SKris Buschelman /*MC 785fafad747SKris Buschelman MATMPIADJ - MATMPIADJ = "mpiadj" - A matrix type to be used for distributed adjacency matrices, 7860bad9183SKris Buschelman intended for use constructing orderings and partitionings. 7870bad9183SKris Buschelman 7880bad9183SKris Buschelman Level: beginner 7890bad9183SKris Buschelman 7900bad9183SKris Buschelman .seealso: MatCreateMPIAdj 7910bad9183SKris Buschelman M*/ 7920bad9183SKris Buschelman 7938cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAdj(Mat B) 794273d9f13SBarry Smith { 795273d9f13SBarry Smith Mat_MPIAdj *b; 7966849ba73SBarry Smith PetscErrorCode ierr; 797273d9f13SBarry Smith 798273d9f13SBarry Smith PetscFunctionBegin; 799b00a9115SJed Brown ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 800b0a32e0cSBarry Smith B->data = (void*)b; 801273d9f13SBarry Smith ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 802273d9f13SBarry Smith B->assembled = PETSC_FALSE; 803273d9f13SBarry Smith 804bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjSetPreallocation_C",MatMPIAdjSetPreallocation_MPIAdj);CHKERRQ(ierr); 805bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjCreateNonemptySubcommMat_C",MatMPIAdjCreateNonemptySubcommMat_MPIAdj);CHKERRQ(ierr); 806b44e7856SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjToSeq_C",MatMPIAdjToSeq_MPIAdj);CHKERRQ(ierr); 80717667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPIADJ);CHKERRQ(ierr); 808273d9f13SBarry Smith PetscFunctionReturn(0); 809273d9f13SBarry Smith } 810273d9f13SBarry Smith 811a23d5eceSKris Buschelman /*@C 812b44e7856SBarry Smith MatMPIAdjToSeq - Converts an parallel MPIAdj matrix to complete MPIAdj on each process (needed by sequential preconditioners) 813b44e7856SBarry Smith 814d083f849SBarry Smith Logically Collective 815b44e7856SBarry Smith 816b44e7856SBarry Smith Input Parameter: 817b44e7856SBarry Smith . A - the matrix 818b44e7856SBarry Smith 819b44e7856SBarry Smith Output Parameter: 820b44e7856SBarry Smith . B - the same matrix on all processes 821b44e7856SBarry Smith 822b44e7856SBarry Smith Level: intermediate 823b44e7856SBarry Smith 824b44e7856SBarry Smith .seealso: MatCreate(), MatCreateMPIAdj(), MatSetValues() 825b44e7856SBarry Smith @*/ 826b44e7856SBarry Smith PetscErrorCode MatMPIAdjToSeq(Mat A,Mat *B) 827b44e7856SBarry Smith { 828b44e7856SBarry Smith PetscErrorCode ierr; 829b44e7856SBarry Smith 830b44e7856SBarry Smith PetscFunctionBegin; 831b44e7856SBarry Smith ierr = PetscUseMethod(A,"MatMPIAdjToSeq_C",(Mat,Mat*),(A,B));CHKERRQ(ierr); 832b44e7856SBarry Smith PetscFunctionReturn(0); 833b44e7856SBarry Smith } 834b44e7856SBarry Smith 835b44e7856SBarry Smith /*@C 836a23d5eceSKris Buschelman MatMPIAdjSetPreallocation - Sets the array used for storing the matrix elements 837a23d5eceSKris Buschelman 838d083f849SBarry Smith Logically Collective 839a23d5eceSKris Buschelman 840a23d5eceSKris Buschelman Input Parameters: 841a23d5eceSKris Buschelman + A - the matrix 842a23d5eceSKris Buschelman . i - the indices into j for the start of each row 843a23d5eceSKris Buschelman . j - the column indices for each row (sorted for each row). 844a23d5eceSKris Buschelman The indices in i and j start with zero (NOT with one). 845a23d5eceSKris Buschelman - values - [optional] edge weights 846a23d5eceSKris Buschelman 847a23d5eceSKris Buschelman Level: intermediate 848a23d5eceSKris Buschelman 849a23d5eceSKris Buschelman .seealso: MatCreate(), MatCreateMPIAdj(), MatSetValues() 850a23d5eceSKris Buschelman @*/ 8517087cfbeSBarry Smith PetscErrorCode MatMPIAdjSetPreallocation(Mat B,PetscInt *i,PetscInt *j,PetscInt *values) 852273d9f13SBarry Smith { 8534ac538c5SBarry Smith PetscErrorCode ierr; 854273d9f13SBarry Smith 855273d9f13SBarry Smith PetscFunctionBegin; 8564ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAdjSetPreallocation_C",(Mat,PetscInt*,PetscInt*,PetscInt*),(B,i,j,values));CHKERRQ(ierr); 857273d9f13SBarry Smith PetscFunctionReturn(0); 858273d9f13SBarry Smith } 859273d9f13SBarry Smith 860b97cf49bSBarry Smith /*@C 8613eda8832SBarry Smith MatCreateMPIAdj - Creates a sparse matrix representing an adjacency list. 862b97cf49bSBarry Smith The matrix does not have numerical values associated with it, but is 863b97cf49bSBarry Smith intended for ordering (to reduce bandwidth etc) and partitioning. 864b97cf49bSBarry Smith 865d083f849SBarry Smith Collective 866ef5ee4d1SLois Curfman McInnes 867b97cf49bSBarry Smith Input Parameters: 868c2e958feSBarry Smith + comm - MPI communicator 8690752156aSBarry Smith . m - number of local rows 87058ec18a5SLisandro Dalcin . N - number of global columns 871b97cf49bSBarry Smith . i - the indices into j for the start of each row 872329f5518SBarry Smith . j - the column indices for each row (sorted for each row). 873ef5ee4d1SLois Curfman McInnes The indices in i and j start with zero (NOT with one). 874329f5518SBarry Smith - values -[optional] edge weights 875b97cf49bSBarry Smith 876b97cf49bSBarry Smith Output Parameter: 877b97cf49bSBarry Smith . A - the matrix 878b97cf49bSBarry Smith 87915091d37SBarry Smith Level: intermediate 88015091d37SBarry Smith 88195452b02SPatrick Sanan Notes: 88295452b02SPatrick Sanan This matrix object does not support most matrix operations, include 8834bc6d8c0SBarry Smith MatSetValues(). 884c2e958feSBarry Smith You must NOT free the ii, values and jj arrays yourself. PETSc will free them 885ededeb1aSvictorle when the matrix is destroyed; you must allocate them with PetscMalloc(). If you 8861198db28SBarry Smith call from Fortran you need not create the arrays with PetscMalloc(). 887327e1a73SBarry Smith Should not include the matrix diagonals. 888b97cf49bSBarry Smith 889e3f7e1d6Svictorle If you already have a matrix, you can create its adjacency matrix by a call 890ededeb1aSvictorle to MatConvert, specifying a type of MATMPIADJ. 891ededeb1aSvictorle 892ef5ee4d1SLois Curfman McInnes Possible values for MatSetOption() - MAT_STRUCTURALLY_SYMMETRIC 893b97cf49bSBarry Smith 894e3f7e1d6Svictorle .seealso: MatCreate(), MatConvert(), MatGetOrdering() 895b97cf49bSBarry Smith @*/ 8967087cfbeSBarry Smith PetscErrorCode MatCreateMPIAdj(MPI_Comm comm,PetscInt m,PetscInt N,PetscInt *i,PetscInt *j,PetscInt *values,Mat *A) 897b97cf49bSBarry Smith { 898dfbe8321SBarry Smith PetscErrorCode ierr; 899b97cf49bSBarry Smith 900433994e6SBarry Smith PetscFunctionBegin; 901f69a0ea3SMatthew Knepley ierr = MatCreate(comm,A);CHKERRQ(ierr); 90258ec18a5SLisandro Dalcin ierr = MatSetSizes(*A,m,PETSC_DETERMINE,PETSC_DETERMINE,N);CHKERRQ(ierr); 903273d9f13SBarry Smith ierr = MatSetType(*A,MATMPIADJ);CHKERRQ(ierr); 904273d9f13SBarry Smith ierr = MatMPIAdjSetPreallocation(*A,i,j,values);CHKERRQ(ierr); 9053a40ed3dSBarry Smith PetscFunctionReturn(0); 906b97cf49bSBarry Smith } 907