1af0996ceSBarry Smith #include <petsc/private/sfimpl.h> /*I "petscsf.h" I*/ 295fce210SBarry Smith #include <petscctable.h> 395fce210SBarry Smith 495fce210SBarry Smith #if defined(PETSC_USE_DEBUG) 595fce210SBarry Smith # define PetscSFCheckGraphSet(sf,arg) do { \ 695fce210SBarry Smith if (PetscUnlikely(!(sf)->graphset)) \ 7dd5b3ca6SJunchao Zhang SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSFSetGraph() or PetscSFSetGraphWithPattern() on argument %D \"%s\" before %s()",(arg),#sf,PETSC_FUNCTION_NAME); \ 895fce210SBarry Smith } while (0) 995fce210SBarry Smith #else 1095fce210SBarry Smith # define PetscSFCheckGraphSet(sf,arg) do {} while (0) 1195fce210SBarry Smith #endif 1295fce210SBarry Smith 1395fce210SBarry Smith const char *const PetscSFDuplicateOptions[] = {"CONFONLY","RANKS","GRAPH","PetscSFDuplicateOption","PETSCSF_DUPLICATE_",0}; 1495fce210SBarry Smith 158af6ec1cSBarry Smith /*@ 1695fce210SBarry Smith PetscSFCreate - create a star forest communication context 1795fce210SBarry Smith 18d083f849SBarry Smith Collective 1995fce210SBarry Smith 2095fce210SBarry Smith Input Arguments: 2195fce210SBarry Smith . comm - communicator on which the star forest will operate 2295fce210SBarry Smith 2395fce210SBarry Smith Output Arguments: 2495fce210SBarry Smith . sf - new star forest context 2595fce210SBarry Smith 26dd5b3ca6SJunchao Zhang Options Database Keys: 27dd5b3ca6SJunchao Zhang + -sf_type basic -Use MPI persistent Isend/Irecv for communication (Default) 28dd5b3ca6SJunchao Zhang . -sf_type window -Use MPI-3 one-sided window for communication 29dd5b3ca6SJunchao Zhang - -sf_type neighbor -Use MPI-3 neighborhood collectives for communication 30dd5b3ca6SJunchao Zhang 3195fce210SBarry Smith Level: intermediate 3295fce210SBarry Smith 33dd5b3ca6SJunchao Zhang Notes: 34dd5b3ca6SJunchao Zhang When one knows the communication graph is one of the predefined graph, such as MPI_Alltoall, MPI_Allgatherv, 35dd5b3ca6SJunchao Zhang MPI_Gatherv, one can create a PetscSF and then set its graph with PetscSFSetGraphWithPattern(). These special 36dd5b3ca6SJunchao Zhang SFs are optimized and they have better performance than general SFs. 37dd5b3ca6SJunchao Zhang 38dd5b3ca6SJunchao Zhang .seealso: PetscSFSetGraph(), PetscSFSetGraphWithPattern(), PetscSFDestroy() 3995fce210SBarry Smith @*/ 4095fce210SBarry Smith PetscErrorCode PetscSFCreate(MPI_Comm comm,PetscSF *sf) 4195fce210SBarry Smith { 4295fce210SBarry Smith PetscErrorCode ierr; 4395fce210SBarry Smith PetscSF b; 4495fce210SBarry Smith 4595fce210SBarry Smith PetscFunctionBegin; 4695fce210SBarry Smith PetscValidPointer(sf,2); 47607a6623SBarry Smith ierr = PetscSFInitializePackage();CHKERRQ(ierr); 4895fce210SBarry Smith 4973107ff1SLisandro Dalcin ierr = PetscHeaderCreate(b,PETSCSF_CLASSID,"PetscSF","Star Forest","PetscSF",comm,PetscSFDestroy,PetscSFView);CHKERRQ(ierr); 5095fce210SBarry Smith 5195fce210SBarry Smith b->nroots = -1; 5295fce210SBarry Smith b->nleaves = -1; 5329046d53SLisandro Dalcin b->minleaf = PETSC_MAX_INT; 5429046d53SLisandro Dalcin b->maxleaf = PETSC_MIN_INT; 5595fce210SBarry Smith b->nranks = -1; 5695fce210SBarry Smith b->rankorder = PETSC_TRUE; 5795fce210SBarry Smith b->ingroup = MPI_GROUP_NULL; 5895fce210SBarry Smith b->outgroup = MPI_GROUP_NULL; 5995fce210SBarry Smith b->graphset = PETSC_FALSE; 6095fce210SBarry Smith 6195fce210SBarry Smith *sf = b; 6295fce210SBarry Smith PetscFunctionReturn(0); 6395fce210SBarry Smith } 6495fce210SBarry Smith 6529046d53SLisandro Dalcin /*@ 6695fce210SBarry Smith PetscSFReset - Reset a star forest so that different sizes or neighbors can be used 6795fce210SBarry Smith 6895fce210SBarry Smith Collective 6995fce210SBarry Smith 7095fce210SBarry Smith Input Arguments: 7195fce210SBarry Smith . sf - star forest 7295fce210SBarry Smith 7395fce210SBarry Smith Level: advanced 7495fce210SBarry Smith 7595fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFSetGraph(), PetscSFDestroy() 7695fce210SBarry Smith @*/ 7795fce210SBarry Smith PetscErrorCode PetscSFReset(PetscSF sf) 7895fce210SBarry Smith { 7995fce210SBarry Smith PetscErrorCode ierr; 8095fce210SBarry Smith 8195fce210SBarry Smith PetscFunctionBegin; 8295fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 8379715d56SJed Brown if (sf->ops->Reset) {ierr = (*sf->ops->Reset)(sf);CHKERRQ(ierr);} 8429046d53SLisandro Dalcin sf->nroots = -1; 8529046d53SLisandro Dalcin sf->nleaves = -1; 8629046d53SLisandro Dalcin sf->minleaf = PETSC_MAX_INT; 8729046d53SLisandro Dalcin sf->maxleaf = PETSC_MIN_INT; 8895fce210SBarry Smith sf->mine = NULL; 8995fce210SBarry Smith sf->remote = NULL; 9029046d53SLisandro Dalcin sf->graphset = PETSC_FALSE; 9129046d53SLisandro Dalcin ierr = PetscFree(sf->mine_alloc);CHKERRQ(ierr); 9295fce210SBarry Smith ierr = PetscFree(sf->remote_alloc);CHKERRQ(ierr); 9321c688dcSJed Brown sf->nranks = -1; 9429046d53SLisandro Dalcin ierr = PetscFree4(sf->ranks,sf->roffset,sf->rmine,sf->rremote);CHKERRQ(ierr); 9529046d53SLisandro Dalcin sf->degreeknown = PETSC_FALSE; 9695fce210SBarry Smith ierr = PetscFree(sf->degree);CHKERRQ(ierr); 9795fce210SBarry Smith if (sf->ingroup != MPI_GROUP_NULL) {ierr = MPI_Group_free(&sf->ingroup);CHKERRQ(ierr);} 9895fce210SBarry Smith if (sf->outgroup != MPI_GROUP_NULL) {ierr = MPI_Group_free(&sf->outgroup);CHKERRQ(ierr);} 9995fce210SBarry Smith ierr = PetscSFDestroy(&sf->multi);CHKERRQ(ierr); 100dd5b3ca6SJunchao Zhang ierr = PetscLayoutDestroy(&sf->map);CHKERRQ(ierr); 10195fce210SBarry Smith sf->setupcalled = PETSC_FALSE; 10295fce210SBarry Smith PetscFunctionReturn(0); 10395fce210SBarry Smith } 10495fce210SBarry Smith 10595fce210SBarry Smith /*@C 10629046d53SLisandro Dalcin PetscSFSetType - Set the PetscSF communication implementation 10795fce210SBarry Smith 10895fce210SBarry Smith Collective on PetscSF 10995fce210SBarry Smith 11095fce210SBarry Smith Input Parameters: 11195fce210SBarry Smith + sf - the PetscSF context 11295fce210SBarry Smith - type - a known method 11395fce210SBarry Smith 11495fce210SBarry Smith Options Database Key: 11595fce210SBarry Smith . -sf_type <type> - Sets the method; use -help for a list 11695fce210SBarry Smith of available methods (for instance, window, pt2pt, neighbor) 11795fce210SBarry Smith 11895fce210SBarry Smith Notes: 11995fce210SBarry Smith See "include/petscsf.h" for available methods (for instance) 12095fce210SBarry Smith + PETSCSFWINDOW - MPI-2/3 one-sided 12195fce210SBarry Smith - PETSCSFBASIC - basic implementation using MPI-1 two-sided 12295fce210SBarry Smith 12395fce210SBarry Smith Level: intermediate 12495fce210SBarry Smith 12595fce210SBarry Smith .seealso: PetscSFType, PetscSFCreate() 12695fce210SBarry Smith @*/ 12795fce210SBarry Smith PetscErrorCode PetscSFSetType(PetscSF sf,PetscSFType type) 12895fce210SBarry Smith { 12995fce210SBarry Smith PetscErrorCode ierr,(*r)(PetscSF); 13095fce210SBarry Smith PetscBool match; 13195fce210SBarry Smith 13295fce210SBarry Smith PetscFunctionBegin; 13395fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 13495fce210SBarry Smith PetscValidCharPointer(type,2); 13595fce210SBarry Smith 13695fce210SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)sf,type,&match);CHKERRQ(ierr); 13795fce210SBarry Smith if (match) PetscFunctionReturn(0); 13895fce210SBarry Smith 139adc40e5bSBarry Smith ierr = PetscFunctionListFind(PetscSFList,type,&r);CHKERRQ(ierr); 14095fce210SBarry Smith if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PetscSF type %s",type); 14129046d53SLisandro Dalcin /* Destroy the previous PetscSF implementation context */ 14229046d53SLisandro Dalcin if (sf->ops->Destroy) {ierr = (*(sf)->ops->Destroy)(sf);CHKERRQ(ierr);} 14395fce210SBarry Smith ierr = PetscMemzero(sf->ops,sizeof(*sf->ops));CHKERRQ(ierr); 14495fce210SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)sf,type);CHKERRQ(ierr); 14595fce210SBarry Smith ierr = (*r)(sf);CHKERRQ(ierr); 14695fce210SBarry Smith PetscFunctionReturn(0); 14795fce210SBarry Smith } 14895fce210SBarry Smith 14929046d53SLisandro Dalcin /*@C 15029046d53SLisandro Dalcin PetscSFGetType - Get the PetscSF communication implementation 15129046d53SLisandro Dalcin 15229046d53SLisandro Dalcin Not Collective 15329046d53SLisandro Dalcin 15429046d53SLisandro Dalcin Input Parameter: 15529046d53SLisandro Dalcin . sf - the PetscSF context 15629046d53SLisandro Dalcin 15729046d53SLisandro Dalcin Output Parameter: 15829046d53SLisandro Dalcin . type - the PetscSF type name 15929046d53SLisandro Dalcin 16029046d53SLisandro Dalcin Level: intermediate 16129046d53SLisandro Dalcin 16229046d53SLisandro Dalcin .seealso: PetscSFSetType(), PetscSFCreate() 16329046d53SLisandro Dalcin @*/ 16429046d53SLisandro Dalcin PetscErrorCode PetscSFGetType(PetscSF sf, PetscSFType *type) 16529046d53SLisandro Dalcin { 16629046d53SLisandro Dalcin PetscFunctionBegin; 16729046d53SLisandro Dalcin PetscValidHeaderSpecific(sf, PETSCSF_CLASSID,1); 16829046d53SLisandro Dalcin PetscValidPointer(type,2); 16929046d53SLisandro Dalcin *type = ((PetscObject)sf)->type_name; 17029046d53SLisandro Dalcin PetscFunctionReturn(0); 17129046d53SLisandro Dalcin } 17229046d53SLisandro Dalcin 173d36d33e4SMatthew G. Knepley /*@ 17495fce210SBarry Smith PetscSFDestroy - destroy star forest 17595fce210SBarry Smith 17695fce210SBarry Smith Collective 17795fce210SBarry Smith 17895fce210SBarry Smith Input Arguments: 17995fce210SBarry Smith . sf - address of star forest 18095fce210SBarry Smith 18195fce210SBarry Smith Level: intermediate 18295fce210SBarry Smith 18395fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFReset() 18495fce210SBarry Smith @*/ 18595fce210SBarry Smith PetscErrorCode PetscSFDestroy(PetscSF *sf) 18695fce210SBarry Smith { 18795fce210SBarry Smith PetscErrorCode ierr; 18895fce210SBarry Smith 18995fce210SBarry Smith PetscFunctionBegin; 19095fce210SBarry Smith if (!*sf) PetscFunctionReturn(0); 19195fce210SBarry Smith PetscValidHeaderSpecific((*sf),PETSCSF_CLASSID,1); 19229046d53SLisandro Dalcin if (--((PetscObject)(*sf))->refct > 0) {*sf = NULL; PetscFunctionReturn(0);} 19395fce210SBarry Smith ierr = PetscSFReset(*sf);CHKERRQ(ierr); 19495fce210SBarry Smith if ((*sf)->ops->Destroy) {ierr = (*(*sf)->ops->Destroy)(*sf);CHKERRQ(ierr);} 19595fce210SBarry Smith ierr = PetscHeaderDestroy(sf);CHKERRQ(ierr); 19695fce210SBarry Smith PetscFunctionReturn(0); 19795fce210SBarry Smith } 19895fce210SBarry Smith 19995fce210SBarry Smith /*@ 20095fce210SBarry Smith PetscSFSetUp - set up communication structures 20195fce210SBarry Smith 20295fce210SBarry Smith Collective 20395fce210SBarry Smith 20495fce210SBarry Smith Input Arguments: 20595fce210SBarry Smith . sf - star forest communication object 20695fce210SBarry Smith 20795fce210SBarry Smith Level: beginner 20895fce210SBarry Smith 20995fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFSetType() 21095fce210SBarry Smith @*/ 21195fce210SBarry Smith PetscErrorCode PetscSFSetUp(PetscSF sf) 21295fce210SBarry Smith { 21395fce210SBarry Smith PetscErrorCode ierr; 21495fce210SBarry Smith 21595fce210SBarry Smith PetscFunctionBegin; 21629046d53SLisandro Dalcin PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 21729046d53SLisandro Dalcin PetscSFCheckGraphSet(sf,1); 21895fce210SBarry Smith if (sf->setupcalled) PetscFunctionReturn(0); 21995fce210SBarry Smith if (!((PetscObject)sf)->type_name) {ierr = PetscSFSetType(sf,PETSCSFBASIC);CHKERRQ(ierr);} 22029046d53SLisandro Dalcin ierr = PetscLogEventBegin(PETSCSF_SetUp,sf,0,0,0);CHKERRQ(ierr); 22195fce210SBarry Smith if (sf->ops->SetUp) {ierr = (*sf->ops->SetUp)(sf);CHKERRQ(ierr);} 22229046d53SLisandro Dalcin ierr = PetscLogEventEnd(PETSCSF_SetUp,sf,0,0,0);CHKERRQ(ierr); 22395fce210SBarry Smith sf->setupcalled = PETSC_TRUE; 22495fce210SBarry Smith PetscFunctionReturn(0); 22595fce210SBarry Smith } 22695fce210SBarry Smith 2278af6ec1cSBarry Smith /*@ 22895fce210SBarry Smith PetscSFSetFromOptions - set PetscSF options using the options database 22995fce210SBarry Smith 23095fce210SBarry Smith Logically Collective 23195fce210SBarry Smith 23295fce210SBarry Smith Input Arguments: 23395fce210SBarry Smith . sf - star forest 23495fce210SBarry Smith 23595fce210SBarry Smith Options Database Keys: 23660263706SJed Brown + -sf_type - implementation type, see PetscSFSetType() 23760263706SJed Brown - -sf_rank_order - sort composite points for gathers and scatters in rank order, gathers are non-deterministic otherwise 23895fce210SBarry Smith 23995fce210SBarry Smith Level: intermediate 24095fce210SBarry Smith 24195fce210SBarry Smith .seealso: PetscSFWindowSetSyncType() 24295fce210SBarry Smith @*/ 24395fce210SBarry Smith PetscErrorCode PetscSFSetFromOptions(PetscSF sf) 24495fce210SBarry Smith { 24595fce210SBarry Smith PetscSFType deft; 24695fce210SBarry Smith char type[256]; 24795fce210SBarry Smith PetscErrorCode ierr; 24895fce210SBarry Smith PetscBool flg; 24995fce210SBarry Smith 25095fce210SBarry Smith PetscFunctionBegin; 25195fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 25295fce210SBarry Smith ierr = PetscObjectOptionsBegin((PetscObject)sf);CHKERRQ(ierr); 25395fce210SBarry Smith deft = ((PetscObject)sf)->type_name ? ((PetscObject)sf)->type_name : PETSCSFBASIC; 25429046d53SLisandro Dalcin ierr = PetscOptionsFList("-sf_type","PetscSF implementation type","PetscSFSetType",PetscSFList,deft,type,sizeof(type),&flg);CHKERRQ(ierr); 25595fce210SBarry Smith ierr = PetscSFSetType(sf,flg ? type : deft);CHKERRQ(ierr); 25695fce210SBarry Smith 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); 257e55864a3SBarry Smith if (sf->ops->SetFromOptions) {ierr = (*sf->ops->SetFromOptions)(PetscOptionsObject,sf);CHKERRQ(ierr);} 25895fce210SBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 25995fce210SBarry Smith PetscFunctionReturn(0); 26095fce210SBarry Smith } 26195fce210SBarry Smith 26229046d53SLisandro Dalcin /*@ 26395fce210SBarry Smith PetscSFSetRankOrder - sort multi-points for gathers and scatters by rank order 26495fce210SBarry Smith 26595fce210SBarry Smith Logically Collective 26695fce210SBarry Smith 26795fce210SBarry Smith Input Arguments: 26895fce210SBarry Smith + sf - star forest 26995fce210SBarry Smith - flg - PETSC_TRUE to sort, PETSC_FALSE to skip sorting (lower setup cost, but non-deterministic) 27095fce210SBarry Smith 27195fce210SBarry Smith Level: advanced 27295fce210SBarry Smith 27395fce210SBarry Smith .seealso: PetscSFGatherBegin(), PetscSFScatterBegin() 27495fce210SBarry Smith @*/ 27595fce210SBarry Smith PetscErrorCode PetscSFSetRankOrder(PetscSF sf,PetscBool flg) 27695fce210SBarry Smith { 27795fce210SBarry Smith 27895fce210SBarry Smith PetscFunctionBegin; 27995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 28095fce210SBarry Smith PetscValidLogicalCollectiveBool(sf,flg,2); 28195fce210SBarry Smith if (sf->multi) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Rank ordering must be set before first call to PetscSFGatherBegin() or PetscSFScatterBegin()"); 28295fce210SBarry Smith sf->rankorder = flg; 28395fce210SBarry Smith PetscFunctionReturn(0); 28495fce210SBarry Smith } 28595fce210SBarry Smith 2868af6ec1cSBarry Smith /*@ 28795fce210SBarry Smith PetscSFSetGraph - Set a parallel star forest 28895fce210SBarry Smith 28995fce210SBarry Smith Collective 29095fce210SBarry Smith 29195fce210SBarry Smith Input Arguments: 29295fce210SBarry Smith + sf - star forest 29395fce210SBarry Smith . nroots - number of root vertices on the current process (these are possible targets for other process to attach leaves) 29495fce210SBarry Smith . nleaves - number of leaf vertices on the current process, each of these references a root on any process 29595fce210SBarry Smith . ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage 29695fce210SBarry Smith . localmode - copy mode for ilocal 29795fce210SBarry Smith . iremote - remote locations of root vertices for each leaf on the current process 29895fce210SBarry Smith - remotemode - copy mode for iremote 29995fce210SBarry Smith 30095fce210SBarry Smith Level: intermediate 30195fce210SBarry Smith 30295452b02SPatrick Sanan Notes: 30395452b02SPatrick Sanan In Fortran you must use PETSC_COPY_VALUES for localmode and remotemode 30438ab3f8aSBarry Smith 3052ad1e87fSLisandro Dalcin Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they 3062ad1e87fSLisandro Dalcin encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not 3072ad1e87fSLisandro Dalcin needed 3082ad1e87fSLisandro Dalcin 30995fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFGetGraph() 31095fce210SBarry Smith @*/ 31195fce210SBarry Smith PetscErrorCode PetscSFSetGraph(PetscSF sf,PetscInt nroots,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscSFNode *iremote,PetscCopyMode remotemode) 31295fce210SBarry Smith { 31395fce210SBarry Smith PetscErrorCode ierr; 31495fce210SBarry Smith 31595fce210SBarry Smith PetscFunctionBegin; 31695fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 31729046d53SLisandro Dalcin if (nleaves > 0 && ilocal) PetscValidIntPointer(ilocal,4); 31829046d53SLisandro Dalcin if (nleaves > 0) PetscValidPointer(iremote,6); 31929046d53SLisandro Dalcin if (nroots < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nroots %D, cannot be negative",nroots); 32095fce210SBarry Smith if (nleaves < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nleaves %D, cannot be negative",nleaves); 32129046d53SLisandro Dalcin 32295fce210SBarry Smith ierr = PetscSFReset(sf);CHKERRQ(ierr); 32329046d53SLisandro Dalcin ierr = PetscLogEventBegin(PETSCSF_SetGraph,sf,0,0,0);CHKERRQ(ierr); 32429046d53SLisandro Dalcin 32595fce210SBarry Smith sf->nroots = nroots; 32695fce210SBarry Smith sf->nleaves = nleaves; 32729046d53SLisandro Dalcin 32829046d53SLisandro Dalcin if (nleaves && ilocal) { 32921c688dcSJed Brown PetscInt i; 33029046d53SLisandro Dalcin PetscInt minleaf = PETSC_MAX_INT; 33129046d53SLisandro Dalcin PetscInt maxleaf = PETSC_MIN_INT; 3322ad1e87fSLisandro Dalcin int contiguous = 1; 33329046d53SLisandro Dalcin for (i=0; i<nleaves; i++) { 33429046d53SLisandro Dalcin minleaf = PetscMin(minleaf,ilocal[i]); 33529046d53SLisandro Dalcin maxleaf = PetscMax(maxleaf,ilocal[i]); 3362ad1e87fSLisandro Dalcin contiguous &= (ilocal[i] == i); 33729046d53SLisandro Dalcin } 33829046d53SLisandro Dalcin sf->minleaf = minleaf; 33929046d53SLisandro Dalcin sf->maxleaf = maxleaf; 3402ad1e87fSLisandro Dalcin if (contiguous) { 3412ad1e87fSLisandro Dalcin if (localmode == PETSC_OWN_POINTER) { 3422ad1e87fSLisandro Dalcin ierr = PetscFree(ilocal);CHKERRQ(ierr); 3432ad1e87fSLisandro Dalcin } 3442ad1e87fSLisandro Dalcin ilocal = NULL; 3452ad1e87fSLisandro Dalcin } 34629046d53SLisandro Dalcin } else { 34729046d53SLisandro Dalcin sf->minleaf = 0; 34829046d53SLisandro Dalcin sf->maxleaf = nleaves - 1; 34929046d53SLisandro Dalcin } 35029046d53SLisandro Dalcin 35129046d53SLisandro Dalcin if (ilocal) { 35295fce210SBarry Smith switch (localmode) { 35395fce210SBarry Smith case PETSC_COPY_VALUES: 354785e854fSJed Brown ierr = PetscMalloc1(nleaves,&sf->mine_alloc);CHKERRQ(ierr); 355580bdb30SBarry Smith ierr = PetscArraycpy(sf->mine_alloc,ilocal,nleaves);CHKERRQ(ierr); 35695fce210SBarry Smith sf->mine = sf->mine_alloc; 35795fce210SBarry Smith break; 35895fce210SBarry Smith case PETSC_OWN_POINTER: 35995fce210SBarry Smith sf->mine_alloc = (PetscInt*)ilocal; 36095fce210SBarry Smith sf->mine = sf->mine_alloc; 36195fce210SBarry Smith break; 36295fce210SBarry Smith case PETSC_USE_POINTER: 36329046d53SLisandro Dalcin sf->mine_alloc = NULL; 36495fce210SBarry Smith sf->mine = (PetscInt*)ilocal; 36595fce210SBarry Smith break; 36695fce210SBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_OUTOFRANGE,"Unknown localmode"); 36795fce210SBarry Smith } 36895fce210SBarry Smith } 36929046d53SLisandro Dalcin 37095fce210SBarry Smith switch (remotemode) { 37195fce210SBarry Smith case PETSC_COPY_VALUES: 372785e854fSJed Brown ierr = PetscMalloc1(nleaves,&sf->remote_alloc);CHKERRQ(ierr); 373580bdb30SBarry Smith ierr = PetscArraycpy(sf->remote_alloc,iremote,nleaves);CHKERRQ(ierr); 37495fce210SBarry Smith sf->remote = sf->remote_alloc; 37595fce210SBarry Smith break; 37695fce210SBarry Smith case PETSC_OWN_POINTER: 37795fce210SBarry Smith sf->remote_alloc = (PetscSFNode*)iremote; 37895fce210SBarry Smith sf->remote = sf->remote_alloc; 37995fce210SBarry Smith break; 38095fce210SBarry Smith case PETSC_USE_POINTER: 38129046d53SLisandro Dalcin sf->remote_alloc = NULL; 38295fce210SBarry Smith sf->remote = (PetscSFNode*)iremote; 38395fce210SBarry Smith break; 38495fce210SBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_OUTOFRANGE,"Unknown remotemode"); 38595fce210SBarry Smith } 38695fce210SBarry Smith 387563ffbabSMatthew G. Knepley ierr = PetscLogEventEnd(PETSCSF_SetGraph,sf,0,0,0);CHKERRQ(ierr); 38829046d53SLisandro Dalcin sf->graphset = PETSC_TRUE; 38995fce210SBarry Smith PetscFunctionReturn(0); 39095fce210SBarry Smith } 39195fce210SBarry Smith 39229046d53SLisandro Dalcin /*@ 393dd5b3ca6SJunchao Zhang PetscSFSetGraphWithPattern - Sets the graph of an SF with a specific pattern 394dd5b3ca6SJunchao Zhang 395dd5b3ca6SJunchao Zhang Collective 396dd5b3ca6SJunchao Zhang 397dd5b3ca6SJunchao Zhang Input Parameters: 398dd5b3ca6SJunchao Zhang + sf - The PetscSF 399dd5b3ca6SJunchao Zhang . map - Layout of roots over all processes (insignificant when pattern is PETSCSF_PATTERN_ALLTOALL) 400dd5b3ca6SJunchao Zhang - pattern - One of PETSCSF_PATTERN_ALLGATHER, PETSCSF_PATTERN_GATHER, PETSCSF_PATTERN_ALLTOALL 401dd5b3ca6SJunchao Zhang 402dd5b3ca6SJunchao Zhang Notes: 403dd5b3ca6SJunchao Zhang It is easier to explain PetscSFPattern using vectors. Suppose we have an MPI vector x and its layout is map. 404dd5b3ca6SJunchao Zhang n and N are local and global sizes of x respectively. 405dd5b3ca6SJunchao Zhang 406dd5b3ca6SJunchao Zhang With PETSCSF_PATTERN_ALLGATHER, the routine creates a graph that if one does Bcast on it, it will copy x to 407dd5b3ca6SJunchao Zhang sequential vectors y on all ranks. 408dd5b3ca6SJunchao Zhang 409dd5b3ca6SJunchao Zhang With PETSCSF_PATTERN_GATHER, the routine creates a graph that if one does Bcast on it, it will copy x to a 410dd5b3ca6SJunchao Zhang sequential vector y on rank 0. 411dd5b3ca6SJunchao Zhang 412dd5b3ca6SJunchao Zhang In above cases, entries of x are roots and entries of y are leaves. 413dd5b3ca6SJunchao Zhang 414dd5b3ca6SJunchao Zhang With PETSCSF_PATTERN_ALLTOALL, map is insignificant. Suppose NP is size of sf's communicator. The routine 415dd5b3ca6SJunchao Zhang creates a graph that every rank has NP leaves and NP roots. On rank i, its leaf j is connected to root i 416dd5b3ca6SJunchao Zhang of rank j. Here 0 <=i,j<NP. It is a kind of MPI_Alltoall with sendcount/recvcount being 1. Note that it does 417dd5b3ca6SJunchao Zhang not mean one can not send multiple items. One just needs to create a new MPI datatype for the mulptiple data 418dd5b3ca6SJunchao Zhang items with MPI_Type_contiguous() and use that as the <unit> argument in SF routines. 419dd5b3ca6SJunchao Zhang 420dd5b3ca6SJunchao Zhang In this case, roots and leaves are symmetric. 421dd5b3ca6SJunchao Zhang 422dd5b3ca6SJunchao Zhang Level: intermediate 423dd5b3ca6SJunchao Zhang @*/ 424dd5b3ca6SJunchao Zhang PetscErrorCode PetscSFSetGraphWithPattern(PetscSF sf,PetscLayout map,PetscSFPattern pattern) 425dd5b3ca6SJunchao Zhang { 426dd5b3ca6SJunchao Zhang MPI_Comm comm; 427dd5b3ca6SJunchao Zhang PetscInt n,N,res[2]; 428dd5b3ca6SJunchao Zhang PetscMPIInt rank,size; 429dd5b3ca6SJunchao Zhang PetscSFType type; 430dd5b3ca6SJunchao Zhang PetscErrorCode ierr; 431dd5b3ca6SJunchao Zhang 432dd5b3ca6SJunchao Zhang PetscFunctionBegin; 433dd5b3ca6SJunchao Zhang ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr); 434dd5b3ca6SJunchao Zhang if (pattern < PETSCSF_PATTERN_ALLGATHER || pattern > PETSCSF_PATTERN_ALLTOALL) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Unsupported PetscSFPattern %D\n",pattern); 435dd5b3ca6SJunchao Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 436dd5b3ca6SJunchao Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 437dd5b3ca6SJunchao Zhang 438dd5b3ca6SJunchao Zhang if (pattern == PETSCSF_PATTERN_ALLTOALL) { 439dd5b3ca6SJunchao Zhang type = PETSCSFALLTOALL; 440dd5b3ca6SJunchao Zhang ierr = PetscLayoutCreate(comm,&sf->map);CHKERRQ(ierr); 441dd5b3ca6SJunchao Zhang ierr = PetscLayoutSetLocalSize(sf->map,size);CHKERRQ(ierr); 442dd5b3ca6SJunchao Zhang ierr = PetscLayoutSetSize(sf->map,((PetscInt)size)*size);CHKERRQ(ierr); 443dd5b3ca6SJunchao Zhang ierr = PetscLayoutSetUp(sf->map);CHKERRQ(ierr); 444dd5b3ca6SJunchao Zhang } else { 445dd5b3ca6SJunchao Zhang ierr = PetscLayoutGetLocalSize(map,&n);CHKERRQ(ierr); 446dd5b3ca6SJunchao Zhang ierr = PetscLayoutGetSize(map,&N);CHKERRQ(ierr); 447dd5b3ca6SJunchao Zhang res[0] = n; 448dd5b3ca6SJunchao Zhang res[1] = -n; 449dd5b3ca6SJunchao Zhang /* Check if n are same over all ranks so that we can optimize it */ 450dd5b3ca6SJunchao Zhang ierr = MPIU_Allreduce(MPI_IN_PLACE,res,2,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr); 451dd5b3ca6SJunchao Zhang if (res[0] == -res[1]) { /* same n */ 452dd5b3ca6SJunchao Zhang type = (pattern == PETSCSF_PATTERN_ALLGATHER) ? PETSCSFALLGATHER : PETSCSFGATHER; 453dd5b3ca6SJunchao Zhang } else { 454dd5b3ca6SJunchao Zhang type = (pattern == PETSCSF_PATTERN_ALLGATHER) ? PETSCSFALLGATHERV : PETSCSFGATHERV; 455dd5b3ca6SJunchao Zhang } 456dd5b3ca6SJunchao Zhang ierr = PetscLayoutReference(map,&sf->map);CHKERRQ(ierr); 457dd5b3ca6SJunchao Zhang } 458dd5b3ca6SJunchao Zhang ierr = PetscSFSetType(sf,type);CHKERRQ(ierr); 459dd5b3ca6SJunchao Zhang 460dd5b3ca6SJunchao Zhang sf->pattern = pattern; 461dd5b3ca6SJunchao Zhang sf->mine = NULL; /* Contiguous */ 462dd5b3ca6SJunchao Zhang 463dd5b3ca6SJunchao Zhang /* Set nleaves, nroots here in case user calls PetscSFGetGraph, which is legal to call even before PetscSFSetUp is called. 464dd5b3ca6SJunchao Zhang Also set other easy stuff. 465dd5b3ca6SJunchao Zhang */ 466dd5b3ca6SJunchao Zhang if (pattern == PETSCSF_PATTERN_ALLGATHER) { 467dd5b3ca6SJunchao Zhang sf->nleaves = N; 468dd5b3ca6SJunchao Zhang sf->nroots = n; 469dd5b3ca6SJunchao Zhang sf->nranks = size; 470dd5b3ca6SJunchao Zhang sf->minleaf = 0; 471dd5b3ca6SJunchao Zhang sf->maxleaf = N - 1; 472dd5b3ca6SJunchao Zhang } else if (pattern == PETSCSF_PATTERN_GATHER) { 473dd5b3ca6SJunchao Zhang sf->nleaves = rank ? 0 : N; 474dd5b3ca6SJunchao Zhang sf->nroots = n; 475dd5b3ca6SJunchao Zhang sf->nranks = rank ? 0 : size; 476dd5b3ca6SJunchao Zhang sf->minleaf = 0; 477dd5b3ca6SJunchao Zhang sf->maxleaf = rank ? -1 : N - 1; 478dd5b3ca6SJunchao Zhang } else if (pattern == PETSCSF_PATTERN_ALLTOALL) { 479dd5b3ca6SJunchao Zhang sf->nleaves = size; 480dd5b3ca6SJunchao Zhang sf->nroots = size; 481dd5b3ca6SJunchao Zhang sf->nranks = size; 482dd5b3ca6SJunchao Zhang sf->minleaf = 0; 483dd5b3ca6SJunchao Zhang sf->maxleaf = size - 1; 484dd5b3ca6SJunchao Zhang } 485dd5b3ca6SJunchao Zhang sf->ndranks = 0; /* We do not need to separate out distinguished ranks for patterned graphs to improve communication performance */ 486dd5b3ca6SJunchao Zhang sf->graphset = PETSC_TRUE; 487dd5b3ca6SJunchao Zhang PetscFunctionReturn(0); 488dd5b3ca6SJunchao Zhang } 489dd5b3ca6SJunchao Zhang 490dd5b3ca6SJunchao Zhang /*@ 49195fce210SBarry Smith PetscSFCreateInverseSF - given a PetscSF in which all vertices have degree 1, creates the inverse map 49295fce210SBarry Smith 49395fce210SBarry Smith Collective 49495fce210SBarry Smith 49595fce210SBarry Smith Input Arguments: 496dd5b3ca6SJunchao Zhang 49795fce210SBarry Smith . sf - star forest to invert 49895fce210SBarry Smith 49995fce210SBarry Smith Output Arguments: 50095fce210SBarry Smith . isf - inverse of sf 50195fce210SBarry Smith Level: advanced 50295fce210SBarry Smith 50395fce210SBarry Smith Notes: 50495fce210SBarry Smith All roots must have degree 1. 50595fce210SBarry Smith 50695fce210SBarry Smith The local space may be a permutation, but cannot be sparse. 50795fce210SBarry Smith 50895fce210SBarry Smith .seealso: PetscSFSetGraph() 50995fce210SBarry Smith @*/ 51095fce210SBarry Smith PetscErrorCode PetscSFCreateInverseSF(PetscSF sf,PetscSF *isf) 51195fce210SBarry Smith { 51295fce210SBarry Smith PetscErrorCode ierr; 51395fce210SBarry Smith PetscMPIInt rank; 51495fce210SBarry Smith PetscInt i,nroots,nleaves,maxlocal,count,*newilocal; 51595fce210SBarry Smith const PetscInt *ilocal; 51695fce210SBarry Smith PetscSFNode *roots,*leaves; 51795fce210SBarry Smith 51895fce210SBarry Smith PetscFunctionBegin; 51929046d53SLisandro Dalcin PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 52029046d53SLisandro Dalcin PetscSFCheckGraphSet(sf,1); 52129046d53SLisandro Dalcin PetscValidPointer(isf,2); 52229046d53SLisandro Dalcin 52395fce210SBarry Smith ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr); 52429046d53SLisandro Dalcin maxlocal = sf->maxleaf+1; /* TODO: We should use PetscSFGetLeafRange() */ 52529046d53SLisandro Dalcin 52629046d53SLisandro Dalcin ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr); 527ae9aee6dSMatthew G. Knepley ierr = PetscMalloc2(nroots,&roots,maxlocal,&leaves);CHKERRQ(ierr); 528ae9aee6dSMatthew G. Knepley for (i=0; i<maxlocal; i++) { 52995fce210SBarry Smith leaves[i].rank = rank; 53095fce210SBarry Smith leaves[i].index = i; 53195fce210SBarry Smith } 53295fce210SBarry Smith for (i=0; i <nroots; i++) { 53395fce210SBarry Smith roots[i].rank = -1; 53495fce210SBarry Smith roots[i].index = -1; 53595fce210SBarry Smith } 5368bfbc91cSJed Brown ierr = PetscSFReduceBegin(sf,MPIU_2INT,leaves,roots,MPIU_REPLACE);CHKERRQ(ierr); 5378bfbc91cSJed Brown ierr = PetscSFReduceEnd(sf,MPIU_2INT,leaves,roots,MPIU_REPLACE);CHKERRQ(ierr); 53895fce210SBarry Smith 53995fce210SBarry Smith /* Check whether our leaves are sparse */ 54095fce210SBarry Smith for (i=0,count=0; i<nroots; i++) if (roots[i].rank >= 0) count++; 54195fce210SBarry Smith if (count == nroots) newilocal = NULL; 54295fce210SBarry Smith else { /* Index for sparse leaves and compact "roots" array (which is to become our leaves). */ 543785e854fSJed Brown ierr = PetscMalloc1(count,&newilocal);CHKERRQ(ierr); 54495fce210SBarry Smith for (i=0,count=0; i<nroots; i++) { 54595fce210SBarry Smith if (roots[i].rank >= 0) { 54695fce210SBarry Smith newilocal[count] = i; 54795fce210SBarry Smith roots[count].rank = roots[i].rank; 54895fce210SBarry Smith roots[count].index = roots[i].index; 54995fce210SBarry Smith count++; 55095fce210SBarry Smith } 55195fce210SBarry Smith } 55295fce210SBarry Smith } 55395fce210SBarry Smith 55495fce210SBarry Smith ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_CONFONLY,isf);CHKERRQ(ierr); 55595fce210SBarry Smith ierr = PetscSFSetGraph(*isf,maxlocal,count,newilocal,PETSC_OWN_POINTER,roots,PETSC_COPY_VALUES);CHKERRQ(ierr); 55695fce210SBarry Smith ierr = PetscFree2(roots,leaves);CHKERRQ(ierr); 55795fce210SBarry Smith PetscFunctionReturn(0); 55895fce210SBarry Smith } 55995fce210SBarry Smith 56095fce210SBarry Smith /*@ 56195fce210SBarry Smith PetscSFDuplicate - duplicate a PetscSF, optionally preserving rank connectivity and graph 56295fce210SBarry Smith 56395fce210SBarry Smith Collective 56495fce210SBarry Smith 56595fce210SBarry Smith Input Arguments: 56695fce210SBarry Smith + sf - communication object to duplicate 56795fce210SBarry Smith - opt - PETSCSF_DUPLICATE_CONFONLY, PETSCSF_DUPLICATE_RANKS, or PETSCSF_DUPLICATE_GRAPH (see PetscSFDuplicateOption) 56895fce210SBarry Smith 56995fce210SBarry Smith Output Arguments: 57095fce210SBarry Smith . newsf - new communication object 57195fce210SBarry Smith 57295fce210SBarry Smith Level: beginner 57395fce210SBarry Smith 57495fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFSetType(), PetscSFSetGraph() 57595fce210SBarry Smith @*/ 57695fce210SBarry Smith PetscErrorCode PetscSFDuplicate(PetscSF sf,PetscSFDuplicateOption opt,PetscSF *newsf) 57795fce210SBarry Smith { 57829046d53SLisandro Dalcin PetscSFType type; 57995fce210SBarry Smith PetscErrorCode ierr; 58095fce210SBarry Smith 58195fce210SBarry Smith PetscFunctionBegin; 58229046d53SLisandro Dalcin PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 58329046d53SLisandro Dalcin PetscValidLogicalCollectiveEnum(sf,opt,2); 58429046d53SLisandro Dalcin PetscValidPointer(newsf,3); 58595fce210SBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)sf),newsf);CHKERRQ(ierr); 58629046d53SLisandro Dalcin ierr = PetscSFGetType(sf,&type);CHKERRQ(ierr); 58729046d53SLisandro Dalcin if (type) {ierr = PetscSFSetType(*newsf,type);CHKERRQ(ierr);} 58895fce210SBarry Smith if (opt == PETSCSF_DUPLICATE_GRAPH) { 589dd5b3ca6SJunchao Zhang PetscSFCheckGraphSet(sf,1); 590dd5b3ca6SJunchao Zhang if (sf->pattern == PETSCSF_PATTERN_GENERAL) { 59195fce210SBarry Smith PetscInt nroots,nleaves; 59295fce210SBarry Smith const PetscInt *ilocal; 59395fce210SBarry Smith const PetscSFNode *iremote; 59495fce210SBarry Smith ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 59595fce210SBarry Smith ierr = PetscSFSetGraph(*newsf,nroots,nleaves,ilocal,PETSC_COPY_VALUES,iremote,PETSC_COPY_VALUES);CHKERRQ(ierr); 596dd5b3ca6SJunchao Zhang } else { 597dd5b3ca6SJunchao Zhang ierr = PetscSFSetGraphWithPattern(*newsf,sf->map,sf->pattern);CHKERRQ(ierr); 598dd5b3ca6SJunchao Zhang } 59995fce210SBarry Smith } 60029046d53SLisandro Dalcin if (sf->ops->Duplicate) {ierr = (*sf->ops->Duplicate)(sf,opt,*newsf);CHKERRQ(ierr);} 60195fce210SBarry Smith PetscFunctionReturn(0); 60295fce210SBarry Smith } 60395fce210SBarry Smith 60495fce210SBarry Smith /*@C 60595fce210SBarry Smith PetscSFGetGraph - Get the graph specifying a parallel star forest 60695fce210SBarry Smith 60795fce210SBarry Smith Not Collective 60895fce210SBarry Smith 60995fce210SBarry Smith Input Arguments: 61095fce210SBarry Smith . sf - star forest 61195fce210SBarry Smith 61295fce210SBarry Smith Output Arguments: 61395fce210SBarry Smith + nroots - number of root vertices on the current process (these are possible targets for other process to attach leaves) 61495fce210SBarry Smith . nleaves - number of leaf vertices on the current process, each of these references a root on any process 61595fce210SBarry Smith . ilocal - locations of leaves in leafdata buffers 61695fce210SBarry Smith - iremote - remote locations of root vertices for each leaf on the current process 61795fce210SBarry Smith 618373e0d91SLisandro Dalcin Notes: 619373e0d91SLisandro Dalcin We are not currently requiring that the graph is set, thus returning nroots=-1 if it has not been set yet 620373e0d91SLisandro Dalcin 62195fce210SBarry Smith Level: intermediate 62295fce210SBarry Smith 62395fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph() 62495fce210SBarry Smith @*/ 62595fce210SBarry Smith PetscErrorCode PetscSFGetGraph(PetscSF sf,PetscInt *nroots,PetscInt *nleaves,const PetscInt **ilocal,const PetscSFNode **iremote) 62695fce210SBarry Smith { 627b8dee149SJunchao Zhang PetscErrorCode ierr; 62895fce210SBarry Smith 62995fce210SBarry Smith PetscFunctionBegin; 63095fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 631b8dee149SJunchao Zhang if (sf->ops->GetGraph) { 632b8dee149SJunchao Zhang ierr = (sf->ops->GetGraph)(sf,nroots,nleaves,ilocal,iremote);CHKERRQ(ierr); 633b8dee149SJunchao Zhang } else { 63495fce210SBarry Smith if (nroots) *nroots = sf->nroots; 63595fce210SBarry Smith if (nleaves) *nleaves = sf->nleaves; 63695fce210SBarry Smith if (ilocal) *ilocal = sf->mine; 63795fce210SBarry Smith if (iremote) *iremote = sf->remote; 638b8dee149SJunchao Zhang } 63995fce210SBarry Smith PetscFunctionReturn(0); 64095fce210SBarry Smith } 64195fce210SBarry Smith 64229046d53SLisandro Dalcin /*@ 64395fce210SBarry Smith PetscSFGetLeafRange - Get the active leaf ranges 64495fce210SBarry Smith 64595fce210SBarry Smith Not Collective 64695fce210SBarry Smith 64795fce210SBarry Smith Input Arguments: 64895fce210SBarry Smith . sf - star forest 64995fce210SBarry Smith 65095fce210SBarry Smith Output Arguments: 651dd5b3ca6SJunchao Zhang + minleaf - minimum active leaf on this process. Return 0 if there are no leaves. 652dd5b3ca6SJunchao Zhang - maxleaf - maximum active leaf on this process. Return -1 if there are no leaves. 65395fce210SBarry Smith 65495fce210SBarry Smith Level: developer 65595fce210SBarry Smith 65695fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph() 65795fce210SBarry Smith @*/ 65895fce210SBarry Smith PetscErrorCode PetscSFGetLeafRange(PetscSF sf,PetscInt *minleaf,PetscInt *maxleaf) 65995fce210SBarry Smith { 66095fce210SBarry Smith 66195fce210SBarry Smith PetscFunctionBegin; 66295fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 66329046d53SLisandro Dalcin PetscSFCheckGraphSet(sf,1); 66495fce210SBarry Smith if (minleaf) *minleaf = sf->minleaf; 66595fce210SBarry Smith if (maxleaf) *maxleaf = sf->maxleaf; 66695fce210SBarry Smith PetscFunctionReturn(0); 66795fce210SBarry Smith } 66895fce210SBarry Smith 66995fce210SBarry Smith /*@C 67095fce210SBarry Smith PetscSFView - view a star forest 67195fce210SBarry Smith 67295fce210SBarry Smith Collective 67395fce210SBarry Smith 67495fce210SBarry Smith Input Arguments: 67595fce210SBarry Smith + sf - star forest 67695fce210SBarry Smith - viewer - viewer to display graph, for example PETSC_VIEWER_STDOUT_WORLD 67795fce210SBarry Smith 67895fce210SBarry Smith Level: beginner 67995fce210SBarry Smith 68095fce210SBarry Smith .seealso: PetscSFCreate(), PetscSFSetGraph() 68195fce210SBarry Smith @*/ 68295fce210SBarry Smith PetscErrorCode PetscSFView(PetscSF sf,PetscViewer viewer) 68395fce210SBarry Smith { 68495fce210SBarry Smith PetscErrorCode ierr; 68595fce210SBarry Smith PetscBool iascii; 68695fce210SBarry Smith PetscViewerFormat format; 68795fce210SBarry Smith 68895fce210SBarry Smith PetscFunctionBegin; 68995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 69095fce210SBarry Smith if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sf),&viewer);CHKERRQ(ierr);} 69195fce210SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 69295fce210SBarry Smith PetscCheckSameComm(sf,1,viewer,2); 69380153354SVaclav Hapla if (sf->graphset) {ierr = PetscSFSetUp(sf);CHKERRQ(ierr);} 69495fce210SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 69595fce210SBarry Smith if (iascii) { 69695fce210SBarry Smith PetscMPIInt rank; 69781bfa7aaSJed Brown PetscInt ii,i,j; 69895fce210SBarry Smith 699dae58748SBarry Smith ierr = PetscObjectPrintClassNamePrefixType((PetscObject)sf,viewer);CHKERRQ(ierr); 70095fce210SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 70195fce210SBarry Smith if (sf->ops->View) {ierr = (*sf->ops->View)(sf,viewer);CHKERRQ(ierr);} 702dd5b3ca6SJunchao Zhang if (sf->pattern == PETSCSF_PATTERN_GENERAL) { 70380153354SVaclav Hapla if (!sf->graphset) { 70480153354SVaclav Hapla ierr = PetscViewerASCIIPrintf(viewer,"PetscSFSetGraph() has not been called yet\n");CHKERRQ(ierr); 70580153354SVaclav Hapla ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 70680153354SVaclav Hapla PetscFunctionReturn(0); 70780153354SVaclav Hapla } 70895fce210SBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr); 7091575c14dSBarry Smith ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 71095fce210SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of roots=%D, leaves=%D, remote ranks=%D\n",rank,sf->nroots,sf->nleaves,sf->nranks);CHKERRQ(ierr); 71195fce210SBarry Smith for (i=0; i<sf->nleaves; i++) { 71295fce210SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D <- (%D,%D)\n",rank,sf->mine ? sf->mine[i] : i,sf->remote[i].rank,sf->remote[i].index);CHKERRQ(ierr); 71395fce210SBarry Smith } 71495fce210SBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 71595fce210SBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 71695fce210SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 71781bfa7aaSJed Brown PetscMPIInt *tmpranks,*perm; 71881bfa7aaSJed Brown ierr = PetscMalloc2(sf->nranks,&tmpranks,sf->nranks,&perm);CHKERRQ(ierr); 719580bdb30SBarry Smith ierr = PetscArraycpy(tmpranks,sf->ranks,sf->nranks);CHKERRQ(ierr); 72081bfa7aaSJed Brown for (i=0; i<sf->nranks; i++) perm[i] = i; 72181bfa7aaSJed Brown ierr = PetscSortMPIIntWithArray(sf->nranks,tmpranks,perm);CHKERRQ(ierr); 72295fce210SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Roots referenced by my leaves, by rank\n",rank);CHKERRQ(ierr); 72381bfa7aaSJed Brown for (ii=0; ii<sf->nranks; ii++) { 72481bfa7aaSJed Brown i = perm[ii]; 7257904a332SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %d: %D edges\n",rank,sf->ranks[i],sf->roffset[i+1]-sf->roffset[i]);CHKERRQ(ierr); 72695fce210SBarry Smith for (j=sf->roffset[i]; j<sf->roffset[i+1]; j++) { 72795fce210SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D <- %D\n",rank,sf->rmine[j],sf->rremote[j]);CHKERRQ(ierr); 72895fce210SBarry Smith } 72995fce210SBarry Smith } 73081bfa7aaSJed Brown ierr = PetscFree2(tmpranks,perm);CHKERRQ(ierr); 73195fce210SBarry Smith } 73295fce210SBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 7331575c14dSBarry Smith ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 734dd5b3ca6SJunchao Zhang } 73595fce210SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 73695fce210SBarry Smith } 73795fce210SBarry Smith PetscFunctionReturn(0); 73895fce210SBarry Smith } 73995fce210SBarry Smith 74095fce210SBarry Smith /*@C 741dec1416fSJunchao Zhang PetscSFGetRootRanks - Get root ranks and number of vertices referenced by leaves on this process 74295fce210SBarry Smith 74395fce210SBarry Smith Not Collective 74495fce210SBarry Smith 74595fce210SBarry Smith Input Arguments: 74695fce210SBarry Smith . sf - star forest 74795fce210SBarry Smith 74895fce210SBarry Smith Output Arguments: 74995fce210SBarry Smith + nranks - number of ranks referenced by local part 75095fce210SBarry Smith . ranks - array of ranks 75195fce210SBarry Smith . roffset - offset in rmine/rremote for each rank (length nranks+1) 75295fce210SBarry Smith . rmine - concatenated array holding local indices referencing each remote rank 75395fce210SBarry Smith - rremote - concatenated array holding remote indices referenced for each remote rank 75495fce210SBarry Smith 75595fce210SBarry Smith Level: developer 75695fce210SBarry Smith 757dec1416fSJunchao Zhang .seealso: PetscSFGetLeafRanks() 75895fce210SBarry Smith @*/ 759dec1416fSJunchao Zhang PetscErrorCode PetscSFGetRootRanks(PetscSF sf,PetscInt *nranks,const PetscMPIInt **ranks,const PetscInt **roffset,const PetscInt **rmine,const PetscInt **rremote) 76095fce210SBarry Smith { 761dec1416fSJunchao Zhang PetscErrorCode ierr; 76295fce210SBarry Smith 76395fce210SBarry Smith PetscFunctionBegin; 76495fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 76529046d53SLisandro Dalcin if (!sf->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSFSetUp() before obtaining ranks"); 766dec1416fSJunchao Zhang if (sf->ops->GetRootRanks) { 767dec1416fSJunchao Zhang ierr = (sf->ops->GetRootRanks)(sf,nranks,ranks,roffset,rmine,rremote);CHKERRQ(ierr); 768dec1416fSJunchao Zhang } else { 769dec1416fSJunchao Zhang /* The generic implementation */ 77095fce210SBarry Smith if (nranks) *nranks = sf->nranks; 77195fce210SBarry Smith if (ranks) *ranks = sf->ranks; 77295fce210SBarry Smith if (roffset) *roffset = sf->roffset; 77395fce210SBarry Smith if (rmine) *rmine = sf->rmine; 77495fce210SBarry Smith if (rremote) *rremote = sf->rremote; 775dec1416fSJunchao Zhang } 77695fce210SBarry Smith PetscFunctionReturn(0); 77795fce210SBarry Smith } 77895fce210SBarry Smith 7798750ddebSJunchao Zhang /*@C 7808750ddebSJunchao Zhang PetscSFGetLeafRanks - Get leaf ranks referencing roots on this process 7818750ddebSJunchao Zhang 7828750ddebSJunchao Zhang Not Collective 7838750ddebSJunchao Zhang 7848750ddebSJunchao Zhang Input Arguments: 7858750ddebSJunchao Zhang . sf - star forest 7868750ddebSJunchao Zhang 7878750ddebSJunchao Zhang Output Arguments: 7888750ddebSJunchao Zhang + niranks - number of leaf ranks referencing roots on this process 7898750ddebSJunchao Zhang . iranks - array of ranks 7908750ddebSJunchao Zhang . ioffset - offset in irootloc for each rank (length niranks+1) 7918750ddebSJunchao Zhang - irootloc - concatenated array holding local indices of roots referenced by each leaf rank 7928750ddebSJunchao Zhang 7938750ddebSJunchao Zhang Level: developer 7948750ddebSJunchao Zhang 795dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks() 7968750ddebSJunchao Zhang @*/ 7978750ddebSJunchao Zhang PetscErrorCode PetscSFGetLeafRanks(PetscSF sf,PetscInt *niranks,const PetscMPIInt **iranks,const PetscInt **ioffset,const PetscInt **irootloc) 7988750ddebSJunchao Zhang { 7998750ddebSJunchao Zhang PetscErrorCode ierr; 8008750ddebSJunchao Zhang 8018750ddebSJunchao Zhang PetscFunctionBegin; 8028750ddebSJunchao Zhang PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 8038750ddebSJunchao Zhang if (!sf->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSFSetUp() before obtaining ranks"); 8048750ddebSJunchao Zhang if (sf->ops->GetLeafRanks) { 8058750ddebSJunchao Zhang ierr = (sf->ops->GetLeafRanks)(sf,niranks,iranks,ioffset,irootloc);CHKERRQ(ierr); 8068750ddebSJunchao Zhang } else { 8078750ddebSJunchao Zhang PetscSFType type; 8088750ddebSJunchao Zhang ierr = PetscSFGetType(sf,&type);CHKERRQ(ierr); 8098750ddebSJunchao Zhang SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscSFGetLeafRanks() is not supported on this StarForest type: %s", type); 8108750ddebSJunchao Zhang } 8118750ddebSJunchao Zhang PetscFunctionReturn(0); 8128750ddebSJunchao Zhang } 8138750ddebSJunchao Zhang 814b5a8e515SJed Brown static PetscBool InList(PetscMPIInt needle,PetscMPIInt n,const PetscMPIInt *list) { 815b5a8e515SJed Brown PetscInt i; 816b5a8e515SJed Brown for (i=0; i<n; i++) { 817b5a8e515SJed Brown if (needle == list[i]) return PETSC_TRUE; 818b5a8e515SJed Brown } 819b5a8e515SJed Brown return PETSC_FALSE; 820b5a8e515SJed Brown } 821b5a8e515SJed Brown 82295fce210SBarry Smith /*@C 82321c688dcSJed Brown PetscSFSetUpRanks - Set up data structures associated with ranks; this is for internal use by PetscSF implementations. 82421c688dcSJed Brown 82521c688dcSJed Brown Collective 82621c688dcSJed Brown 82721c688dcSJed Brown Input Arguments: 828b5a8e515SJed Brown + sf - PetscSF to set up; PetscSFSetGraph() must have been called 829b5a8e515SJed Brown - dgroup - MPI_Group of ranks to be distinguished (e.g., for self or shared memory exchange) 83021c688dcSJed Brown 83121c688dcSJed Brown Level: developer 83221c688dcSJed Brown 833dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks() 83421c688dcSJed Brown @*/ 835b5a8e515SJed Brown PetscErrorCode PetscSFSetUpRanks(PetscSF sf,MPI_Group dgroup) 83621c688dcSJed Brown { 83721c688dcSJed Brown PetscErrorCode ierr; 83821c688dcSJed Brown PetscTable table; 83921c688dcSJed Brown PetscTablePosition pos; 840b5a8e515SJed Brown PetscMPIInt size,groupsize,*groupranks; 841247e8311SStefano Zampini PetscInt *rcount,*ranks; 842247e8311SStefano Zampini PetscInt i, irank = -1,orank = -1; 84321c688dcSJed Brown 84421c688dcSJed Brown PetscFunctionBegin; 84521c688dcSJed Brown PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 84629046d53SLisandro Dalcin PetscSFCheckGraphSet(sf,1); 84721c688dcSJed Brown ierr = MPI_Comm_size(PetscObjectComm((PetscObject)sf),&size);CHKERRQ(ierr); 84821c688dcSJed Brown ierr = PetscTableCreate(10,size,&table);CHKERRQ(ierr); 84921c688dcSJed Brown for (i=0; i<sf->nleaves; i++) { 85021c688dcSJed Brown /* Log 1-based rank */ 85121c688dcSJed Brown ierr = PetscTableAdd(table,sf->remote[i].rank+1,1,ADD_VALUES);CHKERRQ(ierr); 85221c688dcSJed Brown } 85321c688dcSJed Brown ierr = PetscTableGetCount(table,&sf->nranks);CHKERRQ(ierr); 85421c688dcSJed Brown ierr = PetscMalloc4(sf->nranks,&sf->ranks,sf->nranks+1,&sf->roffset,sf->nleaves,&sf->rmine,sf->nleaves,&sf->rremote);CHKERRQ(ierr); 85521c688dcSJed Brown ierr = PetscMalloc2(sf->nranks,&rcount,sf->nranks,&ranks);CHKERRQ(ierr); 85621c688dcSJed Brown ierr = PetscTableGetHeadPosition(table,&pos);CHKERRQ(ierr); 85721c688dcSJed Brown for (i=0; i<sf->nranks; i++) { 85821c688dcSJed Brown ierr = PetscTableGetNext(table,&pos,&ranks[i],&rcount[i]);CHKERRQ(ierr); 85921c688dcSJed Brown ranks[i]--; /* Convert back to 0-based */ 86021c688dcSJed Brown } 86121c688dcSJed Brown ierr = PetscTableDestroy(&table);CHKERRQ(ierr); 862b5a8e515SJed Brown 863b5a8e515SJed Brown /* We expect that dgroup is reliably "small" while nranks could be large */ 864b5a8e515SJed Brown { 8657fb8a5e4SKarl Rupp MPI_Group group = MPI_GROUP_NULL; 866b5a8e515SJed Brown PetscMPIInt *dgroupranks; 867b5a8e515SJed Brown ierr = MPI_Comm_group(PetscObjectComm((PetscObject)sf),&group);CHKERRQ(ierr); 868b5a8e515SJed Brown ierr = MPI_Group_size(dgroup,&groupsize);CHKERRQ(ierr); 869b5a8e515SJed Brown ierr = PetscMalloc1(groupsize,&dgroupranks);CHKERRQ(ierr); 870b5a8e515SJed Brown ierr = PetscMalloc1(groupsize,&groupranks);CHKERRQ(ierr); 871b5a8e515SJed Brown for (i=0; i<groupsize; i++) dgroupranks[i] = i; 872f3fc9a17SJed Brown if (groupsize) {ierr = MPI_Group_translate_ranks(dgroup,groupsize,dgroupranks,group,groupranks);CHKERRQ(ierr);} 873b5a8e515SJed Brown ierr = MPI_Group_free(&group);CHKERRQ(ierr); 874b5a8e515SJed Brown ierr = PetscFree(dgroupranks);CHKERRQ(ierr); 875b5a8e515SJed Brown } 876b5a8e515SJed Brown 877b5a8e515SJed Brown /* Partition ranks[] into distinguished (first sf->ndranks) followed by non-distinguished */ 878b5a8e515SJed Brown for (sf->ndranks=0,i=sf->nranks; sf->ndranks<i; ) { 879b5a8e515SJed Brown for (i--; sf->ndranks<i; i--) { /* Scan i backward looking for distinguished rank */ 880b5a8e515SJed Brown if (InList(ranks[i],groupsize,groupranks)) break; 881b5a8e515SJed Brown } 882b5a8e515SJed Brown for ( ; sf->ndranks<=i; sf->ndranks++) { /* Scan sf->ndranks forward looking for non-distinguished rank */ 883b5a8e515SJed Brown if (!InList(ranks[sf->ndranks],groupsize,groupranks)) break; 884b5a8e515SJed Brown } 885b5a8e515SJed Brown if (sf->ndranks < i) { /* Swap ranks[sf->ndranks] with ranks[i] */ 886b5a8e515SJed Brown PetscInt tmprank,tmpcount; 887247e8311SStefano Zampini 888b5a8e515SJed Brown tmprank = ranks[i]; 889b5a8e515SJed Brown tmpcount = rcount[i]; 890b5a8e515SJed Brown ranks[i] = ranks[sf->ndranks]; 891b5a8e515SJed Brown rcount[i] = rcount[sf->ndranks]; 892b5a8e515SJed Brown ranks[sf->ndranks] = tmprank; 893b5a8e515SJed Brown rcount[sf->ndranks] = tmpcount; 894b5a8e515SJed Brown sf->ndranks++; 895b5a8e515SJed Brown } 896b5a8e515SJed Brown } 897b5a8e515SJed Brown ierr = PetscFree(groupranks);CHKERRQ(ierr); 898b5a8e515SJed Brown ierr = PetscSortIntWithArray(sf->ndranks,ranks,rcount);CHKERRQ(ierr); 899b5a8e515SJed Brown ierr = PetscSortIntWithArray(sf->nranks-sf->ndranks,ranks+sf->ndranks,rcount+sf->ndranks);CHKERRQ(ierr); 90021c688dcSJed Brown sf->roffset[0] = 0; 90121c688dcSJed Brown for (i=0; i<sf->nranks; i++) { 90221c688dcSJed Brown ierr = PetscMPIIntCast(ranks[i],sf->ranks+i);CHKERRQ(ierr); 90321c688dcSJed Brown sf->roffset[i+1] = sf->roffset[i] + rcount[i]; 90421c688dcSJed Brown rcount[i] = 0; 90521c688dcSJed Brown } 906247e8311SStefano Zampini for (i=0, irank = -1, orank = -1; i<sf->nleaves; i++) { 907247e8311SStefano Zampini /* short circuit */ 908247e8311SStefano Zampini if (orank != sf->remote[i].rank) { 90921c688dcSJed Brown /* Search for index of iremote[i].rank in sf->ranks */ 910b5a8e515SJed Brown ierr = PetscFindMPIInt(sf->remote[i].rank,sf->ndranks,sf->ranks,&irank);CHKERRQ(ierr); 911b5a8e515SJed Brown if (irank < 0) { 912b5a8e515SJed Brown ierr = PetscFindMPIInt(sf->remote[i].rank,sf->nranks-sf->ndranks,sf->ranks+sf->ndranks,&irank);CHKERRQ(ierr); 913b5a8e515SJed Brown if (irank >= 0) irank += sf->ndranks; 91421c688dcSJed Brown } 915247e8311SStefano Zampini orank = sf->remote[i].rank; 916247e8311SStefano Zampini } 917b5a8e515SJed Brown if (irank < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not find rank %D in array",sf->remote[i].rank); 91821c688dcSJed Brown sf->rmine[sf->roffset[irank] + rcount[irank]] = sf->mine ? sf->mine[i] : i; 91921c688dcSJed Brown sf->rremote[sf->roffset[irank] + rcount[irank]] = sf->remote[i].index; 92021c688dcSJed Brown rcount[irank]++; 92121c688dcSJed Brown } 92221c688dcSJed Brown ierr = PetscFree2(rcount,ranks);CHKERRQ(ierr); 92321c688dcSJed Brown PetscFunctionReturn(0); 92421c688dcSJed Brown } 92521c688dcSJed Brown 92621c688dcSJed Brown /*@C 92795fce210SBarry Smith PetscSFGetGroups - gets incoming and outgoing process groups 92895fce210SBarry Smith 92995fce210SBarry Smith Collective 93095fce210SBarry Smith 93195fce210SBarry Smith Input Argument: 93295fce210SBarry Smith . sf - star forest 93395fce210SBarry Smith 93495fce210SBarry Smith Output Arguments: 93595fce210SBarry Smith + incoming - group of origin processes for incoming edges (leaves that reference my roots) 93695fce210SBarry Smith - outgoing - group of destination processes for outgoing edges (roots that I reference) 93795fce210SBarry Smith 93895fce210SBarry Smith Level: developer 93995fce210SBarry Smith 94095fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow() 94195fce210SBarry Smith @*/ 94295fce210SBarry Smith PetscErrorCode PetscSFGetGroups(PetscSF sf,MPI_Group *incoming,MPI_Group *outgoing) 94395fce210SBarry Smith { 94495fce210SBarry Smith PetscErrorCode ierr; 9457fb8a5e4SKarl Rupp MPI_Group group = MPI_GROUP_NULL; 94695fce210SBarry Smith 94795fce210SBarry Smith PetscFunctionBegin; 94829046d53SLisandro Dalcin if (!sf->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSFSetUp() before obtaining groups"); 94995fce210SBarry Smith if (sf->ingroup == MPI_GROUP_NULL) { 95095fce210SBarry Smith PetscInt i; 95195fce210SBarry Smith const PetscInt *indegree; 95295fce210SBarry Smith PetscMPIInt rank,*outranks,*inranks; 95395fce210SBarry Smith PetscSFNode *remote; 95495fce210SBarry Smith PetscSF bgcount; 95595fce210SBarry Smith 95695fce210SBarry Smith /* Compute the number of incoming ranks */ 957785e854fSJed Brown ierr = PetscMalloc1(sf->nranks,&remote);CHKERRQ(ierr); 95895fce210SBarry Smith for (i=0; i<sf->nranks; i++) { 95995fce210SBarry Smith remote[i].rank = sf->ranks[i]; 96095fce210SBarry Smith remote[i].index = 0; 96195fce210SBarry Smith } 96295fce210SBarry Smith ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_CONFONLY,&bgcount);CHKERRQ(ierr); 96395fce210SBarry Smith ierr = PetscSFSetGraph(bgcount,1,sf->nranks,NULL,PETSC_COPY_VALUES,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); 96495fce210SBarry Smith ierr = PetscSFComputeDegreeBegin(bgcount,&indegree);CHKERRQ(ierr); 96595fce210SBarry Smith ierr = PetscSFComputeDegreeEnd(bgcount,&indegree);CHKERRQ(ierr); 96695fce210SBarry Smith 96795fce210SBarry Smith /* Enumerate the incoming ranks */ 968dcca6d9dSJed Brown ierr = PetscMalloc2(indegree[0],&inranks,sf->nranks,&outranks);CHKERRQ(ierr); 96995fce210SBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr); 97095fce210SBarry Smith for (i=0; i<sf->nranks; i++) outranks[i] = rank; 97195fce210SBarry Smith ierr = PetscSFGatherBegin(bgcount,MPI_INT,outranks,inranks);CHKERRQ(ierr); 97295fce210SBarry Smith ierr = PetscSFGatherEnd(bgcount,MPI_INT,outranks,inranks);CHKERRQ(ierr); 97395fce210SBarry Smith ierr = MPI_Comm_group(PetscObjectComm((PetscObject)sf),&group);CHKERRQ(ierr); 97495fce210SBarry Smith ierr = MPI_Group_incl(group,indegree[0],inranks,&sf->ingroup);CHKERRQ(ierr); 97595fce210SBarry Smith ierr = MPI_Group_free(&group);CHKERRQ(ierr); 97695fce210SBarry Smith ierr = PetscFree2(inranks,outranks);CHKERRQ(ierr); 97795fce210SBarry Smith ierr = PetscSFDestroy(&bgcount);CHKERRQ(ierr); 97895fce210SBarry Smith } 97995fce210SBarry Smith *incoming = sf->ingroup; 98095fce210SBarry Smith 98195fce210SBarry Smith if (sf->outgroup == MPI_GROUP_NULL) { 98295fce210SBarry Smith ierr = MPI_Comm_group(PetscObjectComm((PetscObject)sf),&group);CHKERRQ(ierr); 98395fce210SBarry Smith ierr = MPI_Group_incl(group,sf->nranks,sf->ranks,&sf->outgroup);CHKERRQ(ierr); 98495fce210SBarry Smith ierr = MPI_Group_free(&group);CHKERRQ(ierr); 98595fce210SBarry Smith } 98695fce210SBarry Smith *outgoing = sf->outgroup; 98795fce210SBarry Smith PetscFunctionReturn(0); 98895fce210SBarry Smith } 98995fce210SBarry Smith 99029046d53SLisandro Dalcin /*@ 99195fce210SBarry Smith PetscSFGetMultiSF - gets the inner SF implemeting gathers and scatters 99295fce210SBarry Smith 99395fce210SBarry Smith Collective 99495fce210SBarry Smith 99595fce210SBarry Smith Input Argument: 99695fce210SBarry Smith . sf - star forest that may contain roots with 0 or with more than 1 vertex 99795fce210SBarry Smith 99895fce210SBarry Smith Output Arguments: 99995fce210SBarry Smith . multi - star forest with split roots, such that each root has degree exactly 1 100095fce210SBarry Smith 100195fce210SBarry Smith Level: developer 100295fce210SBarry Smith 100395fce210SBarry Smith Notes: 100495fce210SBarry Smith 100595fce210SBarry Smith In most cases, users should use PetscSFGatherBegin() and PetscSFScatterBegin() instead of manipulating multi 100695fce210SBarry Smith directly. Since multi satisfies the stronger condition that each entry in the global space has exactly one incoming 100795fce210SBarry Smith edge, it is a candidate for future optimization that might involve its removal. 100895fce210SBarry Smith 1009673100f5SVaclav Hapla .seealso: PetscSFSetGraph(), PetscSFGatherBegin(), PetscSFScatterBegin(), PetscSFComputeMultiRootOriginalNumbering() 101095fce210SBarry Smith @*/ 101195fce210SBarry Smith PetscErrorCode PetscSFGetMultiSF(PetscSF sf,PetscSF *multi) 101295fce210SBarry Smith { 101395fce210SBarry Smith PetscErrorCode ierr; 101495fce210SBarry Smith 101595fce210SBarry Smith PetscFunctionBegin; 101695fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 101795fce210SBarry Smith PetscValidPointer(multi,2); 101895fce210SBarry Smith if (sf->nroots < 0) { /* Graph has not been set yet; why do we need this? */ 101995fce210SBarry Smith ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&sf->multi);CHKERRQ(ierr); 102095fce210SBarry Smith *multi = sf->multi; 102195fce210SBarry Smith PetscFunctionReturn(0); 102295fce210SBarry Smith } 102395fce210SBarry Smith if (!sf->multi) { 102495fce210SBarry Smith const PetscInt *indegree; 10259837ea96SMatthew G. Knepley PetscInt i,*inoffset,*outones,*outoffset,maxlocal; 102695fce210SBarry Smith PetscSFNode *remote; 102729046d53SLisandro Dalcin maxlocal = sf->maxleaf+1; /* TODO: We should use PetscSFGetLeafRange() */ 102895fce210SBarry Smith ierr = PetscSFComputeDegreeBegin(sf,&indegree);CHKERRQ(ierr); 102995fce210SBarry Smith ierr = PetscSFComputeDegreeEnd(sf,&indegree);CHKERRQ(ierr); 10309837ea96SMatthew G. Knepley ierr = PetscMalloc3(sf->nroots+1,&inoffset,maxlocal,&outones,maxlocal,&outoffset);CHKERRQ(ierr); 103195fce210SBarry Smith inoffset[0] = 0; 103295fce210SBarry Smith for (i=0; i<sf->nroots; i++) inoffset[i+1] = inoffset[i] + indegree[i]; 10339837ea96SMatthew G. Knepley for (i=0; i<maxlocal; i++) outones[i] = 1; 1034dbd2ff41SBarry Smith ierr = PetscSFFetchAndOpBegin(sf,MPIU_INT,inoffset,outones,outoffset,MPI_SUM);CHKERRQ(ierr); 1035dbd2ff41SBarry Smith ierr = PetscSFFetchAndOpEnd(sf,MPIU_INT,inoffset,outones,outoffset,MPI_SUM);CHKERRQ(ierr); 103695fce210SBarry Smith for (i=0; i<sf->nroots; i++) inoffset[i] -= indegree[i]; /* Undo the increment */ 103795fce210SBarry Smith #if 0 103895fce210SBarry Smith #if defined(PETSC_USE_DEBUG) /* Check that the expected number of increments occurred */ 103995fce210SBarry Smith for (i=0; i<sf->nroots; i++) { 104095fce210SBarry Smith if (inoffset[i] + indegree[i] != inoffset[i+1]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Incorrect result after PetscSFFetchAndOp"); 104195fce210SBarry Smith } 104295fce210SBarry Smith #endif 104395fce210SBarry Smith #endif 1044785e854fSJed Brown ierr = PetscMalloc1(sf->nleaves,&remote);CHKERRQ(ierr); 104595fce210SBarry Smith for (i=0; i<sf->nleaves; i++) { 104695fce210SBarry Smith remote[i].rank = sf->remote[i].rank; 104738e7336fSToby Isaac remote[i].index = outoffset[sf->mine ? sf->mine[i] : i]; 104895fce210SBarry Smith } 104995fce210SBarry Smith ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&sf->multi);CHKERRQ(ierr); 105001365b40SToby Isaac ierr = PetscSFSetGraph(sf->multi,inoffset[sf->nroots],sf->nleaves,sf->mine,PETSC_COPY_VALUES,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); 105195fce210SBarry Smith if (sf->rankorder) { /* Sort the ranks */ 105295fce210SBarry Smith PetscMPIInt rank; 105395fce210SBarry Smith PetscInt *inranks,*newoffset,*outranks,*newoutoffset,*tmpoffset,maxdegree; 105495fce210SBarry Smith PetscSFNode *newremote; 105595fce210SBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr); 105695fce210SBarry Smith for (i=0,maxdegree=0; i<sf->nroots; i++) maxdegree = PetscMax(maxdegree,indegree[i]); 10579837ea96SMatthew G. Knepley ierr = PetscMalloc5(sf->multi->nroots,&inranks,sf->multi->nroots,&newoffset,maxlocal,&outranks,maxlocal,&newoutoffset,maxdegree,&tmpoffset);CHKERRQ(ierr); 10589837ea96SMatthew G. Knepley for (i=0; i<maxlocal; i++) outranks[i] = rank; 10598bfbc91cSJed Brown ierr = PetscSFReduceBegin(sf->multi,MPIU_INT,outranks,inranks,MPIU_REPLACE);CHKERRQ(ierr); 10608bfbc91cSJed Brown ierr = PetscSFReduceEnd(sf->multi,MPIU_INT,outranks,inranks,MPIU_REPLACE);CHKERRQ(ierr); 106195fce210SBarry Smith /* Sort the incoming ranks at each vertex, build the inverse map */ 106295fce210SBarry Smith for (i=0; i<sf->nroots; i++) { 106395fce210SBarry Smith PetscInt j; 106495fce210SBarry Smith for (j=0; j<indegree[i]; j++) tmpoffset[j] = j; 106595fce210SBarry Smith ierr = PetscSortIntWithArray(indegree[i],inranks+inoffset[i],tmpoffset);CHKERRQ(ierr); 106695fce210SBarry Smith for (j=0; j<indegree[i]; j++) newoffset[inoffset[i] + tmpoffset[j]] = inoffset[i] + j; 106795fce210SBarry Smith } 106895fce210SBarry Smith ierr = PetscSFBcastBegin(sf->multi,MPIU_INT,newoffset,newoutoffset);CHKERRQ(ierr); 106995fce210SBarry Smith ierr = PetscSFBcastEnd(sf->multi,MPIU_INT,newoffset,newoutoffset);CHKERRQ(ierr); 1070785e854fSJed Brown ierr = PetscMalloc1(sf->nleaves,&newremote);CHKERRQ(ierr); 107195fce210SBarry Smith for (i=0; i<sf->nleaves; i++) { 107295fce210SBarry Smith newremote[i].rank = sf->remote[i].rank; 107301365b40SToby Isaac newremote[i].index = newoutoffset[sf->mine ? sf->mine[i] : i]; 107495fce210SBarry Smith } 107501365b40SToby Isaac ierr = PetscSFSetGraph(sf->multi,inoffset[sf->nroots],sf->nleaves,sf->mine,PETSC_COPY_VALUES,newremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 107695fce210SBarry Smith ierr = PetscFree5(inranks,newoffset,outranks,newoutoffset,tmpoffset);CHKERRQ(ierr); 107795fce210SBarry Smith } 107895fce210SBarry Smith ierr = PetscFree3(inoffset,outones,outoffset);CHKERRQ(ierr); 107995fce210SBarry Smith } 108095fce210SBarry Smith *multi = sf->multi; 108195fce210SBarry Smith PetscFunctionReturn(0); 108295fce210SBarry Smith } 108395fce210SBarry Smith 108495fce210SBarry Smith /*@C 108595fce210SBarry Smith PetscSFCreateEmbeddedSF - removes edges from all but the selected roots, does not remap indices 108695fce210SBarry Smith 108795fce210SBarry Smith Collective 108895fce210SBarry Smith 108995fce210SBarry Smith Input Arguments: 109095fce210SBarry Smith + sf - original star forest 1091ba2a7774SJunchao Zhang . nselected - number of selected roots on this process 1092ba2a7774SJunchao Zhang - selected - indices of the selected roots on this process 109395fce210SBarry Smith 109495fce210SBarry Smith Output Arguments: 109595fce210SBarry Smith . newsf - new star forest 109695fce210SBarry Smith 109795fce210SBarry Smith Level: advanced 109895fce210SBarry Smith 109995fce210SBarry Smith Note: 110095fce210SBarry Smith To use the new PetscSF, it may be necessary to know the indices of the leaves that are still participating. This can 110195fce210SBarry Smith be done by calling PetscSFGetGraph(). 110295fce210SBarry Smith 110395fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFGetGraph() 110495fce210SBarry Smith @*/ 1105ba2a7774SJunchao Zhang PetscErrorCode PetscSFCreateEmbeddedSF(PetscSF sf,PetscInt nselected,const PetscInt *selected,PetscSF *newsf) 110695fce210SBarry Smith { 1107f659e5c7SJunchao Zhang PetscInt i,n,*roots,*rootdata,*leafdata,nroots,nleaves,connected_leaves,*new_ilocal; 1108ba2a7774SJunchao Zhang const PetscSFNode *iremote; 1109f659e5c7SJunchao Zhang PetscSFNode *new_iremote; 1110ba2a7774SJunchao Zhang PetscSF tmpsf; 1111f659e5c7SJunchao Zhang MPI_Comm comm; 11120511a646SMatthew G. Knepley PetscErrorCode ierr; 111395fce210SBarry Smith 111495fce210SBarry Smith PetscFunctionBegin; 111595fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 111629046d53SLisandro Dalcin PetscSFCheckGraphSet(sf,1); 1117ba2a7774SJunchao Zhang if (nselected) PetscValidPointer(selected,3); 111895fce210SBarry Smith PetscValidPointer(newsf,4); 11190511a646SMatthew G. Knepley 1120f659e5c7SJunchao Zhang ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 1121f659e5c7SJunchao Zhang 1122f659e5c7SJunchao Zhang /* Uniq selected[] and put results in roots[] */ 1123f659e5c7SJunchao Zhang ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); 1124f659e5c7SJunchao Zhang ierr = PetscMalloc1(nselected,&roots);CHKERRQ(ierr); 1125dd5b3ca6SJunchao Zhang ierr = PetscArraycpy(roots,selected,nselected);CHKERRQ(ierr); 1126f659e5c7SJunchao Zhang ierr = PetscSortedRemoveDupsInt(&nselected,roots);CHKERRQ(ierr); 1127f659e5c7SJunchao Zhang if (nselected && (roots[0] < 0 || roots[nselected-1] >= sf->nroots)) SETERRQ3(comm,PETSC_ERR_ARG_OUTOFRANGE,"Min/Max root indices %D/%D are not in [0,%D)",roots[0],roots[nselected-1],sf->nroots); 1128f659e5c7SJunchao Zhang 1129f659e5c7SJunchao Zhang if (sf->ops->CreateEmbeddedSF) { 1130f659e5c7SJunchao Zhang ierr = (*sf->ops->CreateEmbeddedSF)(sf,nselected,roots,newsf);CHKERRQ(ierr); 1131f659e5c7SJunchao Zhang } else { 1132f659e5c7SJunchao Zhang /* A generic version of creating embedded sf. Note that we called PetscSFSetGraph() twice, which is certainly expensive */ 1133ba2a7774SJunchao Zhang /* Find out which leaves (not leaf data items) are still connected to roots in the embedded sf */ 1134f659e5c7SJunchao Zhang ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr); 1135ba2a7774SJunchao Zhang ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&tmpsf);CHKERRQ(ierr); 1136ba2a7774SJunchao Zhang ierr = PetscSFSetGraph(tmpsf,nroots,nleaves,NULL/*contiguous*/,PETSC_USE_POINTER,iremote,PETSC_USE_POINTER);CHKERRQ(ierr); 1137ba2a7774SJunchao Zhang ierr = PetscCalloc2(nroots,&rootdata,nleaves,&leafdata);CHKERRQ(ierr); 1138f659e5c7SJunchao Zhang for (i=0; i<nselected; ++i) rootdata[roots[i]] = 1; 1139ba2a7774SJunchao Zhang ierr = PetscSFBcastBegin(tmpsf,MPIU_INT,rootdata,leafdata);CHKERRQ(ierr); 1140ba2a7774SJunchao Zhang ierr = PetscSFBcastEnd(tmpsf,MPIU_INT,rootdata,leafdata);CHKERRQ(ierr); 1141ba2a7774SJunchao Zhang ierr = PetscSFDestroy(&tmpsf);CHKERRQ(ierr); 1142ba2a7774SJunchao Zhang 1143ba2a7774SJunchao Zhang /* Build newsf with leaves that are still connected */ 1144f659e5c7SJunchao Zhang connected_leaves = 0; 1145f659e5c7SJunchao Zhang for (i=0; i<nleaves; ++i) connected_leaves += leafdata[i]; 1146f659e5c7SJunchao Zhang ierr = PetscMalloc1(connected_leaves,&new_ilocal);CHKERRQ(ierr); 1147f659e5c7SJunchao Zhang ierr = PetscMalloc1(connected_leaves,&new_iremote);CHKERRQ(ierr); 1148ba2a7774SJunchao Zhang for (i=0, n=0; i<nleaves; ++i) { 1149ba2a7774SJunchao Zhang if (leafdata[i]) { 1150ba2a7774SJunchao Zhang new_ilocal[n] = sf->mine ? sf->mine[i] : i; 1151ba2a7774SJunchao Zhang new_iremote[n].rank = sf->remote[i].rank; 1152ba2a7774SJunchao Zhang new_iremote[n].index = sf->remote[i].index; 1153fc1ede2bSMatthew G. Knepley ++n; 115495fce210SBarry Smith } 115595fce210SBarry Smith } 1156f659e5c7SJunchao Zhang 1157f659e5c7SJunchao Zhang if (n != connected_leaves) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"There is a size mismatch in the SF embedding, %d != %d",n,connected_leaves); 1158f659e5c7SJunchao Zhang ierr = PetscSFCreate(comm,newsf);CHKERRQ(ierr); 1159f659e5c7SJunchao Zhang ierr = PetscSFSetFromOptions(*newsf);CHKERRQ(ierr); 1160f659e5c7SJunchao Zhang ierr = PetscSFSetGraph(*newsf,nroots,connected_leaves,new_ilocal,PETSC_OWN_POINTER,new_iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 116195fce210SBarry Smith ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr); 1162f659e5c7SJunchao Zhang } 1163f659e5c7SJunchao Zhang ierr = PetscFree(roots);CHKERRQ(ierr); 116495fce210SBarry Smith PetscFunctionReturn(0); 116595fce210SBarry Smith } 116695fce210SBarry Smith 11672f5fb4c2SMatthew G. Knepley /*@C 11682f5fb4c2SMatthew G. Knepley PetscSFCreateEmbeddedLeafSF - removes edges from all but the selected leaves, does not remap indices 11692f5fb4c2SMatthew G. Knepley 11702f5fb4c2SMatthew G. Knepley Collective 11712f5fb4c2SMatthew G. Knepley 11722f5fb4c2SMatthew G. Knepley Input Arguments: 11732f5fb4c2SMatthew G. Knepley + sf - original star forest 1174f659e5c7SJunchao Zhang . nselected - number of selected leaves on this process 1175f659e5c7SJunchao Zhang - selected - indices of the selected leaves on this process 11762f5fb4c2SMatthew G. Knepley 11772f5fb4c2SMatthew G. Knepley Output Arguments: 11782f5fb4c2SMatthew G. Knepley . newsf - new star forest 11792f5fb4c2SMatthew G. Knepley 11802f5fb4c2SMatthew G. Knepley Level: advanced 11812f5fb4c2SMatthew G. Knepley 11822f5fb4c2SMatthew G. Knepley .seealso: PetscSFCreateEmbeddedSF(), PetscSFSetGraph(), PetscSFGetGraph() 11832f5fb4c2SMatthew G. Knepley @*/ 1184f659e5c7SJunchao Zhang PetscErrorCode PetscSFCreateEmbeddedLeafSF(PetscSF sf,PetscInt nselected,const PetscInt *selected,PetscSF *newsf) 11852f5fb4c2SMatthew G. Knepley { 1186f659e5c7SJunchao Zhang const PetscSFNode *iremote; 1187f659e5c7SJunchao Zhang PetscSFNode *new_iremote; 1188f659e5c7SJunchao Zhang const PetscInt *ilocal; 1189f659e5c7SJunchao Zhang PetscInt i,nroots,*leaves,*new_ilocal; 1190f659e5c7SJunchao Zhang MPI_Comm comm; 11912f5fb4c2SMatthew G. Knepley PetscErrorCode ierr; 11922f5fb4c2SMatthew G. Knepley 11932f5fb4c2SMatthew G. Knepley PetscFunctionBegin; 11942f5fb4c2SMatthew G. Knepley PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 119529046d53SLisandro Dalcin PetscSFCheckGraphSet(sf,1); 1196f659e5c7SJunchao Zhang if (nselected) PetscValidPointer(selected,3); 11972f5fb4c2SMatthew G. Knepley PetscValidPointer(newsf,4); 11982f5fb4c2SMatthew G. Knepley 1199f659e5c7SJunchao Zhang /* Uniq selected[] and put results in leaves[] */ 1200f659e5c7SJunchao Zhang ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); 1201f659e5c7SJunchao Zhang ierr = PetscMalloc1(nselected,&leaves);CHKERRQ(ierr); 1202dd5b3ca6SJunchao Zhang ierr = PetscArraycpy(leaves,selected,nselected);CHKERRQ(ierr); 1203f659e5c7SJunchao Zhang ierr = PetscSortedRemoveDupsInt(&nselected,leaves);CHKERRQ(ierr); 1204f659e5c7SJunchao Zhang if (nselected && (leaves[0] < 0 || leaves[nselected-1] >= sf->nleaves)) SETERRQ3(comm,PETSC_ERR_ARG_OUTOFRANGE,"Min/Max leaf indices %D/%D are not in [0,%D)",leaves[0],leaves[nselected-1],sf->nleaves); 1205f659e5c7SJunchao Zhang 1206f659e5c7SJunchao Zhang /* Optimize the routine only when sf is setup and hence we can reuse sf's communication pattern */ 1207f659e5c7SJunchao Zhang if (sf->setupcalled && sf->ops->CreateEmbeddedLeafSF) { 1208f659e5c7SJunchao Zhang ierr = (*sf->ops->CreateEmbeddedLeafSF)(sf,nselected,leaves,newsf);CHKERRQ(ierr); 1209f659e5c7SJunchao Zhang } else { 1210f659e5c7SJunchao Zhang ierr = PetscSFGetGraph(sf,&nroots,NULL,&ilocal,&iremote);CHKERRQ(ierr); 1211f659e5c7SJunchao Zhang ierr = PetscMalloc1(nselected,&new_ilocal);CHKERRQ(ierr); 1212f659e5c7SJunchao Zhang ierr = PetscMalloc1(nselected,&new_iremote);CHKERRQ(ierr); 1213f659e5c7SJunchao Zhang for (i=0; i<nselected; ++i) { 1214f659e5c7SJunchao Zhang const PetscInt l = leaves[i]; 1215f659e5c7SJunchao Zhang new_ilocal[i] = ilocal ? ilocal[l] : l; 1216f659e5c7SJunchao Zhang new_iremote[i].rank = iremote[l].rank; 1217f659e5c7SJunchao Zhang new_iremote[i].index = iremote[l].index; 12182f5fb4c2SMatthew G. Knepley } 1219f659e5c7SJunchao Zhang ierr = PetscSFCreate(comm,newsf);CHKERRQ(ierr); 1220f659e5c7SJunchao Zhang ierr = PetscSFSetFromOptions(*newsf);CHKERRQ(ierr); 1221f659e5c7SJunchao Zhang ierr = PetscSFSetGraph(*newsf,nroots,nselected,new_ilocal,PETSC_OWN_POINTER,new_iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 1222f659e5c7SJunchao Zhang } 1223f659e5c7SJunchao Zhang ierr = PetscFree(leaves);CHKERRQ(ierr); 12242f5fb4c2SMatthew G. Knepley PetscFunctionReturn(0); 12252f5fb4c2SMatthew G. Knepley } 12262f5fb4c2SMatthew G. Knepley 122795fce210SBarry Smith /*@C 12283482bfa8SJunchao Zhang PetscSFBcastAndOpBegin - begin pointwise broadcast with root value being reduced to leaf value, to be concluded with call to PetscSFBcastAndOpEnd() 12293482bfa8SJunchao Zhang 12303482bfa8SJunchao Zhang Collective on PetscSF 12313482bfa8SJunchao Zhang 12323482bfa8SJunchao Zhang Input Arguments: 12333482bfa8SJunchao Zhang + sf - star forest on which to communicate 12343482bfa8SJunchao Zhang . unit - data type associated with each node 12353482bfa8SJunchao Zhang . rootdata - buffer to broadcast 12363482bfa8SJunchao Zhang - op - operation to use for reduction 12373482bfa8SJunchao Zhang 12383482bfa8SJunchao Zhang Output Arguments: 12393482bfa8SJunchao Zhang . leafdata - buffer to be reduced with values from each leaf's respective root 12403482bfa8SJunchao Zhang 12413482bfa8SJunchao Zhang Level: intermediate 12423482bfa8SJunchao Zhang 12433482bfa8SJunchao Zhang .seealso: PetscSFBcastAndOpEnd(), PetscSFBcastBegin(), PetscSFBcastEnd() 12443482bfa8SJunchao Zhang @*/ 12453482bfa8SJunchao Zhang PetscErrorCode PetscSFBcastAndOpBegin(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op) 12463482bfa8SJunchao Zhang { 12473482bfa8SJunchao Zhang PetscErrorCode ierr; 12483482bfa8SJunchao Zhang 12493482bfa8SJunchao Zhang PetscFunctionBegin; 12503482bfa8SJunchao Zhang PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 12513482bfa8SJunchao Zhang ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 12523482bfa8SJunchao Zhang ierr = PetscLogEventBegin(PETSCSF_BcastAndOpBegin,sf,0,0,0);CHKERRQ(ierr); 12533482bfa8SJunchao Zhang ierr = (*sf->ops->BcastAndOpBegin)(sf,unit,rootdata,leafdata,op);CHKERRQ(ierr); 12543482bfa8SJunchao Zhang ierr = PetscLogEventEnd(PETSCSF_BcastAndOpBegin,sf,0,0,0);CHKERRQ(ierr); 12553482bfa8SJunchao Zhang PetscFunctionReturn(0); 12563482bfa8SJunchao Zhang } 12573482bfa8SJunchao Zhang 12583482bfa8SJunchao Zhang /*@C 12593482bfa8SJunchao Zhang PetscSFBcastAndOpEnd - end a broadcast & reduce operation started with PetscSFBcastAndOpBegin() 12603482bfa8SJunchao Zhang 12613482bfa8SJunchao Zhang Collective 12623482bfa8SJunchao Zhang 12633482bfa8SJunchao Zhang Input Arguments: 12643482bfa8SJunchao Zhang + sf - star forest 12653482bfa8SJunchao Zhang . unit - data type 12663482bfa8SJunchao Zhang . rootdata - buffer to broadcast 12673482bfa8SJunchao Zhang - op - operation to use for reduction 12683482bfa8SJunchao Zhang 12693482bfa8SJunchao Zhang Output Arguments: 12703482bfa8SJunchao Zhang . leafdata - buffer to be reduced with values from each leaf's respective root 12713482bfa8SJunchao Zhang 12723482bfa8SJunchao Zhang Level: intermediate 12733482bfa8SJunchao Zhang 12743482bfa8SJunchao Zhang .seealso: PetscSFSetGraph(), PetscSFReduceEnd() 12753482bfa8SJunchao Zhang @*/ 12763482bfa8SJunchao Zhang PetscErrorCode PetscSFBcastAndOpEnd(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op) 12773482bfa8SJunchao Zhang { 12783482bfa8SJunchao Zhang PetscErrorCode ierr; 12793482bfa8SJunchao Zhang 12803482bfa8SJunchao Zhang PetscFunctionBegin; 12813482bfa8SJunchao Zhang PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 12823482bfa8SJunchao Zhang ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 12833482bfa8SJunchao Zhang ierr = PetscLogEventBegin(PETSCSF_BcastAndOpEnd,sf,0,0,0);CHKERRQ(ierr); 12843482bfa8SJunchao Zhang ierr = (*sf->ops->BcastAndOpEnd)(sf,unit,rootdata,leafdata,op);CHKERRQ(ierr); 12853482bfa8SJunchao Zhang ierr = PetscLogEventEnd(PETSCSF_BcastAndOpEnd,sf,0,0,0);CHKERRQ(ierr); 12863482bfa8SJunchao Zhang PetscFunctionReturn(0); 12873482bfa8SJunchao Zhang } 12883482bfa8SJunchao Zhang 12893482bfa8SJunchao Zhang /*@C 129095fce210SBarry Smith PetscSFReduceBegin - begin reduction of leafdata into rootdata, to be completed with call to PetscSFReduceEnd() 129195fce210SBarry Smith 129295fce210SBarry Smith Collective 129395fce210SBarry Smith 129495fce210SBarry Smith Input Arguments: 129595fce210SBarry Smith + sf - star forest 129695fce210SBarry Smith . unit - data type 129795fce210SBarry Smith . leafdata - values to reduce 129895fce210SBarry Smith - op - reduction operation 129995fce210SBarry Smith 130095fce210SBarry Smith Output Arguments: 130195fce210SBarry Smith . rootdata - result of reduction of values from all leaves of each root 130295fce210SBarry Smith 130395fce210SBarry Smith Level: intermediate 130495fce210SBarry Smith 130595fce210SBarry Smith .seealso: PetscSFBcastBegin() 130695fce210SBarry Smith @*/ 130795fce210SBarry Smith PetscErrorCode PetscSFReduceBegin(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op) 130895fce210SBarry Smith { 130995fce210SBarry Smith PetscErrorCode ierr; 131095fce210SBarry Smith 131195fce210SBarry Smith PetscFunctionBegin; 131295fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 131395fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 131429046d53SLisandro Dalcin ierr = PetscLogEventBegin(PETSCSF_ReduceBegin,sf,0,0,0);CHKERRQ(ierr); 131595fce210SBarry Smith ierr = (sf->ops->ReduceBegin)(sf,unit,leafdata,rootdata,op);CHKERRQ(ierr); 1316563ffbabSMatthew G. Knepley ierr = PetscLogEventEnd(PETSCSF_ReduceBegin,sf,0,0,0);CHKERRQ(ierr); 131795fce210SBarry Smith PetscFunctionReturn(0); 131895fce210SBarry Smith } 131995fce210SBarry Smith 132095fce210SBarry Smith /*@C 132195fce210SBarry Smith PetscSFReduceEnd - end a reduction operation started with PetscSFReduceBegin() 132295fce210SBarry Smith 132395fce210SBarry Smith Collective 132495fce210SBarry Smith 132595fce210SBarry Smith Input Arguments: 132695fce210SBarry Smith + sf - star forest 132795fce210SBarry Smith . unit - data type 132895fce210SBarry Smith . leafdata - values to reduce 132995fce210SBarry Smith - op - reduction operation 133095fce210SBarry Smith 133195fce210SBarry Smith Output Arguments: 133295fce210SBarry Smith . rootdata - result of reduction of values from all leaves of each root 133395fce210SBarry Smith 133495fce210SBarry Smith Level: intermediate 133595fce210SBarry Smith 133695fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFBcastEnd() 133795fce210SBarry Smith @*/ 133895fce210SBarry Smith PetscErrorCode PetscSFReduceEnd(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op) 133995fce210SBarry Smith { 134095fce210SBarry Smith PetscErrorCode ierr; 134195fce210SBarry Smith 134295fce210SBarry Smith PetscFunctionBegin; 134395fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 134495fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 134529046d53SLisandro Dalcin ierr = PetscLogEventBegin(PETSCSF_ReduceEnd,sf,0,0,0);CHKERRQ(ierr); 134695fce210SBarry Smith ierr = (*sf->ops->ReduceEnd)(sf,unit,leafdata,rootdata,op);CHKERRQ(ierr); 1347563ffbabSMatthew G. Knepley ierr = PetscLogEventEnd(PETSCSF_ReduceEnd,sf,0,0,0);CHKERRQ(ierr); 134895fce210SBarry Smith PetscFunctionReturn(0); 134995fce210SBarry Smith } 135095fce210SBarry Smith 135195fce210SBarry Smith /*@C 135295fce210SBarry Smith PetscSFComputeDegreeBegin - begin computation of degree for each root vertex, to be completed with PetscSFComputeDegreeEnd() 135395fce210SBarry Smith 135495fce210SBarry Smith Collective 135595fce210SBarry Smith 135695fce210SBarry Smith Input Arguments: 135795fce210SBarry Smith . sf - star forest 135895fce210SBarry Smith 135995fce210SBarry Smith Output Arguments: 136095fce210SBarry Smith . degree - degree of each root vertex 136195fce210SBarry Smith 136295fce210SBarry Smith Level: advanced 136395fce210SBarry Smith 1364ffe67aa5SVáclav Hapla Notes: 1365ffe67aa5SVáclav Hapla The returned array is owned by PetscSF and automatically freed by PetscSFDestroy(). Hence no need to call PetscFree() on it. 1366ffe67aa5SVáclav Hapla 136795fce210SBarry Smith .seealso: PetscSFGatherBegin() 136895fce210SBarry Smith @*/ 136995fce210SBarry Smith PetscErrorCode PetscSFComputeDegreeBegin(PetscSF sf,const PetscInt **degree) 137095fce210SBarry Smith { 137195fce210SBarry Smith PetscErrorCode ierr; 137295fce210SBarry Smith 137395fce210SBarry Smith PetscFunctionBegin; 137495fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 137595fce210SBarry Smith PetscSFCheckGraphSet(sf,1); 137695fce210SBarry Smith PetscValidPointer(degree,2); 1377803bd9e8SMatthew G. Knepley if (!sf->degreeknown) { 137829046d53SLisandro Dalcin PetscInt i, nroots = sf->nroots, maxlocal = sf->maxleaf+1; /* TODO: We should use PetscSFGetLeafRange() */ 1379803bd9e8SMatthew G. Knepley if (sf->degree) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Calls to PetscSFComputeDegreeBegin() cannot be nested."); 138029046d53SLisandro Dalcin ierr = PetscMalloc1(nroots,&sf->degree);CHKERRQ(ierr); 138129046d53SLisandro Dalcin ierr = PetscMalloc1(PetscMax(maxlocal,1),&sf->degreetmp);CHKERRQ(ierr); /* allocate at least one entry, see check in PetscSFComputeDegreeEnd() */ 138229046d53SLisandro Dalcin for (i=0; i<nroots; i++) sf->degree[i] = 0; 13839837ea96SMatthew G. Knepley for (i=0; i<maxlocal; i++) sf->degreetmp[i] = 1; 1384dbd2ff41SBarry Smith ierr = PetscSFReduceBegin(sf,MPIU_INT,sf->degreetmp,sf->degree,MPI_SUM);CHKERRQ(ierr); 138595fce210SBarry Smith } 138695fce210SBarry Smith *degree = NULL; 138795fce210SBarry Smith PetscFunctionReturn(0); 138895fce210SBarry Smith } 138995fce210SBarry Smith 139095fce210SBarry Smith /*@C 139195fce210SBarry Smith PetscSFComputeDegreeEnd - complete computation of degree for each root vertex, started with PetscSFComputeDegreeBegin() 139295fce210SBarry Smith 139395fce210SBarry Smith Collective 139495fce210SBarry Smith 139595fce210SBarry Smith Input Arguments: 139695fce210SBarry Smith . sf - star forest 139795fce210SBarry Smith 139895fce210SBarry Smith Output Arguments: 139995fce210SBarry Smith . degree - degree of each root vertex 140095fce210SBarry Smith 140195fce210SBarry Smith Level: developer 140295fce210SBarry Smith 1403ffe67aa5SVáclav Hapla Notes: 1404ffe67aa5SVáclav Hapla The returned array is owned by PetscSF and automatically freed by PetscSFDestroy(). Hence no need to call PetscFree() on it. 1405ffe67aa5SVáclav Hapla 140695fce210SBarry Smith .seealso: 140795fce210SBarry Smith @*/ 140895fce210SBarry Smith PetscErrorCode PetscSFComputeDegreeEnd(PetscSF sf,const PetscInt **degree) 140995fce210SBarry Smith { 141095fce210SBarry Smith PetscErrorCode ierr; 141195fce210SBarry Smith 141295fce210SBarry Smith PetscFunctionBegin; 141395fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 141495fce210SBarry Smith PetscSFCheckGraphSet(sf,1); 141529046d53SLisandro Dalcin PetscValidPointer(degree,2); 141695fce210SBarry Smith if (!sf->degreeknown) { 141729046d53SLisandro Dalcin if (!sf->degreetmp) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSFComputeDegreeBegin() before PetscSFComputeDegreeEnd()"); 1418dbd2ff41SBarry Smith ierr = PetscSFReduceEnd(sf,MPIU_INT,sf->degreetmp,sf->degree,MPI_SUM);CHKERRQ(ierr); 141995fce210SBarry Smith ierr = PetscFree(sf->degreetmp);CHKERRQ(ierr); 142095fce210SBarry Smith sf->degreeknown = PETSC_TRUE; 142195fce210SBarry Smith } 142295fce210SBarry Smith *degree = sf->degree; 142395fce210SBarry Smith PetscFunctionReturn(0); 142495fce210SBarry Smith } 142595fce210SBarry Smith 1426673100f5SVaclav Hapla 1427673100f5SVaclav Hapla /*@C 142866dfcd1aSVaclav Hapla PetscSFComputeMultiRootOriginalNumbering - Returns original numbering of multi-roots (roots of multi-SF returned by PetscSFGetMultiSF()). 142966dfcd1aSVaclav Hapla Each multi-root is assigned index of the corresponding original root. 1430673100f5SVaclav Hapla 1431673100f5SVaclav Hapla Collective 1432673100f5SVaclav Hapla 1433673100f5SVaclav Hapla Input Arguments: 1434673100f5SVaclav Hapla + sf - star forest 1435673100f5SVaclav Hapla - degree - degree of each root vertex, computed with PetscSFComputeDegreeBegin()/PetscSFComputeDegreeEnd() 1436673100f5SVaclav Hapla 1437673100f5SVaclav Hapla Output Arguments: 143866dfcd1aSVaclav Hapla + nMultiRoots - (optional) number of multi-roots (roots of multi-SF) 143966dfcd1aSVaclav Hapla - multiRootsOrigNumbering - original indices of multi-roots; length of this array is nMultiRoots 1440673100f5SVaclav Hapla 1441673100f5SVaclav Hapla Level: developer 1442673100f5SVaclav Hapla 1443ffe67aa5SVáclav Hapla Notes: 1444ffe67aa5SVáclav Hapla The returned array multiRootsOrigNumbering is newly allocated and should be destroyed with PetscFree() when no longer needed. 1445ffe67aa5SVáclav Hapla 1446673100f5SVaclav Hapla .seealso: PetscSFComputeDegreeBegin(), PetscSFComputeDegreeEnd(), PetscSFGetMultiSF() 1447673100f5SVaclav Hapla @*/ 144866dfcd1aSVaclav Hapla PetscErrorCode PetscSFComputeMultiRootOriginalNumbering(PetscSF sf, const PetscInt degree[], PetscInt *nMultiRoots, PetscInt *multiRootsOrigNumbering[]) 1449673100f5SVaclav Hapla { 1450673100f5SVaclav Hapla PetscSF msf; 1451673100f5SVaclav Hapla PetscInt i, j, k, nroots, nmroots; 1452673100f5SVaclav Hapla PetscErrorCode ierr; 1453673100f5SVaclav Hapla 1454673100f5SVaclav Hapla PetscFunctionBegin; 1455673100f5SVaclav Hapla PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 1456673100f5SVaclav Hapla ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 145729328920SVaclav Hapla if (nroots) PetscValidIntPointer(degree,2); 145866dfcd1aSVaclav Hapla if (nMultiRoots) PetscValidIntPointer(nMultiRoots,3); 145966dfcd1aSVaclav Hapla PetscValidPointer(multiRootsOrigNumbering,4); 1460673100f5SVaclav Hapla ierr = PetscSFGetMultiSF(sf,&msf);CHKERRQ(ierr); 1461673100f5SVaclav Hapla ierr = PetscSFGetGraph(msf, &nmroots, NULL, NULL, NULL);CHKERRQ(ierr); 146266dfcd1aSVaclav Hapla ierr = PetscMalloc1(nmroots, multiRootsOrigNumbering);CHKERRQ(ierr); 1463673100f5SVaclav Hapla for (i=0,j=0,k=0; i<nroots; i++) { 1464673100f5SVaclav Hapla if (!degree[i]) continue; 1465673100f5SVaclav Hapla for (j=0; j<degree[i]; j++,k++) { 146666dfcd1aSVaclav Hapla (*multiRootsOrigNumbering)[k] = i; 1467673100f5SVaclav Hapla } 1468673100f5SVaclav Hapla } 1469673100f5SVaclav Hapla #if defined(PETSC_USE_DEBUG) 1470673100f5SVaclav Hapla if (PetscUnlikely(k != nmroots)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"sanity check fail"); 1471673100f5SVaclav Hapla #endif 147266dfcd1aSVaclav Hapla if (nMultiRoots) *nMultiRoots = nmroots; 1473673100f5SVaclav Hapla PetscFunctionReturn(0); 1474673100f5SVaclav Hapla } 1475673100f5SVaclav Hapla 147695fce210SBarry Smith /*@C 147795fce210SBarry Smith PetscSFFetchAndOpBegin - begin operation that fetches values from root and updates atomically by applying operation using my leaf value, to be completed with PetscSFFetchAndOpEnd() 147895fce210SBarry Smith 147995fce210SBarry Smith Collective 148095fce210SBarry Smith 148195fce210SBarry Smith Input Arguments: 148295fce210SBarry Smith + sf - star forest 148395fce210SBarry Smith . unit - data type 148495fce210SBarry Smith . leafdata - leaf values to use in reduction 148595fce210SBarry Smith - op - operation to use for reduction 148695fce210SBarry Smith 148795fce210SBarry Smith Output Arguments: 148895fce210SBarry Smith + rootdata - root values to be updated, input state is seen by first process to perform an update 148995fce210SBarry Smith - leafupdate - state at each leaf's respective root immediately prior to my atomic update 149095fce210SBarry Smith 149195fce210SBarry Smith Level: advanced 149295fce210SBarry Smith 149395fce210SBarry Smith Note: 149495fce210SBarry Smith The update is only atomic at the granularity provided by the hardware. Different roots referenced by the same process 149595fce210SBarry Smith might be updated in a different order. Furthermore, if a composite type is used for the unit datatype, atomicity is 149695fce210SBarry Smith not guaranteed across the whole vertex. Therefore, this function is mostly only used with primitive types such as 149795fce210SBarry Smith integers. 149895fce210SBarry Smith 149995fce210SBarry Smith .seealso: PetscSFComputeDegreeBegin(), PetscSFReduceBegin(), PetscSFSetGraph() 150095fce210SBarry Smith @*/ 150195fce210SBarry Smith PetscErrorCode PetscSFFetchAndOpBegin(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op) 150295fce210SBarry Smith { 150395fce210SBarry Smith PetscErrorCode ierr; 150495fce210SBarry Smith 150595fce210SBarry Smith PetscFunctionBegin; 150695fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 150795fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 150829046d53SLisandro Dalcin ierr = PetscLogEventBegin(PETSCSF_FetchAndOpBegin,sf,0,0,0);CHKERRQ(ierr); 150995fce210SBarry Smith ierr = (*sf->ops->FetchAndOpBegin)(sf,unit,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr); 1510563ffbabSMatthew G. Knepley ierr = PetscLogEventEnd(PETSCSF_FetchAndOpBegin,sf,0,0,0);CHKERRQ(ierr); 151195fce210SBarry Smith PetscFunctionReturn(0); 151295fce210SBarry Smith } 151395fce210SBarry Smith 151495fce210SBarry Smith /*@C 151595fce210SBarry Smith PetscSFFetchAndOpEnd - end operation started in matching call to PetscSFFetchAndOpBegin() to fetch values from roots and update atomically by applying operation using my leaf value 151695fce210SBarry Smith 151795fce210SBarry Smith Collective 151895fce210SBarry Smith 151995fce210SBarry Smith Input Arguments: 152095fce210SBarry Smith + sf - star forest 152195fce210SBarry Smith . unit - data type 152295fce210SBarry Smith . leafdata - leaf values to use in reduction 152395fce210SBarry Smith - op - operation to use for reduction 152495fce210SBarry Smith 152595fce210SBarry Smith Output Arguments: 152695fce210SBarry Smith + rootdata - root values to be updated, input state is seen by first process to perform an update 152795fce210SBarry Smith - leafupdate - state at each leaf's respective root immediately prior to my atomic update 152895fce210SBarry Smith 152995fce210SBarry Smith Level: advanced 153095fce210SBarry Smith 153195fce210SBarry Smith .seealso: PetscSFComputeDegreeEnd(), PetscSFReduceEnd(), PetscSFSetGraph() 153295fce210SBarry Smith @*/ 153395fce210SBarry Smith PetscErrorCode PetscSFFetchAndOpEnd(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op) 153495fce210SBarry Smith { 153595fce210SBarry Smith PetscErrorCode ierr; 153695fce210SBarry Smith 153795fce210SBarry Smith PetscFunctionBegin; 153895fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 153995fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 154029046d53SLisandro Dalcin ierr = PetscLogEventBegin(PETSCSF_FetchAndOpEnd,sf,0,0,0);CHKERRQ(ierr); 154195fce210SBarry Smith ierr = (*sf->ops->FetchAndOpEnd)(sf,unit,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr); 1542563ffbabSMatthew G. Knepley ierr = PetscLogEventEnd(PETSCSF_FetchAndOpEnd,sf,0,0,0);CHKERRQ(ierr); 154395fce210SBarry Smith PetscFunctionReturn(0); 154495fce210SBarry Smith } 154595fce210SBarry Smith 154695fce210SBarry Smith /*@C 154795fce210SBarry Smith PetscSFGatherBegin - begin pointwise gather of all leaves into multi-roots, to be completed with PetscSFGatherEnd() 154895fce210SBarry Smith 154995fce210SBarry Smith Collective 155095fce210SBarry Smith 155195fce210SBarry Smith Input Arguments: 155295fce210SBarry Smith + sf - star forest 155395fce210SBarry Smith . unit - data type 155495fce210SBarry Smith - leafdata - leaf data to gather to roots 155595fce210SBarry Smith 155695fce210SBarry Smith Output Argument: 155795fce210SBarry Smith . multirootdata - root buffer to gather into, amount of space per root is equal to its degree 155895fce210SBarry Smith 155995fce210SBarry Smith Level: intermediate 156095fce210SBarry Smith 156195fce210SBarry Smith .seealso: PetscSFComputeDegreeBegin(), PetscSFScatterBegin() 156295fce210SBarry Smith @*/ 156395fce210SBarry Smith PetscErrorCode PetscSFGatherBegin(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *multirootdata) 156495fce210SBarry Smith { 156595fce210SBarry Smith PetscErrorCode ierr; 156695fce210SBarry Smith PetscSF multi; 156795fce210SBarry Smith 156895fce210SBarry Smith PetscFunctionBegin; 156995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 157029046d53SLisandro Dalcin ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 157195fce210SBarry Smith ierr = PetscSFGetMultiSF(sf,&multi);CHKERRQ(ierr); 15728bfbc91cSJed Brown ierr = PetscSFReduceBegin(multi,unit,leafdata,multirootdata,MPIU_REPLACE);CHKERRQ(ierr); 157395fce210SBarry Smith PetscFunctionReturn(0); 157495fce210SBarry Smith } 157595fce210SBarry Smith 157695fce210SBarry Smith /*@C 157795fce210SBarry Smith PetscSFGatherEnd - ends pointwise gather operation that was started with PetscSFGatherBegin() 157895fce210SBarry Smith 157995fce210SBarry Smith Collective 158095fce210SBarry Smith 158195fce210SBarry Smith Input Arguments: 158295fce210SBarry Smith + sf - star forest 158395fce210SBarry Smith . unit - data type 158495fce210SBarry Smith - leafdata - leaf data to gather to roots 158595fce210SBarry Smith 158695fce210SBarry Smith Output Argument: 158795fce210SBarry Smith . multirootdata - root buffer to gather into, amount of space per root is equal to its degree 158895fce210SBarry Smith 158995fce210SBarry Smith Level: intermediate 159095fce210SBarry Smith 159195fce210SBarry Smith .seealso: PetscSFComputeDegreeEnd(), PetscSFScatterEnd() 159295fce210SBarry Smith @*/ 159395fce210SBarry Smith PetscErrorCode PetscSFGatherEnd(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *multirootdata) 159495fce210SBarry Smith { 159595fce210SBarry Smith PetscErrorCode ierr; 159695fce210SBarry Smith PetscSF multi; 159795fce210SBarry Smith 159895fce210SBarry Smith PetscFunctionBegin; 159995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 160095fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 160195fce210SBarry Smith ierr = PetscSFGetMultiSF(sf,&multi);CHKERRQ(ierr); 16028bfbc91cSJed Brown ierr = PetscSFReduceEnd(multi,unit,leafdata,multirootdata,MPIU_REPLACE);CHKERRQ(ierr); 160395fce210SBarry Smith PetscFunctionReturn(0); 160495fce210SBarry Smith } 160595fce210SBarry Smith 160695fce210SBarry Smith /*@C 160795fce210SBarry Smith PetscSFScatterBegin - begin pointwise scatter operation from multi-roots to leaves, to be completed with PetscSFScatterEnd() 160895fce210SBarry Smith 160995fce210SBarry Smith Collective 161095fce210SBarry Smith 161195fce210SBarry Smith Input Arguments: 161295fce210SBarry Smith + sf - star forest 161395fce210SBarry Smith . unit - data type 161495fce210SBarry Smith - multirootdata - root buffer to send to each leaf, one unit of data per leaf 161595fce210SBarry Smith 161695fce210SBarry Smith Output Argument: 161795fce210SBarry Smith . leafdata - leaf data to be update with personal data from each respective root 161895fce210SBarry Smith 161995fce210SBarry Smith Level: intermediate 162095fce210SBarry Smith 162195fce210SBarry Smith .seealso: PetscSFComputeDegreeBegin(), PetscSFScatterBegin() 162295fce210SBarry Smith @*/ 162395fce210SBarry Smith PetscErrorCode PetscSFScatterBegin(PetscSF sf,MPI_Datatype unit,const void *multirootdata,void *leafdata) 162495fce210SBarry Smith { 162595fce210SBarry Smith PetscErrorCode ierr; 162695fce210SBarry Smith PetscSF multi; 162795fce210SBarry Smith 162895fce210SBarry Smith PetscFunctionBegin; 162995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 163095fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 163195fce210SBarry Smith ierr = PetscSFGetMultiSF(sf,&multi);CHKERRQ(ierr); 163295fce210SBarry Smith ierr = PetscSFBcastBegin(multi,unit,multirootdata,leafdata);CHKERRQ(ierr); 163395fce210SBarry Smith PetscFunctionReturn(0); 163495fce210SBarry Smith } 163595fce210SBarry Smith 163695fce210SBarry Smith /*@C 163795fce210SBarry Smith PetscSFScatterEnd - ends pointwise scatter operation that was started with PetscSFScatterBegin() 163895fce210SBarry Smith 163995fce210SBarry Smith Collective 164095fce210SBarry Smith 164195fce210SBarry Smith Input Arguments: 164295fce210SBarry Smith + sf - star forest 164395fce210SBarry Smith . unit - data type 164495fce210SBarry Smith - multirootdata - root buffer to send to each leaf, one unit of data per leaf 164595fce210SBarry Smith 164695fce210SBarry Smith Output Argument: 164795fce210SBarry Smith . leafdata - leaf data to be update with personal data from each respective root 164895fce210SBarry Smith 164995fce210SBarry Smith Level: intermediate 165095fce210SBarry Smith 165195fce210SBarry Smith .seealso: PetscSFComputeDegreeEnd(), PetscSFScatterEnd() 165295fce210SBarry Smith @*/ 165395fce210SBarry Smith PetscErrorCode PetscSFScatterEnd(PetscSF sf,MPI_Datatype unit,const void *multirootdata,void *leafdata) 165495fce210SBarry Smith { 165595fce210SBarry Smith PetscErrorCode ierr; 165695fce210SBarry Smith PetscSF multi; 165795fce210SBarry Smith 165895fce210SBarry Smith PetscFunctionBegin; 165995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 166095fce210SBarry Smith ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 166195fce210SBarry Smith ierr = PetscSFGetMultiSF(sf,&multi);CHKERRQ(ierr); 166295fce210SBarry Smith ierr = PetscSFBcastEnd(multi,unit,multirootdata,leafdata);CHKERRQ(ierr); 166395fce210SBarry Smith PetscFunctionReturn(0); 166495fce210SBarry Smith } 1665a7b3aa13SAta Mesgarnejad 1666a7b3aa13SAta Mesgarnejad /*@ 166704c0ada0SJunchao Zhang PetscSFCompose - Compose a new PetscSF by putting the second SF under the first one in a top (roots) down (leaves) view 1668a7b3aa13SAta Mesgarnejad 1669a7b3aa13SAta Mesgarnejad Input Parameters: 167004c0ada0SJunchao Zhang + sfA - The first PetscSF, whose local space may be a permutation, but can not be sparse. 167104c0ada0SJunchao Zhang - sfB - The second PetscSF, whose number of roots must be equal to number of leaves of sfA on each processor 1672a7b3aa13SAta Mesgarnejad 1673a7b3aa13SAta Mesgarnejad Output Parameters: 167404c0ada0SJunchao Zhang . sfBA - The composite SF. Doing a Bcast on the new SF is equvalent to doing Bcast on sfA, then Bcast on sfB 1675a7b3aa13SAta Mesgarnejad 1676a7b3aa13SAta Mesgarnejad Level: developer 1677a7b3aa13SAta Mesgarnejad 167804c0ada0SJunchao Zhang .seealso: PetscSF, PetscSFComposeInverse(), PetscSFGetGraph(), PetscSFSetGraph() 1679a7b3aa13SAta Mesgarnejad @*/ 1680a7b3aa13SAta Mesgarnejad PetscErrorCode PetscSFCompose(PetscSF sfA,PetscSF sfB,PetscSF *sfBA) 1681a7b3aa13SAta Mesgarnejad { 168204c0ada0SJunchao Zhang PetscErrorCode ierr; 1683a7b3aa13SAta Mesgarnejad MPI_Comm comm; 1684a7b3aa13SAta Mesgarnejad const PetscSFNode *remotePointsA,*remotePointsB; 1685*d41018fbSJunchao Zhang PetscSFNode *remotePointsBA=NULL,*reorderedRemotePointsA = NULL,*leafdataB; 1686*d41018fbSJunchao Zhang const PetscInt *localPointsA,*localPointsB,*localPointsBA; 1687*d41018fbSJunchao Zhang PetscInt i,numRootsA,numLeavesA,numRootsB,numLeavesB,minleaf,maxleaf; 1688a7b3aa13SAta Mesgarnejad 1689a7b3aa13SAta Mesgarnejad PetscFunctionBegin; 1690a7b3aa13SAta Mesgarnejad PetscValidHeaderSpecific(sfA,PETSCSF_CLASSID,1); 169129046d53SLisandro Dalcin PetscSFCheckGraphSet(sfA,1); 169229046d53SLisandro Dalcin PetscValidHeaderSpecific(sfB,PETSCSF_CLASSID,2); 169329046d53SLisandro Dalcin PetscSFCheckGraphSet(sfB,2); 169429046d53SLisandro Dalcin PetscValidPointer(sfBA,3); 1695a7b3aa13SAta Mesgarnejad ierr = PetscObjectGetComm((PetscObject)sfA,&comm);CHKERRQ(ierr); 1696a7b3aa13SAta Mesgarnejad ierr = PetscSFGetGraph(sfA,&numRootsA,&numLeavesA,&localPointsA,&remotePointsA);CHKERRQ(ierr); 1697a7b3aa13SAta Mesgarnejad ierr = PetscSFGetGraph(sfB,&numRootsB,&numLeavesB,&localPointsB,&remotePointsB);CHKERRQ(ierr); 169804c0ada0SJunchao Zhang ierr = PetscSFGetLeafRange(sfA,&minleaf,&maxleaf);CHKERRQ(ierr); 1699*d41018fbSJunchao Zhang if (maxleaf+1 != numLeavesA || minleaf) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"The first SF can not have sparse local space"); 170004c0ada0SJunchao Zhang if (numRootsB != numLeavesA) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"The second SF's number of roots must be equal to the first SF's number of leaves"); 1701*d41018fbSJunchao Zhang if (localPointsA) { 1702*d41018fbSJunchao Zhang /* Local space is dense permutation of identity. Need to rewire order of the remote points */ 1703*d41018fbSJunchao Zhang ierr = PetscMalloc1(numLeavesA,&reorderedRemotePointsA);CHKERRQ(ierr); 1704*d41018fbSJunchao Zhang for (i=0; i<numLeavesA; i++) reorderedRemotePointsA[localPointsA[i]-minleaf] = remotePointsA[i]; 1705*d41018fbSJunchao Zhang remotePointsA = reorderedRemotePointsA; 1706*d41018fbSJunchao Zhang } 1707*d41018fbSJunchao Zhang ierr = PetscSFGetLeafRange(sfB,&minleaf,&maxleaf);CHKERRQ(ierr); 1708*d41018fbSJunchao Zhang ierr = PetscMalloc1(maxleaf-minleaf+1,&leafdataB);CHKERRQ(ierr); 1709*d41018fbSJunchao Zhang ierr = PetscSFBcastBegin(sfB,MPIU_2INT,remotePointsA,leafdataB-minleaf);CHKERRQ(ierr); 1710*d41018fbSJunchao Zhang ierr = PetscSFBcastEnd(sfB,MPIU_2INT,remotePointsA,leafdataB-minleaf);CHKERRQ(ierr); 1711*d41018fbSJunchao Zhang ierr = PetscFree(reorderedRemotePointsA);CHKERRQ(ierr); 1712*d41018fbSJunchao Zhang 1713*d41018fbSJunchao Zhang if (minleaf == 0 && maxleaf + 1 == numLeavesB) { /* Local space of sfB is an identity or permutation */ 1714*d41018fbSJunchao Zhang localPointsBA = NULL; 1715*d41018fbSJunchao Zhang remotePointsBA = leafdataB; 1716*d41018fbSJunchao Zhang } else { 1717*d41018fbSJunchao Zhang localPointsBA = localPointsB; 1718a7b3aa13SAta Mesgarnejad ierr = PetscMalloc1(numLeavesB,&remotePointsBA);CHKERRQ(ierr); 1719*d41018fbSJunchao Zhang for (i=0; i<numLeavesB; i++) remotePointsBA[i] = leafdataB[localPointsB[i]-minleaf]; 1720*d41018fbSJunchao Zhang ierr = PetscFree(leafdataB);CHKERRQ(ierr); 1721*d41018fbSJunchao Zhang } 1722a7b3aa13SAta Mesgarnejad ierr = PetscSFCreate(comm, sfBA);CHKERRQ(ierr); 1723*d41018fbSJunchao Zhang ierr = PetscSFSetGraph(*sfBA,numRootsA,numLeavesB,localPointsBA,PETSC_COPY_VALUES,remotePointsBA,PETSC_OWN_POINTER);CHKERRQ(ierr); 1724a7b3aa13SAta Mesgarnejad PetscFunctionReturn(0); 1725a7b3aa13SAta Mesgarnejad } 17261c6ba672SJunchao Zhang 172704c0ada0SJunchao Zhang /*@ 172804c0ada0SJunchao Zhang PetscSFComposeInverse - Compose a new PetscSF by putting inverse of the second SF under the first one 172904c0ada0SJunchao Zhang 173004c0ada0SJunchao Zhang Input Parameters: 173104c0ada0SJunchao Zhang + sfA - The first PetscSF, whose local space may be a permutation, but can not be sparse. 173204c0ada0SJunchao Zhang - sfB - The second PetscSF, whose number of leaves must be equal to number of leaves of sfA on each processor. All roots must have degree 1. 173304c0ada0SJunchao Zhang 173404c0ada0SJunchao Zhang Output Parameters: 173504c0ada0SJunchao Zhang . sfBA - The composite SF. Doing a Bcast on the new SF is equvalent to doing Bcast on sfA, then Bcast on inverse of sfB 173604c0ada0SJunchao Zhang 173704c0ada0SJunchao Zhang Level: developer 173804c0ada0SJunchao Zhang 173904c0ada0SJunchao Zhang .seealso: PetscSF, PetscSFCompose(), PetscSFGetGraph(), PetscSFSetGraph() 174004c0ada0SJunchao Zhang @*/ 174104c0ada0SJunchao Zhang PetscErrorCode PetscSFComposeInverse(PetscSF sfA,PetscSF sfB,PetscSF *sfBA) 174204c0ada0SJunchao Zhang { 174304c0ada0SJunchao Zhang PetscErrorCode ierr; 174404c0ada0SJunchao Zhang MPI_Comm comm; 174504c0ada0SJunchao Zhang const PetscSFNode *remotePointsA,*remotePointsB; 174604c0ada0SJunchao Zhang PetscSFNode *remotePointsBA; 174704c0ada0SJunchao Zhang const PetscInt *localPointsA,*localPointsB; 174804c0ada0SJunchao Zhang PetscInt numRootsA,numLeavesA,numRootsB,numLeavesB,minleaf,maxleaf; 174904c0ada0SJunchao Zhang 175004c0ada0SJunchao Zhang PetscFunctionBegin; 175104c0ada0SJunchao Zhang PetscValidHeaderSpecific(sfA,PETSCSF_CLASSID,1); 175204c0ada0SJunchao Zhang PetscSFCheckGraphSet(sfA,1); 175304c0ada0SJunchao Zhang PetscValidHeaderSpecific(sfB,PETSCSF_CLASSID,2); 175404c0ada0SJunchao Zhang PetscSFCheckGraphSet(sfB,2); 175504c0ada0SJunchao Zhang PetscValidPointer(sfBA,3); 175604c0ada0SJunchao Zhang ierr = PetscObjectGetComm((PetscObject) sfA, &comm);CHKERRQ(ierr); 175704c0ada0SJunchao Zhang ierr = PetscSFGetGraph(sfA, &numRootsA, &numLeavesA, &localPointsA, &remotePointsA);CHKERRQ(ierr); 175804c0ada0SJunchao Zhang ierr = PetscSFGetGraph(sfB, &numRootsB, &numLeavesB, &localPointsB, &remotePointsB);CHKERRQ(ierr); 175904c0ada0SJunchao Zhang ierr = PetscSFGetLeafRange(sfA,&minleaf,&maxleaf);CHKERRQ(ierr); 176004c0ada0SJunchao Zhang if (maxleaf+1-minleaf != numLeavesA) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"The first SF can not have sparse local space"); 176104c0ada0SJunchao Zhang if (numLeavesA != numLeavesB) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"The second SF's number of leaves must be equal to the first SF's number of leaves"); 176204c0ada0SJunchao Zhang ierr = PetscMalloc1(numRootsB,&remotePointsBA);CHKERRQ(ierr); 176304c0ada0SJunchao Zhang ierr = PetscSFReduceBegin(sfB,MPIU_2INT,remotePointsA,remotePointsBA,MPIU_REPLACE);CHKERRQ(ierr); 176404c0ada0SJunchao Zhang ierr = PetscSFReduceEnd(sfB,MPIU_2INT,remotePointsA,remotePointsBA,MPIU_REPLACE);CHKERRQ(ierr); 176504c0ada0SJunchao Zhang ierr = PetscSFCreate(comm,sfBA);CHKERRQ(ierr); 176604c0ada0SJunchao Zhang ierr = PetscSFSetGraph(*sfBA,numRootsA,numRootsB,NULL,PETSC_COPY_VALUES,remotePointsBA,PETSC_OWN_POINTER);CHKERRQ(ierr); 176704c0ada0SJunchao Zhang PetscFunctionReturn(0); 176804c0ada0SJunchao Zhang } 176904c0ada0SJunchao Zhang 17701c6ba672SJunchao Zhang /* 17711c6ba672SJunchao Zhang PetscSFCreateLocalSF_Private - Creates a local PetscSF that only has intra-process edges of the global PetscSF 17721c6ba672SJunchao Zhang 17731c6ba672SJunchao Zhang Input Parameters: 17741c6ba672SJunchao Zhang . sf - The global PetscSF 17751c6ba672SJunchao Zhang 17761c6ba672SJunchao Zhang Output Parameters: 17771c6ba672SJunchao Zhang . out - The local PetscSF 17781c6ba672SJunchao Zhang */ 17791c6ba672SJunchao Zhang PetscErrorCode PetscSFCreateLocalSF_Private(PetscSF sf,PetscSF *out) 17801c6ba672SJunchao Zhang { 17811c6ba672SJunchao Zhang MPI_Comm comm; 17821c6ba672SJunchao Zhang PetscMPIInt myrank; 17831c6ba672SJunchao Zhang const PetscInt *ilocal; 17841c6ba672SJunchao Zhang const PetscSFNode *iremote; 17851c6ba672SJunchao Zhang PetscInt i,j,nroots,nleaves,lnleaves,*lilocal; 17861c6ba672SJunchao Zhang PetscSFNode *liremote; 17871c6ba672SJunchao Zhang PetscSF lsf; 17881c6ba672SJunchao Zhang PetscErrorCode ierr; 17891c6ba672SJunchao Zhang 17901c6ba672SJunchao Zhang PetscFunctionBegin; 17911c6ba672SJunchao Zhang PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 17921c6ba672SJunchao Zhang if (sf->ops->CreateLocalSF) { 17931c6ba672SJunchao Zhang ierr = (*sf->ops->CreateLocalSF)(sf,out);CHKERRQ(ierr); 17941c6ba672SJunchao Zhang } else { 17951c6ba672SJunchao Zhang /* Could use PetscSFCreateEmbeddedLeafSF, but since we know the comm is PETSC_COMM_SELF, we can make it fast */ 17961c6ba672SJunchao Zhang ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); 17971c6ba672SJunchao Zhang ierr = MPI_Comm_rank(comm,&myrank);CHKERRQ(ierr); 17981c6ba672SJunchao Zhang 17991c6ba672SJunchao Zhang /* Find out local edges and build a local SF */ 18001c6ba672SJunchao Zhang ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 18011c6ba672SJunchao Zhang for (i=lnleaves=0; i<nleaves; i++) {if (iremote[i].rank == (PetscInt)myrank) lnleaves++;} 18021c6ba672SJunchao Zhang ierr = PetscMalloc1(lnleaves,&lilocal);CHKERRQ(ierr); 18031c6ba672SJunchao Zhang ierr = PetscMalloc1(lnleaves,&liremote);CHKERRQ(ierr); 18041c6ba672SJunchao Zhang 18051c6ba672SJunchao Zhang for (i=j=0; i<nleaves; i++) { 18061c6ba672SJunchao Zhang if (iremote[i].rank == (PetscInt)myrank) { 18071c6ba672SJunchao Zhang lilocal[j] = ilocal? ilocal[i] : i; /* ilocal=NULL for contiguous storage */ 18081c6ba672SJunchao Zhang liremote[j].rank = 0; /* rank in PETSC_COMM_SELF */ 18091c6ba672SJunchao Zhang liremote[j].index = iremote[i].index; 18101c6ba672SJunchao Zhang j++; 18111c6ba672SJunchao Zhang } 18121c6ba672SJunchao Zhang } 18131c6ba672SJunchao Zhang ierr = PetscSFCreate(PETSC_COMM_SELF,&lsf);CHKERRQ(ierr); 18141c6ba672SJunchao Zhang ierr = PetscSFSetGraph(lsf,nroots,lnleaves,lilocal,PETSC_OWN_POINTER,liremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 18151c6ba672SJunchao Zhang ierr = PetscSFSetUp(lsf);CHKERRQ(ierr); 18161c6ba672SJunchao Zhang *out = lsf; 18171c6ba672SJunchao Zhang } 18181c6ba672SJunchao Zhang PetscFunctionReturn(0); 18191c6ba672SJunchao Zhang } 1820dd5b3ca6SJunchao Zhang 1821dd5b3ca6SJunchao Zhang /* Similar to PetscSFBcast, but only Bcast to leaves on rank 0 */ 1822dd5b3ca6SJunchao Zhang PetscErrorCode PetscSFBcastToZero_Private(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata) 1823dd5b3ca6SJunchao Zhang { 1824dd5b3ca6SJunchao Zhang PetscErrorCode ierr; 1825dd5b3ca6SJunchao Zhang 1826dd5b3ca6SJunchao Zhang PetscFunctionBegin; 1827dd5b3ca6SJunchao Zhang PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 1828dd5b3ca6SJunchao Zhang ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 1829dd5b3ca6SJunchao Zhang ierr = PetscLogEventBegin(PETSCSF_BcastAndOpBegin,sf,0,0,0);CHKERRQ(ierr); 1830dd5b3ca6SJunchao Zhang if (sf->ops->BcastToZero) { 1831dd5b3ca6SJunchao Zhang ierr = (*sf->ops->BcastToZero)(sf,unit,rootdata,leafdata);CHKERRQ(ierr); 1832dd5b3ca6SJunchao Zhang } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscSFBcastToZero_Private is not supported on this SF type"); 1833dd5b3ca6SJunchao Zhang ierr = PetscLogEventEnd(PETSCSF_BcastAndOpBegin,sf,0,0,0);CHKERRQ(ierr); 1834dd5b3ca6SJunchao Zhang PetscFunctionReturn(0); 1835dd5b3ca6SJunchao Zhang } 1836dd5b3ca6SJunchao Zhang 1837