xref: /petsc/src/mat/impls/adj/mpi/mpiadj.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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 
2540244768SBarry Smith   PetscFunctionBegin;
265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)adj,&comm));
275f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLayouts(adj,&rmap,NULL));
285f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(irows,&nlrows_is));
295f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(irows,&irows_indices));
305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nlrows_is,&iremote));
3140244768SBarry Smith   /* construct sf graph*/
3240244768SBarry Smith   nleaves = nlrows_is;
3340244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
3440244768SBarry Smith     owner = -1;
3540244768SBarry Smith     rlocalindex = -1;
365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutFindOwnerIndex(rmap,irows_indices[i],&owner,&rlocalindex));
3740244768SBarry Smith     iremote[i].rank  = owner;
3840244768SBarry Smith     iremote[i].index = rlocalindex;
3940244768SBarry Smith   }
405f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done));
415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc4(nlrows_mat,&ncols_send,nlrows_is,&xadj_recv,nlrows_is+1,&ncols_recv_offsets,nlrows_is,&ncols_recv));
4240244768SBarry Smith   nroots = nlrows_mat;
4340244768SBarry Smith   for (i=0; i<nlrows_mat; i++) {
4440244768SBarry Smith     ncols_send[i] = xadj[i+1]-xadj[i];
4540244768SBarry Smith   }
465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(comm,&sf));
475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER));
485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetType(sf,PETSCSFBASIC));
495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetFromOptions(sf));
505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(sf,MPIU_INT,ncols_send,ncols_recv,MPI_REPLACE));
515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(sf,MPIU_INT,ncols_send,ncols_recv,MPI_REPLACE));
525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(sf,MPIU_INT,xadj,xadj_recv,MPI_REPLACE));
535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(sf,MPIU_INT,xadj,xadj_recv,MPI_REPLACE));
545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sf));
5540244768SBarry Smith   Ncols_recv =0;
5640244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
5740244768SBarry Smith     Ncols_recv             += ncols_recv[i];
5840244768SBarry Smith     ncols_recv_offsets[i+1] = ncols_recv[i]+ncols_recv_offsets[i];
5940244768SBarry Smith   }
6040244768SBarry Smith   Ncols_send = 0;
6140244768SBarry Smith   for (i=0; i<nlrows_mat; i++) {
6240244768SBarry Smith     Ncols_send += ncols_send[i];
6340244768SBarry Smith   }
645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(Ncols_recv,&iremote));
655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(Ncols_recv,&adjncy_recv));
6640244768SBarry Smith   nleaves = Ncols_recv;
6740244768SBarry Smith   Ncols_recv = 0;
6840244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutFindOwner(rmap,irows_indices[i],&owner));
7040244768SBarry Smith     for (j=0; j<ncols_recv[i]; j++) {
7140244768SBarry Smith       iremote[Ncols_recv].rank    = owner;
7240244768SBarry Smith       iremote[Ncols_recv++].index = xadj_recv[i]+j;
7340244768SBarry Smith     }
7440244768SBarry Smith   }
755f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(irows,&irows_indices));
7640244768SBarry Smith   /*if we need to deal with edge weights ???*/
775f80ce2aSJacob Faibussowitsch   if (a->useedgeweights) CHKERRQ(PetscCalloc1(Ncols_recv,&values_recv));
7840244768SBarry Smith   nroots = Ncols_send;
795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(comm,&sf));
805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER));
815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetType(sf,PETSCSFBASIC));
825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetFromOptions(sf));
835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(sf,MPIU_INT,adjncy,adjncy_recv,MPI_REPLACE));
845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(sf,MPIU_INT,adjncy,adjncy_recv,MPI_REPLACE));
85e895ccc0SFande Kong   if (a->useedgeweights) {
865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sf,MPIU_INT,a->values,values_recv,MPI_REPLACE));
875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sf,MPIU_INT,a->values,values_recv,MPI_REPLACE));
8840244768SBarry Smith   }
895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sf));
905f80ce2aSJacob Faibussowitsch   CHKERRQ(MatRestoreRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done));
915f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(icols,&icols_n));
925f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(icols,&icols_indices));
9340244768SBarry Smith   rnclos = 0;
9440244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
9540244768SBarry Smith     for (j=ncols_recv_offsets[i]; j<ncols_recv_offsets[i+1]; j++) {
965f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFindInt(adjncy_recv[j], icols_n, icols_indices, &loc));
9740244768SBarry Smith       if (loc<0) {
9840244768SBarry Smith         adjncy_recv[j] = -1;
99e895ccc0SFande Kong         if (a->useedgeweights) values_recv[j] = -1;
10040244768SBarry Smith         ncols_recv[i]--;
10140244768SBarry Smith       } else {
10240244768SBarry Smith         rnclos++;
10340244768SBarry Smith       }
10440244768SBarry Smith     }
10540244768SBarry Smith   }
1065f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(icols,&icols_indices));
1075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(rnclos,&sadjncy));
1085f80ce2aSJacob Faibussowitsch   if (a->useedgeweights) CHKERRQ(PetscCalloc1(rnclos,&svalues));
1095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(nlrows_is+1,&sxadj));
11040244768SBarry Smith   rnclos = 0;
11140244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
11240244768SBarry Smith     for (j=ncols_recv_offsets[i]; j<ncols_recv_offsets[i+1]; j++) {
11340244768SBarry Smith       if (adjncy_recv[j]<0) continue;
11440244768SBarry Smith       sadjncy[rnclos] = adjncy_recv[j];
115e895ccc0SFande Kong       if (a->useedgeweights) svalues[rnclos] = values_recv[j];
11640244768SBarry Smith       rnclos++;
11740244768SBarry Smith     }
11840244768SBarry Smith   }
11940244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
12040244768SBarry Smith     sxadj[i+1] = sxadj[i]+ncols_recv[i];
12140244768SBarry Smith   }
1225f80ce2aSJacob Faibussowitsch   if (sadj_xadj)  { *sadj_xadj = sxadj;} else    CHKERRQ(PetscFree(sxadj));
1235f80ce2aSJacob Faibussowitsch   if (sadj_adjncy) { *sadj_adjncy = sadjncy;} else CHKERRQ(PetscFree(sadjncy));
12440244768SBarry Smith   if (sadj_values) {
125f4259b30SLisandro Dalcin     if (a->useedgeweights) *sadj_values = svalues; else *sadj_values=NULL;
12640244768SBarry Smith   } else {
1275f80ce2aSJacob Faibussowitsch     if (a->useedgeweights) CHKERRQ(PetscFree(svalues));
12840244768SBarry Smith   }
1295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree4(ncols_send,xadj_recv,ncols_recv_offsets,ncols_recv));
1305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(adjncy_recv));
1315f80ce2aSJacob Faibussowitsch   if (a->useedgeweights) CHKERRQ(PetscFree(values_recv));
13240244768SBarry Smith   PetscFunctionReturn(0);
13340244768SBarry Smith }
13440244768SBarry Smith 
1357dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrices_MPIAdj_Private(Mat mat,PetscInt n,const IS irow[],const IS icol[],PetscBool subcomm,MatReuse scall,Mat *submat[])
13640244768SBarry Smith {
13740244768SBarry Smith   PetscInt           i,irow_n,icol_n,*sxadj,*sadjncy,*svalues;
13840244768SBarry Smith   PetscInt          *indices,nindx,j,k,loc;
13940244768SBarry Smith   PetscMPIInt        issame;
14040244768SBarry Smith   const PetscInt    *irow_indices,*icol_indices;
14140244768SBarry Smith   MPI_Comm           scomm_row,scomm_col,scomm_mat;
14240244768SBarry Smith 
14340244768SBarry Smith   PetscFunctionBegin;
14440244768SBarry Smith   nindx = 0;
14540244768SBarry Smith   /*
14640244768SBarry Smith    * Estimate a maximum number for allocating memory
14740244768SBarry Smith    */
14840244768SBarry Smith   for (i=0; i<n; i++) {
1495f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(irow[i],&irow_n));
1505f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(icol[i],&icol_n));
15140244768SBarry Smith     nindx = nindx>(irow_n+icol_n)? nindx:(irow_n+icol_n);
15240244768SBarry Smith   }
1535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nindx,&indices));
15440244768SBarry Smith   /* construct a submat */
15540244768SBarry Smith   for (i=0; i<n; i++) {
15640244768SBarry Smith     if (subcomm) {
1575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetComm((PetscObject)irow[i],&scomm_row));
1585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetComm((PetscObject)icol[i],&scomm_col));
1595f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_compare(scomm_row,scomm_col,&issame));
1602c71b3e2SJacob 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");
1615f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_compare(scomm_row,PETSC_COMM_SELF,&issame));
1622c71b3e2SJacob 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");
16340244768SBarry Smith     } else {
16440244768SBarry Smith       scomm_row = PETSC_COMM_SELF;
16540244768SBarry Smith     }
16640244768SBarry Smith     /*get sub-matrix data*/
167f4259b30SLisandro Dalcin     sxadj=NULL; sadjncy=NULL; svalues=NULL;
1685f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrix_MPIAdj_data(mat,irow[i],icol[i],&sxadj,&sadjncy,&svalues));
1695f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(irow[i],&irow_n));
1705f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(icol[i],&icol_n));
1715f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(irow[i],&irow_indices));
1725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(indices,irow_indices,irow_n));
1735f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(irow[i],&irow_indices));
1745f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(icol[i],&icol_indices));
1755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(indices+irow_n,icol_indices,icol_n));
1765f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(icol[i],&icol_indices));
17740244768SBarry Smith     nindx = irow_n+icol_n;
1785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortRemoveDupsInt(&nindx,indices));
17940244768SBarry Smith     /* renumber columns */
18040244768SBarry Smith     for (j=0; j<irow_n; j++) {
18140244768SBarry Smith       for (k=sxadj[j]; k<sxadj[j+1]; k++) {
1825f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFindInt(sadjncy[k],nindx,indices,&loc));
1832c71b3e2SJacob Faibussowitsch         PetscCheckFalse(loc<0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"can not find col %" PetscInt_FMT,sadjncy[k]);
18440244768SBarry Smith         sadjncy[k] = loc;
18540244768SBarry Smith       }
18640244768SBarry Smith     }
18740244768SBarry Smith     if (scall==MAT_INITIAL_MATRIX) {
1885f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateMPIAdj(scomm_row,irow_n,icol_n,sxadj,sadjncy,svalues,submat[i]));
18940244768SBarry Smith     } else {
19040244768SBarry Smith        Mat                sadj = *(submat[i]);
19140244768SBarry Smith        Mat_MPIAdj         *sa  = (Mat_MPIAdj*)((sadj)->data);
1925f80ce2aSJacob Faibussowitsch        CHKERRQ(PetscObjectGetComm((PetscObject)sadj,&scomm_mat));
1935f80ce2aSJacob Faibussowitsch        CHKERRMPI(MPI_Comm_compare(scomm_row,scomm_mat,&issame));
1942c71b3e2SJacob Faibussowitsch        PetscCheckFalse(issame != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"submatrix  must have the same comm as the col index set");
1955f80ce2aSJacob Faibussowitsch        CHKERRQ(PetscArraycpy(sa->i,sxadj,irow_n+1));
1965f80ce2aSJacob Faibussowitsch        CHKERRQ(PetscArraycpy(sa->j,sadjncy,sxadj[irow_n]));
1975f80ce2aSJacob Faibussowitsch        if (svalues) CHKERRQ(PetscArraycpy(sa->values,svalues,sxadj[irow_n]));
1985f80ce2aSJacob Faibussowitsch        CHKERRQ(PetscFree(sxadj));
1995f80ce2aSJacob Faibussowitsch        CHKERRQ(PetscFree(sadjncy));
2005f80ce2aSJacob Faibussowitsch        if (svalues) CHKERRQ(PetscFree(svalues));
20140244768SBarry Smith     }
20240244768SBarry Smith   }
2035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(indices));
20440244768SBarry Smith   PetscFunctionReturn(0);
20540244768SBarry Smith }
20640244768SBarry Smith 
2077dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatricesMPI_MPIAdj(Mat mat,PetscInt n, const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
20840244768SBarry Smith {
20940244768SBarry Smith   /*get sub-matrices across a sub communicator */
21040244768SBarry Smith   PetscFunctionBegin;
2115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrices_MPIAdj_Private(mat,n,irow,icol,PETSC_TRUE,scall,submat));
21240244768SBarry Smith   PetscFunctionReturn(0);
21340244768SBarry Smith }
21440244768SBarry Smith 
2157dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrices_MPIAdj(Mat mat,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *submat[])
21640244768SBarry Smith {
21740244768SBarry Smith   PetscFunctionBegin;
21840244768SBarry Smith   /*get sub-matrices based on PETSC_COMM_SELF */
2195f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrices_MPIAdj_Private(mat,n,irow,icol,PETSC_FALSE,scall,submat));
22040244768SBarry Smith   PetscFunctionReturn(0);
22140244768SBarry Smith }
22240244768SBarry Smith 
22340244768SBarry Smith static PetscErrorCode MatView_MPIAdj_ASCII(Mat A,PetscViewer viewer)
224b97cf49bSBarry Smith {
2253eda8832SBarry Smith   Mat_MPIAdj        *a = (Mat_MPIAdj*)A->data;
226d0f46423SBarry Smith   PetscInt          i,j,m = A->rmap->n;
2272dcb1b2aSMatthew Knepley   const char        *name;
228ce1411ecSBarry Smith   PetscViewerFormat format;
229b97cf49bSBarry Smith 
230433994e6SBarry Smith   PetscFunctionBegin;
2315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject)A,&name));
2325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetFormat(viewer,&format));
233fb9695e5SSatish Balay   if (format == PETSC_VIEWER_ASCII_INFO) {
2343a40ed3dSBarry Smith     PetscFunctionReturn(0);
2352c71b3e2SJacob Faibussowitsch   } else PetscCheckFalse(format == PETSC_VIEWER_ASCII_MATLAB,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MATLAB format not supported");
2366c4ed002SBarry Smith   else {
2375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
2385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPushSynchronized(viewer));
239b97cf49bSBarry Smith     for (i=0; i<m; i++) {
2405f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer,"row %" PetscInt_FMT ":",i+A->rmap->rstart));
241b97cf49bSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
2420170919eSFande Kong         if (a->values) {
2435f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer," (%" PetscInt_FMT ", %" PetscInt_FMT ") ",a->j[j], a->values[j]));
2440170919eSFande Kong         } else {
2455f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer," %" PetscInt_FMT " ",a->j[j]));
2460752156aSBarry Smith         }
2470170919eSFande Kong       }
2485f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer,"\n"));
249b97cf49bSBarry Smith     }
2505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
2515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(viewer));
2525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
2537b23a99aSBarry Smith   }
2543a40ed3dSBarry Smith   PetscFunctionReturn(0);
255b97cf49bSBarry Smith }
256b97cf49bSBarry Smith 
25740244768SBarry Smith static PetscErrorCode MatView_MPIAdj(Mat A,PetscViewer viewer)
258b97cf49bSBarry Smith {
259ace3abfcSBarry Smith   PetscBool      iascii;
260b97cf49bSBarry Smith 
261433994e6SBarry Smith   PetscFunctionBegin;
2625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
26332077d6dSBarry Smith   if (iascii) {
2645f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView_MPIAdj_ASCII(A,viewer));
265b97cf49bSBarry Smith   }
2663a40ed3dSBarry Smith   PetscFunctionReturn(0);
267b97cf49bSBarry Smith }
268b97cf49bSBarry Smith 
26940244768SBarry Smith static PetscErrorCode MatDestroy_MPIAdj(Mat mat)
270b97cf49bSBarry Smith {
2713eda8832SBarry Smith   Mat_MPIAdj     *a = (Mat_MPIAdj*)mat->data;
27294d884c6SBarry Smith 
27394d884c6SBarry Smith   PetscFunctionBegin;
274aa482453SBarry Smith #if defined(PETSC_USE_LOG)
275c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)mat,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,mat->rmap->n,mat->cmap->n,a->nz);
276b97cf49bSBarry Smith #endif
2775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->diag));
2780400557aSBarry Smith   if (a->freeaij) {
27914196391SBarry Smith     if (a->freeaijwithfree) {
28014196391SBarry Smith       if (a->i) free(a->i);
28114196391SBarry Smith       if (a->j) free(a->j);
28214196391SBarry Smith     } else {
2835f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(a->i));
2845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(a->j));
2855f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(a->values));
28614196391SBarry Smith     }
2870400557aSBarry Smith   }
2885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->rowvalues));
2895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mat->data));
2905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)mat,NULL));
2915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjSetPreallocation_C",NULL));
2925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjCreateNonemptySubcommMat_C",NULL));
2933a40ed3dSBarry Smith   PetscFunctionReturn(0);
294b97cf49bSBarry Smith }
295b97cf49bSBarry Smith 
29640244768SBarry Smith static PetscErrorCode MatSetOption_MPIAdj(Mat A,MatOption op,PetscBool flg)
297b97cf49bSBarry Smith {
2983eda8832SBarry Smith   Mat_MPIAdj     *a = (Mat_MPIAdj*)A->data;
299b97cf49bSBarry Smith 
300433994e6SBarry Smith   PetscFunctionBegin;
30112c028f9SKris Buschelman   switch (op) {
30277e54ba9SKris Buschelman   case MAT_SYMMETRIC:
30312c028f9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
3049a4540c5SBarry Smith   case MAT_HERMITIAN:
3054e0d8c25SBarry Smith     a->symmetric = flg;
3069a4540c5SBarry Smith     break;
3079a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
3089a4540c5SBarry Smith     break;
30912c028f9SKris Buschelman   default:
3105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(A,"Option %s ignored\n",MatOptions[op]));
31112c028f9SKris Buschelman     break;
312b97cf49bSBarry Smith   }
3133a40ed3dSBarry Smith   PetscFunctionReturn(0);
314b97cf49bSBarry Smith }
315b97cf49bSBarry Smith 
31640244768SBarry Smith static PetscErrorCode MatGetRow_MPIAdj(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
317b97cf49bSBarry Smith {
3183eda8832SBarry Smith   Mat_MPIAdj *a = (Mat_MPIAdj*)A->data;
319b97cf49bSBarry Smith 
320433994e6SBarry Smith   PetscFunctionBegin;
321d0f46423SBarry Smith   row -= A->rmap->rstart;
3222c71b3e2SJacob Faibussowitsch   PetscCheckFalse(row < 0 || row >= A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row out of range");
323b97cf49bSBarry Smith   *nz = a->i[row+1] - a->i[row];
3242b1d8763SJed Brown   if (v) {
3252b1d8763SJed Brown     PetscInt j;
3262b1d8763SJed Brown     if (a->rowvalues_alloc < *nz) {
3275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(a->rowvalues));
3282b1d8763SJed Brown       a->rowvalues_alloc = PetscMax(a->rowvalues_alloc*2, *nz);
3295f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(a->rowvalues_alloc,&a->rowvalues));
330b97cf49bSBarry Smith     }
33191f8cafeSFande Kong     for (j=0; j<*nz; j++) {
33291f8cafeSFande Kong       a->rowvalues[j] = a->values ? a->values[a->i[row]+j]:1.0;
33391f8cafeSFande Kong     }
3342b1d8763SJed Brown     *v = (*nz) ? a->rowvalues : NULL;
335b97cf49bSBarry Smith   }
33692b6f2a0SJed Brown   if (idx) *idx = (*nz) ? a->j + a->i[row] : NULL;
3373a40ed3dSBarry Smith   PetscFunctionReturn(0);
338b97cf49bSBarry Smith }
339b97cf49bSBarry Smith 
34040244768SBarry Smith static PetscErrorCode MatRestoreRow_MPIAdj(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
341b97cf49bSBarry Smith {
342433994e6SBarry Smith   PetscFunctionBegin;
3433a40ed3dSBarry Smith   PetscFunctionReturn(0);
344b97cf49bSBarry Smith }
345b97cf49bSBarry Smith 
34640244768SBarry Smith static PetscErrorCode MatEqual_MPIAdj(Mat A,Mat B,PetscBool * flg)
347b97cf49bSBarry Smith {
3483eda8832SBarry Smith   Mat_MPIAdj     *a = (Mat_MPIAdj*)A->data,*b = (Mat_MPIAdj*)B->data;
349ace3abfcSBarry Smith   PetscBool      flag;
350b97cf49bSBarry Smith 
351433994e6SBarry Smith   PetscFunctionBegin;
352b97cf49bSBarry Smith   /* If the  matrix dimensions are not equal,or no of nonzeros */
353d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) ||(a->nz != b->nz)) {
3540f5bd95cSBarry Smith     flag = PETSC_FALSE;
355b97cf49bSBarry Smith   }
356b97cf49bSBarry Smith 
357b97cf49bSBarry Smith   /* if the a->i are the same */
3585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycmp(a->i,b->i,A->rmap->n+1,&flag));
359b97cf49bSBarry Smith 
360b97cf49bSBarry Smith   /* if a->j are the same */
3615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),&flag));
362b97cf49bSBarry Smith 
3635f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&flag,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
3643a40ed3dSBarry Smith   PetscFunctionReturn(0);
365b97cf49bSBarry Smith }
366b97cf49bSBarry Smith 
36740244768SBarry Smith static PetscErrorCode MatGetRowIJ_MPIAdj(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt *m,const PetscInt *inia[],const PetscInt *inja[],PetscBool  *done)
3686cd91f64SBarry Smith {
369b24ad042SBarry Smith   PetscInt   i;
3706cd91f64SBarry Smith   Mat_MPIAdj *a   = (Mat_MPIAdj*)A->data;
3711a83f524SJed Brown   PetscInt   **ia = (PetscInt**)inia,**ja = (PetscInt**)inja;
3726cd91f64SBarry Smith 
3736cd91f64SBarry Smith   PetscFunctionBegin;
374d0f46423SBarry Smith   *m    = A->rmap->n;
3756cd91f64SBarry Smith   *ia   = a->i;
3766cd91f64SBarry Smith   *ja   = a->j;
3776cd91f64SBarry Smith   *done = PETSC_TRUE;
378d42735a1SBarry Smith   if (oshift) {
379d42735a1SBarry Smith     for (i=0; i<(*ia)[*m]; i++) {
380d42735a1SBarry Smith       (*ja)[i]++;
381d42735a1SBarry Smith     }
382d42735a1SBarry Smith     for (i=0; i<=(*m); i++) (*ia)[i]++;
383d42735a1SBarry Smith   }
384d42735a1SBarry Smith   PetscFunctionReturn(0);
385d42735a1SBarry Smith }
386d42735a1SBarry Smith 
38740244768SBarry Smith static PetscErrorCode MatRestoreRowIJ_MPIAdj(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt *m,const PetscInt *inia[],const PetscInt *inja[],PetscBool  *done)
388d42735a1SBarry Smith {
389b24ad042SBarry Smith   PetscInt   i;
390d42735a1SBarry Smith   Mat_MPIAdj *a   = (Mat_MPIAdj*)A->data;
3911a83f524SJed Brown   PetscInt   **ia = (PetscInt**)inia,**ja = (PetscInt**)inja;
392d42735a1SBarry Smith 
393d42735a1SBarry Smith   PetscFunctionBegin;
3942c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ia && a->i != *ia,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"ia passed back is not one obtained with MatGetRowIJ()");
3952c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ja && a->j != *ja,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"ja passed back is not one obtained with MatGetRowIJ()");
396d42735a1SBarry Smith   if (oshift) {
397*28b400f6SJacob Faibussowitsch     PetscCheck(ia,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"If oshift then you must passed in inia[] argument");
398*28b400f6SJacob Faibussowitsch     PetscCheck(ja,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"If oshift then you must passed in inja[] argument");
399d42735a1SBarry Smith     for (i=0; i<=(*m); i++) (*ia)[i]--;
400d42735a1SBarry Smith     for (i=0; i<(*ia)[*m]; i++) {
401d42735a1SBarry Smith       (*ja)[i]--;
402d42735a1SBarry Smith     }
403d42735a1SBarry Smith   }
4046cd91f64SBarry Smith   PetscFunctionReturn(0);
4056cd91f64SBarry Smith }
406b97cf49bSBarry Smith 
40719fd82e9SBarry Smith PetscErrorCode  MatConvertFrom_MPIAdj(Mat A,MatType type,MatReuse reuse,Mat *newmat)
40817667f90SBarry Smith {
40917667f90SBarry Smith   Mat               B;
41017667f90SBarry Smith   PetscInt          i,m,N,nzeros = 0,*ia,*ja,len,rstart,cnt,j,*a;
41117667f90SBarry Smith   const PetscInt    *rj;
41217667f90SBarry Smith   const PetscScalar *ra;
41317667f90SBarry Smith   MPI_Comm          comm;
41417667f90SBarry Smith 
41517667f90SBarry Smith   PetscFunctionBegin;
4165f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,NULL,&N));
4175f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(A,&m,NULL));
4185f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRange(A,&rstart,NULL));
41917667f90SBarry Smith 
42017667f90SBarry Smith   /* count the number of nonzeros per row */
42117667f90SBarry Smith   for (i=0; i<m; i++) {
4225f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRow(A,i+rstart,&len,&rj,NULL));
4235ee9ba1cSJed Brown     for (j=0; j<len; j++) {
4245ee9ba1cSJed Brown       if (rj[j] == i+rstart) {len--; break;}    /* don't count diagonal */
4255ee9ba1cSJed Brown     }
42617667f90SBarry Smith     nzeros += len;
4275f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRow(A,i+rstart,&len,&rj,NULL));
42817667f90SBarry Smith   }
42917667f90SBarry Smith 
43017667f90SBarry Smith   /* malloc space for nonzeros */
4315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nzeros+1,&a));
4325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(N+1,&ia));
4335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nzeros+1,&ja));
43417667f90SBarry Smith 
43517667f90SBarry Smith   nzeros = 0;
43617667f90SBarry Smith   ia[0]  = 0;
43717667f90SBarry Smith   for (i=0; i<m; i++) {
4385f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRow(A,i+rstart,&len,&rj,&ra));
43917667f90SBarry Smith     cnt  = 0;
44017667f90SBarry Smith     for (j=0; j<len; j++) {
4415ee9ba1cSJed Brown       if (rj[j] != i+rstart) { /* if not diagonal */
44217667f90SBarry Smith         a[nzeros+cnt]    = (PetscInt) PetscAbsScalar(ra[j]);
44317667f90SBarry Smith         ja[nzeros+cnt++] = rj[j];
44417667f90SBarry Smith       }
4455ee9ba1cSJed Brown     }
4465f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRow(A,i+rstart,&len,&rj,&ra));
44717667f90SBarry Smith     nzeros += cnt;
44817667f90SBarry Smith     ia[i+1] = nzeros;
44917667f90SBarry Smith   }
45017667f90SBarry Smith 
4515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)A,&comm));
4525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,&B));
4535f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(B,m,PETSC_DETERMINE,PETSC_DETERMINE,N));
4545f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(B,type));
4555f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAdjSetPreallocation(B,ia,ja,a));
45617667f90SBarry Smith 
457511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
4585f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHeaderReplace(A,&B));
45917667f90SBarry Smith   } else {
46017667f90SBarry Smith     *newmat = B;
46117667f90SBarry Smith   }
46217667f90SBarry Smith   PetscFunctionReturn(0);
46317667f90SBarry Smith }
46417667f90SBarry Smith 
465b97cf49bSBarry Smith /* -------------------------------------------------------------------*/
466f4259b30SLisandro Dalcin static struct _MatOps MatOps_Values = {NULL,
4673eda8832SBarry Smith                                        MatGetRow_MPIAdj,
4683eda8832SBarry Smith                                        MatRestoreRow_MPIAdj,
469f4259b30SLisandro Dalcin                                        NULL,
470f4259b30SLisandro Dalcin                                 /* 4*/ NULL,
471f4259b30SLisandro Dalcin                                        NULL,
472f4259b30SLisandro Dalcin                                        NULL,
473f4259b30SLisandro Dalcin                                        NULL,
474f4259b30SLisandro Dalcin                                        NULL,
475f4259b30SLisandro Dalcin                                        NULL,
476f4259b30SLisandro Dalcin                                 /*10*/ NULL,
477f4259b30SLisandro Dalcin                                        NULL,
478f4259b30SLisandro Dalcin                                        NULL,
479f4259b30SLisandro Dalcin                                        NULL,
480f4259b30SLisandro Dalcin                                        NULL,
481f4259b30SLisandro Dalcin                                 /*15*/ NULL,
4823eda8832SBarry Smith                                        MatEqual_MPIAdj,
483f4259b30SLisandro Dalcin                                        NULL,
484f4259b30SLisandro Dalcin                                        NULL,
485f4259b30SLisandro Dalcin                                        NULL,
486f4259b30SLisandro Dalcin                                 /*20*/ NULL,
487f4259b30SLisandro Dalcin                                        NULL,
4883eda8832SBarry Smith                                        MatSetOption_MPIAdj,
489f4259b30SLisandro Dalcin                                        NULL,
490f4259b30SLisandro Dalcin                                 /*24*/ NULL,
491f4259b30SLisandro Dalcin                                        NULL,
492f4259b30SLisandro Dalcin                                        NULL,
493f4259b30SLisandro Dalcin                                        NULL,
494f4259b30SLisandro Dalcin                                        NULL,
495f4259b30SLisandro Dalcin                                 /*29*/ NULL,
496f4259b30SLisandro Dalcin                                        NULL,
497f4259b30SLisandro Dalcin                                        NULL,
498f4259b30SLisandro Dalcin                                        NULL,
499f4259b30SLisandro Dalcin                                        NULL,
500f4259b30SLisandro Dalcin                                 /*34*/ NULL,
501f4259b30SLisandro Dalcin                                        NULL,
502f4259b30SLisandro Dalcin                                        NULL,
503f4259b30SLisandro Dalcin                                        NULL,
504f4259b30SLisandro Dalcin                                        NULL,
505f4259b30SLisandro Dalcin                                 /*39*/ NULL,
5067dae84e0SHong Zhang                                        MatCreateSubMatrices_MPIAdj,
507f4259b30SLisandro Dalcin                                        NULL,
508f4259b30SLisandro Dalcin                                        NULL,
509f4259b30SLisandro Dalcin                                        NULL,
510f4259b30SLisandro Dalcin                                 /*44*/ NULL,
511f4259b30SLisandro Dalcin                                        NULL,
5127d68702bSBarry Smith                                        MatShift_Basic,
513f4259b30SLisandro Dalcin                                        NULL,
514f4259b30SLisandro Dalcin                                        NULL,
515f4259b30SLisandro Dalcin                                 /*49*/ NULL,
5166cd91f64SBarry Smith                                        MatGetRowIJ_MPIAdj,
517d42735a1SBarry Smith                                        MatRestoreRowIJ_MPIAdj,
518f4259b30SLisandro Dalcin                                        NULL,
519f4259b30SLisandro Dalcin                                        NULL,
520f4259b30SLisandro Dalcin                                 /*54*/ NULL,
521f4259b30SLisandro Dalcin                                        NULL,
522f4259b30SLisandro Dalcin                                        NULL,
523f4259b30SLisandro Dalcin                                        NULL,
524f4259b30SLisandro Dalcin                                        NULL,
525f4259b30SLisandro Dalcin                                 /*59*/ NULL,
526b9b97703SBarry Smith                                        MatDestroy_MPIAdj,
527b9b97703SBarry Smith                                        MatView_MPIAdj,
52817667f90SBarry Smith                                        MatConvertFrom_MPIAdj,
529f4259b30SLisandro Dalcin                                        NULL,
530f4259b30SLisandro Dalcin                                 /*64*/ NULL,
531f4259b30SLisandro Dalcin                                        NULL,
532f4259b30SLisandro Dalcin                                        NULL,
533f4259b30SLisandro Dalcin                                        NULL,
534f4259b30SLisandro Dalcin                                        NULL,
535f4259b30SLisandro Dalcin                                 /*69*/ NULL,
536f4259b30SLisandro Dalcin                                        NULL,
537f4259b30SLisandro Dalcin                                        NULL,
538f4259b30SLisandro Dalcin                                        NULL,
539f4259b30SLisandro Dalcin                                        NULL,
540f4259b30SLisandro Dalcin                                 /*74*/ NULL,
541f4259b30SLisandro Dalcin                                        NULL,
542f4259b30SLisandro Dalcin                                        NULL,
543f4259b30SLisandro Dalcin                                        NULL,
544f4259b30SLisandro Dalcin                                        NULL,
545f4259b30SLisandro Dalcin                                 /*79*/ NULL,
546f4259b30SLisandro Dalcin                                        NULL,
547f4259b30SLisandro Dalcin                                        NULL,
548f4259b30SLisandro Dalcin                                        NULL,
549f4259b30SLisandro Dalcin                                        NULL,
550f4259b30SLisandro Dalcin                                 /*84*/ NULL,
551f4259b30SLisandro Dalcin                                        NULL,
552f4259b30SLisandro Dalcin                                        NULL,
553f4259b30SLisandro Dalcin                                        NULL,
554f4259b30SLisandro Dalcin                                        NULL,
555f4259b30SLisandro Dalcin                                 /*89*/ NULL,
556f4259b30SLisandro Dalcin                                        NULL,
557f4259b30SLisandro Dalcin                                        NULL,
558f4259b30SLisandro Dalcin                                        NULL,
559f4259b30SLisandro Dalcin                                        NULL,
560f4259b30SLisandro Dalcin                                 /*94*/ NULL,
561f4259b30SLisandro Dalcin                                        NULL,
562f4259b30SLisandro Dalcin                                        NULL,
563f4259b30SLisandro Dalcin                                        NULL,
564f4259b30SLisandro Dalcin                                        NULL,
565f4259b30SLisandro Dalcin                                 /*99*/ NULL,
566f4259b30SLisandro Dalcin                                        NULL,
567f4259b30SLisandro Dalcin                                        NULL,
568f4259b30SLisandro Dalcin                                        NULL,
569f4259b30SLisandro Dalcin                                        NULL,
570f4259b30SLisandro Dalcin                                /*104*/ NULL,
571f4259b30SLisandro Dalcin                                        NULL,
572f4259b30SLisandro Dalcin                                        NULL,
573f4259b30SLisandro Dalcin                                        NULL,
574f4259b30SLisandro Dalcin                                        NULL,
575f4259b30SLisandro Dalcin                                /*109*/ NULL,
576f4259b30SLisandro Dalcin                                        NULL,
577f4259b30SLisandro Dalcin                                        NULL,
578f4259b30SLisandro Dalcin                                        NULL,
579f4259b30SLisandro Dalcin                                        NULL,
580f4259b30SLisandro Dalcin                                /*114*/ NULL,
581f4259b30SLisandro Dalcin                                        NULL,
582f4259b30SLisandro Dalcin                                        NULL,
583f4259b30SLisandro Dalcin                                        NULL,
584f4259b30SLisandro Dalcin                                        NULL,
585f4259b30SLisandro Dalcin                                /*119*/ NULL,
586f4259b30SLisandro Dalcin                                        NULL,
587f4259b30SLisandro Dalcin                                        NULL,
588f4259b30SLisandro Dalcin                                        NULL,
589f4259b30SLisandro Dalcin                                        NULL,
590f4259b30SLisandro Dalcin                                /*124*/ NULL,
591f4259b30SLisandro Dalcin                                        NULL,
592f4259b30SLisandro Dalcin                                        NULL,
593f4259b30SLisandro Dalcin                                        NULL,
5947dae84e0SHong Zhang                                        MatCreateSubMatricesMPI_MPIAdj,
595f4259b30SLisandro Dalcin                                /*129*/ NULL,
596f4259b30SLisandro Dalcin                                        NULL,
597f4259b30SLisandro Dalcin                                        NULL,
598f4259b30SLisandro Dalcin                                        NULL,
599f4259b30SLisandro Dalcin                                        NULL,
600f4259b30SLisandro Dalcin                                /*134*/ NULL,
601f4259b30SLisandro Dalcin                                        NULL,
602f4259b30SLisandro Dalcin                                        NULL,
603f4259b30SLisandro Dalcin                                        NULL,
604f4259b30SLisandro Dalcin                                        NULL,
605f4259b30SLisandro Dalcin                                /*139*/ NULL,
606f4259b30SLisandro Dalcin                                        NULL,
607d70f29a3SPierre Jolivet                                        NULL,
608d70f29a3SPierre Jolivet                                        NULL,
609d70f29a3SPierre Jolivet                                        NULL,
610d70f29a3SPierre Jolivet                                 /*144*/NULL,
611d70f29a3SPierre Jolivet                                        NULL,
612d70f29a3SPierre Jolivet                                        NULL,
613f4259b30SLisandro Dalcin                                        NULL
6143964eb88SJed Brown };
615b97cf49bSBarry Smith 
616f7a08781SBarry Smith static PetscErrorCode  MatMPIAdjSetPreallocation_MPIAdj(Mat B,PetscInt *i,PetscInt *j,PetscInt *values)
617a23d5eceSKris Buschelman {
618a23d5eceSKris Buschelman   Mat_MPIAdj     *b = (Mat_MPIAdj*)B->data;
619e895ccc0SFande Kong   PetscBool       useedgeweights;
620a23d5eceSKris Buschelman 
621a23d5eceSKris Buschelman   PetscFunctionBegin;
6225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(B->rmap));
6235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(B->cmap));
624e895ccc0SFande Kong   if (values) useedgeweights = PETSC_TRUE; else useedgeweights = PETSC_FALSE;
625e895ccc0SFande Kong   /* Make everybody knows if they are using edge weights or not */
6265f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce((int*)&useedgeweights,(int*)&b->useedgeweights,1,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)B)));
62758ec18a5SLisandro Dalcin 
62876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
62976bd3646SJed Brown     PetscInt ii;
63076bd3646SJed Brown 
6312c71b3e2SJacob 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]);
632d0f46423SBarry Smith     for (ii=1; ii<B->rmap->n; ii++) {
6332c71b3e2SJacob 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]);
634a23d5eceSKris Buschelman     }
635d0f46423SBarry Smith     for (ii=0; ii<i[B->rmap->n]; ii++) {
6362c71b3e2SJacob 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]);
637a23d5eceSKris Buschelman     }
63876bd3646SJed Brown   }
63958ec18a5SLisandro Dalcin   B->preallocated = PETSC_TRUE;
640a23d5eceSKris Buschelman 
641a23d5eceSKris Buschelman   b->j      = j;
642a23d5eceSKris Buschelman   b->i      = i;
643a23d5eceSKris Buschelman   b->values = values;
644a23d5eceSKris Buschelman 
645d0f46423SBarry Smith   b->nz        = i[B->rmap->n];
646f4259b30SLisandro Dalcin   b->diag      = NULL;
647a23d5eceSKris Buschelman   b->symmetric = PETSC_FALSE;
648a23d5eceSKris Buschelman   b->freeaij   = PETSC_TRUE;
649a23d5eceSKris Buschelman 
6505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
6515f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
652a23d5eceSKris Buschelman   PetscFunctionReturn(0);
653a23d5eceSKris Buschelman }
654b97cf49bSBarry Smith 
655f7a08781SBarry Smith static PetscErrorCode MatMPIAdjCreateNonemptySubcommMat_MPIAdj(Mat A,Mat *B)
6569a3665c6SJed Brown {
6579a3665c6SJed Brown   Mat_MPIAdj     *a = (Mat_MPIAdj*)A->data;
6589a3665c6SJed Brown   const PetscInt *ranges;
6599a3665c6SJed Brown   MPI_Comm       acomm,bcomm;
6609a3665c6SJed Brown   MPI_Group      agroup,bgroup;
6619a3665c6SJed Brown   PetscMPIInt    i,rank,size,nranks,*ranks;
6629a3665c6SJed Brown 
6639a3665c6SJed Brown   PetscFunctionBegin;
6640298fd71SBarry Smith   *B    = NULL;
6655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)A,&acomm));
6665f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(acomm,&size));
6675f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(acomm,&rank));
6685f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRanges(A,&ranges));
6699a3665c6SJed Brown   for (i=0,nranks=0; i<size; i++) {
6709a3665c6SJed Brown     if (ranges[i+1] - ranges[i] > 0) nranks++;
6719a3665c6SJed Brown   }
6729a3665c6SJed Brown   if (nranks == size) {         /* All ranks have a positive number of rows, so we do not need to create a subcomm; */
6735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)A));
6749a3665c6SJed Brown     *B   = A;
6759a3665c6SJed Brown     PetscFunctionReturn(0);
6769a3665c6SJed Brown   }
6779a3665c6SJed Brown 
6785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nranks,&ranks));
6799a3665c6SJed Brown   for (i=0,nranks=0; i<size; i++) {
6809a3665c6SJed Brown     if (ranges[i+1] - ranges[i] > 0) ranks[nranks++] = i;
6819a3665c6SJed Brown   }
6825f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_group(acomm,&agroup));
6835f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Group_incl(agroup,nranks,ranks,&bgroup));
6845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(ranks));
6855f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_create(acomm,bgroup,&bcomm));
6865f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Group_free(&agroup));
6875f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Group_free(&bgroup));
6889a3665c6SJed Brown   if (bcomm != MPI_COMM_NULL) {
6899a3665c6SJed Brown     PetscInt   m,N;
6909a3665c6SJed Brown     Mat_MPIAdj *b;
6915f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalSize(A,&m,NULL));
6925f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(A,NULL,&N));
6935f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateMPIAdj(bcomm,m,N,a->i,a->j,a->values,B));
6949a3665c6SJed Brown     b          = (Mat_MPIAdj*)(*B)->data;
6959a3665c6SJed Brown     b->freeaij = PETSC_FALSE;
6965f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_free(&bcomm));
6979a3665c6SJed Brown   }
6989a3665c6SJed Brown   PetscFunctionReturn(0);
6999a3665c6SJed Brown }
7009a3665c6SJed Brown 
701b44e7856SBarry Smith PetscErrorCode  MatMPIAdjToSeq_MPIAdj(Mat A,Mat *B)
702b44e7856SBarry Smith {
703b44e7856SBarry Smith   PetscInt       M,N,*II,*J,NZ,nz,m,nzstart,i;
704b44e7856SBarry Smith   PetscInt       *Values = NULL;
705b44e7856SBarry Smith   Mat_MPIAdj     *adj = (Mat_MPIAdj*)A->data;
706b44e7856SBarry Smith   PetscMPIInt    mnz,mm,*allnz,*allm,size,*dispnz,*dispm;
707b44e7856SBarry Smith 
708b44e7856SBarry Smith   PetscFunctionBegin;
7095f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
7105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&M,&N));
7115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(A,&m,NULL));
712b44e7856SBarry Smith   nz   = adj->nz;
7132c71b3e2SJacob 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]);
7145f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allreduce(&nz,&NZ,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A)));
715d4e69552SBarry Smith 
7165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMPIIntCast(nz,&mnz));
7175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(size,&allnz,size,&dispnz));
7185f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allgather(&mnz,1,MPI_INT,allnz,1,MPI_INT,PetscObjectComm((PetscObject)A)));
719b44e7856SBarry Smith   dispnz[0] = 0; for (i=1; i<size; i++) dispnz[i] = dispnz[i-1]+ allnz[i-1];
720b44e7856SBarry Smith   if (adj->values) {
7215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(NZ,&Values));
7225f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allgatherv(adj->values,mnz,MPIU_INT,Values,allnz,dispnz,MPIU_INT,PetscObjectComm((PetscObject)A)));
723b44e7856SBarry Smith   }
7245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(NZ,&J));
7255f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allgatherv(adj->j,mnz,MPIU_INT,J,allnz,dispnz,MPIU_INT,PetscObjectComm((PetscObject)A)));
7265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(allnz,dispnz));
7275f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Scan(&nz,&nzstart,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A)));
728b44e7856SBarry Smith   nzstart -= nz;
729b44e7856SBarry Smith   /* shift the i[] values so they will be correct after being received */
730b44e7856SBarry Smith   for (i=0; i<m; i++) adj->i[i] += nzstart;
7315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(M+1,&II));
7325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMPIIntCast(m,&mm));
7335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(size,&allm,size,&dispm));
7345f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allgather(&mm,1,MPI_INT,allm,1,MPI_INT,PetscObjectComm((PetscObject)A)));
735b44e7856SBarry Smith   dispm[0] = 0; for (i=1; i<size; i++) dispm[i] = dispm[i-1]+ allm[i-1];
7365f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allgatherv(adj->i,mm,MPIU_INT,II,allm,dispm,MPIU_INT,PetscObjectComm((PetscObject)A)));
7375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(allm,dispm));
738b44e7856SBarry Smith   II[M] = NZ;
739b44e7856SBarry Smith   /* shift the i[] values back */
740b44e7856SBarry Smith   for (i=0; i<m; i++) adj->i[i] -= nzstart;
7415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateMPIAdj(PETSC_COMM_SELF,M,N,II,J,Values,B));
742b44e7856SBarry Smith   PetscFunctionReturn(0);
743b44e7856SBarry Smith }
744b44e7856SBarry Smith 
7459a3665c6SJed Brown /*@
7469a3665c6SJed Brown    MatMPIAdjCreateNonemptySubcommMat - create the same MPIAdj matrix on a subcommunicator containing only processes owning a positive number of rows
7479a3665c6SJed Brown 
7489a3665c6SJed Brown    Collective
7499a3665c6SJed Brown 
7504165533cSJose E. Roman    Input Parameter:
7519a3665c6SJed Brown .  A - original MPIAdj matrix
7529a3665c6SJed Brown 
7534165533cSJose E. Roman    Output Parameter:
7540298fd71SBarry Smith .  B - matrix on subcommunicator, NULL on ranks that owned zero rows of A
7559a3665c6SJed Brown 
7569a3665c6SJed Brown    Level: developer
7579a3665c6SJed Brown 
7589a3665c6SJed Brown    Note:
7599a3665c6SJed Brown    This function is mostly useful for internal use by mesh partitioning packages that require that every process owns at least one row.
7609a3665c6SJed Brown 
7619a3665c6SJed Brown    The matrix B should be destroyed with MatDestroy(). The arrays are not copied, so B should be destroyed before A is destroyed.
7629a3665c6SJed Brown 
7639a3665c6SJed Brown .seealso: MatCreateMPIAdj()
7649a3665c6SJed Brown @*/
7659a3665c6SJed Brown PetscErrorCode MatMPIAdjCreateNonemptySubcommMat(Mat A,Mat *B)
7669a3665c6SJed Brown {
7679a3665c6SJed Brown   PetscFunctionBegin;
7689a3665c6SJed Brown   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
7695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(A,"MatMPIAdjCreateNonemptySubcommMat_C",(Mat,Mat*),(A,B)));
7709a3665c6SJed Brown   PetscFunctionReturn(0);
7719a3665c6SJed Brown }
7729a3665c6SJed Brown 
7730bad9183SKris Buschelman /*MC
774fafad747SKris Buschelman    MATMPIADJ - MATMPIADJ = "mpiadj" - A matrix type to be used for distributed adjacency matrices,
7750bad9183SKris Buschelman    intended for use constructing orderings and partitionings.
7760bad9183SKris Buschelman 
7770bad9183SKris Buschelman   Level: beginner
7780bad9183SKris Buschelman 
7790bad9183SKris Buschelman .seealso: MatCreateMPIAdj
7800bad9183SKris Buschelman M*/
7810bad9183SKris Buschelman 
7828cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAdj(Mat B)
783273d9f13SBarry Smith {
784273d9f13SBarry Smith   Mat_MPIAdj     *b;
785273d9f13SBarry Smith 
786273d9f13SBarry Smith   PetscFunctionBegin;
7875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(B,&b));
788b0a32e0cSBarry Smith   B->data      = (void*)b;
7895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps)));
790273d9f13SBarry Smith   B->assembled = PETSC_FALSE;
791273d9f13SBarry Smith 
7925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjSetPreallocation_C",MatMPIAdjSetPreallocation_MPIAdj));
7935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjCreateNonemptySubcommMat_C",MatMPIAdjCreateNonemptySubcommMat_MPIAdj));
7945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjToSeq_C",MatMPIAdjToSeq_MPIAdj));
7955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)B,MATMPIADJ));
796273d9f13SBarry Smith   PetscFunctionReturn(0);
797273d9f13SBarry Smith }
798273d9f13SBarry Smith 
799a23d5eceSKris Buschelman /*@C
800b44e7856SBarry Smith    MatMPIAdjToSeq - Converts an parallel MPIAdj matrix to complete MPIAdj on each process (needed by sequential preconditioners)
801b44e7856SBarry Smith 
802d083f849SBarry Smith    Logically Collective
803b44e7856SBarry Smith 
804b44e7856SBarry Smith    Input Parameter:
805b44e7856SBarry Smith .  A - the matrix
806b44e7856SBarry Smith 
807b44e7856SBarry Smith    Output Parameter:
808b44e7856SBarry Smith .  B - the same matrix on all processes
809b44e7856SBarry Smith 
810b44e7856SBarry Smith    Level: intermediate
811b44e7856SBarry Smith 
812b44e7856SBarry Smith .seealso: MatCreate(), MatCreateMPIAdj(), MatSetValues()
813b44e7856SBarry Smith @*/
814b44e7856SBarry Smith PetscErrorCode  MatMPIAdjToSeq(Mat A,Mat *B)
815b44e7856SBarry Smith {
816b44e7856SBarry Smith   PetscFunctionBegin;
8175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(A,"MatMPIAdjToSeq_C",(Mat,Mat*),(A,B)));
818b44e7856SBarry Smith   PetscFunctionReturn(0);
819b44e7856SBarry Smith }
820b44e7856SBarry Smith 
821b44e7856SBarry Smith /*@C
822a23d5eceSKris Buschelman    MatMPIAdjSetPreallocation - Sets the array used for storing the matrix elements
823a23d5eceSKris Buschelman 
824d083f849SBarry Smith    Logically Collective
825a23d5eceSKris Buschelman 
826a23d5eceSKris Buschelman    Input Parameters:
827a23d5eceSKris Buschelman +  A - the matrix
828a23d5eceSKris Buschelman .  i - the indices into j for the start of each row
829a23d5eceSKris Buschelman .  j - the column indices for each row (sorted for each row).
830a23d5eceSKris Buschelman        The indices in i and j start with zero (NOT with one).
831a23d5eceSKris Buschelman -  values - [optional] edge weights
832a23d5eceSKris Buschelman 
833a23d5eceSKris Buschelman    Level: intermediate
834a23d5eceSKris Buschelman 
835a23d5eceSKris Buschelman .seealso: MatCreate(), MatCreateMPIAdj(), MatSetValues()
836a23d5eceSKris Buschelman @*/
8377087cfbeSBarry Smith PetscErrorCode  MatMPIAdjSetPreallocation(Mat B,PetscInt *i,PetscInt *j,PetscInt *values)
838273d9f13SBarry Smith {
839273d9f13SBarry Smith   PetscFunctionBegin;
8405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(B,"MatMPIAdjSetPreallocation_C",(Mat,PetscInt*,PetscInt*,PetscInt*),(B,i,j,values)));
841273d9f13SBarry Smith   PetscFunctionReturn(0);
842273d9f13SBarry Smith }
843273d9f13SBarry Smith 
844b97cf49bSBarry Smith /*@C
8453eda8832SBarry Smith    MatCreateMPIAdj - Creates a sparse matrix representing an adjacency list.
846b97cf49bSBarry Smith    The matrix does not have numerical values associated with it, but is
847b97cf49bSBarry Smith    intended for ordering (to reduce bandwidth etc) and partitioning.
848b97cf49bSBarry Smith 
849d083f849SBarry Smith    Collective
850ef5ee4d1SLois Curfman McInnes 
851b97cf49bSBarry Smith    Input Parameters:
852c2e958feSBarry Smith +  comm - MPI communicator
8530752156aSBarry Smith .  m - number of local rows
85458ec18a5SLisandro Dalcin .  N - number of global columns
855b97cf49bSBarry Smith .  i - the indices into j for the start of each row
856329f5518SBarry Smith .  j - the column indices for each row (sorted for each row).
857ef5ee4d1SLois Curfman McInnes        The indices in i and j start with zero (NOT with one).
858329f5518SBarry Smith -  values -[optional] edge weights
859b97cf49bSBarry Smith 
860b97cf49bSBarry Smith    Output Parameter:
861b97cf49bSBarry Smith .  A - the matrix
862b97cf49bSBarry Smith 
86315091d37SBarry Smith    Level: intermediate
86415091d37SBarry Smith 
86595452b02SPatrick Sanan    Notes:
86695452b02SPatrick Sanan     This matrix object does not support most matrix operations, include
8674bc6d8c0SBarry Smith    MatSetValues().
868c2e958feSBarry Smith    You must NOT free the ii, values and jj arrays yourself. PETSc will free them
869ededeb1aSvictorle    when the matrix is destroyed; you must allocate them with PetscMalloc(). If you
8701198db28SBarry Smith     call from Fortran you need not create the arrays with PetscMalloc().
871327e1a73SBarry Smith    Should not include the matrix diagonals.
872b97cf49bSBarry Smith 
873e3f7e1d6Svictorle    If you already have a matrix, you can create its adjacency matrix by a call
874ededeb1aSvictorle    to MatConvert, specifying a type of MATMPIADJ.
875ededeb1aSvictorle 
876ef5ee4d1SLois Curfman McInnes    Possible values for MatSetOption() - MAT_STRUCTURALLY_SYMMETRIC
877b97cf49bSBarry Smith 
878e3f7e1d6Svictorle .seealso: MatCreate(), MatConvert(), MatGetOrdering()
879b97cf49bSBarry Smith @*/
8807087cfbeSBarry Smith PetscErrorCode  MatCreateMPIAdj(MPI_Comm comm,PetscInt m,PetscInt N,PetscInt *i,PetscInt *j,PetscInt *values,Mat *A)
881b97cf49bSBarry Smith {
882433994e6SBarry Smith   PetscFunctionBegin;
8835f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,A));
8845f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*A,m,PETSC_DETERMINE,PETSC_DETERMINE,N));
8855f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*A,MATMPIADJ));
8865f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAdjSetPreallocation(*A,i,j,values));
8873a40ed3dSBarry Smith   PetscFunctionReturn(0);
888b97cf49bSBarry Smith }
889