/* * Increase the overlap of a 'big' subdomain across several processor cores * * Author: Fande Kong */ #include #include /* * 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; PetscFunctionBegin; /* get a sub communicator before call individual MatIncreaseOverlap * since the sub communicator may be changed. * */ PetscCall(PetscObjectGetComm((PetscObject)(*is),&dcomm)); /* make a copy before the original one is deleted */ PetscCall(PetscCommDuplicate(dcomm,&scomm,NULL)); /* get a global communicator, where mat should be a global matrix */ PetscCall(PetscObjectGetComm((PetscObject)mat,&gcomm)); PetscCall((*mat->ops->increaseoverlap)(mat,1,is,ov)); PetscCallMPI(MPI_Comm_compare(gcomm,scomm,&issamecomm)); /* 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) { PetscCall(PetscCommDestroy(&scomm)); PetscFunctionReturn(0); } /* if the sub-communicator is petsc_comm_self, * user also does not care the sub-communicator * */ PetscCallMPI(MPI_Comm_compare(scomm,PETSC_COMM_SELF,&issamecomm)); if (issamecomm == MPI_IDENT || issamecomm == MPI_CONGRUENT) { PetscCall(PetscCommDestroy(&scomm)); PetscFunctionReturn(0); } PetscCallMPI(MPI_Comm_rank(scomm,&srank)); PetscCallMPI(MPI_Comm_size(scomm,&ssize)); PetscCallMPI(MPI_Comm_rank(gcomm,&grank)); /* create a new IS based on sub-communicator * since the old IS is often based on petsc_comm_self * */ PetscCall(ISGetLocalSize(*is,&nindx)); PetscCall(PetscMalloc1(nindx,&indices_sc)); PetscCall(ISGetIndices(*is,&indices)); PetscCall(PetscArraycpy(indices_sc,indices,nindx)); PetscCall(ISRestoreIndices(*is,&indices)); /* we do not need any more */ PetscCall(ISDestroy(is)); /* create a index set based on the sub communicator */ PetscCall(ISCreateGeneral(scomm,nindx,indices_sc,PETSC_OWN_POINTER,&is_sc)); /* gather all indices within the sub communicator */ PetscCall(ISAllGather(is_sc,&allis_sc)); PetscCall(ISDestroy(&is_sc)); /* gather local sizes */ PetscCall(PetscMalloc1(ssize,&localsizes_sc)); /* get individual local sizes for all index sets */ PetscCallMPI(MPI_Gather(&nindx,1,MPIU_INT,localsizes_sc,1,MPIU_INT,0,scomm)); /* only root does these computations */ if (!srank) { /* get local size for the big index set */ PetscCall(ISGetLocalSize(allis_sc,&localsize)); PetscCall(PetscCalloc2(localsize,&indices_ov,localsize,&sources_sc)); PetscCall(PetscCalloc2(localsize,&indices_ov_rd,localsize,&sources_sc_rd)); PetscCall(ISGetIndices(allis_sc,&indices)); PetscCall(PetscArraycpy(indices_ov,indices,localsize)); PetscCall(ISRestoreIndices(allis_sc,&indices)); PetscCall(ISDestroy(&allis_sc)); /* assign corresponding sources */ localsize_tmp = 0; for (k=0; k