1 2 #include "petscsf.h" 3 #include <../src/vec/is/sf/impls/basic/sfbasic.h> 4 #include <../src/vec/is/sf/impls/basic/sfpack.h> 5 6 /*===================================================================================*/ 7 /* SF public interface implementations */ 8 /*===================================================================================*/ 9 PETSC_INTERN PetscErrorCode PetscSFSetUp_Basic(PetscSF sf) 10 { 11 PetscErrorCode ierr; 12 PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 13 PetscInt *rlengths,*ilengths,i; 14 PetscMPIInt rank,niranks,*iranks,tag; 15 MPI_Comm comm; 16 MPI_Group group; 17 MPI_Request *rootreqs,*leafreqs; 18 19 PetscFunctionBegin; 20 ierr = MPI_Comm_group(PETSC_COMM_SELF,&group);CHKERRQ(ierr); 21 ierr = PetscSFSetUpRanks(sf,group);CHKERRQ(ierr); 22 ierr = MPI_Group_free(&group);CHKERRQ(ierr); 23 ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); 24 ierr = PetscObjectGetNewTag((PetscObject)sf,&tag);CHKERRQ(ierr); 25 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 26 /* 27 * Inform roots about how many leaves and from which ranks 28 */ 29 ierr = PetscMalloc1(sf->nranks,&rlengths);CHKERRQ(ierr); 30 /* Determine number, sending ranks and length of incoming */ 31 for (i=0; i<sf->nranks; i++) { 32 rlengths[i] = sf->roffset[i+1] - sf->roffset[i]; /* Number of roots referenced by my leaves; for rank sf->ranks[i] */ 33 } 34 ierr = PetscCommBuildTwoSided(comm,1,MPIU_INT,sf->nranks-sf->ndranks,sf->ranks+sf->ndranks,rlengths+sf->ndranks,&niranks,&iranks,(void**)&ilengths);CHKERRQ(ierr); 35 36 /* Sort iranks. See use of VecScatterGetRemoteOrdered_Private() in MatGetBrowsOfAoCols_MPIAIJ() on why. 37 We could sort ranks there at the price of allocating extra working arrays. Presumably, niranks is 38 small and the sorting is cheap. 39 */ 40 ierr = PetscSortMPIIntWithIntArray(niranks,iranks,ilengths);CHKERRQ(ierr); 41 42 /* Partition into distinguished and non-distinguished incoming ranks */ 43 bas->ndiranks = sf->ndranks; 44 bas->niranks = bas->ndiranks + niranks; 45 ierr = PetscMalloc2(bas->niranks,&bas->iranks,bas->niranks+1,&bas->ioffset);CHKERRQ(ierr); 46 bas->ioffset[0] = 0; 47 for (i=0; i<bas->ndiranks; i++) { 48 bas->iranks[i] = sf->ranks[i]; 49 bas->ioffset[i+1] = bas->ioffset[i] + rlengths[i]; 50 } 51 if (bas->ndiranks > 1 || (bas->ndiranks == 1 && bas->iranks[0] != rank)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Broken setup for shared ranks"); 52 for (; i<bas->niranks; i++) { 53 bas->iranks[i] = iranks[i-bas->ndiranks]; 54 bas->ioffset[i+1] = bas->ioffset[i] + ilengths[i-bas->ndiranks]; 55 } 56 bas->itotal = bas->ioffset[i]; 57 ierr = PetscFree(rlengths);CHKERRQ(ierr); 58 ierr = PetscFree(iranks);CHKERRQ(ierr); 59 ierr = PetscFree(ilengths);CHKERRQ(ierr); 60 61 /* Send leaf identities to roots */ 62 ierr = PetscMalloc1(bas->itotal,&bas->irootloc);CHKERRQ(ierr); 63 ierr = PetscMalloc2(bas->niranks-bas->ndiranks,&rootreqs,sf->nranks-sf->ndranks,&leafreqs);CHKERRQ(ierr); 64 for (i=bas->ndiranks; i<bas->niranks; i++) { 65 ierr = MPI_Irecv(bas->irootloc+bas->ioffset[i],bas->ioffset[i+1]-bas->ioffset[i],MPIU_INT,bas->iranks[i],tag,comm,&rootreqs[i-bas->ndiranks]);CHKERRQ(ierr); 66 } 67 for (i=0; i<sf->nranks; i++) { 68 PetscMPIInt npoints; 69 ierr = PetscMPIIntCast(sf->roffset[i+1] - sf->roffset[i],&npoints);CHKERRQ(ierr); 70 if (i < sf->ndranks) { 71 if (sf->ranks[i] != rank) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot interpret distinguished leaf rank"); 72 if (bas->iranks[0] != rank) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot interpret distinguished root rank"); 73 if (npoints != bas->ioffset[1]-bas->ioffset[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Distinguished rank exchange has mismatched lengths"); 74 ierr = PetscArraycpy(bas->irootloc+bas->ioffset[0],sf->rremote+sf->roffset[i],npoints);CHKERRQ(ierr); 75 continue; 76 } 77 ierr = MPI_Isend(sf->rremote+sf->roffset[i],npoints,MPIU_INT,sf->ranks[i],tag,comm,&leafreqs[i-sf->ndranks]);CHKERRQ(ierr); 78 } 79 ierr = MPI_Waitall(bas->niranks-bas->ndiranks,rootreqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); 80 ierr = MPI_Waitall(sf->nranks-sf->ndranks,leafreqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); 81 ierr = PetscFree2(rootreqs,leafreqs);CHKERRQ(ierr); 82 83 sf->nleafreqs = sf->nranks - sf->ndranks; 84 bas->nrootreqs = bas->niranks - bas->ndiranks; 85 sf->persistent = PETSC_TRUE; 86 87 /* Setup fields related to packing */ 88 ierr = PetscSFSetUpPackFields(sf);CHKERRQ(ierr); 89 PetscFunctionReturn(0); 90 } 91 92 PETSC_INTERN PetscErrorCode PetscSFReset_Basic(PetscSF sf) 93 { 94 PetscErrorCode ierr; 95 PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 96 97 PetscFunctionBegin; 98 if (bas->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Outstanding operation has not been completed"); 99 ierr = PetscFree2(bas->iranks,bas->ioffset);CHKERRQ(ierr); 100 ierr = PetscFree(bas->irootloc);CHKERRQ(ierr); 101 #if defined(PETSC_HAVE_DEVICE) 102 for (PetscInt i=0; i<2; i++) {ierr = PetscSFFree(sf,PETSC_MEMTYPE_DEVICE,bas->irootloc_d[i]);CHKERRQ(ierr);} 103 #endif 104 ierr = PetscSFLinkDestroy(sf,&bas->avail);CHKERRQ(ierr); 105 ierr = PetscSFResetPackFields(sf);CHKERRQ(ierr); 106 PetscFunctionReturn(0); 107 } 108 109 PETSC_INTERN PetscErrorCode PetscSFDestroy_Basic(PetscSF sf) 110 { 111 PetscErrorCode ierr; 112 113 PetscFunctionBegin; 114 ierr = PetscSFReset_Basic(sf);CHKERRQ(ierr); 115 ierr = PetscFree(sf->data);CHKERRQ(ierr); 116 PetscFunctionReturn(0); 117 } 118 119 PETSC_INTERN PetscErrorCode PetscSFView_Basic(PetscSF sf,PetscViewer viewer) 120 { 121 PetscErrorCode ierr; 122 PetscBool iascii; 123 124 PetscFunctionBegin; 125 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 126 if (iascii) {ierr = PetscViewerASCIIPrintf(viewer," sort=%s\n",sf->rankorder ? "rank-order" : "unordered");CHKERRQ(ierr);} 127 PetscFunctionReturn(0); 128 } 129 130 static PetscErrorCode PetscSFBcastAndOpBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op) 131 { 132 PetscErrorCode ierr; 133 PetscSFLink link = NULL; 134 MPI_Request *rootreqs = NULL,*leafreqs = NULL; 135 PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 136 137 PetscFunctionBegin; 138 /* Create a communication link, which provides buffers & MPI requests etc */ 139 ierr = PetscSFLinkCreate(sf,unit,rootmtype,rootdata,leafmtype,leafdata,op,PETSCSF_BCAST,&link);CHKERRQ(ierr); 140 /* Get MPI requests from the link. We do not need buffers explicitly since we use persistent MPI */ 141 ierr = PetscSFLinkGetMPIBuffersAndRequests(sf,link,PETSCSF_ROOT2LEAF,NULL,NULL,&rootreqs,&leafreqs);CHKERRQ(ierr); 142 /* Post Irecv for remote */ 143 ierr = MPI_Startall_irecv(sf->leafbuflen[PETSCSF_REMOTE],unit,sf->nleafreqs,leafreqs);CHKERRQ(ierr); 144 /* Pack rootdata and do Isend for remote */ 145 ierr = PetscSFLinkPackRootData(sf,link,PETSCSF_REMOTE,rootdata);CHKERRQ(ierr); 146 ierr = MPI_Startall_isend(bas->rootbuflen[PETSCSF_REMOTE],unit,bas->nrootreqs,rootreqs);CHKERRQ(ierr); 147 /* Do local BcastAndOp, which overlaps with the irecv/isend above */ 148 ierr = PetscSFLinkBcastAndOpLocal(sf,link,rootdata,leafdata,op);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 PETSC_INTERN PetscErrorCode PetscSFBcastAndOpEnd_Basic(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op) 153 { 154 PetscErrorCode ierr; 155 PetscSFLink link = NULL; 156 157 PetscFunctionBegin; 158 /* Retrieve the link used in XxxBegin() with root/leafdata as key */ 159 ierr = PetscSFLinkGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 160 /* Wait for the completion of mpi */ 161 ierr = PetscSFLinkMPIWaitall(sf,link,PETSCSF_ROOT2LEAF);CHKERRQ(ierr); 162 /* Unpack leafdata and reclaim the link */ 163 ierr = PetscSFLinkUnpackLeafData(sf,link,PETSCSF_REMOTE,leafdata,op);CHKERRQ(ierr); 164 ierr = PetscSFLinkReclaim(sf,&link);CHKERRQ(ierr); 165 PetscFunctionReturn(0); 166 } 167 168 /* Shared by ReduceBegin and FetchAndOpBegin */ 169 PETSC_STATIC_INLINE PetscErrorCode PetscSFLeafToRootBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op,PetscSFOperation sfop,PetscSFLink *out) 170 { 171 PetscErrorCode ierr; 172 PetscSFLink link; 173 PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 174 MPI_Request *rootreqs = NULL,*leafreqs = NULL; 175 176 PetscFunctionBegin; 177 ierr = PetscSFLinkCreate(sf,unit,rootmtype,rootdata,leafmtype,leafdata,op,sfop,&link);CHKERRQ(ierr); 178 ierr = PetscSFLinkGetMPIBuffersAndRequests(sf,link,PETSCSF_LEAF2ROOT,NULL,NULL,&rootreqs,&leafreqs);CHKERRQ(ierr); 179 ierr = MPI_Startall_irecv(bas->rootbuflen[PETSCSF_REMOTE],unit,bas->nrootreqs,rootreqs);CHKERRQ(ierr); 180 ierr = PetscSFLinkPackLeafData(sf,link,PETSCSF_REMOTE,leafdata);CHKERRQ(ierr); 181 ierr = MPI_Startall_isend(sf->leafbuflen[PETSCSF_REMOTE],unit,sf->nleafreqs,leafreqs);CHKERRQ(ierr); 182 *out = link; 183 PetscFunctionReturn(0); 184 } 185 186 /* leaf -> root with reduction */ 187 static PetscErrorCode PetscSFReduceBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op) 188 { 189 PetscErrorCode ierr; 190 PetscSFLink link = NULL; 191 192 PetscFunctionBegin; 193 ierr = PetscSFLeafToRootBegin_Basic(sf,unit,leafmtype,leafdata,rootmtype,rootdata,op,PETSCSF_REDUCE,&link);CHKERRQ(ierr); 194 ierr = PetscSFLinkReduceLocal(sf,link,leafdata,rootdata,op);CHKERRQ(ierr); 195 PetscFunctionReturn(0); 196 } 197 198 PETSC_INTERN PetscErrorCode PetscSFReduceEnd_Basic(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op) 199 { 200 PetscErrorCode ierr; 201 PetscSFLink link = NULL; 202 203 PetscFunctionBegin; 204 ierr = PetscSFLinkGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 205 ierr = PetscSFLinkMPIWaitall(sf,link,PETSCSF_LEAF2ROOT);CHKERRQ(ierr); 206 ierr = PetscSFLinkUnpackRootData(sf,link,PETSCSF_REMOTE,rootdata,op);CHKERRQ(ierr); 207 ierr = PetscSFLinkReclaim(sf,&link);CHKERRQ(ierr); 208 PetscFunctionReturn(0); 209 } 210 211 PETSC_INTERN PetscErrorCode PetscSFFetchAndOpBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op) 212 { 213 PetscErrorCode ierr; 214 PetscSFLink link = NULL; 215 216 PetscFunctionBegin; 217 ierr = PetscSFLeafToRootBegin_Basic(sf,unit,leafmtype,leafdata,rootmtype,rootdata,op,PETSCSF_FETCH,&link);CHKERRQ(ierr); 218 ierr = PetscSFLinkFetchAndOpLocal(sf,link,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr); 219 PetscFunctionReturn(0); 220 } 221 222 static PetscErrorCode PetscSFFetchAndOpEnd_Basic(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op) 223 { 224 PetscErrorCode ierr; 225 PetscSFLink link = NULL; 226 MPI_Request *rootreqs = NULL,*leafreqs = NULL; 227 PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 228 229 PetscFunctionBegin; 230 ierr = PetscSFLinkGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 231 /* This implementation could be changed to unpack as receives arrive, at the cost of non-determinism */ 232 ierr = PetscSFLinkMPIWaitall(sf,link,PETSCSF_LEAF2ROOT);CHKERRQ(ierr); 233 /* Do fetch-and-op, the (remote) update results are in rootbuf */ 234 ierr = PetscSFLinkFetchRootData(sf,link,PETSCSF_REMOTE,rootdata,op);CHKERRQ(ierr); 235 236 /* Bcast rootbuf to leafupdate */ 237 ierr = PetscSFLinkGetMPIBuffersAndRequests(sf,link,PETSCSF_ROOT2LEAF,NULL,NULL,&rootreqs,&leafreqs);CHKERRQ(ierr); 238 /* Post leaf receives and root sends */ 239 ierr = MPI_Startall_irecv(sf->leafbuflen[PETSCSF_REMOTE],unit,sf->nleafreqs,leafreqs);CHKERRQ(ierr); 240 ierr = MPI_Startall_isend(bas->rootbuflen[PETSCSF_REMOTE],unit,bas->nrootreqs,rootreqs);CHKERRQ(ierr); 241 /* Unpack and insert fetched data into leaves */ 242 ierr = PetscSFLinkMPIWaitall(sf,link,PETSCSF_ROOT2LEAF);CHKERRQ(ierr); 243 ierr = PetscSFLinkUnpackLeafData(sf,link,PETSCSF_REMOTE,leafupdate,MPIU_REPLACE);CHKERRQ(ierr); 244 ierr = PetscSFLinkReclaim(sf,&link);CHKERRQ(ierr); 245 PetscFunctionReturn(0); 246 } 247 248 PETSC_INTERN PetscErrorCode PetscSFGetLeafRanks_Basic(PetscSF sf,PetscInt *niranks,const PetscMPIInt **iranks,const PetscInt **ioffset,const PetscInt **irootloc) 249 { 250 PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 251 252 PetscFunctionBegin; 253 if (niranks) *niranks = bas->niranks; 254 if (iranks) *iranks = bas->iranks; 255 if (ioffset) *ioffset = bas->ioffset; 256 if (irootloc) *irootloc = bas->irootloc; 257 PetscFunctionReturn(0); 258 } 259 260 /* An optimized PetscSFCreateEmbeddedSF. We aggresively make use of the established communication on sf. 261 We need one bcast on sf, and no communication anymore to build the embedded sf. Note that selected[] 262 was sorted before calling the routine. 263 */ 264 PETSC_INTERN PetscErrorCode PetscSFCreateEmbeddedSF_Basic(PetscSF sf,PetscInt nselected,const PetscInt *selected,PetscSF *newsf) 265 { 266 PetscSF esf; 267 PetscInt esf_nranks,esf_ndranks,*esf_roffset,*esf_rmine,*esf_rremote; 268 PetscInt i,j,p,q,nroots,esf_nleaves,*new_ilocal,nranks,ndranks,niranks,ndiranks,minleaf,maxleaf,maxlocal; 269 char *rootdata,*leafdata,*leafmem; /* Only stores 0 or 1, so we can save memory with char */ 270 PetscMPIInt *esf_ranks; 271 const PetscMPIInt *ranks,*iranks; 272 const PetscInt *roffset,*rmine,*rremote,*ioffset,*irootloc; 273 PetscBool connected; 274 PetscSFNode *new_iremote; 275 PetscSF_Basic *bas; 276 PetscErrorCode ierr; 277 278 PetscFunctionBegin; 279 ierr = PetscSFCreate(PetscObjectComm((PetscObject)sf),&esf);CHKERRQ(ierr); 280 ierr = PetscSFSetFromOptions(esf);CHKERRQ(ierr); 281 ierr = PetscSFSetType(esf,PETSCSFBASIC);CHKERRQ(ierr); /* This optimized routine can only create a basic sf */ 282 283 /* Find out which leaves are still connected to roots in the embedded sf by doing a Bcast */ 284 ierr = PetscSFGetGraph(sf,&nroots,NULL,NULL,NULL);CHKERRQ(ierr); 285 ierr = PetscSFGetLeafRange(sf,&minleaf,&maxleaf);CHKERRQ(ierr); 286 maxlocal = maxleaf - minleaf + 1; 287 ierr = PetscCalloc2(nroots,&rootdata,maxlocal,&leafmem);CHKERRQ(ierr); 288 leafdata = leafmem - minleaf; 289 /* Tag selected roots */ 290 for (i=0; i<nselected; ++i) rootdata[selected[i]] = 1; 291 292 ierr = PetscSFBcastBegin(sf,MPI_CHAR,rootdata,leafdata);CHKERRQ(ierr); 293 ierr = PetscSFBcastEnd(sf,MPI_CHAR,rootdata,leafdata);CHKERRQ(ierr); 294 ierr = PetscSFGetLeafInfo_Basic(sf,&nranks,&ndranks,&ranks,&roffset,&rmine,&rremote);CHKERRQ(ierr); /* Get send info */ 295 esf_nranks = esf_ndranks = esf_nleaves = 0; 296 for (i=0; i<nranks; i++) { 297 connected = PETSC_FALSE; /* Is this process still connected to this remote root rank? */ 298 for (j=roffset[i]; j<roffset[i+1]; j++) {if (leafdata[rmine[j]]) {esf_nleaves++; connected = PETSC_TRUE;}} 299 if (connected) {esf_nranks++; if (i < ndranks) esf_ndranks++;} 300 } 301 302 /* Set graph of esf and also set up its outgoing communication (i.e., send info), which is usually done by PetscSFSetUpRanks */ 303 ierr = PetscMalloc1(esf_nleaves,&new_ilocal);CHKERRQ(ierr); 304 ierr = PetscMalloc1(esf_nleaves,&new_iremote);CHKERRQ(ierr); 305 ierr = PetscMalloc4(esf_nranks,&esf_ranks,esf_nranks+1,&esf_roffset,esf_nleaves,&esf_rmine,esf_nleaves,&esf_rremote);CHKERRQ(ierr); 306 p = 0; /* Counter for connected root ranks */ 307 q = 0; /* Counter for connected leaves */ 308 esf_roffset[0] = 0; 309 for (i=0; i<nranks; i++) { /* Scan leaf data again to fill esf arrays */ 310 connected = PETSC_FALSE; 311 for (j=roffset[i]; j<roffset[i+1]; j++) { 312 if (leafdata[rmine[j]]) { 313 esf_rmine[q] = new_ilocal[q] = rmine[j]; 314 esf_rremote[q] = rremote[j]; 315 new_iremote[q].index = rremote[j]; 316 new_iremote[q].rank = ranks[i]; 317 connected = PETSC_TRUE; 318 q++; 319 } 320 } 321 if (connected) { 322 esf_ranks[p] = ranks[i]; 323 esf_roffset[p+1] = q; 324 p++; 325 } 326 } 327 328 /* SetGraph internally resets the SF, so we only set its fields after the call */ 329 ierr = PetscSFSetGraph(esf,nroots,esf_nleaves,new_ilocal,PETSC_OWN_POINTER,new_iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 330 esf->nranks = esf_nranks; 331 esf->ndranks = esf_ndranks; 332 esf->ranks = esf_ranks; 333 esf->roffset = esf_roffset; 334 esf->rmine = esf_rmine; 335 esf->rremote = esf_rremote; 336 esf->nleafreqs = esf_nranks - esf_ndranks; 337 338 /* Set up the incoming communication (i.e., recv info) stored in esf->data, which is usually done by PetscSFSetUp_Basic */ 339 bas = (PetscSF_Basic*)esf->data; 340 ierr = PetscSFGetRootInfo_Basic(sf,&niranks,&ndiranks,&iranks,&ioffset,&irootloc);CHKERRQ(ierr); /* Get recv info */ 341 /* Embedded sf always has simpler communication than the original one. We might allocate longer arrays than needed here. But we 342 we do not care since these arrays are usually short. The benefit is we can fill these arrays by just parsing irootloc once. 343 */ 344 ierr = PetscMalloc2(niranks,&bas->iranks,niranks+1,&bas->ioffset);CHKERRQ(ierr); 345 ierr = PetscMalloc1(ioffset[niranks],&bas->irootloc);CHKERRQ(ierr); 346 bas->niranks = bas->ndiranks = bas->ioffset[0] = 0; 347 p = 0; /* Counter for connected leaf ranks */ 348 q = 0; /* Counter for connected roots */ 349 for (i=0; i<niranks; i++) { 350 connected = PETSC_FALSE; /* Is the current process still connected to this remote leaf rank? */ 351 for (j=ioffset[i]; j<ioffset[i+1]; j++) { 352 if (rootdata[irootloc[j]]) { 353 bas->irootloc[q++] = irootloc[j]; 354 connected = PETSC_TRUE; 355 } 356 } 357 if (connected) { 358 bas->niranks++; 359 if (i<ndiranks) bas->ndiranks++; /* Note that order of ranks (including distinguished ranks) is kept */ 360 bas->iranks[p] = iranks[i]; 361 bas->ioffset[p+1] = q; 362 p++; 363 } 364 } 365 bas->itotal = q; 366 bas->nrootreqs = bas->niranks - bas->ndiranks; 367 esf->persistent = PETSC_TRUE; 368 /* Setup packing related fields */ 369 ierr = PetscSFSetUpPackFields(esf);CHKERRQ(ierr); 370 371 /* Copy from PetscSFSetUp(), since this method wants to skip PetscSFSetUp(). */ 372 #if defined(PETSC_HAVE_CUDA) 373 if (esf->backend == PETSCSF_BACKEND_CUDA) { 374 esf->ops->Malloc = PetscSFMalloc_Cuda; 375 esf->ops->Free = PetscSFFree_Cuda; 376 } 377 #endif 378 379 #if defined(PETSC_HAVE_KOKKOS) 380 if (esf->backend == PETSCSF_BACKEND_KOKKOS) { 381 esf->ops->Malloc = PetscSFMalloc_Kokkos; 382 esf->ops->Free = PetscSFFree_Kokkos; 383 } 384 #endif 385 esf->setupcalled = PETSC_TRUE; /* We have done setup ourselves! */ 386 ierr = PetscFree2(rootdata,leafmem);CHKERRQ(ierr); 387 *newsf = esf; 388 PetscFunctionReturn(0); 389 } 390 391 PETSC_EXTERN PetscErrorCode PetscSFCreate_Basic(PetscSF sf) 392 { 393 PetscSF_Basic *dat; 394 PetscErrorCode ierr; 395 396 PetscFunctionBegin; 397 sf->ops->SetUp = PetscSFSetUp_Basic; 398 sf->ops->Reset = PetscSFReset_Basic; 399 sf->ops->Destroy = PetscSFDestroy_Basic; 400 sf->ops->View = PetscSFView_Basic; 401 sf->ops->BcastAndOpBegin = PetscSFBcastAndOpBegin_Basic; 402 sf->ops->BcastAndOpEnd = PetscSFBcastAndOpEnd_Basic; 403 sf->ops->ReduceBegin = PetscSFReduceBegin_Basic; 404 sf->ops->ReduceEnd = PetscSFReduceEnd_Basic; 405 sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Basic; 406 sf->ops->FetchAndOpEnd = PetscSFFetchAndOpEnd_Basic; 407 sf->ops->GetLeafRanks = PetscSFGetLeafRanks_Basic; 408 sf->ops->CreateEmbeddedSF = PetscSFCreateEmbeddedSF_Basic; 409 410 ierr = PetscNewLog(sf,&dat);CHKERRQ(ierr); 411 sf->data = (void*)dat; 412 PetscFunctionReturn(0); 413 } 414