xref: /petsc/src/mat/impls/adj/mpi/mpiadj.c (revision 6a09307c880f3cf726d2c2fd1cfca70c4fcbcfe1)
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;
269566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)adj,&comm));
279566063dSJacob Faibussowitsch   PetscCall(MatGetLayouts(adj,&rmap,NULL));
289566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(irows,&nlrows_is));
299566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(irows,&irows_indices));
309566063dSJacob Faibussowitsch   PetscCall(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;
369566063dSJacob Faibussowitsch     PetscCall(PetscLayoutFindOwnerIndex(rmap,irows_indices[i],&owner,&rlocalindex));
3740244768SBarry Smith     iremote[i].rank  = owner;
3840244768SBarry Smith     iremote[i].index = rlocalindex;
3940244768SBarry Smith   }
409566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done));
419566063dSJacob Faibussowitsch   PetscCall(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   }
469566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm,&sf));
479566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER));
489566063dSJacob Faibussowitsch   PetscCall(PetscSFSetType(sf,PETSCSFBASIC));
499566063dSJacob Faibussowitsch   PetscCall(PetscSFSetFromOptions(sf));
509566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf,MPIU_INT,ncols_send,ncols_recv,MPI_REPLACE));
519566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf,MPIU_INT,ncols_send,ncols_recv,MPI_REPLACE));
529566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf,MPIU_INT,xadj,xadj_recv,MPI_REPLACE));
539566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf,MPIU_INT,xadj,xadj_recv,MPI_REPLACE));
549566063dSJacob Faibussowitsch   PetscCall(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   }
649566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Ncols_recv,&iremote));
659566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Ncols_recv,&adjncy_recv));
6640244768SBarry Smith   nleaves = Ncols_recv;
6740244768SBarry Smith   Ncols_recv = 0;
6840244768SBarry Smith   for (i=0; i<nlrows_is; i++) {
699566063dSJacob Faibussowitsch     PetscCall(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   }
759566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(irows,&irows_indices));
7640244768SBarry Smith   /*if we need to deal with edge weights ???*/
779566063dSJacob Faibussowitsch   if (a->useedgeweights) PetscCall(PetscCalloc1(Ncols_recv,&values_recv));
7840244768SBarry Smith   nroots = Ncols_send;
799566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm,&sf));
809566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER));
819566063dSJacob Faibussowitsch   PetscCall(PetscSFSetType(sf,PETSCSFBASIC));
829566063dSJacob Faibussowitsch   PetscCall(PetscSFSetFromOptions(sf));
839566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(sf,MPIU_INT,adjncy,adjncy_recv,MPI_REPLACE));
849566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(sf,MPIU_INT,adjncy,adjncy_recv,MPI_REPLACE));
85e895ccc0SFande Kong   if (a->useedgeweights) {
869566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf,MPIU_INT,a->values,values_recv,MPI_REPLACE));
879566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf,MPIU_INT,a->values,values_recv,MPI_REPLACE));
8840244768SBarry Smith   }
899566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sf));
909566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done));
919566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(icols,&icols_n));
929566063dSJacob Faibussowitsch   PetscCall(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++) {
969566063dSJacob Faibussowitsch       PetscCall(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   }
1069566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(icols,&icols_indices));
1079566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(rnclos,&sadjncy));
1089566063dSJacob Faibussowitsch   if (a->useedgeweights) PetscCall(PetscCalloc1(rnclos,&svalues));
1099566063dSJacob Faibussowitsch   PetscCall(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   }
1229566063dSJacob Faibussowitsch   if (sadj_xadj)  { *sadj_xadj = sxadj;} else    PetscCall(PetscFree(sxadj));
1239566063dSJacob Faibussowitsch   if (sadj_adjncy) { *sadj_adjncy = sadjncy;} else PetscCall(PetscFree(sadjncy));
12440244768SBarry Smith   if (sadj_values) {
125f4259b30SLisandro Dalcin     if (a->useedgeweights) *sadj_values = svalues; else *sadj_values=NULL;
12640244768SBarry Smith   } else {
1279566063dSJacob Faibussowitsch     if (a->useedgeweights) PetscCall(PetscFree(svalues));
12840244768SBarry Smith   }
1299566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ncols_send,xadj_recv,ncols_recv_offsets,ncols_recv));
1309566063dSJacob Faibussowitsch   PetscCall(PetscFree(adjncy_recv));
1319566063dSJacob Faibussowitsch   if (a->useedgeweights) PetscCall(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++) {
1499566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow[i],&irow_n));
1509566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol[i],&icol_n));
15140244768SBarry Smith     nindx = nindx>(irow_n+icol_n)? nindx:(irow_n+icol_n);
15240244768SBarry Smith   }
1539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nindx,&indices));
15440244768SBarry Smith   /* construct a submat */
15540244768SBarry Smith   for (i=0; i<n; i++) {
15640244768SBarry Smith     if (subcomm) {
1579566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetComm((PetscObject)irow[i],&scomm_row));
1589566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetComm((PetscObject)icol[i],&scomm_col));
1599566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_compare(scomm_row,scomm_col,&issame));
16008401ef6SPierre Jolivet       PetscCheck(issame == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"row index set must have the same comm as the col index set");
1619566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_compare(scomm_row,PETSC_COMM_SELF,&issame));
16208401ef6SPierre Jolivet       PetscCheck(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;
1689566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix_MPIAdj_data(mat,irow[i],icol[i],&sxadj,&sadjncy,&svalues));
1699566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow[i],&irow_n));
1709566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol[i],&icol_n));
1719566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow[i],&irow_indices));
1729566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(indices,irow_indices,irow_n));
1739566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow[i],&irow_indices));
1749566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(icol[i],&icol_indices));
1759566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(indices+irow_n,icol_indices,icol_n));
1769566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(icol[i],&icol_indices));
17740244768SBarry Smith     nindx = irow_n+icol_n;
1789566063dSJacob Faibussowitsch     PetscCall(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++) {
1829566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(sadjncy[k],nindx,indices,&loc));
18308401ef6SPierre Jolivet         PetscCheck(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) {
1889566063dSJacob Faibussowitsch       PetscCall(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);
1929566063dSJacob Faibussowitsch        PetscCall(PetscObjectGetComm((PetscObject)sadj,&scomm_mat));
1939566063dSJacob Faibussowitsch        PetscCallMPI(MPI_Comm_compare(scomm_row,scomm_mat,&issame));
19408401ef6SPierre Jolivet        PetscCheck(issame == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"submatrix  must have the same comm as the col index set");
1959566063dSJacob Faibussowitsch        PetscCall(PetscArraycpy(sa->i,sxadj,irow_n+1));
1969566063dSJacob Faibussowitsch        PetscCall(PetscArraycpy(sa->j,sadjncy,sxadj[irow_n]));
1979566063dSJacob Faibussowitsch        if (svalues) PetscCall(PetscArraycpy(sa->values,svalues,sxadj[irow_n]));
1989566063dSJacob Faibussowitsch        PetscCall(PetscFree(sxadj));
1999566063dSJacob Faibussowitsch        PetscCall(PetscFree(sadjncy));
2009566063dSJacob Faibussowitsch        if (svalues) PetscCall(PetscFree(svalues));
20140244768SBarry Smith     }
20240244768SBarry Smith   }
2039566063dSJacob Faibussowitsch   PetscCall(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;
2119566063dSJacob Faibussowitsch   PetscCall(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 */
2199566063dSJacob Faibussowitsch   PetscCall(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;
2319566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)A,&name));
2329566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer,&format));
233fb9695e5SSatish Balay   if (format == PETSC_VIEWER_ASCII_INFO) {
2343a40ed3dSBarry Smith     PetscFunctionReturn(0);
235f7d195e4SLawrence Mitchell   } else {
236f7d195e4SLawrence Mitchell     PetscCheck(format != PETSC_VIEWER_ASCII_MATLAB,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MATLAB format not supported");
2379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
2389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
239b97cf49bSBarry Smith     for (i=0; i<m; i++) {
2409566063dSJacob Faibussowitsch       PetscCall(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) {
2439566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer," (%" PetscInt_FMT ", %" PetscInt_FMT ") ",a->j[j], a->values[j]));
2440170919eSFande Kong         } else {
2459566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer," %" PetscInt_FMT " ",a->j[j]));
2460752156aSBarry Smith         }
2470170919eSFande Kong       }
2489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer,"\n"));
249b97cf49bSBarry Smith     }
2509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
2519566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
2529566063dSJacob Faibussowitsch     PetscCall(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;
2629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
2631baa6e33SBarry Smith   if (iascii) PetscCall(MatView_MPIAdj_ASCII(A,viewer));
2643a40ed3dSBarry Smith   PetscFunctionReturn(0);
265b97cf49bSBarry Smith }
266b97cf49bSBarry Smith 
26740244768SBarry Smith static PetscErrorCode MatDestroy_MPIAdj(Mat mat)
268b97cf49bSBarry Smith {
2693eda8832SBarry Smith   Mat_MPIAdj     *a = (Mat_MPIAdj*)mat->data;
27094d884c6SBarry Smith 
27194d884c6SBarry Smith   PetscFunctionBegin;
272aa482453SBarry Smith #if defined(PETSC_USE_LOG)
273c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)mat,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,mat->rmap->n,mat->cmap->n,a->nz);
274b97cf49bSBarry Smith #endif
2759566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->diag));
2760400557aSBarry Smith   if (a->freeaij) {
27714196391SBarry Smith     if (a->freeaijwithfree) {
27814196391SBarry Smith       if (a->i) free(a->i);
27914196391SBarry Smith       if (a->j) free(a->j);
28014196391SBarry Smith     } else {
2819566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->i));
2829566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->j));
2839566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->values));
28414196391SBarry Smith     }
2850400557aSBarry Smith   }
2869566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->rowvalues));
2879566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
2889566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat,NULL));
2899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjSetPreallocation_C",NULL));
2909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjCreateNonemptySubcommMat_C",NULL));
2912e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat,"MatMPIAdjToSeq_C",NULL));
2923a40ed3dSBarry Smith   PetscFunctionReturn(0);
293b97cf49bSBarry Smith }
294b97cf49bSBarry Smith 
29540244768SBarry Smith static PetscErrorCode MatSetOption_MPIAdj(Mat A,MatOption op,PetscBool flg)
296b97cf49bSBarry Smith {
2973eda8832SBarry Smith   Mat_MPIAdj     *a = (Mat_MPIAdj*)A->data;
298b97cf49bSBarry Smith 
299433994e6SBarry Smith   PetscFunctionBegin;
30012c028f9SKris Buschelman   switch (op) {
30177e54ba9SKris Buschelman   case MAT_SYMMETRIC:
30212c028f9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
3039a4540c5SBarry Smith   case MAT_HERMITIAN:
3044e0d8c25SBarry Smith     a->symmetric = flg;
3059a4540c5SBarry Smith     break;
3069a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
3079a4540c5SBarry Smith     break;
30812c028f9SKris Buschelman   default:
3099566063dSJacob Faibussowitsch     PetscCall(PetscInfo(A,"Option %s ignored\n",MatOptions[op]));
31012c028f9SKris Buschelman     break;
311b97cf49bSBarry Smith   }
3123a40ed3dSBarry Smith   PetscFunctionReturn(0);
313b97cf49bSBarry Smith }
314b97cf49bSBarry Smith 
31540244768SBarry Smith static PetscErrorCode MatGetRow_MPIAdj(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
316b97cf49bSBarry Smith {
3173eda8832SBarry Smith   Mat_MPIAdj *a = (Mat_MPIAdj*)A->data;
318b97cf49bSBarry Smith 
319433994e6SBarry Smith   PetscFunctionBegin;
320d0f46423SBarry Smith   row -= A->rmap->rstart;
321aed4548fSBarry Smith   PetscCheck(row >= 0 && row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row out of range");
322b97cf49bSBarry Smith   *nz = a->i[row+1] - a->i[row];
3232b1d8763SJed Brown   if (v) {
3242b1d8763SJed Brown     PetscInt j;
3252b1d8763SJed Brown     if (a->rowvalues_alloc < *nz) {
3269566063dSJacob Faibussowitsch       PetscCall(PetscFree(a->rowvalues));
3272b1d8763SJed Brown       a->rowvalues_alloc = PetscMax(a->rowvalues_alloc*2, *nz);
3289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(a->rowvalues_alloc,&a->rowvalues));
329b97cf49bSBarry Smith     }
33091f8cafeSFande Kong     for (j=0; j<*nz; j++) {
33191f8cafeSFande Kong       a->rowvalues[j] = a->values ? a->values[a->i[row]+j]:1.0;
33291f8cafeSFande Kong     }
3332b1d8763SJed Brown     *v = (*nz) ? a->rowvalues : NULL;
334b97cf49bSBarry Smith   }
33592b6f2a0SJed Brown   if (idx) *idx = (*nz) ? a->j + a->i[row] : NULL;
3363a40ed3dSBarry Smith   PetscFunctionReturn(0);
337b97cf49bSBarry Smith }
338b97cf49bSBarry Smith 
33940244768SBarry Smith static PetscErrorCode MatRestoreRow_MPIAdj(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
340b97cf49bSBarry Smith {
341433994e6SBarry Smith   PetscFunctionBegin;
3423a40ed3dSBarry Smith   PetscFunctionReturn(0);
343b97cf49bSBarry Smith }
344b97cf49bSBarry Smith 
34540244768SBarry Smith static PetscErrorCode MatEqual_MPIAdj(Mat A,Mat B,PetscBool * flg)
346b97cf49bSBarry Smith {
3473eda8832SBarry Smith   Mat_MPIAdj     *a = (Mat_MPIAdj*)A->data,*b = (Mat_MPIAdj*)B->data;
348ace3abfcSBarry Smith   PetscBool      flag;
349b97cf49bSBarry Smith 
350433994e6SBarry Smith   PetscFunctionBegin;
351b97cf49bSBarry Smith   /* If the  matrix dimensions are not equal,or no of nonzeros */
352d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) ||(a->nz != b->nz)) {
3530f5bd95cSBarry Smith     flag = PETSC_FALSE;
354b97cf49bSBarry Smith   }
355b97cf49bSBarry Smith 
356b97cf49bSBarry Smith   /* if the a->i are the same */
3579566063dSJacob Faibussowitsch   PetscCall(PetscArraycmp(a->i,b->i,A->rmap->n+1,&flag));
358b97cf49bSBarry Smith 
359b97cf49bSBarry Smith   /* if a->j are the same */
3609566063dSJacob Faibussowitsch   PetscCall(PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),&flag));
361b97cf49bSBarry Smith 
3621c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&flag,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
3633a40ed3dSBarry Smith   PetscFunctionReturn(0);
364b97cf49bSBarry Smith }
365b97cf49bSBarry Smith 
36640244768SBarry Smith static PetscErrorCode MatGetRowIJ_MPIAdj(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt *m,const PetscInt *inia[],const PetscInt *inja[],PetscBool  *done)
3676cd91f64SBarry Smith {
368b24ad042SBarry Smith   PetscInt   i;
3696cd91f64SBarry Smith   Mat_MPIAdj *a   = (Mat_MPIAdj*)A->data;
3701a83f524SJed Brown   PetscInt   **ia = (PetscInt**)inia,**ja = (PetscInt**)inja;
3716cd91f64SBarry Smith 
3726cd91f64SBarry Smith   PetscFunctionBegin;
373d0f46423SBarry Smith   *m    = A->rmap->n;
3746cd91f64SBarry Smith   *ia   = a->i;
3756cd91f64SBarry Smith   *ja   = a->j;
3766cd91f64SBarry Smith   *done = PETSC_TRUE;
377d42735a1SBarry Smith   if (oshift) {
378d42735a1SBarry Smith     for (i=0; i<(*ia)[*m]; i++) {
379d42735a1SBarry Smith       (*ja)[i]++;
380d42735a1SBarry Smith     }
381d42735a1SBarry Smith     for (i=0; i<=(*m); i++) (*ia)[i]++;
382d42735a1SBarry Smith   }
383d42735a1SBarry Smith   PetscFunctionReturn(0);
384d42735a1SBarry Smith }
385d42735a1SBarry Smith 
38640244768SBarry Smith static PetscErrorCode MatRestoreRowIJ_MPIAdj(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool blockcompressed,PetscInt *m,const PetscInt *inia[],const PetscInt *inja[],PetscBool  *done)
387d42735a1SBarry Smith {
388b24ad042SBarry Smith   PetscInt   i;
389d42735a1SBarry Smith   Mat_MPIAdj *a   = (Mat_MPIAdj*)A->data;
3901a83f524SJed Brown   PetscInt   **ia = (PetscInt**)inia,**ja = (PetscInt**)inja;
391d42735a1SBarry Smith 
392d42735a1SBarry Smith   PetscFunctionBegin;
393aed4548fSBarry Smith   PetscCheck(!ia || a->i == *ia,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"ia passed back is not one obtained with MatGetRowIJ()");
394aed4548fSBarry Smith   PetscCheck(!ja || a->j == *ja,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"ja passed back is not one obtained with MatGetRowIJ()");
395d42735a1SBarry Smith   if (oshift) {
39628b400f6SJacob Faibussowitsch     PetscCheck(ia,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"If oshift then you must passed in inia[] argument");
39728b400f6SJacob Faibussowitsch     PetscCheck(ja,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"If oshift then you must passed in inja[] argument");
398d42735a1SBarry Smith     for (i=0; i<=(*m); i++) (*ia)[i]--;
399d42735a1SBarry Smith     for (i=0; i<(*ia)[*m]; i++) {
400d42735a1SBarry Smith       (*ja)[i]--;
401d42735a1SBarry Smith     }
402d42735a1SBarry Smith   }
4036cd91f64SBarry Smith   PetscFunctionReturn(0);
4046cd91f64SBarry Smith }
405b97cf49bSBarry Smith 
40619fd82e9SBarry Smith PetscErrorCode  MatConvertFrom_MPIAdj(Mat A,MatType type,MatReuse reuse,Mat *newmat)
40717667f90SBarry Smith {
40817667f90SBarry Smith   Mat               B;
40917667f90SBarry Smith   PetscInt          i,m,N,nzeros = 0,*ia,*ja,len,rstart,cnt,j,*a;
41017667f90SBarry Smith   const PetscInt    *rj;
41117667f90SBarry Smith   const PetscScalar *ra;
41217667f90SBarry Smith   MPI_Comm          comm;
41317667f90SBarry Smith 
41417667f90SBarry Smith   PetscFunctionBegin;
4159566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,NULL,&N));
4169566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&m,NULL));
4179566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A,&rstart,NULL));
41817667f90SBarry Smith 
41917667f90SBarry Smith   /* count the number of nonzeros per row */
42017667f90SBarry Smith   for (i=0; i<m; i++) {
4219566063dSJacob Faibussowitsch     PetscCall(MatGetRow(A,i+rstart,&len,&rj,NULL));
4225ee9ba1cSJed Brown     for (j=0; j<len; j++) {
4235ee9ba1cSJed Brown       if (rj[j] == i+rstart) {len--; break;}    /* don't count diagonal */
4245ee9ba1cSJed Brown     }
42517667f90SBarry Smith     nzeros += len;
4269566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(A,i+rstart,&len,&rj,NULL));
42717667f90SBarry Smith   }
42817667f90SBarry Smith 
42917667f90SBarry Smith   /* malloc space for nonzeros */
4309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nzeros+1,&a));
4319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N+1,&ia));
4329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nzeros+1,&ja));
43317667f90SBarry Smith 
43417667f90SBarry Smith   nzeros = 0;
43517667f90SBarry Smith   ia[0]  = 0;
43617667f90SBarry Smith   for (i=0; i<m; i++) {
4379566063dSJacob Faibussowitsch     PetscCall(MatGetRow(A,i+rstart,&len,&rj,&ra));
43817667f90SBarry Smith     cnt  = 0;
43917667f90SBarry Smith     for (j=0; j<len; j++) {
4405ee9ba1cSJed Brown       if (rj[j] != i+rstart) { /* if not diagonal */
44117667f90SBarry Smith         a[nzeros+cnt]    = (PetscInt) PetscAbsScalar(ra[j]);
44217667f90SBarry Smith         ja[nzeros+cnt++] = rj[j];
44317667f90SBarry Smith       }
4445ee9ba1cSJed Brown     }
4459566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(A,i+rstart,&len,&rj,&ra));
44617667f90SBarry Smith     nzeros += cnt;
44717667f90SBarry Smith     ia[i+1] = nzeros;
44817667f90SBarry Smith   }
44917667f90SBarry Smith 
4509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
4519566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&B));
4529566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B,m,PETSC_DETERMINE,PETSC_DETERMINE,N));
4539566063dSJacob Faibussowitsch   PetscCall(MatSetType(B,type));
4549566063dSJacob Faibussowitsch   PetscCall(MatMPIAdjSetPreallocation(B,ia,ja,a));
45517667f90SBarry Smith 
456511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
4579566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A,&B));
45817667f90SBarry Smith   } else {
45917667f90SBarry Smith     *newmat = B;
46017667f90SBarry Smith   }
46117667f90SBarry Smith   PetscFunctionReturn(0);
46217667f90SBarry Smith }
46317667f90SBarry Smith 
464*6a09307cSBarry Smith PetscErrorCode MatSetValues_MPIAdj(Mat A,PetscInt m,const PetscInt *rows,PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode im)
465*6a09307cSBarry Smith {
466*6a09307cSBarry Smith   Mat_MPIAdj *adj = (Mat_MPIAdj*)A->data;
467*6a09307cSBarry Smith   PetscInt   rStart, rEnd, cStart, cEnd;
468*6a09307cSBarry Smith 
469*6a09307cSBarry Smith   PetscFunctionBegin;
470*6a09307cSBarry Smith   PetscCheck(!adj->i,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is already assembled, cannot change its values");
471*6a09307cSBarry Smith   PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd));
472*6a09307cSBarry Smith   PetscCall(MatGetOwnershipRangeColumn(A, &cStart, &cEnd));
473*6a09307cSBarry Smith   if (!adj->ht) {
474*6a09307cSBarry Smith     PetscCall(PetscHSetIJCreate(&adj->ht));
475*6a09307cSBarry Smith     PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject) A), 1, &A->stash));
476*6a09307cSBarry Smith     PetscCall(PetscLayoutSetUp(A->rmap));
477*6a09307cSBarry Smith     PetscCall(PetscLayoutSetUp(A->cmap));
478*6a09307cSBarry Smith   }
479*6a09307cSBarry Smith   for (PetscInt r = 0; r < m; ++r) {
480*6a09307cSBarry Smith     PetscHashIJKey key;
481*6a09307cSBarry Smith 
482*6a09307cSBarry Smith     key.i = rows[r];
483*6a09307cSBarry Smith     if (key.i < 0) continue;
484*6a09307cSBarry Smith     if ((key.i < rStart) || (key.i >= rEnd)) {
485*6a09307cSBarry Smith       PetscCall(MatStashValuesRow_Private(&A->stash, key.i, n, cols, values, PETSC_FALSE));
486*6a09307cSBarry Smith     } else {
487*6a09307cSBarry Smith       for (PetscInt c = 0; c < n; ++c) {
488*6a09307cSBarry Smith         key.j = cols[c];
489*6a09307cSBarry Smith         if (key.j < 0 || key.i == key.j) continue;
490*6a09307cSBarry Smith         PetscCall(PetscHSetIJAdd(adj->ht, key));
491*6a09307cSBarry Smith       }
492*6a09307cSBarry Smith     }
493*6a09307cSBarry Smith   }
494*6a09307cSBarry Smith   PetscFunctionReturn(0);
495*6a09307cSBarry Smith }
496*6a09307cSBarry Smith 
497*6a09307cSBarry Smith PetscErrorCode MatAssemblyBegin_MPIAdj(Mat A, MatAssemblyType type)
498*6a09307cSBarry Smith {
499*6a09307cSBarry Smith   PetscInt   nstash, reallocs;
500*6a09307cSBarry Smith   Mat_MPIAdj *adj = (Mat_MPIAdj*)A->data;
501*6a09307cSBarry Smith 
502*6a09307cSBarry Smith   PetscFunctionBegin;
503*6a09307cSBarry Smith   if (!adj->ht) {
504*6a09307cSBarry Smith     PetscCall(PetscHSetIJCreate(&adj->ht));
505*6a09307cSBarry Smith     PetscCall(PetscLayoutSetUp(A->rmap));
506*6a09307cSBarry Smith     PetscCall(PetscLayoutSetUp(A->cmap));
507*6a09307cSBarry Smith   }
508*6a09307cSBarry Smith   PetscCall(MatStashScatterBegin_Private(A, &A->stash, A->rmap->range));
509*6a09307cSBarry Smith   PetscCall(MatStashGetInfo_Private(&A->stash, &nstash, &reallocs));
510*6a09307cSBarry Smith   PetscCall(PetscInfo(A, "Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n", nstash, reallocs));
511*6a09307cSBarry Smith   PetscFunctionReturn(0);
512*6a09307cSBarry Smith }
513*6a09307cSBarry Smith 
514*6a09307cSBarry Smith PetscErrorCode MatAssemblyEnd_MPIAdj(Mat A, MatAssemblyType type)
515*6a09307cSBarry Smith {
516*6a09307cSBarry Smith   PetscScalar    *val;
517*6a09307cSBarry Smith   PetscInt       *row, *col,m,rstart,*rowstarts;
518*6a09307cSBarry Smith   PetscInt       i, j, ncols, flg, nz;
519*6a09307cSBarry Smith   PetscMPIInt    n;
520*6a09307cSBarry Smith   Mat_MPIAdj     *adj = (Mat_MPIAdj*)A->data;
521*6a09307cSBarry Smith   PetscHashIter  hi;
522*6a09307cSBarry Smith   PetscHashIJKey key;
523*6a09307cSBarry Smith   PetscHSetIJ    ht = adj->ht;
524*6a09307cSBarry Smith 
525*6a09307cSBarry Smith   PetscFunctionBegin;
526*6a09307cSBarry Smith   while (1) {
527*6a09307cSBarry Smith     PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
528*6a09307cSBarry Smith      if (!flg) break;
529*6a09307cSBarry Smith 
530*6a09307cSBarry Smith     for (i = 0; i < n;) {
531*6a09307cSBarry Smith       /* Identify the consecutive vals belonging to the same row */
532*6a09307cSBarry Smith       for (j = i, rstart = row[j]; j < n; j++) {
533*6a09307cSBarry Smith         if (row[j] != rstart) break;
534*6a09307cSBarry Smith       }
535*6a09307cSBarry Smith       if (j < n) ncols = j-i;
536*6a09307cSBarry Smith       else       ncols = n-i;
537*6a09307cSBarry Smith       /* Set all these values with a single function call */
538*6a09307cSBarry Smith       PetscCall(MatSetValues_MPIAdj(A, 1, row+i, ncols, col+i, val+i, INSERT_VALUES));
539*6a09307cSBarry Smith       i = j;
540*6a09307cSBarry Smith     }
541*6a09307cSBarry Smith   }
542*6a09307cSBarry Smith   PetscCall(MatStashScatterEnd_Private(&A->stash));
543*6a09307cSBarry Smith   PetscCall(MatStashDestroy_Private(&A->stash));
544*6a09307cSBarry Smith 
545*6a09307cSBarry Smith   PetscCall(MatGetLocalSize(A,&m,NULL));
546*6a09307cSBarry Smith   PetscCall(MatGetOwnershipRange(A,&rstart,NULL));
547*6a09307cSBarry Smith   PetscCall(PetscCalloc1(m+1,&rowstarts));
548*6a09307cSBarry Smith   PetscHashIterBegin(ht,hi);
549*6a09307cSBarry Smith   for (; !PetscHashIterAtEnd(ht,hi);) {
550*6a09307cSBarry Smith     PetscHashIterGetKey(ht,hi,key);
551*6a09307cSBarry Smith     rowstarts[key.i - rstart + 1]++;
552*6a09307cSBarry Smith     PetscHashIterNext(ht,hi);
553*6a09307cSBarry Smith   }
554*6a09307cSBarry Smith   for (i=1; i<m+1; i++) {
555*6a09307cSBarry Smith     rowstarts[i] = rowstarts[i-1] + rowstarts[i];
556*6a09307cSBarry Smith   }
557*6a09307cSBarry Smith 
558*6a09307cSBarry Smith   PetscCall(PetscHSetIJGetSize(ht,&nz));
559*6a09307cSBarry Smith   PetscCall(PetscMalloc1(nz,&col));
560*6a09307cSBarry Smith   PetscHashIterBegin(ht,hi);
561*6a09307cSBarry Smith   for (; !PetscHashIterAtEnd(ht,hi);) {
562*6a09307cSBarry Smith     PetscHashIterGetKey(ht,hi,key);
563*6a09307cSBarry Smith     col[rowstarts[key.i - rstart]++] = key.j;
564*6a09307cSBarry Smith     PetscHashIterNext(ht,hi);
565*6a09307cSBarry Smith   }
566*6a09307cSBarry Smith   PetscCall(PetscHSetIJDestroy(&ht));
567*6a09307cSBarry Smith   for (i=m; i>0; i--) {
568*6a09307cSBarry Smith     rowstarts[i] = rowstarts[i-1];
569*6a09307cSBarry Smith   }
570*6a09307cSBarry Smith   rowstarts[0] = 0;
571*6a09307cSBarry Smith 
572*6a09307cSBarry Smith   for (PetscInt i=0; i<m; i++) {
573*6a09307cSBarry Smith     PetscCall(PetscSortInt(rowstarts[i+1]-rowstarts[i],&col[rowstarts[i]]));
574*6a09307cSBarry Smith   }
575*6a09307cSBarry Smith 
576*6a09307cSBarry Smith   adj->i       = rowstarts;
577*6a09307cSBarry Smith   adj->j       = col;
578*6a09307cSBarry Smith   adj->freeaij = PETSC_TRUE;
579*6a09307cSBarry Smith   PetscFunctionReturn(0);
580*6a09307cSBarry Smith }
581*6a09307cSBarry Smith 
582b97cf49bSBarry Smith /* -------------------------------------------------------------------*/
583*6a09307cSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIAdj,
5843eda8832SBarry Smith                                        MatGetRow_MPIAdj,
5853eda8832SBarry Smith                                        MatRestoreRow_MPIAdj,
586f4259b30SLisandro Dalcin                                        NULL,
587f4259b30SLisandro Dalcin                                 /* 4*/ NULL,
588f4259b30SLisandro Dalcin                                        NULL,
589f4259b30SLisandro Dalcin                                        NULL,
590f4259b30SLisandro Dalcin                                        NULL,
591f4259b30SLisandro Dalcin                                        NULL,
592f4259b30SLisandro Dalcin                                        NULL,
593f4259b30SLisandro Dalcin                                 /*10*/ NULL,
594f4259b30SLisandro Dalcin                                        NULL,
595f4259b30SLisandro Dalcin                                        NULL,
596f4259b30SLisandro Dalcin                                        NULL,
597f4259b30SLisandro Dalcin                                        NULL,
598f4259b30SLisandro Dalcin                                 /*15*/ NULL,
5993eda8832SBarry Smith                                        MatEqual_MPIAdj,
600f4259b30SLisandro Dalcin                                        NULL,
601f4259b30SLisandro Dalcin                                        NULL,
602f4259b30SLisandro Dalcin                                        NULL,
603*6a09307cSBarry Smith                                 /*20*/ MatAssemblyBegin_MPIAdj,
604*6a09307cSBarry Smith                                        MatAssemblyEnd_MPIAdj,
6053eda8832SBarry Smith                                        MatSetOption_MPIAdj,
606f4259b30SLisandro Dalcin                                        NULL,
607f4259b30SLisandro Dalcin                                 /*24*/ NULL,
608f4259b30SLisandro Dalcin                                        NULL,
609f4259b30SLisandro Dalcin                                        NULL,
610f4259b30SLisandro Dalcin                                        NULL,
611f4259b30SLisandro Dalcin                                        NULL,
612f4259b30SLisandro Dalcin                                 /*29*/ NULL,
613f4259b30SLisandro Dalcin                                        NULL,
614f4259b30SLisandro Dalcin                                        NULL,
615f4259b30SLisandro Dalcin                                        NULL,
616f4259b30SLisandro Dalcin                                        NULL,
617f4259b30SLisandro Dalcin                                 /*34*/ NULL,
618f4259b30SLisandro Dalcin                                        NULL,
619f4259b30SLisandro Dalcin                                        NULL,
620f4259b30SLisandro Dalcin                                        NULL,
621f4259b30SLisandro Dalcin                                        NULL,
622f4259b30SLisandro Dalcin                                 /*39*/ NULL,
6237dae84e0SHong Zhang                                        MatCreateSubMatrices_MPIAdj,
624f4259b30SLisandro Dalcin                                        NULL,
625f4259b30SLisandro Dalcin                                        NULL,
626f4259b30SLisandro Dalcin                                        NULL,
627f4259b30SLisandro Dalcin                                 /*44*/ NULL,
628f4259b30SLisandro Dalcin                                        NULL,
6297d68702bSBarry Smith                                        MatShift_Basic,
630f4259b30SLisandro Dalcin                                        NULL,
631f4259b30SLisandro Dalcin                                        NULL,
632f4259b30SLisandro Dalcin                                 /*49*/ NULL,
6336cd91f64SBarry Smith                                        MatGetRowIJ_MPIAdj,
634d42735a1SBarry Smith                                        MatRestoreRowIJ_MPIAdj,
635f4259b30SLisandro Dalcin                                        NULL,
636f4259b30SLisandro Dalcin                                        NULL,
637f4259b30SLisandro Dalcin                                 /*54*/ NULL,
638f4259b30SLisandro Dalcin                                        NULL,
639f4259b30SLisandro Dalcin                                        NULL,
640f4259b30SLisandro Dalcin                                        NULL,
641f4259b30SLisandro Dalcin                                        NULL,
642f4259b30SLisandro Dalcin                                 /*59*/ NULL,
643b9b97703SBarry Smith                                        MatDestroy_MPIAdj,
644b9b97703SBarry Smith                                        MatView_MPIAdj,
64517667f90SBarry Smith                                        MatConvertFrom_MPIAdj,
646f4259b30SLisandro Dalcin                                        NULL,
647f4259b30SLisandro Dalcin                                 /*64*/ NULL,
648f4259b30SLisandro Dalcin                                        NULL,
649f4259b30SLisandro Dalcin                                        NULL,
650f4259b30SLisandro Dalcin                                        NULL,
651f4259b30SLisandro Dalcin                                        NULL,
652f4259b30SLisandro Dalcin                                 /*69*/ NULL,
653f4259b30SLisandro Dalcin                                        NULL,
654f4259b30SLisandro Dalcin                                        NULL,
655f4259b30SLisandro Dalcin                                        NULL,
656f4259b30SLisandro Dalcin                                        NULL,
657f4259b30SLisandro Dalcin                                 /*74*/ NULL,
658f4259b30SLisandro Dalcin                                        NULL,
659f4259b30SLisandro Dalcin                                        NULL,
660f4259b30SLisandro Dalcin                                        NULL,
661f4259b30SLisandro Dalcin                                        NULL,
662f4259b30SLisandro Dalcin                                 /*79*/ NULL,
663f4259b30SLisandro Dalcin                                        NULL,
664f4259b30SLisandro Dalcin                                        NULL,
665f4259b30SLisandro Dalcin                                        NULL,
666f4259b30SLisandro Dalcin                                        NULL,
667f4259b30SLisandro Dalcin                                 /*84*/ NULL,
668f4259b30SLisandro Dalcin                                        NULL,
669f4259b30SLisandro Dalcin                                        NULL,
670f4259b30SLisandro Dalcin                                        NULL,
671f4259b30SLisandro Dalcin                                        NULL,
672f4259b30SLisandro Dalcin                                 /*89*/ NULL,
673f4259b30SLisandro Dalcin                                        NULL,
674f4259b30SLisandro Dalcin                                        NULL,
675f4259b30SLisandro Dalcin                                        NULL,
676f4259b30SLisandro Dalcin                                        NULL,
677f4259b30SLisandro Dalcin                                 /*94*/ NULL,
678f4259b30SLisandro Dalcin                                        NULL,
679f4259b30SLisandro Dalcin                                        NULL,
680f4259b30SLisandro Dalcin                                        NULL,
681f4259b30SLisandro Dalcin                                        NULL,
682f4259b30SLisandro Dalcin                                 /*99*/ NULL,
683f4259b30SLisandro Dalcin                                        NULL,
684f4259b30SLisandro Dalcin                                        NULL,
685f4259b30SLisandro Dalcin                                        NULL,
686f4259b30SLisandro Dalcin                                        NULL,
687f4259b30SLisandro Dalcin                                /*104*/ NULL,
688f4259b30SLisandro Dalcin                                        NULL,
689f4259b30SLisandro Dalcin                                        NULL,
690f4259b30SLisandro Dalcin                                        NULL,
691f4259b30SLisandro Dalcin                                        NULL,
692f4259b30SLisandro Dalcin                                /*109*/ NULL,
693f4259b30SLisandro Dalcin                                        NULL,
694f4259b30SLisandro Dalcin                                        NULL,
695f4259b30SLisandro Dalcin                                        NULL,
696f4259b30SLisandro Dalcin                                        NULL,
697f4259b30SLisandro Dalcin                                /*114*/ NULL,
698f4259b30SLisandro Dalcin                                        NULL,
699f4259b30SLisandro Dalcin                                        NULL,
700f4259b30SLisandro Dalcin                                        NULL,
701f4259b30SLisandro Dalcin                                        NULL,
702f4259b30SLisandro Dalcin                                /*119*/ NULL,
703f4259b30SLisandro Dalcin                                        NULL,
704f4259b30SLisandro Dalcin                                        NULL,
705f4259b30SLisandro Dalcin                                        NULL,
706f4259b30SLisandro Dalcin                                        NULL,
707f4259b30SLisandro Dalcin                                /*124*/ NULL,
708f4259b30SLisandro Dalcin                                        NULL,
709f4259b30SLisandro Dalcin                                        NULL,
710f4259b30SLisandro Dalcin                                        NULL,
7117dae84e0SHong Zhang                                        MatCreateSubMatricesMPI_MPIAdj,
712f4259b30SLisandro Dalcin                                /*129*/ NULL,
713f4259b30SLisandro Dalcin                                        NULL,
714f4259b30SLisandro Dalcin                                        NULL,
715f4259b30SLisandro Dalcin                                        NULL,
716f4259b30SLisandro Dalcin                                        NULL,
717f4259b30SLisandro Dalcin                                /*134*/ NULL,
718f4259b30SLisandro Dalcin                                        NULL,
719f4259b30SLisandro Dalcin                                        NULL,
720f4259b30SLisandro Dalcin                                        NULL,
721f4259b30SLisandro Dalcin                                        NULL,
722f4259b30SLisandro Dalcin                                /*139*/ NULL,
723f4259b30SLisandro Dalcin                                        NULL,
724d70f29a3SPierre Jolivet                                        NULL,
725d70f29a3SPierre Jolivet                                        NULL,
726d70f29a3SPierre Jolivet                                        NULL,
727d70f29a3SPierre Jolivet                                 /*144*/NULL,
728d70f29a3SPierre Jolivet                                        NULL,
729d70f29a3SPierre Jolivet                                        NULL,
73099a7f59eSMark Adams                                        NULL,
73199a7f59eSMark Adams                                        NULL,
732f4259b30SLisandro Dalcin                                        NULL
7333964eb88SJed Brown };
734b97cf49bSBarry Smith 
735f7a08781SBarry Smith static PetscErrorCode  MatMPIAdjSetPreallocation_MPIAdj(Mat B,PetscInt *i,PetscInt *j,PetscInt *values)
736a23d5eceSKris Buschelman {
737a23d5eceSKris Buschelman   Mat_MPIAdj     *b = (Mat_MPIAdj*)B->data;
738e895ccc0SFande Kong   PetscBool       useedgeweights;
739a23d5eceSKris Buschelman 
740a23d5eceSKris Buschelman   PetscFunctionBegin;
7419566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
7429566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
743e895ccc0SFande Kong   if (values) useedgeweights = PETSC_TRUE; else useedgeweights = PETSC_FALSE;
744e895ccc0SFande Kong   /* Make everybody knows if they are using edge weights or not */
7451c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce((int*)&useedgeweights,(int*)&b->useedgeweights,1,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)B)));
74658ec18a5SLisandro Dalcin 
74776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
74876bd3646SJed Brown     PetscInt ii;
74976bd3646SJed Brown 
75008401ef6SPierre Jolivet     PetscCheck(i[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"First i[] index must be zero, instead it is %" PetscInt_FMT,i[0]);
751d0f46423SBarry Smith     for (ii=1; ii<B->rmap->n; ii++) {
752aed4548fSBarry Smith       PetscCheck(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]);
753a23d5eceSKris Buschelman     }
754d0f46423SBarry Smith     for (ii=0; ii<i[B->rmap->n]; ii++) {
755aed4548fSBarry Smith       PetscCheck(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]);
756a23d5eceSKris Buschelman     }
75776bd3646SJed Brown   }
758a23d5eceSKris Buschelman   b->j      = j;
759a23d5eceSKris Buschelman   b->i      = i;
760a23d5eceSKris Buschelman   b->values = values;
761a23d5eceSKris Buschelman 
762d0f46423SBarry Smith   b->nz        = i[B->rmap->n];
763f4259b30SLisandro Dalcin   b->diag      = NULL;
764a23d5eceSKris Buschelman   b->symmetric = PETSC_FALSE;
765a23d5eceSKris Buschelman   b->freeaij   = PETSC_TRUE;
766a23d5eceSKris Buschelman 
767*6a09307cSBarry Smith   B->ops->assemblybegin = NULL;
768*6a09307cSBarry Smith   B->ops->assemblyend   = NULL;
7699566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
7709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
771*6a09307cSBarry Smith   PetscCall(MatStashDestroy_Private(&B->stash));
772a23d5eceSKris Buschelman   PetscFunctionReturn(0);
773a23d5eceSKris Buschelman }
774b97cf49bSBarry Smith 
775f7a08781SBarry Smith static PetscErrorCode MatMPIAdjCreateNonemptySubcommMat_MPIAdj(Mat A,Mat *B)
7769a3665c6SJed Brown {
7779a3665c6SJed Brown   Mat_MPIAdj     *a = (Mat_MPIAdj*)A->data;
7789a3665c6SJed Brown   const PetscInt *ranges;
7799a3665c6SJed Brown   MPI_Comm       acomm,bcomm;
7809a3665c6SJed Brown   MPI_Group      agroup,bgroup;
7819a3665c6SJed Brown   PetscMPIInt    i,rank,size,nranks,*ranks;
7829a3665c6SJed Brown 
7839a3665c6SJed Brown   PetscFunctionBegin;
7840298fd71SBarry Smith   *B    = NULL;
7859566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&acomm));
7869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(acomm,&size));
7879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(acomm,&rank));
7889566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRanges(A,&ranges));
7899a3665c6SJed Brown   for (i=0,nranks=0; i<size; i++) {
7909a3665c6SJed Brown     if (ranges[i+1] - ranges[i] > 0) nranks++;
7919a3665c6SJed Brown   }
7929a3665c6SJed Brown   if (nranks == size) {         /* All ranks have a positive number of rows, so we do not need to create a subcomm; */
7939566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
7949a3665c6SJed Brown     *B   = A;
7959a3665c6SJed Brown     PetscFunctionReturn(0);
7969a3665c6SJed Brown   }
7979a3665c6SJed Brown 
7989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nranks,&ranks));
7999a3665c6SJed Brown   for (i=0,nranks=0; i<size; i++) {
8009a3665c6SJed Brown     if (ranges[i+1] - ranges[i] > 0) ranks[nranks++] = i;
8019a3665c6SJed Brown   }
8029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_group(acomm,&agroup));
8039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Group_incl(agroup,nranks,ranks,&bgroup));
8049566063dSJacob Faibussowitsch   PetscCall(PetscFree(ranks));
8059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_create(acomm,bgroup,&bcomm));
8069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Group_free(&agroup));
8079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Group_free(&bgroup));
8089a3665c6SJed Brown   if (bcomm != MPI_COMM_NULL) {
8099a3665c6SJed Brown     PetscInt   m,N;
8109a3665c6SJed Brown     Mat_MPIAdj *b;
8119566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A,&m,NULL));
8129566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A,NULL,&N));
8139566063dSJacob Faibussowitsch     PetscCall(MatCreateMPIAdj(bcomm,m,N,a->i,a->j,a->values,B));
8149a3665c6SJed Brown     b          = (Mat_MPIAdj*)(*B)->data;
8159a3665c6SJed Brown     b->freeaij = PETSC_FALSE;
8169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_free(&bcomm));
8179a3665c6SJed Brown   }
8189a3665c6SJed Brown   PetscFunctionReturn(0);
8199a3665c6SJed Brown }
8209a3665c6SJed Brown 
821b44e7856SBarry Smith PetscErrorCode  MatMPIAdjToSeq_MPIAdj(Mat A,Mat *B)
822b44e7856SBarry Smith {
823b44e7856SBarry Smith   PetscInt       M,N,*II,*J,NZ,nz,m,nzstart,i;
824b44e7856SBarry Smith   PetscInt       *Values = NULL;
825b44e7856SBarry Smith   Mat_MPIAdj     *adj = (Mat_MPIAdj*)A->data;
826b44e7856SBarry Smith   PetscMPIInt    mnz,mm,*allnz,*allm,size,*dispnz,*dispm;
827b44e7856SBarry Smith 
828b44e7856SBarry Smith   PetscFunctionBegin;
8299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
8309566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,&N));
8319566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&m,NULL));
832b44e7856SBarry Smith   nz   = adj->nz;
83308401ef6SPierre Jolivet   PetscCheck(adj->i[m] == nz,PETSC_COMM_SELF,PETSC_ERR_PLIB,"nz %" PetscInt_FMT " not correct i[m] %" PetscInt_FMT,nz,adj->i[m]);
8349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&nz,&NZ,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A)));
835d4e69552SBarry Smith 
8369566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(nz,&mnz));
8379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size,&allnz,size,&dispnz));
8389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(&mnz,1,MPI_INT,allnz,1,MPI_INT,PetscObjectComm((PetscObject)A)));
839b44e7856SBarry Smith   dispnz[0] = 0; for (i=1; i<size; i++) dispnz[i] = dispnz[i-1]+ allnz[i-1];
840b44e7856SBarry Smith   if (adj->values) {
8419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(NZ,&Values));
8429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allgatherv(adj->values,mnz,MPIU_INT,Values,allnz,dispnz,MPIU_INT,PetscObjectComm((PetscObject)A)));
843b44e7856SBarry Smith   }
8449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NZ,&J));
8459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgatherv(adj->j,mnz,MPIU_INT,J,allnz,dispnz,MPIU_INT,PetscObjectComm((PetscObject)A)));
8469566063dSJacob Faibussowitsch   PetscCall(PetscFree2(allnz,dispnz));
8479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&nz,&nzstart,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A)));
848b44e7856SBarry Smith   nzstart -= nz;
849b44e7856SBarry Smith   /* shift the i[] values so they will be correct after being received */
850b44e7856SBarry Smith   for (i=0; i<m; i++) adj->i[i] += nzstart;
8519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(M+1,&II));
8529566063dSJacob Faibussowitsch   PetscCall(PetscMPIIntCast(m,&mm));
8539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size,&allm,size,&dispm));
8549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(&mm,1,MPI_INT,allm,1,MPI_INT,PetscObjectComm((PetscObject)A)));
855b44e7856SBarry Smith   dispm[0] = 0; for (i=1; i<size; i++) dispm[i] = dispm[i-1]+ allm[i-1];
8569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgatherv(adj->i,mm,MPIU_INT,II,allm,dispm,MPIU_INT,PetscObjectComm((PetscObject)A)));
8579566063dSJacob Faibussowitsch   PetscCall(PetscFree2(allm,dispm));
858b44e7856SBarry Smith   II[M] = NZ;
859b44e7856SBarry Smith   /* shift the i[] values back */
860b44e7856SBarry Smith   for (i=0; i<m; i++) adj->i[i] -= nzstart;
8619566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIAdj(PETSC_COMM_SELF,M,N,II,J,Values,B));
862b44e7856SBarry Smith   PetscFunctionReturn(0);
863b44e7856SBarry Smith }
864b44e7856SBarry Smith 
8659a3665c6SJed Brown /*@
8669a3665c6SJed Brown    MatMPIAdjCreateNonemptySubcommMat - create the same MPIAdj matrix on a subcommunicator containing only processes owning a positive number of rows
8679a3665c6SJed Brown 
8689a3665c6SJed Brown    Collective
8699a3665c6SJed Brown 
8704165533cSJose E. Roman    Input Parameter:
8719a3665c6SJed Brown .  A - original MPIAdj matrix
8729a3665c6SJed Brown 
8734165533cSJose E. Roman    Output Parameter:
8740298fd71SBarry Smith .  B - matrix on subcommunicator, NULL on ranks that owned zero rows of A
8759a3665c6SJed Brown 
8769a3665c6SJed Brown    Level: developer
8779a3665c6SJed Brown 
8789a3665c6SJed Brown    Note:
8799a3665c6SJed Brown    This function is mostly useful for internal use by mesh partitioning packages that require that every process owns at least one row.
8809a3665c6SJed Brown 
8819a3665c6SJed Brown    The matrix B should be destroyed with MatDestroy(). The arrays are not copied, so B should be destroyed before A is destroyed.
8829a3665c6SJed Brown 
883db781477SPatrick Sanan .seealso: `MatCreateMPIAdj()`
8849a3665c6SJed Brown @*/
8859a3665c6SJed Brown PetscErrorCode MatMPIAdjCreateNonemptySubcommMat(Mat A,Mat *B)
8869a3665c6SJed Brown {
8879a3665c6SJed Brown   PetscFunctionBegin;
8889a3665c6SJed Brown   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
889cac4c232SBarry Smith   PetscUseMethod(A,"MatMPIAdjCreateNonemptySubcommMat_C",(Mat,Mat*),(A,B));
8909a3665c6SJed Brown   PetscFunctionReturn(0);
8919a3665c6SJed Brown }
8929a3665c6SJed Brown 
8930bad9183SKris Buschelman /*MC
894fafad747SKris Buschelman    MATMPIADJ - MATMPIADJ = "mpiadj" - A matrix type to be used for distributed adjacency matrices,
8950bad9183SKris Buschelman    intended for use constructing orderings and partitionings.
8960bad9183SKris Buschelman 
8970bad9183SKris Buschelman   Level: beginner
8980bad9183SKris Buschelman 
899*6a09307cSBarry Smith   Notes:
900*6a09307cSBarry Smith     You can provide values to the matrix using MatMPIAdjSetPreallocation(), MatCreateMPIAdj(), or
901*6a09307cSBarry Smith     by calling MatSetValues() and MatAssemblyBegin() followed by MatAssemblyEnd()
902*6a09307cSBarry Smith 
903*6a09307cSBarry Smith .seealso: `MatCreateMPIAdj()`, `MatMPIAdjSetPreallocation()`, `MatSetValues()`
9040bad9183SKris Buschelman M*/
9050bad9183SKris Buschelman 
9068cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAdj(Mat B)
907273d9f13SBarry Smith {
908273d9f13SBarry Smith   Mat_MPIAdj     *b;
909273d9f13SBarry Smith 
910273d9f13SBarry Smith   PetscFunctionBegin;
9119566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&b));
912b0a32e0cSBarry Smith   B->data      = (void*)b;
9139566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps)));
914273d9f13SBarry Smith   B->assembled = PETSC_FALSE;
915*6a09307cSBarry Smith   B->preallocated = PETSC_TRUE; /* so that MatSetValues() may be used */
916273d9f13SBarry Smith 
9179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjSetPreallocation_C",MatMPIAdjSetPreallocation_MPIAdj));
9189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjCreateNonemptySubcommMat_C",MatMPIAdjCreateNonemptySubcommMat_MPIAdj));
9199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatMPIAdjToSeq_C",MatMPIAdjToSeq_MPIAdj));
9209566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATMPIADJ));
921273d9f13SBarry Smith   PetscFunctionReturn(0);
922273d9f13SBarry Smith }
923273d9f13SBarry Smith 
924a23d5eceSKris Buschelman /*@C
925b44e7856SBarry Smith    MatMPIAdjToSeq - Converts an parallel MPIAdj matrix to complete MPIAdj on each process (needed by sequential preconditioners)
926b44e7856SBarry Smith 
927d083f849SBarry Smith    Logically Collective
928b44e7856SBarry Smith 
929b44e7856SBarry Smith    Input Parameter:
930b44e7856SBarry Smith .  A - the matrix
931b44e7856SBarry Smith 
932b44e7856SBarry Smith    Output Parameter:
933b44e7856SBarry Smith .  B - the same matrix on all processes
934b44e7856SBarry Smith 
935b44e7856SBarry Smith    Level: intermediate
936b44e7856SBarry Smith 
937db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateMPIAdj()`, `MatSetValues()`
938b44e7856SBarry Smith @*/
939b44e7856SBarry Smith PetscErrorCode  MatMPIAdjToSeq(Mat A,Mat *B)
940b44e7856SBarry Smith {
941b44e7856SBarry Smith   PetscFunctionBegin;
942cac4c232SBarry Smith   PetscUseMethod(A,"MatMPIAdjToSeq_C",(Mat,Mat*),(A,B));
943b44e7856SBarry Smith   PetscFunctionReturn(0);
944b44e7856SBarry Smith }
945b44e7856SBarry Smith 
946b44e7856SBarry Smith /*@C
947a23d5eceSKris Buschelman    MatMPIAdjSetPreallocation - Sets the array used for storing the matrix elements
948a23d5eceSKris Buschelman 
949d083f849SBarry Smith    Logically Collective
950a23d5eceSKris Buschelman 
951a23d5eceSKris Buschelman    Input Parameters:
952a23d5eceSKris Buschelman +  A - the matrix
953a23d5eceSKris Buschelman .  i - the indices into j for the start of each row
954a23d5eceSKris Buschelman .  j - the column indices for each row (sorted for each row).
955a23d5eceSKris Buschelman        The indices in i and j start with zero (NOT with one).
956a23d5eceSKris Buschelman -  values - [optional] edge weights
957a23d5eceSKris Buschelman 
958a23d5eceSKris Buschelman    Level: intermediate
959a23d5eceSKris Buschelman 
960*6a09307cSBarry Smith .seealso: `MatCreate()`, `MatCreateMPIAdj()`, `MatSetValues()`, `MATMPIADJ`, `MatCreateMPIAdj()`
961a23d5eceSKris Buschelman @*/
9627087cfbeSBarry Smith PetscErrorCode  MatMPIAdjSetPreallocation(Mat B,PetscInt *i,PetscInt *j,PetscInt *values)
963273d9f13SBarry Smith {
964273d9f13SBarry Smith   PetscFunctionBegin;
965cac4c232SBarry Smith   PetscTryMethod(B,"MatMPIAdjSetPreallocation_C",(Mat,PetscInt*,PetscInt*,PetscInt*),(B,i,j,values));
966273d9f13SBarry Smith   PetscFunctionReturn(0);
967273d9f13SBarry Smith }
968273d9f13SBarry Smith 
969b97cf49bSBarry Smith /*@C
9703eda8832SBarry Smith    MatCreateMPIAdj - Creates a sparse matrix representing an adjacency list.
971b97cf49bSBarry Smith    The matrix does not have numerical values associated with it, but is
972b97cf49bSBarry Smith    intended for ordering (to reduce bandwidth etc) and partitioning.
973b97cf49bSBarry Smith 
974d083f849SBarry Smith    Collective
975ef5ee4d1SLois Curfman McInnes 
976b97cf49bSBarry Smith    Input Parameters:
977c2e958feSBarry Smith +  comm - MPI communicator
9780752156aSBarry Smith .  m - number of local rows
97958ec18a5SLisandro Dalcin .  N - number of global columns
980b97cf49bSBarry Smith .  i - the indices into j for the start of each row
981329f5518SBarry Smith .  j - the column indices for each row (sorted for each row).
982ef5ee4d1SLois Curfman McInnes        The indices in i and j start with zero (NOT with one).
983329f5518SBarry Smith -  values -[optional] edge weights
984b97cf49bSBarry Smith 
985b97cf49bSBarry Smith    Output Parameter:
986b97cf49bSBarry Smith .  A - the matrix
987b97cf49bSBarry Smith 
98815091d37SBarry Smith    Level: intermediate
98915091d37SBarry Smith 
99095452b02SPatrick Sanan    Notes:
991c2e958feSBarry Smith    You must NOT free the ii, values and jj arrays yourself. PETSc will free them
992ededeb1aSvictorle    when the matrix is destroyed; you must allocate them with PetscMalloc(). If you
9931198db28SBarry Smith    call from Fortran you need not create the arrays with PetscMalloc().
994*6a09307cSBarry Smith 
995*6a09307cSBarry Smith    You should not include the matrix diagonals.
996b97cf49bSBarry Smith 
997e3f7e1d6Svictorle    If you already have a matrix, you can create its adjacency matrix by a call
998*6a09307cSBarry Smith    to MatConvert(), specifying a type of MATMPIADJ.
999ededeb1aSvictorle 
1000ef5ee4d1SLois Curfman McInnes    Possible values for MatSetOption() - MAT_STRUCTURALLY_SYMMETRIC
1001b97cf49bSBarry Smith 
1002*6a09307cSBarry Smith .seealso: `MatCreate()`, `MatConvert()`, `MatGetOrdering()`, `MATMPIADJ`, `MatMPIAdjSetPreallocation()`
1003b97cf49bSBarry Smith @*/
10047087cfbeSBarry Smith PetscErrorCode  MatCreateMPIAdj(MPI_Comm comm,PetscInt m,PetscInt N,PetscInt *i,PetscInt *j,PetscInt *values,Mat *A)
1005b97cf49bSBarry Smith {
1006433994e6SBarry Smith   PetscFunctionBegin;
10079566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,A));
10089566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A,m,PETSC_DETERMINE,PETSC_DETERMINE,N));
10099566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A,MATMPIADJ));
10109566063dSJacob Faibussowitsch   PetscCall(MatMPIAdjSetPreallocation(*A,i,j,values));
10113a40ed3dSBarry Smith   PetscFunctionReturn(0);
1012b97cf49bSBarry Smith }
1013