/*@ PetscSFSetUp - set up communication structures Collective Input Arguments: . sf - star forest communication object Level: beginner .seealso: PetscSFSetFromOptions(), PetscSFSetType() @*/ PetscErrorCode PetscSFSetUp(PetscSF sf) { PetscErrorCode ierr; PetscFunctionBegin; if (sf->setupcalled) PetscFunctionReturn(0); if (!((PetscObject)sf)->type_name) {ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr);} if (sf->ops->SetUp) {ierr = (*sf->ops->SetUp)(sf);CHKERRQ(ierr);} sf->setupcalled = PETSC_TRUE; PetscFunctionReturn(0); }
PetscErrorCode MatPartitioningHierarchical_ReassembleFineparts(Mat adj, IS fineparts, ISLocalToGlobalMapping mapping, IS *sfineparts) { PetscInt *local_indices, *global_indices,*owners,*sfineparts_indices,localsize,i; const PetscInt *ranges,*fineparts_indices; PetscMPIInt rank; MPI_Comm comm; PetscLayout rmap; PetscSFNode *remote; PetscSF sf; PetscErrorCode ierr; PetscFunctionBegin; /*get communicator */ ierr = PetscObjectGetComm((PetscObject)adj,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MatGetLayouts(adj,&rmap,PETSC_NULL);CHKERRQ(ierr); ierr = ISGetLocalSize(fineparts,&localsize);CHKERRQ(ierr); ierr = PetscCalloc2(localsize,&global_indices,localsize,&local_indices);CHKERRQ(ierr); for(i=0; i<localsize; i++){ local_indices[i] = i; } /*global indices */ ierr = ISLocalToGlobalMappingApply(mapping,localsize,local_indices,global_indices);CHKERRQ(ierr); ierr = PetscCalloc1(localsize,&owners);CHKERRQ(ierr); /*find owners for global indices */ for(i=0; i<localsize; i++){ ierr = PetscLayoutFindOwner(rmap,global_indices[i],&owners[i]);CHKERRQ(ierr); } /*ranges */ ierr = PetscLayoutGetRanges(rmap,&ranges);CHKERRQ(ierr); ierr = PetscCalloc1(ranges[rank+1]-ranges[rank],&sfineparts_indices);CHKERRQ(ierr); ierr = ISGetIndices(fineparts,&fineparts_indices);CHKERRQ(ierr); /*create a SF to exchange data */ ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); ierr = PetscCalloc1(localsize,&remote);CHKERRQ(ierr); for(i=0; i<localsize; i++){ remote[i].rank = owners[i]; remote[i].index = global_indices[i]-ranges[owners[i]]; } ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); /*not sure how to add prefix to sf*/ ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,localsize,localsize,PETSC_NULL,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); ierr = PetscSFReduceBegin(sf,MPIU_INT,fineparts_indices,sfineparts_indices,MPIU_REPLACE);CHKERRQ(ierr); ierr = PetscSFReduceEnd(sf,MPIU_INT,fineparts_indices,sfineparts_indices,MPIU_REPLACE);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = ISRestoreIndices(fineparts,&fineparts_indices);CHKERRQ(ierr); /* comm self */ ierr = ISCreateGeneral(comm,ranges[rank+1]-ranges[rank],sfineparts_indices,PETSC_OWN_POINTER,sfineparts);CHKERRQ(ierr); ierr = PetscFree2(global_indices,local_indices);CHKERRQ(ierr); ierr = PetscFree(owners);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscSFDuplicate - duplicate a PetscSF, optionally preserving rank connectivity and graph Collective Input Arguments: + sf - communication object to duplicate - opt - PETSCSF_DUPLICATE_CONFONLY, PETSCSF_DUPLICATE_RANKS, or PETSCSF_DUPLICATE_GRAPH (see PetscSFDuplicateOption) Output Arguments: . newsf - new communication object Level: beginner .seealso: PetscSFCreate(), PetscSFSetType(), PetscSFSetGraph() @*/ PetscErrorCode PetscSFDuplicate(PetscSF sf,PetscSFDuplicateOption opt,PetscSF *newsf) { PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscSFCreate(PetscObjectComm((PetscObject)sf),newsf);CHKERRQ(ierr); ierr = PetscSFSetType(*newsf,((PetscObject)sf)->type_name);CHKERRQ(ierr); if (sf->ops->Duplicate) {ierr = (*sf->ops->Duplicate)(sf,opt,*newsf);CHKERRQ(ierr);} if (opt == PETSCSF_DUPLICATE_GRAPH) { PetscInt nroots,nleaves; const PetscInt *ilocal; const PetscSFNode *iremote; ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); ierr = PetscSFSetGraph(*newsf,nroots,nleaves,ilocal,PETSC_COPY_VALUES,iremote,PETSC_COPY_VALUES);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@C PetscSFSetFromOptions - set PetscSF options using the options database Logically Collective Input Arguments: . sf - star forest Options Database Keys: + -sf_type - implementation type, see PetscSFSetType() - -sf_rank_order - sort composite points for gathers and scatters in rank order, gathers are non-deterministic otherwise Level: intermediate .keywords: KSP, set, from, options, database .seealso: PetscSFWindowSetSyncType() @*/ PetscErrorCode PetscSFSetFromOptions(PetscSF sf) { PetscSFType deft; char type[256]; PetscErrorCode ierr; PetscBool flg; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); ierr = PetscObjectOptionsBegin((PetscObject)sf);CHKERRQ(ierr); deft = ((PetscObject)sf)->type_name ? ((PetscObject)sf)->type_name : PETSCSFBASIC; ierr = PetscOptionsFList("-sf_type","PetscSF implementation type","PetscSFSetType",PetscSFList,deft,type,256,&flg);CHKERRQ(ierr); ierr = PetscSFSetType(sf,flg ? type : deft);CHKERRQ(ierr); ierr = PetscOptionsBool("-sf_rank_order","sort composite points for gathers and scatters in rank order, gathers are non-deterministic otherwise","PetscSFSetRankOrder",sf->rankorder,&sf->rankorder,NULL);CHKERRQ(ierr); if (sf->ops->SetFromOptions) {ierr = (*sf->ops->SetFromOptions)(PetscOptionsObject,sf);CHKERRQ(ierr);} ierr = PetscOptionsEnd();CHKERRQ(ierr); PetscFunctionReturn(0); }
/* * Increase overlap for the sub-matrix across sub communicator * sub-matrix could be a graph or numerical matrix * */ PetscErrorCode MatIncreaseOverlapSplit_Single(Mat mat,IS *is,PetscInt ov) { PetscInt i,nindx,*indices_sc,*indices_ov,localsize,*localsizes_sc,localsize_tmp; PetscInt *indices_ov_rd,nroots,nleaves,*localoffsets,*indices_recv,*sources_sc,*sources_sc_rd; const PetscInt *indices; PetscMPIInt srank,ssize,issamecomm,k,grank; IS is_sc,allis_sc,partitioning; MPI_Comm gcomm,dcomm,scomm; PetscSF sf; PetscSFNode *remote; Mat *smat; MatPartitioning part; PetscErrorCode ierr; PetscFunctionBegin; /* get a sub communicator before call individual MatIncreaseOverlap * since the sub communicator may be changed. * */ ierr = PetscObjectGetComm((PetscObject)(*is),&dcomm);CHKERRQ(ierr); /*make a copy before the original one is deleted*/ ierr = PetscCommDuplicate(dcomm,&scomm,NULL);CHKERRQ(ierr); /*get a global communicator, where mat should be a global matrix */ ierr = PetscObjectGetComm((PetscObject)mat,&gcomm);CHKERRQ(ierr); /*increase overlap on each individual subdomain*/ ierr = (*mat->ops->increaseoverlap)(mat,1,is,ov);CHKERRQ(ierr); /*compare communicators */ ierr = MPI_Comm_compare(gcomm,scomm,&issamecomm);CHKERRQ(ierr); /* if the sub-communicator is the same as the global communicator, * user does not want to use a sub-communicator * */ if(issamecomm == MPI_IDENT || issamecomm == MPI_CONGRUENT) PetscFunctionReturn(0); /* if the sub-communicator is petsc_comm_self, * user also does not care the sub-communicator * */ ierr = MPI_Comm_compare(scomm,PETSC_COMM_SELF,&issamecomm);CHKERRQ(ierr); if(issamecomm == MPI_IDENT || issamecomm == MPI_CONGRUENT){PetscFunctionReturn(0);} /*local rank, size in a sub-communicator */ ierr = MPI_Comm_rank(scomm,&srank);CHKERRQ(ierr); ierr = MPI_Comm_size(scomm,&ssize);CHKERRQ(ierr); ierr = MPI_Comm_rank(gcomm,&grank);CHKERRQ(ierr); /*create a new IS based on sub-communicator * since the old IS is often based on petsc_comm_self * */ ierr = ISGetLocalSize(*is,&nindx);CHKERRQ(ierr); ierr = PetscCalloc1(nindx,&indices_sc);CHKERRQ(ierr); ierr = ISGetIndices(*is,&indices);CHKERRQ(ierr); ierr = PetscMemcpy(indices_sc,indices,sizeof(PetscInt)*nindx);CHKERRQ(ierr); ierr = ISRestoreIndices(*is,&indices);CHKERRQ(ierr); /*we do not need any more*/ ierr = ISDestroy(is);CHKERRQ(ierr); /*create a index set based on the sub communicator */ ierr = ISCreateGeneral(scomm,nindx,indices_sc,PETSC_OWN_POINTER,&is_sc);CHKERRQ(ierr); /*gather all indices within the sub communicator*/ ierr = ISAllGather(is_sc,&allis_sc);CHKERRQ(ierr); ierr = ISDestroy(&is_sc);CHKERRQ(ierr); /* gather local sizes */ ierr = PetscMalloc1(ssize,&localsizes_sc);CHKERRQ(ierr); /*get individual local sizes for all index sets*/ ierr = MPI_Gather(&nindx,1,MPIU_INT,localsizes_sc,1,MPIU_INT,0,scomm);CHKERRQ(ierr); /*only root does these computations */ if(!srank){ /*get local size for the big index set*/ ierr = ISGetLocalSize(allis_sc,&localsize);CHKERRQ(ierr); ierr = PetscCalloc2(localsize,&indices_ov,localsize,&sources_sc);CHKERRQ(ierr); ierr = PetscCalloc2(localsize,&indices_ov_rd,localsize,&sources_sc_rd);CHKERRQ(ierr); ierr = ISGetIndices(allis_sc,&indices);CHKERRQ(ierr); ierr = PetscMemcpy(indices_ov,indices,sizeof(PetscInt)*localsize);CHKERRQ(ierr); ierr = ISRestoreIndices(allis_sc,&indices);CHKERRQ(ierr); /*we do not need it any more */ ierr = ISDestroy(&allis_sc);CHKERRQ(ierr); /*assign corresponding sources */ localsize_tmp = 0; for(k=0; k<ssize; k++){ for(i=0; i<localsizes_sc[k]; i++){ sources_sc[localsize_tmp++] = k; } } /*record where indices come from */ ierr = PetscSortIntWithArray(localsize,indices_ov,sources_sc);CHKERRQ(ierr); /*count local sizes for reduced indices */ ierr = PetscMemzero(localsizes_sc,sizeof(PetscInt)*ssize);CHKERRQ(ierr); /*initialize the first entity*/ if(localsize){ indices_ov_rd[0] = indices_ov[0]; sources_sc_rd[0] = sources_sc[0]; localsizes_sc[sources_sc[0]]++; } localsize_tmp = 1; /*remove duplicate integers */ for(i=1; i<localsize; i++){ if(indices_ov[i] != indices_ov[i-1]){ indices_ov_rd[localsize_tmp] = indices_ov[i]; sources_sc_rd[localsize_tmp++] = sources_sc[i]; localsizes_sc[sources_sc[i]]++; } } ierr = PetscFree2(indices_ov,sources_sc);CHKERRQ(ierr); ierr = PetscCalloc1(ssize+1,&localoffsets);CHKERRQ(ierr); for(k=0; k<ssize; k++){ localoffsets[k+1] = localoffsets[k] + localsizes_sc[k]; } /*construct a star forest to send data back */ nleaves = localoffsets[ssize]; ierr = PetscMemzero(localoffsets,(ssize+1)*sizeof(PetscInt));CHKERRQ(ierr); nroots = localsizes_sc[srank]; ierr = PetscCalloc1(nleaves,&remote);CHKERRQ(ierr); for(i=0; i<nleaves; i++){ remote[i].rank = sources_sc_rd[i]; remote[i].index = localoffsets[sources_sc_rd[i]]++; } ierr = PetscFree(localoffsets);CHKERRQ(ierr); }else{ ierr = ISDestroy(&allis_sc);CHKERRQ(ierr); /*Allocate a 'zero' pointer */ ierr = PetscCalloc1(0,&remote);CHKERRQ(ierr); nleaves = 0; indices_ov_rd = 0; sources_sc_rd = 0; } /*scatter sizes to everybody */ ierr = MPI_Scatter(localsizes_sc,1, MPIU_INT,&nroots,1, MPIU_INT,0,scomm);CHKERRQ(ierr); /*free memory */ ierr = PetscFree(localsizes_sc);CHKERRQ(ierr); ierr = PetscCalloc1(nroots,&indices_recv);CHKERRQ(ierr); /*ierr = MPI_Comm_dup(scomm,&dcomm);CHKERRQ(ierr);*/ /*set data back to every body */ ierr = PetscSFCreate(scomm,&sf);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,nroots,nleaves,PETSC_NULL,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); ierr = PetscSFReduceBegin(sf,MPIU_INT,indices_ov_rd,indices_recv,MPIU_REPLACE);CHKERRQ(ierr); ierr = PetscSFReduceEnd(sf,MPIU_INT,indices_ov_rd,indices_recv,MPIU_REPLACE);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* free memory */ ierr = PetscFree2(indices_ov_rd,sources_sc_rd);CHKERRQ(ierr); /*create a index set*/ ierr = ISCreateGeneral(scomm,nroots,indices_recv,PETSC_OWN_POINTER,&is_sc);CHKERRQ(ierr); /*construct a parallel submatrix */ ierr = MatGetSubMatricesMPI(mat,1,&is_sc,&is_sc,MAT_INITIAL_MATRIX,&smat);CHKERRQ(ierr); /* we do not need them any more */ ierr = ISDestroy(&allis_sc);CHKERRQ(ierr); /*create a partitioner to repartition the sub-matrix*/ ierr = MatPartitioningCreate(scomm,&part);CHKERRQ(ierr); ierr = MatPartitioningSetAdjacency(part,smat[0]);CHKERRQ(ierr); #if PETSC_HAVE_PARMETIS /* if there exists a ParMETIS installation, we try to use ParMETIS * because a repartition routine possibly work better * */ ierr = MatPartitioningSetType(part,MATPARTITIONINGPARMETIS);CHKERRQ(ierr); /*try to use reparition function, instead of partition function */ ierr = MatPartitioningParmetisSetRepartition(part);CHKERRQ(ierr); #else /*we at least provide a default partitioner to rebalance the computation */ ierr = MatPartitioningSetType(part,MATPARTITIONINGAVERAGE);CHKERRQ(ierr); #endif /*user can pick up any partitioner by using an option*/ ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr); /* apply partition */ ierr = MatPartitioningApply(part,&partitioning);CHKERRQ(ierr); ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr); ierr = MatDestroy(&(smat[0]));CHKERRQ(ierr); ierr = PetscFree(smat);CHKERRQ(ierr); /* get local rows including overlap */ ierr = ISBuildTwoSided(partitioning,is_sc,is);CHKERRQ(ierr); /* destroy */ ierr = ISDestroy(&is_sc);CHKERRQ(ierr); ierr = ISDestroy(&partitioning);CHKERRQ(ierr); ierr = PetscCommDestroy(&scomm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ ISBuildTwoSided - Takes an IS that describes where we will go. Generates an IS that contains new numbers from remote or local on the IS. Collective on IS Input Parameters . to - an IS describes where we will go. Negative target rank will be ignored . toindx - an IS describes what indices should send. NULL means sending natural numbering Output Parameter: . rows - contains new numbers from remote or local Level: advanced .seealso: MatPartitioningCreate(), ISPartitioningToNumbering(), ISPartitioningCount() @*/ PetscErrorCode ISBuildTwoSided(IS ito,IS toindx, IS *rows) { const PetscInt *ito_indices,*toindx_indices; PetscInt *send_indices,rstart,*recv_indices,nrecvs,nsends; PetscInt *tosizes,*fromsizes,i,j,*tosizes_tmp,*tooffsets_tmp,ito_ln; PetscMPIInt *toranks,*fromranks,size,target_rank,*fromperm_newtoold,nto,nfrom; PetscLayout isrmap; MPI_Comm comm; PetscSF sf; PetscSFNode *iremote; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)ito,&comm);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = ISGetLocalSize(ito,&ito_ln);CHKERRQ(ierr); /* why we do not have ISGetLayout? */ isrmap = ito->map; ierr = PetscLayoutGetRange(isrmap,&rstart,NULL);CHKERRQ(ierr); ierr = ISGetIndices(ito,&ito_indices);CHKERRQ(ierr); ierr = PetscCalloc2(size,&tosizes_tmp,size+1,&tooffsets_tmp);CHKERRQ(ierr); for(i=0; i<ito_ln; i++){ if(ito_indices[i]<0) continue; #if defined(PETSC_USE_DEBUG) if(ito_indices[i]>=size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"target rank %d is larger than communicator size %d ",ito_indices[i],size); #endif tosizes_tmp[ito_indices[i]]++; } nto = 0; for(i=0; i<size; i++){ tooffsets_tmp[i+1] = tooffsets_tmp[i]+tosizes_tmp[i]; if(tosizes_tmp[i]>0) nto++; } ierr = PetscCalloc2(nto,&toranks,2*nto,&tosizes);CHKERRQ(ierr); nto = 0; for(i=0; i<size; i++){ if(tosizes_tmp[i]>0){ toranks[nto] = i; tosizes[2*nto] = tosizes_tmp[i];/* size */ tosizes[2*nto+1] = tooffsets_tmp[i];/* offset */ nto++; } } nsends = tooffsets_tmp[size]; ierr = PetscCalloc1(nsends,&send_indices);CHKERRQ(ierr); if(toindx){ ierr = ISGetIndices(toindx,&toindx_indices);CHKERRQ(ierr); } for(i=0; i<ito_ln; i++){ if(ito_indices[i]<0) continue; target_rank = ito_indices[i]; send_indices[tooffsets_tmp[target_rank]] = toindx? toindx_indices[i]:(i+rstart); tooffsets_tmp[target_rank]++; } if(toindx){ ierr = ISRestoreIndices(toindx,&toindx_indices);CHKERRQ(ierr); } ierr = ISRestoreIndices(ito,&ito_indices);CHKERRQ(ierr); ierr = PetscFree2(tosizes_tmp,tooffsets_tmp);CHKERRQ(ierr); ierr = PetscCommBuildTwoSided(comm,2,MPIU_INT,nto,toranks,tosizes,&nfrom,&fromranks,&fromsizes);CHKERRQ(ierr); ierr = PetscFree2(toranks,tosizes);CHKERRQ(ierr); ierr = PetscCalloc1(nfrom,&fromperm_newtoold);CHKERRQ(ierr); for(i=0; i<nfrom; i++){ fromperm_newtoold[i] = i; } ierr = PetscSortMPIIntWithArray(nfrom,fromranks,fromperm_newtoold);CHKERRQ(ierr); nrecvs = 0; for(i=0; i<nfrom; i++){ nrecvs += fromsizes[i*2]; } ierr = PetscCalloc1(nrecvs,&recv_indices);CHKERRQ(ierr); ierr = PetscCalloc1(nrecvs,&iremote);CHKERRQ(ierr); nrecvs = 0; for(i=0; i<nfrom; i++){ for(j=0; j<fromsizes[2*fromperm_newtoold[i]]; j++){ iremote[nrecvs].rank = fromranks[i]; iremote[nrecvs++].index = fromsizes[2*fromperm_newtoold[i]+1]+j; } } ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,nsends,nrecvs,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); /* how to put a prefix ? */ ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sf,MPIU_INT,send_indices,recv_indices);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf,MPIU_INT,send_indices,recv_indices);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = PetscFree(fromranks);CHKERRQ(ierr); ierr = PetscFree(fromsizes);CHKERRQ(ierr); ierr = PetscFree(fromperm_newtoold);CHKERRQ(ierr); ierr = PetscFree(send_indices);CHKERRQ(ierr); if(rows){ ierr = PetscSortInt(nrecvs,recv_indices);CHKERRQ(ierr); ierr = ISCreateGeneral(comm, nrecvs,recv_indices,PETSC_OWN_POINTER,rows);CHKERRQ(ierr); }else{ ierr = PetscFree(recv_indices);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* * The interface should be easy to use for both MatGetSubMatrix (parallel sub-matrix) and MatGetSubMatrices (sequential sub-matrices) * */ static PetscErrorCode MatGetSubMatrix_MPIAdj_data(Mat adj,IS irows, IS icols, PetscInt **sadj_xadj,PetscInt **sadj_adjncy,PetscInt **sadj_values) { PetscInt nlrows_is,icols_n,i,j,nroots,nleaves,owner,rlocalindex,*ncols_send,*ncols_recv; PetscInt nlrows_mat,*adjncy_recv,Ncols_recv,Ncols_send,*xadj_recv,*values_recv; PetscInt *ncols_recv_offsets,loc,rnclos,*sadjncy,*sxadj,*svalues,isvalue; const PetscInt *irows_indices,*icols_indices,*xadj, *adjncy; Mat_MPIAdj *a = (Mat_MPIAdj*)adj->data; PetscLayout rmap; MPI_Comm comm; PetscSF sf; PetscSFNode *iremote; PetscBool done; PetscErrorCode ierr; PetscFunctionBegin; /* communicator */ ierr = PetscObjectGetComm((PetscObject)adj,&comm);CHKERRQ(ierr); /* Layouts */ ierr = MatGetLayouts(adj,&rmap,PETSC_NULL);CHKERRQ(ierr); /* get rows information */ ierr = ISGetLocalSize(irows,&nlrows_is);CHKERRQ(ierr); ierr = ISGetIndices(irows,&irows_indices);CHKERRQ(ierr); ierr = PetscCalloc1(nlrows_is,&iremote);CHKERRQ(ierr); /* construct sf graph*/ nleaves = nlrows_is; for(i=0; i<nlrows_is; i++){ owner = -1; rlocalindex = -1; ierr = PetscLayoutFindOwnerIndex(rmap,irows_indices[i],&owner,&rlocalindex);CHKERRQ(ierr); iremote[i].rank = owner; iremote[i].index = rlocalindex; } ierr = MatGetRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done);CHKERRQ(ierr); ierr = PetscCalloc4(nlrows_mat,&ncols_send,nlrows_is,&xadj_recv,nlrows_is+1,&ncols_recv_offsets,nlrows_is,&ncols_recv);CHKERRQ(ierr); nroots = nlrows_mat; for(i=0; i<nlrows_mat; i++){ ncols_send[i] = xadj[i+1]-xadj[i]; } ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,nroots,nleaves,PETSC_NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sf,MPIU_INT,ncols_send,ncols_recv);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf,MPIU_INT,ncols_send,ncols_recv);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sf,MPIU_INT,xadj,xadj_recv);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf,MPIU_INT,xadj,xadj_recv);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); Ncols_recv =0; for(i=0; i<nlrows_is; i++){ Ncols_recv += ncols_recv[i]; ncols_recv_offsets[i+1] = ncols_recv[i]+ncols_recv_offsets[i]; } Ncols_send = 0; for(i=0; i<nlrows_mat; i++){ Ncols_send += ncols_send[i]; } ierr = PetscCalloc1(Ncols_recv,&iremote);CHKERRQ(ierr); ierr = PetscCalloc1(Ncols_recv,&adjncy_recv);CHKERRQ(ierr); nleaves = Ncols_recv; Ncols_recv = 0; for(i=0; i<nlrows_is; i++){ ierr = PetscLayoutFindOwner(rmap,irows_indices[i],&owner);CHKERRQ(ierr); for(j=0; j<ncols_recv[i]; j++){ iremote[Ncols_recv].rank = owner; iremote[Ncols_recv++].index = xadj_recv[i]+j; } } ierr = ISRestoreIndices(irows,&irows_indices);CHKERRQ(ierr); /*if we need to deal with edge weights ???*/ if(a->values){isvalue=1;}else{isvalue=0;} /*involve a global communication */ /*ierr = MPI_Allreduce(&isvalue,&isvalue,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);*/ if(isvalue){ierr = PetscCalloc1(Ncols_recv,&values_recv);CHKERRQ(ierr);} nroots = Ncols_send; ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,nroots,nleaves,PETSC_NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sf,MPIU_INT,adjncy,adjncy_recv);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf,MPIU_INT,adjncy,adjncy_recv);CHKERRQ(ierr); if(isvalue){ ierr = PetscSFBcastBegin(sf,MPIU_INT,a->values,values_recv);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sf,MPIU_INT,a->values,values_recv);CHKERRQ(ierr); } ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = MatRestoreRowIJ(adj,0,PETSC_FALSE,PETSC_FALSE,&nlrows_mat,&xadj,&adjncy,&done);CHKERRQ(ierr); ierr = ISGetLocalSize(icols,&icols_n);CHKERRQ(ierr); ierr = ISGetIndices(icols,&icols_indices);CHKERRQ(ierr); rnclos = 0; for(i=0; i<nlrows_is; i++){ for(j=ncols_recv_offsets[i]; j<ncols_recv_offsets[i+1]; j++){ ierr = PetscFindInt(adjncy_recv[j], icols_n, icols_indices, &loc);CHKERRQ(ierr); if(loc<0){ adjncy_recv[j] = -1; if(isvalue) values_recv[j] = -1; ncols_recv[i]--; }else{ rnclos++; } } } ierr = ISRestoreIndices(icols,&icols_indices);CHKERRQ(ierr); ierr = PetscCalloc1(rnclos,&sadjncy);CHKERRQ(ierr); if(isvalue) {ierr = PetscCalloc1(rnclos,&svalues);CHKERRQ(ierr);} ierr = PetscCalloc1(nlrows_is+1,&sxadj);CHKERRQ(ierr); rnclos = 0; for(i=0; i<nlrows_is; i++){ for(j=ncols_recv_offsets[i]; j<ncols_recv_offsets[i+1]; j++){ if(adjncy_recv[j]<0) continue; sadjncy[rnclos] = adjncy_recv[j]; if(isvalue) svalues[rnclos] = values_recv[j]; rnclos++; } } for(i=0; i<nlrows_is; i++){ sxadj[i+1] = sxadj[i]+ncols_recv[i]; } if(sadj_xadj) { *sadj_xadj = sxadj;}else { ierr = PetscFree(sxadj);CHKERRQ(ierr);} if(sadj_adjncy){ *sadj_adjncy = sadjncy;}else{ ierr = PetscFree(sadjncy);CHKERRQ(ierr);} if(sadj_values){ if(isvalue) *sadj_values = svalues; else *sadj_values=0; }else{ if(isvalue) {ierr = PetscFree(svalues);CHKERRQ(ierr);} } ierr = PetscFree4(ncols_send,xadj_recv,ncols_recv_offsets,ncols_recv);CHKERRQ(ierr); ierr = PetscFree(adjncy_recv);CHKERRQ(ierr); if(isvalue) {ierr = PetscFree(values_recv);CHKERRQ(ierr);} PetscFunctionReturn(0); }
int main(int argc,char **argv) { PetscSF sf,sfDup,sfInv,sfEmbed,sfA,sfB,sfBA; const PetscInt *degree; PetscErrorCode ierr; ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr; ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFReset(sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFReset(sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = CheckGraphEmpty(sf);CHKERRQ(ierr); ierr = PetscSFReset(sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = CheckGraphEmpty(sf);CHKERRQ(ierr); ierr = PetscSFReset(sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test setup */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = CheckRanksNotSet(sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = CheckRanksNotSet(sf);CHKERRQ(ierr); ierr = PetscSFSetUp(sf);CHKERRQ(ierr); ierr = CheckRanksEmpty(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test setup then reset */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFSetUp(sf);CHKERRQ(ierr); ierr = PetscSFReset(sf);CHKERRQ(ierr); ierr = CheckRanksNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test view (no graph set, no type set) */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFView(sf,NULL);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test set graph then view (no type set) */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFView(sf,NULL);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test set type then view (no graph set) */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = PetscSFView(sf,NULL);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test set type then graph then view */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFView(sf,NULL);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test set graph then type */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr); ierr = CheckGraphEmpty(sf);CHKERRQ(ierr); ierr = PetscSFReset(sf);CHKERRQ(ierr); ierr = CheckGraphNotSet(sf);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test Bcast */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sf,MPI_INT,NULL,NULL);CHKERRQ(ierr); ierr = PetscSFBcastEnd (sf,MPI_INT,NULL,NULL);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test Reduce */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFReduceBegin(sf,MPI_INT,NULL,NULL,MPIU_REPLACE);CHKERRQ(ierr); ierr = PetscSFReduceEnd (sf,MPI_INT,NULL,NULL,MPIU_REPLACE);CHKERRQ(ierr); ierr = PetscSFReduceBegin(sf,MPI_INT,NULL,NULL,MPI_SUM);CHKERRQ(ierr); ierr = PetscSFReduceEnd (sf,MPI_INT,NULL,NULL,MPI_SUM);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test FetchAndOp */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFFetchAndOpBegin(sf,MPI_INT,NULL,NULL,NULL,MPI_SUM);CHKERRQ(ierr); ierr = PetscSFFetchAndOpEnd (sf,MPI_INT,NULL,NULL,NULL,MPI_SUM);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test ComputeDegree */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_COPY_VALUES,NULL,PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscSFComputeDegreeBegin(sf,°ree);CHKERRQ(ierr); ierr = PetscSFComputeDegreeEnd(sf,°ree);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test PetscSFDuplicate() */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_USE_POINTER,NULL,PETSC_USE_POINTER);CHKERRQ(ierr); ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_GRAPH,&sfDup);CHKERRQ(ierr); ierr = CheckGraphEmpty(sfDup);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfDup);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test PetscSFCreateInverseSF() */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_USE_POINTER,NULL,PETSC_USE_POINTER);CHKERRQ(ierr); ierr = PetscSFCreateInverseSF(sf,&sfInv);CHKERRQ(ierr); ierr = CheckGraphEmpty(sfInv);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfInv);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test PetscSFCreateEmbeddedSF() */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_USE_POINTER,NULL,PETSC_USE_POINTER);CHKERRQ(ierr); ierr = PetscSFCreateEmbeddedSF(sf,0,NULL,&sfEmbed);CHKERRQ(ierr); ierr = CheckGraphEmpty(sfEmbed);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfEmbed);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test PetscSFCreateEmbeddedLeafSF() */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr); ierr = PetscSFSetGraph(sf,0,0,NULL,PETSC_USE_POINTER,NULL,PETSC_USE_POINTER);CHKERRQ(ierr); ierr = PetscSFCreateEmbeddedLeafSF(sf,0,NULL,&sfEmbed);CHKERRQ(ierr); ierr = CheckGraphEmpty(sfEmbed);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfEmbed);CHKERRQ(ierr); ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); /* Test PetscSFCompose() */ ierr = PetscSFCreate(PETSC_COMM_WORLD,&sfA);CHKERRQ(ierr); ierr = PetscSFSetGraph(sfA,0,0,NULL,PETSC_USE_POINTER,NULL,PETSC_USE_POINTER);CHKERRQ(ierr); ierr = PetscSFCreate(PETSC_COMM_WORLD,&sfB);CHKERRQ(ierr); ierr = PetscSFSetGraph(sfB,0,0,NULL,PETSC_USE_POINTER,NULL,PETSC_USE_POINTER);CHKERRQ(ierr); ierr = PetscSFCompose(sfA,sfB,&sfBA);CHKERRQ(ierr); ierr = CheckGraphEmpty(sfBA);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfBA);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfA);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfB);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }