1b0c7db22SLisandro Dalcin #include <petsc/private/sfimpl.h> /*I "petscsf.h" I*/ 2b0c7db22SLisandro Dalcin #include <petsc/private/sectionimpl.h> 3b0c7db22SLisandro Dalcin 4b0c7db22SLisandro Dalcin /*@C 5b0c7db22SLisandro Dalcin PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout 6b0c7db22SLisandro Dalcin 7b0c7db22SLisandro Dalcin Collective 8b0c7db22SLisandro Dalcin 94165533cSJose E. Roman Input Parameters: 10b0c7db22SLisandro Dalcin + sf - star forest 11ddea5d60SJunchao Zhang . layout - PetscLayout defining the global space for roots 12b0c7db22SLisandro Dalcin . nleaves - number of leaf vertices on the current process, each of these references a root on any process 13b0c7db22SLisandro Dalcin . ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage 14b0c7db22SLisandro Dalcin . localmode - copy mode for ilocal 1586c56f52SVaclav Hapla - iremote - root vertices in global numbering corresponding to leaves in ilocal 16b0c7db22SLisandro Dalcin 17b0c7db22SLisandro Dalcin Level: intermediate 18b0c7db22SLisandro Dalcin 1986c56f52SVaclav Hapla Notes: 2086c56f52SVaclav Hapla Global indices must lie in [0, N) where N is the global size of layout. 21db2b9530SVaclav Hapla Leaf indices in ilocal get sorted; this means the user-provided array gets sorted if localmode is PETSC_OWN_POINTER. 2286c56f52SVaclav Hapla 23db2b9530SVaclav Hapla Developer Notes: 2486c56f52SVaclav Hapla Local indices which are the identity permutation in the range [0,nleaves) are discarded as they 25b0c7db22SLisandro Dalcin encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not 26b0c7db22SLisandro Dalcin needed 27b0c7db22SLisandro Dalcin 28b0c7db22SLisandro Dalcin .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph() 29b0c7db22SLisandro Dalcin @*/ 30db2b9530SVaclav Hapla PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote) 31b0c7db22SLisandro Dalcin { 3238a25198SStefano Zampini const PetscInt *range; 3338a25198SStefano Zampini PetscInt i, nroots, ls = -1, ln = -1; 3438a25198SStefano Zampini PetscMPIInt lr = -1; 35b0c7db22SLisandro Dalcin PetscSFNode *remote; 36b0c7db22SLisandro Dalcin 37b0c7db22SLisandro Dalcin PetscFunctionBegin; 389566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetLocalSize(layout,&nroots)); 399566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout,&range)); 409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&remote)); 4138a25198SStefano Zampini if (nleaves) { ls = iremote[0] + 1; } 42b0c7db22SLisandro Dalcin for (i=0; i<nleaves; i++) { 4338a25198SStefano Zampini const PetscInt idx = iremote[i] - ls; 4438a25198SStefano Zampini if (idx < 0 || idx >= ln) { /* short-circuit the search */ 459566063dSJacob Faibussowitsch PetscCall(PetscLayoutFindOwnerIndex(layout,iremote[i],&lr,&remote[i].index)); 4638a25198SStefano Zampini remote[i].rank = lr; 4738a25198SStefano Zampini ls = range[lr]; 4838a25198SStefano Zampini ln = range[lr+1] - ls; 4938a25198SStefano Zampini } else { 5038a25198SStefano Zampini remote[i].rank = lr; 5138a25198SStefano Zampini remote[i].index = idx; 5238a25198SStefano Zampini } 53b0c7db22SLisandro Dalcin } 549566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER)); 55b0c7db22SLisandro Dalcin PetscFunctionReturn(0); 56b0c7db22SLisandro Dalcin } 57b0c7db22SLisandro Dalcin 58b0c7db22SLisandro Dalcin /*@ 59b0c7db22SLisandro Dalcin PetscSFSetGraphSection - Sets the PetscSF graph encoding the parallel dof overlap based upon the PetscSections 60b0c7db22SLisandro Dalcin describing the data layout. 61b0c7db22SLisandro Dalcin 62b0c7db22SLisandro Dalcin Input Parameters: 63b0c7db22SLisandro Dalcin + sf - The SF 64b0c7db22SLisandro Dalcin . localSection - PetscSection describing the local data layout 65b0c7db22SLisandro Dalcin - globalSection - PetscSection describing the global data layout 66b0c7db22SLisandro Dalcin 67b0c7db22SLisandro Dalcin Level: developer 68b0c7db22SLisandro Dalcin 69b0c7db22SLisandro Dalcin .seealso: PetscSFSetGraph(), PetscSFSetGraphLayout() 70b0c7db22SLisandro Dalcin @*/ 71b0c7db22SLisandro Dalcin PetscErrorCode PetscSFSetGraphSection(PetscSF sf, PetscSection localSection, PetscSection globalSection) 72b0c7db22SLisandro Dalcin { 73b0c7db22SLisandro Dalcin MPI_Comm comm; 74b0c7db22SLisandro Dalcin PetscLayout layout; 75b0c7db22SLisandro Dalcin const PetscInt *ranges; 76b0c7db22SLisandro Dalcin PetscInt *local; 77b0c7db22SLisandro Dalcin PetscSFNode *remote; 78b0c7db22SLisandro Dalcin PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 79b0c7db22SLisandro Dalcin PetscMPIInt size, rank; 80b0c7db22SLisandro Dalcin 81b0c7db22SLisandro Dalcin PetscFunctionBegin; 82b0c7db22SLisandro Dalcin PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 83b0c7db22SLisandro Dalcin PetscValidHeaderSpecific(localSection, PETSC_SECTION_CLASSID, 2); 84b0c7db22SLisandro Dalcin PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 85b0c7db22SLisandro Dalcin 869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)sf,&comm)); 879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd)); 909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots)); 919566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &layout)); 929566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 939566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, nroots)); 949566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout)); 959566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout, &ranges)); 96b0c7db22SLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 97b0c7db22SLisandro Dalcin PetscInt gdof, gcdof; 98b0c7db22SLisandro Dalcin 999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalSection, p, &gdof)); 1009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof)); 1012c71b3e2SJacob Faibussowitsch PetscCheckFalse(gcdof > (gdof < 0 ? -(gdof+1) : gdof),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " has %" PetscInt_FMT " constraints > %" PetscInt_FMT " dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof)); 102b0c7db22SLisandro Dalcin nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 103b0c7db22SLisandro Dalcin } 1049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &local)); 1059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remote)); 106b0c7db22SLisandro Dalcin for (p = pStart, l = 0; p < pEnd; ++p) { 107b0c7db22SLisandro Dalcin const PetscInt *cind; 108b0c7db22SLisandro Dalcin PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 109b0c7db22SLisandro Dalcin 1109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localSection, p, &dof)); 1119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localSection, p, &off)); 1129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof)); 1139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(localSection, p, &cind)); 1149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalSection, p, &gdof)); 1159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof)); 1169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &goff)); 117b0c7db22SLisandro Dalcin if (!gdof) continue; /* Censored point */ 118b0c7db22SLisandro Dalcin gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 119b0c7db22SLisandro Dalcin if (gsize != dof-cdof) { 120*08401ef6SPierre Jolivet PetscCheck(gsize == dof,comm, PETSC_ERR_ARG_WRONG, "Global dof %" PetscInt_FMT " for point %" PetscInt_FMT " is neither the constrained size %" PetscInt_FMT ", nor the unconstrained %" PetscInt_FMT, gsize, p, dof-cdof, dof); 121b0c7db22SLisandro Dalcin cdof = 0; /* Ignore constraints */ 122b0c7db22SLisandro Dalcin } 123b0c7db22SLisandro Dalcin for (d = 0, c = 0; d < dof; ++d) { 124b0c7db22SLisandro Dalcin if ((c < cdof) && (cind[c] == d)) {++c; continue;} 125b0c7db22SLisandro Dalcin local[l+d-c] = off+d; 126b0c7db22SLisandro Dalcin } 127*08401ef6SPierre Jolivet PetscCheck(d-c == gsize,comm, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT ": Global dof %" PetscInt_FMT " != %" PetscInt_FMT " size - number of constraints", p, gsize, d-c); 128b0c7db22SLisandro Dalcin if (gdof < 0) { 129b0c7db22SLisandro Dalcin for (d = 0; d < gsize; ++d, ++l) { 130b0c7db22SLisandro Dalcin PetscInt offset = -(goff+1) + d, r; 131b0c7db22SLisandro Dalcin 1329566063dSJacob Faibussowitsch PetscCall(PetscFindInt(offset,size+1,ranges,&r)); 133b0c7db22SLisandro Dalcin if (r < 0) r = -(r+2); 134*08401ef6SPierre Jolivet PetscCheck(!(r < 0) && !(r >= size),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")", p, r, gdof, goff); 135b0c7db22SLisandro Dalcin remote[l].rank = r; 136b0c7db22SLisandro Dalcin remote[l].index = offset - ranges[r]; 137b0c7db22SLisandro Dalcin } 138b0c7db22SLisandro Dalcin } else { 139b0c7db22SLisandro Dalcin for (d = 0; d < gsize; ++d, ++l) { 140b0c7db22SLisandro Dalcin remote[l].rank = rank; 141b0c7db22SLisandro Dalcin remote[l].index = goff+d - ranges[rank]; 142b0c7db22SLisandro Dalcin } 143b0c7db22SLisandro Dalcin } 144b0c7db22SLisandro Dalcin } 145*08401ef6SPierre Jolivet PetscCheck(l == nleaves,comm, PETSC_ERR_PLIB, "Iteration error, l %" PetscInt_FMT " != nleaves %" PetscInt_FMT, l, nleaves); 1469566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 1479566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 148b0c7db22SLisandro Dalcin PetscFunctionReturn(0); 149b0c7db22SLisandro Dalcin } 150b0c7db22SLisandro Dalcin 151b0c7db22SLisandro Dalcin /*@C 152b0c7db22SLisandro Dalcin PetscSFDistributeSection - Create a new PetscSection reorganized, moving from the root to the leaves of the SF 153b0c7db22SLisandro Dalcin 154b0c7db22SLisandro Dalcin Collective on sf 155b0c7db22SLisandro Dalcin 156b0c7db22SLisandro Dalcin Input Parameters: 157b0c7db22SLisandro Dalcin + sf - The SF 158b0c7db22SLisandro Dalcin - rootSection - Section defined on root space 159b0c7db22SLisandro Dalcin 160b0c7db22SLisandro Dalcin Output Parameters: 161b0c7db22SLisandro Dalcin + remoteOffsets - root offsets in leaf storage, or NULL 162b0c7db22SLisandro Dalcin - leafSection - Section defined on the leaf space 163b0c7db22SLisandro Dalcin 164b0c7db22SLisandro Dalcin Level: advanced 165b0c7db22SLisandro Dalcin 166b0c7db22SLisandro Dalcin .seealso: PetscSFCreate() 167b0c7db22SLisandro Dalcin @*/ 168b0c7db22SLisandro Dalcin PetscErrorCode PetscSFDistributeSection(PetscSF sf, PetscSection rootSection, PetscInt **remoteOffsets, PetscSection leafSection) 169b0c7db22SLisandro Dalcin { 170b0c7db22SLisandro Dalcin PetscSF embedSF; 171b0c7db22SLisandro Dalcin const PetscInt *indices; 172b0c7db22SLisandro Dalcin IS selected; 173b0c7db22SLisandro Dalcin PetscInt numFields, nroots, rpStart, rpEnd, lpStart = PETSC_MAX_INT, lpEnd = -1, f, c; 174b0c7db22SLisandro Dalcin PetscBool *sub, hasc; 175b0c7db22SLisandro Dalcin 176b0c7db22SLisandro Dalcin PetscFunctionBegin; 1779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCSF_DistSect,sf,0,0,0)); 1789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(rootSection, &numFields)); 179029e8818Sksagiyam if (numFields) { 180029e8818Sksagiyam IS perm; 181029e8818Sksagiyam 182029e8818Sksagiyam /* PetscSectionSetNumFields() calls PetscSectionReset(), which destroys 183029e8818Sksagiyam leafSection->perm. To keep this permutation set by the user, we grab 184029e8818Sksagiyam the reference before calling PetscSectionSetNumFields() and set it 185029e8818Sksagiyam back after. */ 1869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPermutation(leafSection, &perm)); 1879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)perm)); 1889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(leafSection, numFields)); 1899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(leafSection, perm)); 1909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 191029e8818Sksagiyam } 1929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields+2, &sub)); 193b0c7db22SLisandro Dalcin sub[1] = rootSection->bc ? PETSC_TRUE : PETSC_FALSE; 194b0c7db22SLisandro Dalcin for (f = 0; f < numFields; ++f) { 1952ee82556SMatthew G. Knepley PetscSectionSym sym, dsym = NULL; 196b0c7db22SLisandro Dalcin const char *name = NULL; 197b0c7db22SLisandro Dalcin PetscInt numComp = 0; 198b0c7db22SLisandro Dalcin 199b0c7db22SLisandro Dalcin sub[2 + f] = rootSection->field[f]->bc ? PETSC_TRUE : PETSC_FALSE; 2009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(rootSection, f, &numComp)); 2019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(rootSection, f, &name)); 2029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldSym(rootSection, f, &sym)); 2039566063dSJacob Faibussowitsch if (sym) PetscCall(PetscSectionSymDistribute(sym, sf, &dsym)); 2049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(leafSection, f, numComp)); 2059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldName(leafSection, f, name)); 2069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldSym(leafSection, f, dsym)); 2079566063dSJacob Faibussowitsch PetscCall(PetscSectionSymDestroy(&dsym)); 208b0c7db22SLisandro Dalcin for (c = 0; c < rootSection->numFieldComponents[f]; ++c) { 2099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetComponentName(rootSection, f, c, &name)); 2109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetComponentName(leafSection, f, c, name)); 211b0c7db22SLisandro Dalcin } 212b0c7db22SLisandro Dalcin } 2139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(rootSection, &rpStart, &rpEnd)); 2149566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf,&nroots,NULL,NULL,NULL)); 215b0c7db22SLisandro Dalcin rpEnd = PetscMin(rpEnd,nroots); 216b0c7db22SLisandro Dalcin rpEnd = PetscMax(rpStart,rpEnd); 217b0c7db22SLisandro Dalcin /* see if we can avoid creating the embedded SF, since it can cost more than an allreduce */ 218b0c7db22SLisandro Dalcin sub[0] = (PetscBool)(nroots != rpEnd - rpStart); 2191c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, sub, 2+numFields, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf))); 220b0c7db22SLisandro Dalcin if (sub[0]) { 2219566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected)); 2229566063dSJacob Faibussowitsch PetscCall(ISGetIndices(selected, &indices)); 2239566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(sf, rpEnd - rpStart, indices, &embedSF)); 2249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(selected, &indices)); 2259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&selected)); 226b0c7db22SLisandro Dalcin } else { 2279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sf)); 228b0c7db22SLisandro Dalcin embedSF = sf; 229b0c7db22SLisandro Dalcin } 2309566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRange(embedSF, &lpStart, &lpEnd)); 231b0c7db22SLisandro Dalcin lpEnd++; 232b0c7db22SLisandro Dalcin 2339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection, lpStart, lpEnd)); 234b0c7db22SLisandro Dalcin 235b0c7db22SLisandro Dalcin /* Constrained dof section */ 236b0c7db22SLisandro Dalcin hasc = sub[1]; 237b0c7db22SLisandro Dalcin for (f = 0; f < numFields; ++f) hasc = (PetscBool)(hasc || sub[2+f]); 238b0c7db22SLisandro Dalcin 239b0c7db22SLisandro Dalcin /* Could fuse these at the cost of copies and extra allocation */ 2409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart],MPI_REPLACE)); 2419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart],MPI_REPLACE)); 242b0c7db22SLisandro Dalcin if (sub[1]) { 2437c0883d5SVaclav Hapla PetscCall(PetscSectionCheckConstraints_Private(rootSection)); 2447c0883d5SVaclav Hapla PetscCall(PetscSectionCheckConstraints_Private(leafSection)); 2459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->bc->atlasDof[-rpStart], &leafSection->bc->atlasDof[-lpStart],MPI_REPLACE)); 2469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->bc->atlasDof[-rpStart], &leafSection->bc->atlasDof[-lpStart],MPI_REPLACE)); 247b0c7db22SLisandro Dalcin } 248b0c7db22SLisandro Dalcin for (f = 0; f < numFields; ++f) { 2499566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart],MPI_REPLACE)); 2509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart],MPI_REPLACE)); 251b0c7db22SLisandro Dalcin if (sub[2+f]) { 2527c0883d5SVaclav Hapla PetscCall(PetscSectionCheckConstraints_Private(rootSection->field[f])); 2537c0883d5SVaclav Hapla PetscCall(PetscSectionCheckConstraints_Private(leafSection->field[f])); 2549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->field[f]->bc->atlasDof[-rpStart], &leafSection->field[f]->bc->atlasDof[-lpStart],MPI_REPLACE)); 2559566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->field[f]->bc->atlasDof[-rpStart], &leafSection->field[f]->bc->atlasDof[-lpStart],MPI_REPLACE)); 256b0c7db22SLisandro Dalcin } 257b0c7db22SLisandro Dalcin } 258b0c7db22SLisandro Dalcin if (remoteOffsets) { 2599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lpEnd - lpStart, remoteOffsets)); 2609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart],MPI_REPLACE)); 2619566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart],MPI_REPLACE)); 262b0c7db22SLisandro Dalcin } 26369c11d05SVaclav Hapla PetscCall(PetscSectionInvalidateMaxDof_Internal(leafSection)); 2649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection)); 265b0c7db22SLisandro Dalcin if (hasc) { /* need to communicate bcIndices */ 266b0c7db22SLisandro Dalcin PetscSF bcSF; 267b0c7db22SLisandro Dalcin PetscInt *rOffBc; 268b0c7db22SLisandro Dalcin 2699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lpEnd - lpStart, &rOffBc)); 270b0c7db22SLisandro Dalcin if (sub[1]) { 2719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->bc->atlasOff[-rpStart], &rOffBc[-lpStart],MPI_REPLACE)); 2729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->bc->atlasOff[-rpStart], &rOffBc[-lpStart],MPI_REPLACE)); 2739566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(embedSF, rootSection->bc, rOffBc, leafSection->bc, &bcSF)); 2749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(bcSF, MPIU_INT, rootSection->bcIndices, leafSection->bcIndices,MPI_REPLACE)); 2759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(bcSF, MPIU_INT, rootSection->bcIndices, leafSection->bcIndices,MPI_REPLACE)); 2769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&bcSF)); 277b0c7db22SLisandro Dalcin } 278b0c7db22SLisandro Dalcin for (f = 0; f < numFields; ++f) { 279b0c7db22SLisandro Dalcin if (sub[2+f]) { 2809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->field[f]->bc->atlasOff[-rpStart], &rOffBc[-lpStart],MPI_REPLACE)); 2819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->field[f]->bc->atlasOff[-rpStart], &rOffBc[-lpStart],MPI_REPLACE)); 2829566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(embedSF, rootSection->field[f]->bc, rOffBc, leafSection->field[f]->bc, &bcSF)); 2839566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(bcSF, MPIU_INT, rootSection->field[f]->bcIndices, leafSection->field[f]->bcIndices,MPI_REPLACE)); 2849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(bcSF, MPIU_INT, rootSection->field[f]->bcIndices, leafSection->field[f]->bcIndices,MPI_REPLACE)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&bcSF)); 286b0c7db22SLisandro Dalcin } 287b0c7db22SLisandro Dalcin } 2889566063dSJacob Faibussowitsch PetscCall(PetscFree(rOffBc)); 289b0c7db22SLisandro Dalcin } 2909566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&embedSF)); 2919566063dSJacob Faibussowitsch PetscCall(PetscFree(sub)); 2929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCSF_DistSect,sf,0,0,0)); 293b0c7db22SLisandro Dalcin PetscFunctionReturn(0); 294b0c7db22SLisandro Dalcin } 295b0c7db22SLisandro Dalcin 296b0c7db22SLisandro Dalcin /*@C 297b0c7db22SLisandro Dalcin PetscSFCreateRemoteOffsets - Create offsets for point data on remote processes 298b0c7db22SLisandro Dalcin 299b0c7db22SLisandro Dalcin Collective on sf 300b0c7db22SLisandro Dalcin 301b0c7db22SLisandro Dalcin Input Parameters: 302b0c7db22SLisandro Dalcin + sf - The SF 303b0c7db22SLisandro Dalcin . rootSection - Data layout of remote points for outgoing data (this is layout for SF roots) 304b0c7db22SLisandro Dalcin - leafSection - Data layout of local points for incoming data (this is layout for SF leaves) 305b0c7db22SLisandro Dalcin 306b0c7db22SLisandro Dalcin Output Parameter: 307b0c7db22SLisandro Dalcin . remoteOffsets - Offsets for point data on remote processes (these are offsets from the root section), or NULL 308b0c7db22SLisandro Dalcin 309b0c7db22SLisandro Dalcin Level: developer 310b0c7db22SLisandro Dalcin 311b0c7db22SLisandro Dalcin .seealso: PetscSFCreate() 312b0c7db22SLisandro Dalcin @*/ 313b0c7db22SLisandro Dalcin PetscErrorCode PetscSFCreateRemoteOffsets(PetscSF sf, PetscSection rootSection, PetscSection leafSection, PetscInt **remoteOffsets) 314b0c7db22SLisandro Dalcin { 315b0c7db22SLisandro Dalcin PetscSF embedSF; 316b0c7db22SLisandro Dalcin const PetscInt *indices; 317b0c7db22SLisandro Dalcin IS selected; 318b0c7db22SLisandro Dalcin PetscInt numRoots, rpStart = 0, rpEnd = 0, lpStart = 0, lpEnd = 0; 319b0c7db22SLisandro Dalcin 320b0c7db22SLisandro Dalcin PetscFunctionBegin; 321b0c7db22SLisandro Dalcin *remoteOffsets = NULL; 3229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &numRoots, NULL, NULL, NULL)); 323b0c7db22SLisandro Dalcin if (numRoots < 0) PetscFunctionReturn(0); 3249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCSF_RemoteOff,sf,0,0,0)); 3259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(rootSection, &rpStart, &rpEnd)); 3269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafSection, &lpStart, &lpEnd)); 3279566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected)); 3289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(selected, &indices)); 3299566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(sf, rpEnd - rpStart, indices, &embedSF)); 3309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(selected, &indices)); 3319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&selected)); 3329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(lpEnd - lpStart, remoteOffsets)); 3339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart],MPI_REPLACE)); 3349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart],MPI_REPLACE)); 3359566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&embedSF)); 3369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCSF_RemoteOff,sf,0,0,0)); 337b0c7db22SLisandro Dalcin PetscFunctionReturn(0); 338b0c7db22SLisandro Dalcin } 339b0c7db22SLisandro Dalcin 340b0c7db22SLisandro Dalcin /*@C 341b0c7db22SLisandro Dalcin PetscSFCreateSectionSF - Create an expanded SF of dofs, assuming the input SF relates points 342b0c7db22SLisandro Dalcin 343b0c7db22SLisandro Dalcin Collective on sf 344b0c7db22SLisandro Dalcin 345b0c7db22SLisandro Dalcin Input Parameters: 346b0c7db22SLisandro Dalcin + sf - The SF 347b0c7db22SLisandro Dalcin . rootSection - Data layout of remote points for outgoing data (this is usually the serial section) 348b0c7db22SLisandro Dalcin . remoteOffsets - Offsets for point data on remote processes (these are offsets from the root section), or NULL 349b0c7db22SLisandro Dalcin - leafSection - Data layout of local points for incoming data (this is the distributed section) 350b0c7db22SLisandro Dalcin 351b0c7db22SLisandro Dalcin Output Parameters: 352b0c7db22SLisandro Dalcin - sectionSF - The new SF 353b0c7db22SLisandro Dalcin 354b0c7db22SLisandro Dalcin Note: Either rootSection or remoteOffsets can be specified 355b0c7db22SLisandro Dalcin 356b0c7db22SLisandro Dalcin Level: advanced 357b0c7db22SLisandro Dalcin 358b0c7db22SLisandro Dalcin .seealso: PetscSFCreate() 359b0c7db22SLisandro Dalcin @*/ 360b0c7db22SLisandro Dalcin PetscErrorCode PetscSFCreateSectionSF(PetscSF sf, PetscSection rootSection, PetscInt remoteOffsets[], PetscSection leafSection, PetscSF *sectionSF) 361b0c7db22SLisandro Dalcin { 362b0c7db22SLisandro Dalcin MPI_Comm comm; 363b0c7db22SLisandro Dalcin const PetscInt *localPoints; 364b0c7db22SLisandro Dalcin const PetscSFNode *remotePoints; 365b0c7db22SLisandro Dalcin PetscInt lpStart, lpEnd; 366b0c7db22SLisandro Dalcin PetscInt numRoots, numSectionRoots, numPoints, numIndices = 0; 367b0c7db22SLisandro Dalcin PetscInt *localIndices; 368b0c7db22SLisandro Dalcin PetscSFNode *remoteIndices; 369b0c7db22SLisandro Dalcin PetscInt i, ind; 370b0c7db22SLisandro Dalcin 371b0c7db22SLisandro Dalcin PetscFunctionBegin; 372b0c7db22SLisandro Dalcin PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 373b0c7db22SLisandro Dalcin PetscValidPointer(rootSection,2); 374b0c7db22SLisandro Dalcin /* Cannot check PetscValidIntPointer(remoteOffsets,3) because it can be NULL if sf does not reference any points in leafSection */ 375b0c7db22SLisandro Dalcin PetscValidPointer(leafSection,4); 376b0c7db22SLisandro Dalcin PetscValidPointer(sectionSF,5); 3779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)sf,&comm)); 3789566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sectionSF)); 3799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafSection, &lpStart, &lpEnd)); 3809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &numSectionRoots)); 3819566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &numRoots, &numPoints, &localPoints, &remotePoints)); 382b0c7db22SLisandro Dalcin if (numRoots < 0) PetscFunctionReturn(0); 3839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCSF_SectSF,sf,0,0,0)); 384b0c7db22SLisandro Dalcin for (i = 0; i < numPoints; ++i) { 385b0c7db22SLisandro Dalcin PetscInt localPoint = localPoints ? localPoints[i] : i; 386b0c7db22SLisandro Dalcin PetscInt dof; 387b0c7db22SLisandro Dalcin 388b0c7db22SLisandro Dalcin if ((localPoint >= lpStart) && (localPoint < lpEnd)) { 3899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, localPoint, &dof)); 390b0c7db22SLisandro Dalcin numIndices += dof; 391b0c7db22SLisandro Dalcin } 392b0c7db22SLisandro Dalcin } 3939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numIndices, &localIndices)); 3949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numIndices, &remoteIndices)); 395b0c7db22SLisandro Dalcin /* Create new index graph */ 396b0c7db22SLisandro Dalcin for (i = 0, ind = 0; i < numPoints; ++i) { 397b0c7db22SLisandro Dalcin PetscInt localPoint = localPoints ? localPoints[i] : i; 398b0c7db22SLisandro Dalcin PetscInt rank = remotePoints[i].rank; 399b0c7db22SLisandro Dalcin 400b0c7db22SLisandro Dalcin if ((localPoint >= lpStart) && (localPoint < lpEnd)) { 401b0c7db22SLisandro Dalcin PetscInt remoteOffset = remoteOffsets[localPoint-lpStart]; 402b0c7db22SLisandro Dalcin PetscInt loff, dof, d; 403b0c7db22SLisandro Dalcin 4049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, localPoint, &loff)); 4059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, localPoint, &dof)); 406b0c7db22SLisandro Dalcin for (d = 0; d < dof; ++d, ++ind) { 407b0c7db22SLisandro Dalcin localIndices[ind] = loff+d; 408b0c7db22SLisandro Dalcin remoteIndices[ind].rank = rank; 409b0c7db22SLisandro Dalcin remoteIndices[ind].index = remoteOffset+d; 410b0c7db22SLisandro Dalcin } 411b0c7db22SLisandro Dalcin } 412b0c7db22SLisandro Dalcin } 413*08401ef6SPierre Jolivet PetscCheck(numIndices == ind,comm, PETSC_ERR_PLIB, "Inconsistency in indices, %" PetscInt_FMT " should be %" PetscInt_FMT, ind, numIndices); 4149566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sectionSF, numSectionRoots, numIndices, localIndices, PETSC_OWN_POINTER, remoteIndices, PETSC_OWN_POINTER)); 4159566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(*sectionSF)); 4169566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCSF_SectSF,sf,0,0,0)); 417b0c7db22SLisandro Dalcin PetscFunctionReturn(0); 418b0c7db22SLisandro Dalcin } 4198fa9e22eSVaclav Hapla 4208fa9e22eSVaclav Hapla /*@C 4218fa9e22eSVaclav Hapla PetscSFCreateFromLayouts - Creates a parallel star forest mapping two PetscLayout objects 4228fa9e22eSVaclav Hapla 4238fa9e22eSVaclav Hapla Collective 4248fa9e22eSVaclav Hapla 4254165533cSJose E. Roman Input Parameters: 4268fa9e22eSVaclav Hapla + rmap - PetscLayout defining the global root space 4278fa9e22eSVaclav Hapla - lmap - PetscLayout defining the global leaf space 4288fa9e22eSVaclav Hapla 4294165533cSJose E. Roman Output Parameter: 4308fa9e22eSVaclav Hapla . sf - The parallel star forest 4318fa9e22eSVaclav Hapla 4328fa9e22eSVaclav Hapla Level: intermediate 4338fa9e22eSVaclav Hapla 4348fa9e22eSVaclav Hapla .seealso: PetscSFCreate(), PetscLayoutCreate(), PetscSFSetGraphLayout() 4358fa9e22eSVaclav Hapla @*/ 4368fa9e22eSVaclav Hapla PetscErrorCode PetscSFCreateFromLayouts(PetscLayout rmap, PetscLayout lmap, PetscSF* sf) 4378fa9e22eSVaclav Hapla { 4388fa9e22eSVaclav Hapla PetscInt i,nroots,nleaves = 0; 4398fa9e22eSVaclav Hapla PetscInt rN, lst, len; 4408fa9e22eSVaclav Hapla PetscMPIInt owner = -1; 4418fa9e22eSVaclav Hapla PetscSFNode *remote; 4428fa9e22eSVaclav Hapla MPI_Comm rcomm = rmap->comm; 4438fa9e22eSVaclav Hapla MPI_Comm lcomm = lmap->comm; 4448fa9e22eSVaclav Hapla PetscMPIInt flg; 4458fa9e22eSVaclav Hapla 4468fa9e22eSVaclav Hapla PetscFunctionBegin; 4478fa9e22eSVaclav Hapla PetscValidPointer(sf,3); 44828b400f6SJacob Faibussowitsch PetscCheck(rmap->setupcalled,rcomm,PETSC_ERR_ARG_WRONGSTATE,"Root layout not setup"); 44928b400f6SJacob Faibussowitsch PetscCheck(lmap->setupcalled,lcomm,PETSC_ERR_ARG_WRONGSTATE,"Leaf layout not setup"); 4509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(rcomm,lcomm,&flg)); 4512c71b3e2SJacob Faibussowitsch PetscCheckFalse(flg != MPI_CONGRUENT && flg != MPI_IDENT,rcomm,PETSC_ERR_SUP,"cannot map two layouts with non-matching communicators"); 4529566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(rcomm,sf)); 4539566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetLocalSize(rmap,&nroots)); 4549566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(rmap,&rN)); 4559566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(lmap,&lst,&len)); 4569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len-lst,&remote)); 4578fa9e22eSVaclav Hapla for (i = lst; i < len && i < rN; i++) { 4588fa9e22eSVaclav Hapla if (owner < -1 || i >= rmap->range[owner+1]) { 4599566063dSJacob Faibussowitsch PetscCall(PetscLayoutFindOwner(rmap,i,&owner)); 4608fa9e22eSVaclav Hapla } 4618fa9e22eSVaclav Hapla remote[nleaves].rank = owner; 4628fa9e22eSVaclav Hapla remote[nleaves].index = i - rmap->range[owner]; 4638fa9e22eSVaclav Hapla nleaves++; 4648fa9e22eSVaclav Hapla } 4659566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,remote,PETSC_COPY_VALUES)); 4669566063dSJacob Faibussowitsch PetscCall(PetscFree(remote)); 4678fa9e22eSVaclav Hapla PetscFunctionReturn(0); 4688fa9e22eSVaclav Hapla } 4698fa9e22eSVaclav Hapla 4708fa9e22eSVaclav Hapla /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */ 4718fa9e22eSVaclav Hapla PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs) 4728fa9e22eSVaclav Hapla { 4738fa9e22eSVaclav Hapla PetscInt *owners = map->range; 4748fa9e22eSVaclav Hapla PetscInt n = map->n; 4758fa9e22eSVaclav Hapla PetscSF sf; 4768fa9e22eSVaclav Hapla PetscInt *lidxs,*work = NULL; 4778fa9e22eSVaclav Hapla PetscSFNode *ridxs; 4788fa9e22eSVaclav Hapla PetscMPIInt rank, p = 0; 4798fa9e22eSVaclav Hapla PetscInt r, len = 0; 4808fa9e22eSVaclav Hapla 4818fa9e22eSVaclav Hapla PetscFunctionBegin; 4828fa9e22eSVaclav Hapla if (on) *on = 0; /* squelch -Wmaybe-uninitialized */ 4838fa9e22eSVaclav Hapla /* Create SF where leaves are input idxs and roots are owned idxs */ 4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(map->comm,&rank)); 4859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&lidxs)); 4868fa9e22eSVaclav Hapla for (r = 0; r < n; ++r) lidxs[r] = -1; 4879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(N,&ridxs)); 4888fa9e22eSVaclav Hapla for (r = 0; r < N; ++r) { 4898fa9e22eSVaclav Hapla const PetscInt idx = idxs[r]; 4902c71b3e2SJacob Faibussowitsch PetscCheckFalse(idx < 0 || map->N <= idx,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %" PetscInt_FMT " out of range [0,%" PetscInt_FMT ")",idx,map->N); 4918fa9e22eSVaclav Hapla if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */ 4929566063dSJacob Faibussowitsch PetscCall(PetscLayoutFindOwner(map,idx,&p)); 4938fa9e22eSVaclav Hapla } 4948fa9e22eSVaclav Hapla ridxs[r].rank = p; 4958fa9e22eSVaclav Hapla ridxs[r].index = idxs[r] - owners[p]; 4968fa9e22eSVaclav Hapla } 4979566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(map->comm,&sf)); 4989566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER)); 4999566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR)); 5009566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR)); 5018fa9e22eSVaclav Hapla if (ogidxs) { /* communicate global idxs */ 5028fa9e22eSVaclav Hapla PetscInt cum = 0,start,*work2; 5038fa9e22eSVaclav Hapla 5049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&work)); 5059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(N,&work2)); 5068fa9e22eSVaclav Hapla for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++; 5079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm)); 5088fa9e22eSVaclav Hapla start -= cum; 5098fa9e22eSVaclav Hapla cum = 0; 5108fa9e22eSVaclav Hapla for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++; 5119566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPI_REPLACE)); 5129566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPI_REPLACE)); 5139566063dSJacob Faibussowitsch PetscCall(PetscFree(work2)); 5148fa9e22eSVaclav Hapla } 5159566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 5168fa9e22eSVaclav Hapla /* Compress and put in indices */ 5178fa9e22eSVaclav Hapla for (r = 0; r < n; ++r) 5188fa9e22eSVaclav Hapla if (lidxs[r] >= 0) { 5198fa9e22eSVaclav Hapla if (work) work[len] = work[r]; 5208fa9e22eSVaclav Hapla lidxs[len++] = r; 5218fa9e22eSVaclav Hapla } 5228fa9e22eSVaclav Hapla if (on) *on = len; 5238fa9e22eSVaclav Hapla if (oidxs) *oidxs = lidxs; 5248fa9e22eSVaclav Hapla if (ogidxs) *ogidxs = work; 5258fa9e22eSVaclav Hapla PetscFunctionReturn(0); 5268fa9e22eSVaclav Hapla } 527deffd5ebSksagiyam 528deffd5ebSksagiyam /*@ 529deffd5ebSksagiyam PetscSFCreateByMatchingIndices - Create SF by matching root and leaf indices 530deffd5ebSksagiyam 531deffd5ebSksagiyam Collective 532deffd5ebSksagiyam 533deffd5ebSksagiyam Input Parameters: 534deffd5ebSksagiyam + layout - PetscLayout defining the global index space and the rank that brokers each index 535deffd5ebSksagiyam . numRootIndices - size of rootIndices 536deffd5ebSksagiyam . rootIndices - PetscInt array of global indices of which this process requests ownership 537deffd5ebSksagiyam . rootLocalIndices - root local index permutation (NULL if no permutation) 538deffd5ebSksagiyam . rootLocalOffset - offset to be added to root local indices 539deffd5ebSksagiyam . numLeafIndices - size of leafIndices 540deffd5ebSksagiyam . leafIndices - PetscInt array of global indices with which this process requires data associated 541deffd5ebSksagiyam . leafLocalIndices - leaf local index permutation (NULL if no permutation) 542deffd5ebSksagiyam - leafLocalOffset - offset to be added to leaf local indices 543deffd5ebSksagiyam 544d8d19677SJose E. Roman Output Parameters: 545deffd5ebSksagiyam + sfA - star forest representing the communication pattern from the layout space to the leaf space (NULL if not needed) 546deffd5ebSksagiyam - sf - star forest representing the communication pattern from the root space to the leaf space 547deffd5ebSksagiyam 548deffd5ebSksagiyam Example 1: 549deffd5ebSksagiyam $ 550deffd5ebSksagiyam $ rank : 0 1 2 551deffd5ebSksagiyam $ rootIndices : [1 0 2] [3] [3] 552deffd5ebSksagiyam $ rootLocalOffset : 100 200 300 553deffd5ebSksagiyam $ layout : [0 1] [2] [3] 554deffd5ebSksagiyam $ leafIndices : [0] [2] [0 3] 555deffd5ebSksagiyam $ leafLocalOffset : 400 500 600 556deffd5ebSksagiyam $ 5577ef5781fSVaclav Hapla would build the following SF 558deffd5ebSksagiyam $ 559deffd5ebSksagiyam $ [0] 400 <- (0,101) 560deffd5ebSksagiyam $ [1] 500 <- (0,102) 561deffd5ebSksagiyam $ [2] 600 <- (0,101) 562deffd5ebSksagiyam $ [2] 601 <- (2,300) 563deffd5ebSksagiyam $ 564deffd5ebSksagiyam Example 2: 565deffd5ebSksagiyam $ 566deffd5ebSksagiyam $ rank : 0 1 2 567deffd5ebSksagiyam $ rootIndices : [1 0 2] [3] [3] 568deffd5ebSksagiyam $ rootLocalOffset : 100 200 300 569deffd5ebSksagiyam $ layout : [0 1] [2] [3] 570deffd5ebSksagiyam $ leafIndices : rootIndices rootIndices rootIndices 571deffd5ebSksagiyam $ leafLocalOffset : rootLocalOffset rootLocalOffset rootLocalOffset 572deffd5ebSksagiyam $ 5737ef5781fSVaclav Hapla would build the following SF 574deffd5ebSksagiyam $ 575deffd5ebSksagiyam $ [1] 200 <- (2,300) 576deffd5ebSksagiyam $ 577deffd5ebSksagiyam Example 3: 578deffd5ebSksagiyam $ 579deffd5ebSksagiyam $ No process requests ownership of global index 1, but no process needs it. 580deffd5ebSksagiyam $ 581deffd5ebSksagiyam $ rank : 0 1 2 582deffd5ebSksagiyam $ numRootIndices : 2 1 1 583deffd5ebSksagiyam $ rootIndices : [0 2] [3] [3] 584deffd5ebSksagiyam $ rootLocalOffset : 100 200 300 585deffd5ebSksagiyam $ layout : [0 1] [2] [3] 586deffd5ebSksagiyam $ numLeafIndices : 1 1 2 587deffd5ebSksagiyam $ leafIndices : [0] [2] [0 3] 588deffd5ebSksagiyam $ leafLocalOffset : 400 500 600 589deffd5ebSksagiyam $ 5907ef5781fSVaclav Hapla would build the following SF 591deffd5ebSksagiyam $ 592deffd5ebSksagiyam $ [0] 400 <- (0,100) 593deffd5ebSksagiyam $ [1] 500 <- (0,101) 594deffd5ebSksagiyam $ [2] 600 <- (0,100) 595deffd5ebSksagiyam $ [2] 601 <- (2,300) 596deffd5ebSksagiyam $ 597deffd5ebSksagiyam 598deffd5ebSksagiyam Notes: 599deffd5ebSksagiyam The layout parameter represents any partitioning of [0, N), where N is the total number of global indices, and its 600deffd5ebSksagiyam local size can be set to PETSC_DECIDE. 601deffd5ebSksagiyam If a global index x lies in the partition owned by process i, each process whose rootIndices contains x requests 602deffd5ebSksagiyam ownership of x and sends its own rank and the local index of x to process i. 603deffd5ebSksagiyam If multiple processes request ownership of x, the one with the highest rank is to own x. 604deffd5ebSksagiyam Process i then broadcasts the ownership information, so that each process whose leafIndices contains x knows the 605deffd5ebSksagiyam ownership information of x. 606deffd5ebSksagiyam The output sf is constructed by associating each leaf point to a root point in this way. 607deffd5ebSksagiyam 608deffd5ebSksagiyam Suppose there is point data ordered according to the global indices and partitioned according to the given layout. 609deffd5ebSksagiyam The optional output PetscSF object sfA can be used to push such data to leaf points. 610deffd5ebSksagiyam 611deffd5ebSksagiyam All indices in rootIndices and leafIndices must lie in the layout range. The union (over all processes) of rootIndices 612deffd5ebSksagiyam must cover that of leafIndices, but need not cover the entire layout. 613deffd5ebSksagiyam 614deffd5ebSksagiyam If (leafIndices, leafLocalIndices, leafLocalOffset) == (rootIndices, rootLocalIndices, rootLocalOffset), the output 615deffd5ebSksagiyam star forest is almost identity, so will only include non-trivial part of the map. 616deffd5ebSksagiyam 617deffd5ebSksagiyam Developer Notes: 618deffd5ebSksagiyam Current approach of a process of the highest rank gaining the ownership may cause load imbalance; consider using 619deffd5ebSksagiyam hash(rank, root_local_index) as the bid for the ownership determination. 620deffd5ebSksagiyam 621deffd5ebSksagiyam Level: advanced 622deffd5ebSksagiyam 623deffd5ebSksagiyam .seealso: PetscSFCreate() 624deffd5ebSksagiyam @*/ 625deffd5ebSksagiyam PetscErrorCode PetscSFCreateByMatchingIndices(PetscLayout layout, PetscInt numRootIndices, const PetscInt *rootIndices, const PetscInt *rootLocalIndices, PetscInt rootLocalOffset, PetscInt numLeafIndices, const PetscInt *leafIndices, const PetscInt *leafLocalIndices, PetscInt leafLocalOffset, PetscSF *sfA, PetscSF *sf) 626deffd5ebSksagiyam { 627deffd5ebSksagiyam MPI_Comm comm = layout->comm; 628deffd5ebSksagiyam PetscMPIInt size, rank; 629deffd5ebSksagiyam PetscSF sf1; 630deffd5ebSksagiyam PetscSFNode *owners, *buffer, *iremote; 631deffd5ebSksagiyam PetscInt *ilocal, nleaves, N, n, i; 632deffd5ebSksagiyam #if defined(PETSC_USE_DEBUG) 633deffd5ebSksagiyam PetscInt N1; 634deffd5ebSksagiyam #endif 635deffd5ebSksagiyam PetscBool flag; 636deffd5ebSksagiyam 637deffd5ebSksagiyam PetscFunctionBegin; 638deffd5ebSksagiyam if (rootIndices) PetscValidIntPointer(rootIndices,3); 639deffd5ebSksagiyam if (rootLocalIndices) PetscValidIntPointer(rootLocalIndices,4); 640deffd5ebSksagiyam if (leafIndices) PetscValidIntPointer(leafIndices,7); 641deffd5ebSksagiyam if (leafLocalIndices) PetscValidIntPointer(leafLocalIndices,8); 642deffd5ebSksagiyam if (sfA) PetscValidPointer(sfA,10); 643deffd5ebSksagiyam PetscValidPointer(sf,11); 644*08401ef6SPierre Jolivet PetscCheck(numRootIndices >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "numRootIndices (%" PetscInt_FMT ") must be non-negative", numRootIndices); 645*08401ef6SPierre Jolivet PetscCheck(numLeafIndices >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "numLeafIndices (%" PetscInt_FMT ") must be non-negative", numLeafIndices); 6469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 6479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6489566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout)); 6499566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, &N)); 6509566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetLocalSize(layout, &n)); 651deffd5ebSksagiyam flag = (PetscBool)(leafIndices == rootIndices); 6521c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &flag, 1, MPIU_BOOL, MPI_LAND, comm)); 6532c71b3e2SJacob Faibussowitsch PetscCheckFalse(flag && numLeafIndices != numRootIndices,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "leafIndices == rootIndices, but numLeafIndices (%" PetscInt_FMT ") != numRootIndices(%" PetscInt_FMT ")", numLeafIndices, numRootIndices); 654deffd5ebSksagiyam #if defined(PETSC_USE_DEBUG) 655deffd5ebSksagiyam N1 = PETSC_MIN_INT; 656deffd5ebSksagiyam for (i = 0; i < numRootIndices; i++) if (rootIndices[i] > N1) N1 = rootIndices[i]; 6579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &N1, 1, MPIU_INT, MPI_MAX, comm)); 658*08401ef6SPierre Jolivet PetscCheck(N1 < N,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Max. root index (%" PetscInt_FMT ") out of layout range [0,%" PetscInt_FMT ")", N1, N); 659deffd5ebSksagiyam if (!flag) { 660deffd5ebSksagiyam N1 = PETSC_MIN_INT; 661deffd5ebSksagiyam for (i = 0; i < numLeafIndices; i++) if (leafIndices[i] > N1) N1 = leafIndices[i]; 6629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &N1, 1, MPIU_INT, MPI_MAX, comm)); 663*08401ef6SPierre Jolivet PetscCheck(N1 < N,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Max. leaf index (%" PetscInt_FMT ") out of layout range [0,%" PetscInt_FMT ")", N1, N); 664deffd5ebSksagiyam } 665deffd5ebSksagiyam #endif 666deffd5ebSksagiyam /* Reduce: owners -> buffer */ 6679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &buffer)); 6689566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf1)); 6699566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(sf1)); 6709566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf1, layout, numRootIndices, NULL, PETSC_OWN_POINTER, rootIndices)); 6719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &owners)); 672deffd5ebSksagiyam for (i = 0; i < numRootIndices; ++i) { 673deffd5ebSksagiyam owners[i].rank = rank; 674deffd5ebSksagiyam owners[i].index = rootLocalOffset + (rootLocalIndices ? rootLocalIndices[i] : i); 675deffd5ebSksagiyam } 676deffd5ebSksagiyam for (i = 0; i < n; ++i) { 677deffd5ebSksagiyam buffer[i].index = -1; 678deffd5ebSksagiyam buffer[i].rank = -1; 679deffd5ebSksagiyam } 6809566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf1, MPIU_2INT, owners, buffer, MPI_MAXLOC)); 6819566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf1, MPIU_2INT, owners, buffer, MPI_MAXLOC)); 682deffd5ebSksagiyam /* Bcast: buffer -> owners */ 683deffd5ebSksagiyam if (!flag) { 684deffd5ebSksagiyam /* leafIndices is different from rootIndices */ 6859566063dSJacob Faibussowitsch PetscCall(PetscFree(owners)); 6869566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf1, layout, numLeafIndices, NULL, PETSC_OWN_POINTER, leafIndices)); 6879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafIndices, &owners)); 688deffd5ebSksagiyam } 6899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf1, MPIU_2INT, buffer, owners, MPI_REPLACE)); 6909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf1, MPIU_2INT, buffer, owners, MPI_REPLACE)); 691*08401ef6SPierre Jolivet for (i = 0; i < numLeafIndices; ++i) PetscCheck(owners[i].rank >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global point %" PetscInt_FMT " was unclaimed", leafIndices[i]); 6929566063dSJacob Faibussowitsch PetscCall(PetscFree(buffer)); 693deffd5ebSksagiyam if (sfA) {*sfA = sf1;} 6949566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sf1)); 695deffd5ebSksagiyam /* Create sf */ 696deffd5ebSksagiyam if (flag && rootLocalIndices == leafLocalIndices && leafLocalOffset == rootLocalOffset) { 697deffd5ebSksagiyam /* leaf space == root space */ 698deffd5ebSksagiyam for (i = 0, nleaves = 0; i < numLeafIndices; ++i) if (owners[i].rank != rank) ++nleaves; 6999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &ilocal)); 7009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &iremote)); 701deffd5ebSksagiyam for (i = 0, nleaves = 0; i < numLeafIndices; ++i) { 702deffd5ebSksagiyam if (owners[i].rank != rank) { 703deffd5ebSksagiyam ilocal[nleaves] = leafLocalOffset + i; 704deffd5ebSksagiyam iremote[nleaves].rank = owners[i].rank; 705deffd5ebSksagiyam iremote[nleaves].index = owners[i].index; 706deffd5ebSksagiyam ++nleaves; 707deffd5ebSksagiyam } 708deffd5ebSksagiyam } 7099566063dSJacob Faibussowitsch PetscCall(PetscFree(owners)); 710deffd5ebSksagiyam } else { 711deffd5ebSksagiyam nleaves = numLeafIndices; 7129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &ilocal)); 713deffd5ebSksagiyam for (i = 0; i < nleaves; ++i) {ilocal[i] = leafLocalOffset + (leafLocalIndices ? leafLocalIndices[i] : i);} 714deffd5ebSksagiyam iremote = owners; 715deffd5ebSksagiyam } 7169566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 7179566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*sf)); 7189566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, rootLocalOffset + numRootIndices, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 719deffd5ebSksagiyam PetscFunctionReturn(0); 720deffd5ebSksagiyam } 721