/* * 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; 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); ierr = (*mat->ops->increaseoverlap)(mat,1,is,ov);CHKERRQ(ierr); ierr = MPI_Comm_compare(gcomm,scomm,&issamecomm);CHKERRMPI(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) { ierr = PetscCommDestroy(&scomm);CHKERRQ(ierr); 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);CHKERRMPI(ierr); if (issamecomm == MPI_IDENT || issamecomm == MPI_CONGRUENT) { ierr = PetscCommDestroy(&scomm);CHKERRQ(ierr); PetscFunctionReturn(0); } ierr = MPI_Comm_rank(scomm,&srank);CHKERRMPI(ierr); ierr = MPI_Comm_size(scomm,&ssize);CHKERRMPI(ierr); ierr = MPI_Comm_rank(gcomm,&grank);CHKERRMPI(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 = PetscMalloc1(nindx,&indices_sc);CHKERRQ(ierr); ierr = ISGetIndices(*is,&indices);CHKERRQ(ierr); ierr = PetscArraycpy(indices_sc,indices,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);CHKERRMPI(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 = PetscArraycpy(indices_ov,indices,localsize);CHKERRQ(ierr); ierr = ISRestoreIndices(allis_sc,&indices);CHKERRQ(ierr); ierr = ISDestroy(&allis_sc);CHKERRQ(ierr); /* assign corresponding sources */ localsize_tmp = 0; for (k=0; k