1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc-private/isimpl.h> 3 #include <petscsf.h> 4 #include <petscds.h> 5 6 #undef __FUNCT__ 7 #define __FUNCT__ "DMPlexComputeAnchorAdjacencies" 8 /* get adjacencies due to point-to-point constraints that can't be found with DMPlexGetAdjacency() */ 9 static PetscErrorCode DMPlexComputeAnchorAdjacencies(DM dm, PetscBool useCone, PetscBool useClosure, PetscSection *anchorSectionAdj, PetscInt *anchorAdj[]) 10 { 11 PetscInt pStart, pEnd; 12 PetscSection section, sectionGlobal, adjSec, aSec; 13 IS aIS; 14 PetscErrorCode ierr; 15 16 PetscFunctionBegin; 17 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 18 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 19 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) section), &adjSec);CHKERRQ(ierr); 20 ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 21 ierr = PetscSectionSetChart(adjSec,pStart,pEnd);CHKERRQ(ierr); 22 23 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 24 if (aSec) { 25 const PetscInt *anchors; 26 PetscInt p, q, a, aSize, *offsets, aStart, aEnd, *inverse, iSize, *adj, adjSize; 27 PetscInt *tmpAdjP = NULL, *tmpAdjQ = NULL; 28 PetscSection inverseSec; 29 30 /* invert the constraint-to-anchor map */ 31 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)aSec),&inverseSec);CHKERRQ(ierr); 32 ierr = PetscSectionSetChart(inverseSec,pStart,pEnd);CHKERRQ(ierr); 33 ierr = ISGetLocalSize(aIS, &aSize);CHKERRQ(ierr); 34 ierr = ISGetIndices(aIS, &anchors);CHKERRQ(ierr); 35 36 for (p = 0; p < aSize; p++) { 37 PetscInt a = anchors[p]; 38 39 ierr = PetscSectionAddDof(inverseSec,a,1);CHKERRQ(ierr); 40 } 41 ierr = PetscSectionSetUp(inverseSec);CHKERRQ(ierr); 42 ierr = PetscSectionGetStorageSize(inverseSec,&iSize);CHKERRQ(ierr); 43 ierr = PetscMalloc1(iSize,&inverse);CHKERRQ(ierr); 44 ierr = PetscCalloc1(pEnd-pStart,&offsets);CHKERRQ(ierr); 45 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 46 for (p = aStart; p < aEnd; p++) { 47 PetscInt dof, off; 48 49 ierr = PetscSectionGetDof(aSec, p, &dof);CHKERRQ(ierr); 50 ierr = PetscSectionGetOffset(aSec, p, &off);CHKERRQ(ierr); 51 52 for (q = 0; q < dof; q++) { 53 PetscInt iOff; 54 55 a = anchors[off + q]; 56 ierr = PetscSectionGetOffset(inverseSec, a, &iOff);CHKERRQ(ierr); 57 inverse[iOff + offsets[a-pStart]++] = p; 58 } 59 } 60 ierr = ISRestoreIndices(aIS, &anchors);CHKERRQ(ierr); 61 ierr = PetscFree(offsets);CHKERRQ(ierr); 62 63 /* construct anchorAdj and adjSec 64 * 65 * loop over anchors: 66 * construct anchor adjacency 67 * loop over constrained: 68 * construct constrained adjacency 69 * if not in anchor adjacency, add to dofs 70 * setup adjSec, allocate anchorAdj 71 * loop over anchors: 72 * construct anchor adjacency 73 * loop over constrained: 74 * construct constrained adjacency 75 * if not in anchor adjacency 76 * if not already in list, put in list 77 * sort, unique, reduce dof count 78 * optional: compactify 79 */ 80 for (p = pStart; p < pEnd; p++) { 81 PetscInt iDof, iOff, i, r, s, numAdjP = PETSC_DETERMINE; 82 83 ierr = PetscSectionGetDof(inverseSec,p,&iDof);CHKERRQ(ierr); 84 if (!iDof) continue; 85 ierr = PetscSectionGetOffset(inverseSec,p,&iOff);CHKERRQ(ierr); 86 ierr = DMPlexGetAdjacency_Internal(dm,p,useCone,useClosure,PETSC_TRUE,&numAdjP,&tmpAdjP);CHKERRQ(ierr); 87 for (i = 0; i < iDof; i++) { 88 PetscInt iNew = 0, qAdj, qAdjDof, qAdjCDof, numAdjQ = PETSC_DETERMINE; 89 90 q = inverse[iOff + i]; 91 ierr = DMPlexGetAdjacency_Internal(dm,q,useCone,useClosure,PETSC_TRUE,&numAdjQ,&tmpAdjQ);CHKERRQ(ierr); 92 for (r = 0; r < numAdjQ; r++) { 93 qAdj = tmpAdjQ[r]; 94 if ((qAdj < pStart) || (qAdj >= pEnd)) continue; 95 for (s = 0; s < numAdjP; s++) { 96 if (qAdj == tmpAdjP[s]) break; 97 } 98 if (s < numAdjP) continue; 99 ierr = PetscSectionGetDof(section,qAdj,&qAdjDof);CHKERRQ(ierr); 100 ierr = PetscSectionGetConstraintDof(section,qAdj,&qAdjCDof);CHKERRQ(ierr); 101 iNew += qAdjDof - qAdjCDof; 102 } 103 ierr = PetscSectionAddDof(adjSec,p,iNew);CHKERRQ(ierr); 104 } 105 } 106 107 ierr = PetscSectionSetUp(adjSec);CHKERRQ(ierr); 108 ierr = PetscSectionGetStorageSize(adjSec,&adjSize);CHKERRQ(ierr); 109 ierr = PetscMalloc1(adjSize,&adj);CHKERRQ(ierr); 110 111 for (p = pStart; p < pEnd; p++) { 112 PetscInt iDof, iOff, i, r, s, aOff, aOffOrig, aDof, numAdjP = PETSC_DETERMINE; 113 114 ierr = PetscSectionGetDof(inverseSec,p,&iDof);CHKERRQ(ierr); 115 if (!iDof) continue; 116 ierr = PetscSectionGetOffset(inverseSec,p,&iOff);CHKERRQ(ierr); 117 ierr = DMPlexGetAdjacency_Internal(dm,p,useCone,useClosure,PETSC_TRUE,&numAdjP,&tmpAdjP);CHKERRQ(ierr); 118 ierr = PetscSectionGetDof(adjSec,p,&aDof);CHKERRQ(ierr); 119 ierr = PetscSectionGetOffset(adjSec,p,&aOff);CHKERRQ(ierr); 120 aOffOrig = aOff; 121 for (i = 0; i < iDof; i++) { 122 PetscInt qAdj, qAdjDof, qAdjCDof, qAdjOff, nd, numAdjQ = PETSC_DETERMINE; 123 124 q = inverse[iOff + i]; 125 ierr = DMPlexGetAdjacency_Internal(dm,q,useCone,useClosure,PETSC_TRUE,&numAdjQ,&tmpAdjQ);CHKERRQ(ierr); 126 for (r = 0; r < numAdjQ; r++) { 127 qAdj = tmpAdjQ[r]; 128 if ((qAdj < pStart) || (qAdj >= pEnd)) continue; 129 for (s = 0; s < numAdjP; s++) { 130 if (qAdj == tmpAdjP[s]) break; 131 } 132 if (s < numAdjP) continue; 133 ierr = PetscSectionGetDof(section,qAdj,&qAdjDof);CHKERRQ(ierr); 134 ierr = PetscSectionGetConstraintDof(section,qAdj,&qAdjCDof);CHKERRQ(ierr); 135 ierr = PetscSectionGetOffset(sectionGlobal,qAdj,&qAdjOff);CHKERRQ(ierr); 136 for (nd = 0; nd < qAdjDof-qAdjCDof; ++nd) { 137 adj[aOff++] = (qAdjOff < 0 ? -(qAdjOff+1) : qAdjOff) + nd; 138 } 139 } 140 } 141 ierr = PetscSortRemoveDupsInt(&aDof,&adj[aOffOrig]);CHKERRQ(ierr); 142 ierr = PetscSectionSetDof(adjSec,p,aDof);CHKERRQ(ierr); 143 } 144 *anchorAdj = adj; 145 146 /* clean up */ 147 ierr = PetscSectionDestroy(&inverseSec);CHKERRQ(ierr); 148 ierr = PetscFree(inverse);CHKERRQ(ierr); 149 ierr = PetscFree(tmpAdjP);CHKERRQ(ierr); 150 ierr = PetscFree(tmpAdjQ);CHKERRQ(ierr); 151 } 152 else { 153 *anchorAdj = NULL; 154 ierr = PetscSectionSetUp(adjSec);CHKERRQ(ierr); 155 } 156 *anchorSectionAdj = adjSec; 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNCT__ 161 #define __FUNCT__ "DMPlexCreateAdjacencySection_Static" 162 PetscErrorCode DMPlexCreateAdjacencySection_Static(DM dm, PetscInt bs, PetscSF sfDof, PetscBool useCone, PetscBool useClosure, PetscBool useAnchors, PetscSection *sA, PetscInt **colIdx) 163 { 164 MPI_Comm comm; 165 PetscMPIInt size; 166 PetscBool doCommLocal, doComm, debug = PETSC_FALSE; 167 PetscSF sf, sfAdj; 168 PetscSection section, sectionGlobal, leafSectionAdj, rootSectionAdj, sectionAdj, anchorSectionAdj; 169 PetscInt nroots, nleaves, l, p, r; 170 const PetscInt *leaves; 171 const PetscSFNode *remotes; 172 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 173 PetscInt *tmpAdj = NULL, *adj, *rootAdj, *anchorAdj = NULL, *cols, *remoteOffsets; 174 PetscInt adjSize; 175 PetscErrorCode ierr; 176 177 PetscFunctionBegin; 178 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 179 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 180 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 181 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 182 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 183 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 184 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 185 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 186 doCommLocal = (size > 1) && (nroots >= 0) ? PETSC_TRUE : PETSC_FALSE; 187 ierr = MPI_Allreduce(&doCommLocal, &doComm, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 188 /* Create section for dof adjacency (dof ==> # adj dof) */ 189 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 190 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 191 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 192 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 193 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 194 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 195 /* Fill in the ghost dofs on the interface */ 196 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 197 /* 198 section - maps points to (# dofs, local dofs) 199 sectionGlobal - maps points to (# dofs, global dofs) 200 leafSectionAdj - maps unowned local dofs to # adj dofs 201 rootSectionAdj - maps owned local dofs to # adj dofs 202 adj - adj global dofs indexed by leafSectionAdj 203 rootAdj - adj global dofs indexed by rootSectionAdj 204 sf - describes shared points across procs 205 sfDof - describes shared dofs across procs 206 sfAdj - describes shared adjacent dofs across procs 207 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 208 (0). If there are point-to-point constraints, add the adjacencies of constrained points to anchors in anchorAdj 209 (This is done in DMPlexComputeAnchorAdjacencies()) 210 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 211 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 212 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 213 Create sfAdj connecting rootSectionAdj and leafSectionAdj 214 3. Visit unowned points on interface, write adjacencies to adj 215 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 216 4. Visit owned points on interface, write adjacencies to rootAdj 217 Remove redundancy in rootAdj 218 ** The last two traversals use transitive closure 219 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 220 Allocate memory addressed by sectionAdj (cols) 221 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 222 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 223 */ 224 ierr = DMPlexComputeAnchorAdjacencies(dm, useCone, useClosure, &anchorSectionAdj, &anchorAdj);CHKERRQ(ierr); 225 for (l = 0; l < nleaves; ++l) { 226 PetscInt dof, off, d, q, anDof; 227 PetscInt p = leaves[l], numAdj = PETSC_DETERMINE; 228 229 if ((p < pStart) || (p >= pEnd)) continue; 230 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 231 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 232 ierr = DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj);CHKERRQ(ierr); 233 for (q = 0; q < numAdj; ++q) { 234 const PetscInt padj = tmpAdj[q]; 235 PetscInt ndof, ncdof; 236 237 if ((padj < pStart) || (padj >= pEnd)) continue; 238 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 239 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 240 for (d = off; d < off+dof; ++d) { 241 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 242 } 243 } 244 ierr = PetscSectionGetDof(anchorSectionAdj, p, &anDof);CHKERRQ(ierr); 245 if (anDof) { 246 for (d = off; d < off+dof; ++d) { 247 ierr = PetscSectionAddDof(leafSectionAdj, d, anDof);CHKERRQ(ierr); 248 } 249 } 250 } 251 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 252 if (debug) { 253 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 254 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 255 } 256 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 257 if (doComm) { 258 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 259 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 260 } 261 if (debug) { 262 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 263 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 264 } 265 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 266 for (p = pStart; p < pEnd; ++p) { 267 PetscInt numAdj = PETSC_DETERMINE, adof, dof, off, d, q, anDof; 268 269 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 270 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 271 if (!dof) continue; 272 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 273 if (adof <= 0) continue; 274 ierr = DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj);CHKERRQ(ierr); 275 for (q = 0; q < numAdj; ++q) { 276 const PetscInt padj = tmpAdj[q]; 277 PetscInt ndof, ncdof; 278 279 if ((padj < pStart) || (padj >= pEnd)) continue; 280 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 281 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 282 for (d = off; d < off+dof; ++d) { 283 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 284 } 285 } 286 ierr = PetscSectionGetDof(anchorSectionAdj, p, &anDof);CHKERRQ(ierr); 287 if (anDof) { 288 for (d = off; d < off+dof; ++d) { 289 ierr = PetscSectionAddDof(rootSectionAdj, d, anDof);CHKERRQ(ierr); 290 } 291 } 292 } 293 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 294 if (debug) { 295 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 296 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 297 } 298 /* Create adj SF based on dof SF */ 299 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 300 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 301 if (debug) { 302 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 303 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 304 } 305 /* Create leaf adjacency */ 306 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 307 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 308 ierr = PetscCalloc1(adjSize, &adj);CHKERRQ(ierr); 309 for (l = 0; l < nleaves; ++l) { 310 PetscInt dof, off, d, q, anDof, anOff; 311 PetscInt p = leaves[l], numAdj = PETSC_DETERMINE; 312 313 if ((p < pStart) || (p >= pEnd)) continue; 314 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 315 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 316 ierr = DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj);CHKERRQ(ierr); 317 ierr = PetscSectionGetDof(anchorSectionAdj, p, &anDof);CHKERRQ(ierr); 318 ierr = PetscSectionGetOffset(anchorSectionAdj, p, &anOff);CHKERRQ(ierr); 319 for (d = off; d < off+dof; ++d) { 320 PetscInt aoff, i = 0; 321 322 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 323 for (q = 0; q < numAdj; ++q) { 324 const PetscInt padj = tmpAdj[q]; 325 PetscInt ndof, ncdof, ngoff, nd; 326 327 if ((padj < pStart) || (padj >= pEnd)) continue; 328 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 329 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 330 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 331 for (nd = 0; nd < ndof-ncdof; ++nd) { 332 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 333 ++i; 334 } 335 } 336 for (q = 0; q < anDof; q++) { 337 adj[aoff+i] = anchorAdj[anOff+q]; 338 ++i; 339 } 340 } 341 } 342 /* Debugging */ 343 if (debug) { 344 IS tmp; 345 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 346 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 347 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 348 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 349 } 350 /* Gather adjacent indices to root */ 351 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 352 ierr = PetscMalloc1(adjSize, &rootAdj);CHKERRQ(ierr); 353 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 354 if (doComm) { 355 const PetscInt *indegree; 356 PetscInt *remoteadj, radjsize = 0; 357 358 ierr = PetscSFComputeDegreeBegin(sfAdj, &indegree);CHKERRQ(ierr); 359 ierr = PetscSFComputeDegreeEnd(sfAdj, &indegree);CHKERRQ(ierr); 360 for (p = 0; p < adjSize; ++p) radjsize += indegree[p]; 361 ierr = PetscMalloc1(radjsize, &remoteadj);CHKERRQ(ierr); 362 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, remoteadj);CHKERRQ(ierr); 363 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, remoteadj);CHKERRQ(ierr); 364 for (p = 0, l = 0, r = 0; p < adjSize; ++p, l = PetscMax(p, l + indegree[p-1])) { 365 PetscInt s; 366 for (s = 0; s < indegree[p]; ++s, ++r) rootAdj[l+s] = remoteadj[r]; 367 } 368 if (r != radjsize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistency in communication %d != %d", r, radjsize); 369 if (l != adjSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistency in communication %d != %d", l, adjSize); 370 ierr = PetscFree(remoteadj);CHKERRQ(ierr); 371 } 372 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 373 ierr = PetscFree(adj);CHKERRQ(ierr); 374 /* Debugging */ 375 if (debug) { 376 IS tmp; 377 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 378 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 379 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 380 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 381 } 382 /* Add in local adjacency indices for owned dofs on interface (roots) */ 383 for (p = pStart; p < pEnd; ++p) { 384 PetscInt numAdj = PETSC_DETERMINE, adof, dof, off, d, q, anDof, anOff; 385 386 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 387 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 388 if (!dof) continue; 389 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 390 if (adof <= 0) continue; 391 ierr = DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj);CHKERRQ(ierr); 392 ierr = PetscSectionGetDof(anchorSectionAdj, p, &anDof);CHKERRQ(ierr); 393 ierr = PetscSectionGetOffset(anchorSectionAdj, p, &anOff);CHKERRQ(ierr); 394 for (d = off; d < off+dof; ++d) { 395 PetscInt adof, aoff, i; 396 397 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 398 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 399 i = adof-1; 400 for (q = 0; q < anDof; q++) { 401 rootAdj[aoff+i] = anchorAdj[anOff+q]; 402 --i; 403 } 404 for (q = 0; q < numAdj; ++q) { 405 const PetscInt padj = tmpAdj[q]; 406 PetscInt ndof, ncdof, ngoff, nd; 407 408 if ((padj < pStart) || (padj >= pEnd)) continue; 409 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 410 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 411 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 412 for (nd = 0; nd < ndof-ncdof; ++nd) { 413 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 414 --i; 415 } 416 } 417 } 418 } 419 /* Debugging */ 420 if (debug) { 421 IS tmp; 422 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 423 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 424 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 425 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 426 } 427 /* Compress indices */ 428 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 429 for (p = pStart; p < pEnd; ++p) { 430 PetscInt dof, cdof, off, d; 431 PetscInt adof, aoff; 432 433 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 434 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 435 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 436 if (!dof) continue; 437 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 438 if (adof <= 0) continue; 439 for (d = off; d < off+dof-cdof; ++d) { 440 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 441 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 442 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 443 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 444 } 445 } 446 /* Debugging */ 447 if (debug) { 448 IS tmp; 449 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 450 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 451 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 452 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 453 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 454 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 455 } 456 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 457 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 458 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 459 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 460 for (p = pStart; p < pEnd; ++p) { 461 PetscInt numAdj = PETSC_DETERMINE, dof, cdof, off, goff, d, q, anDof; 462 PetscBool found = PETSC_TRUE; 463 464 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 465 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 466 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 467 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 468 for (d = 0; d < dof-cdof; ++d) { 469 PetscInt ldof, rdof; 470 471 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 472 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 473 if (ldof > 0) { 474 /* We do not own this point */ 475 } else if (rdof > 0) { 476 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 477 } else { 478 found = PETSC_FALSE; 479 } 480 } 481 if (found) continue; 482 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 483 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 484 ierr = DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj);CHKERRQ(ierr); 485 for (q = 0; q < numAdj; ++q) { 486 const PetscInt padj = tmpAdj[q]; 487 PetscInt ndof, ncdof, noff; 488 489 if ((padj < pStart) || (padj >= pEnd)) continue; 490 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 491 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 492 ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 493 for (d = goff; d < goff+dof-cdof; ++d) { 494 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 495 } 496 } 497 ierr = PetscSectionGetDof(anchorSectionAdj, p, &anDof);CHKERRQ(ierr); 498 if (anDof) { 499 for (d = goff; d < goff+dof-cdof; ++d) { 500 ierr = PetscSectionAddDof(sectionAdj, d, anDof);CHKERRQ(ierr); 501 } 502 } 503 } 504 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 505 if (debug) { 506 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 507 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 508 } 509 /* Get adjacent indices */ 510 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 511 ierr = PetscMalloc1(numCols, &cols);CHKERRQ(ierr); 512 for (p = pStart; p < pEnd; ++p) { 513 PetscInt numAdj = PETSC_DETERMINE, dof, cdof, off, goff, d, q, anDof, anOff; 514 PetscBool found = PETSC_TRUE; 515 516 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 517 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 518 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 519 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 520 for (d = 0; d < dof-cdof; ++d) { 521 PetscInt ldof, rdof; 522 523 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 524 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 525 if (ldof > 0) { 526 /* We do not own this point */ 527 } else if (rdof > 0) { 528 PetscInt aoff, roff; 529 530 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 531 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 532 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 533 } else { 534 found = PETSC_FALSE; 535 } 536 } 537 if (found) continue; 538 ierr = DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, &numAdj, &tmpAdj);CHKERRQ(ierr); 539 ierr = PetscSectionGetDof(anchorSectionAdj, p, &anDof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(anchorSectionAdj, p, &anOff);CHKERRQ(ierr); 541 for (d = goff; d < goff+dof-cdof; ++d) { 542 PetscInt adof, aoff, i = 0; 543 544 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 545 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 546 for (q = 0; q < numAdj; ++q) { 547 const PetscInt padj = tmpAdj[q]; 548 PetscInt ndof, ncdof, ngoff, nd; 549 const PetscInt *ncind; 550 551 /* Adjacent points may not be in the section chart */ 552 if ((padj < pStart) || (padj >= pEnd)) continue; 553 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 554 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 555 ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 556 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 557 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 558 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 559 } 560 } 561 for (q = 0; q < anDof; q++, i++) { 562 cols[aoff+i] = anchorAdj[anOff + q]; 563 } 564 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 565 } 566 } 567 ierr = PetscSectionDestroy(&anchorSectionAdj);CHKERRQ(ierr); 568 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 569 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 570 ierr = PetscFree(anchorAdj);CHKERRQ(ierr); 571 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 572 ierr = PetscFree(tmpAdj);CHKERRQ(ierr); 573 /* Debugging */ 574 if (debug) { 575 IS tmp; 576 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 577 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 578 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 579 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 580 } 581 582 *sA = sectionAdj; 583 *colIdx = cols; 584 PetscFunctionReturn(0); 585 } 586 587 #undef __FUNCT__ 588 #define __FUNCT__ "DMPlexUpdateAllocation_Static" 589 PetscErrorCode DMPlexUpdateAllocation_Static(DM dm, PetscLayout rLayout, PetscInt bs, PetscInt f, PetscSection sectionAdj, const PetscInt cols[], PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[]) 590 { 591 PetscSection section; 592 PetscInt rStart, rEnd, r, pStart, pEnd, p; 593 PetscErrorCode ierr; 594 595 PetscFunctionBegin; 596 /* This loop needs to change to a loop over points, then field dofs, which means we need to look both sections */ 597 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 598 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject) rLayout), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 599 if (f >= 0 && bs == 1) { 600 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 601 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 602 for (p = pStart; p < pEnd; ++p) { 603 PetscInt goff, loff, lfoff, fdof, fcdof, rS, rE; 604 605 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 606 ierr = PetscSectionGetOffset(section, p, &loff);CHKERRQ(ierr); 607 ierr = PetscSectionGetFieldOffset(section, p, f, &lfoff);CHKERRQ(ierr); 608 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 609 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 610 rS = goff + (lfoff - loff); 611 rE = rS + fdof - fcdof; 612 for (r = rS; r < rE; ++r) { 613 PetscInt numCols, cStart, c; 614 615 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 616 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 617 for (c = cStart; c < cStart+numCols; ++c) { 618 if ((cols[c] >= rStart) && (cols[c] < rEnd)) { 619 ++dnz[r-rStart]; 620 if (cols[c] >= r) ++dnzu[r-rStart]; 621 } else { 622 ++onz[r-rStart]; 623 if (cols[c] >= r) ++onzu[r-rStart]; 624 } 625 } 626 } 627 } 628 } else { 629 /* Only loop over blocks of rows */ 630 for (r = rStart/bs; r < rEnd/bs; ++r) { 631 const PetscInt row = r*bs; 632 PetscInt numCols, cStart, c; 633 634 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 635 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 636 for (c = cStart; c < cStart+numCols; ++c) { 637 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 638 ++dnz[r-rStart]; 639 if (cols[c] >= row) ++dnzu[r-rStart]; 640 } else { 641 ++onz[r-rStart]; 642 if (cols[c] >= row) ++onzu[r-rStart]; 643 } 644 } 645 } 646 for (r = 0; r < (rEnd - rStart)/bs; ++r) { 647 dnz[r] /= bs; 648 onz[r] /= bs; 649 dnzu[r] /= bs; 650 onzu[r] /= bs; 651 } 652 } 653 PetscFunctionReturn(0); 654 } 655 656 #undef __FUNCT__ 657 #define __FUNCT__ "DMPlexFillMatrix_Static" 658 PetscErrorCode DMPlexFillMatrix_Static(DM dm, PetscLayout rLayout, PetscInt bs, PetscInt f, PetscSection sectionAdj, const PetscInt cols[], Mat A) 659 { 660 PetscSection section; 661 PetscScalar *values; 662 PetscInt rStart, rEnd, r, pStart, pEnd, p, len, maxRowLen = 0; 663 PetscErrorCode ierr; 664 665 PetscFunctionBegin; 666 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 667 for (r = rStart; r < rEnd; ++r) { 668 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 669 maxRowLen = PetscMax(maxRowLen, len); 670 } 671 ierr = PetscCalloc1(maxRowLen, &values);CHKERRQ(ierr); 672 if (f >=0 && bs == 1) { 673 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 674 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 675 for (p = pStart; p < pEnd; ++p) { 676 PetscInt goff, loff, lfoff, fdof, fcdof, rS, rE; 677 678 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 679 ierr = PetscSectionGetOffset(section, p, &loff);CHKERRQ(ierr); 680 ierr = PetscSectionGetFieldOffset(section, p, f, &lfoff);CHKERRQ(ierr); 681 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 682 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 683 rS = goff + (lfoff - loff); 684 rE = rS + fdof - fcdof; 685 for (r = rS; r < rE; ++r) { 686 PetscInt numCols, cStart; 687 688 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 689 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 690 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 691 } 692 } 693 } else { 694 for (r = rStart; r < rEnd; ++r) { 695 PetscInt numCols, cStart; 696 697 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 698 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 699 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 700 } 701 } 702 ierr = PetscFree(values);CHKERRQ(ierr); 703 PetscFunctionReturn(0); 704 } 705 706 #undef __FUNCT__ 707 #define __FUNCT__ "DMPlexPreallocateOperator" 708 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 709 { 710 MPI_Comm comm; 711 PetscDS prob; 712 MatType mtype; 713 PetscSF sf, sfDof; 714 PetscSection section; 715 PetscInt *remoteOffsets; 716 PetscSection sectionAdj[4] = {NULL, NULL, NULL, NULL}; 717 PetscInt *cols[4] = {NULL, NULL, NULL, NULL}; 718 PetscBool useCone, useClosure; 719 PetscInt Nf, f, idx, locRows; 720 PetscLayout rLayout; 721 PetscBool isSymBlock, isSymSeqBlock, isSymMPIBlock, debug = PETSC_FALSE; 722 PetscErrorCode ierr; 723 724 PetscFunctionBegin; 725 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 726 PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 727 if (dnz) PetscValidPointer(dnz,5); if (onz) PetscValidPointer(onz,6); 728 if (dnzu) PetscValidPointer(dnzu,7); if (onzu) PetscValidPointer(onzu,8); 729 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 730 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 731 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 732 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 733 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 734 ierr = PetscLogEventBegin(DMPLEX_Preallocate,dm,0,0,0);CHKERRQ(ierr); 735 /* Create dof SF based on point SF */ 736 if (debug) { 737 PetscSection section, sectionGlobal; 738 PetscSF sf; 739 740 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 741 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 742 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 743 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 744 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 745 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 746 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 747 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 748 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 749 } 750 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 751 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 752 if (debug) { 753 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 754 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 755 } 756 /* Create allocation vectors from adjacency graph */ 757 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 758 ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr); 759 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 760 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 761 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 762 /* There are 4 types of adjacency */ 763 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 764 if (Nf < 1 || bs > 1) { 765 ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 766 ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr); 767 idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 768 ierr = DMPlexCreateAdjacencySection_Static(dm, bs, sfDof, useCone, useClosure, PETSC_TRUE, §ionAdj[idx], &cols[idx]);CHKERRQ(ierr); 769 ierr = DMPlexUpdateAllocation_Static(dm, rLayout, bs, -1, sectionAdj[idx], cols[idx], dnz, onz, dnzu, onzu);CHKERRQ(ierr); 770 } else { 771 for (f = 0; f < Nf; ++f) { 772 ierr = PetscDSGetAdjacency(prob, f, &useCone, &useClosure);CHKERRQ(ierr); 773 idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 774 if (!sectionAdj[idx]) {ierr = DMPlexCreateAdjacencySection_Static(dm, bs, sfDof, useCone, useClosure, PETSC_TRUE, §ionAdj[idx], &cols[idx]);CHKERRQ(ierr);} 775 ierr = DMPlexUpdateAllocation_Static(dm, rLayout, bs, f, sectionAdj[idx], cols[idx], dnz, onz, dnzu, onzu);CHKERRQ(ierr); 776 } 777 } 778 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 779 /* Set matrix pattern */ 780 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 781 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 782 /* Check for symmetric storage */ 783 ierr = MatGetType(A, &mtype);CHKERRQ(ierr); 784 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 785 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 786 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 787 if (isSymBlock || isSymSeqBlock || isSymMPIBlock) {ierr = MatSetOption(A, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr);} 788 /* Fill matrix with zeros */ 789 if (fillMatrix) { 790 if (Nf < 1 || bs > 1) { 791 ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 792 ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr); 793 idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 794 ierr = DMPlexFillMatrix_Static(dm, rLayout, bs, -1, sectionAdj[idx], cols[idx], A);CHKERRQ(ierr); 795 } else { 796 for (f = 0; f < Nf; ++f) { 797 ierr = PetscDSGetAdjacency(prob, f, &useCone, &useClosure);CHKERRQ(ierr); 798 idx = (useCone ? 1 : 0) + (useClosure ? 2 : 0); 799 ierr = DMPlexFillMatrix_Static(dm, rLayout, bs, f, sectionAdj[idx], cols[idx], A);CHKERRQ(ierr); 800 } 801 } 802 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 803 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 804 } 805 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 806 for (idx = 0; idx < 4; ++idx) {ierr = PetscSectionDestroy(§ionAdj[idx]);CHKERRQ(ierr); ierr = PetscFree(cols[idx]);CHKERRQ(ierr);} 807 ierr = PetscLogEventEnd(DMPLEX_Preallocate,dm,0,0,0);CHKERRQ(ierr); 808 PetscFunctionReturn(0); 809 } 810 811 #if 0 812 #undef __FUNCT__ 813 #define __FUNCT__ "DMPlexPreallocateOperator_2" 814 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 815 { 816 PetscInt *tmpClosure,*tmpAdj,*visits; 817 PetscInt c,cStart,cEnd,pStart,pEnd; 818 PetscErrorCode ierr; 819 820 PetscFunctionBegin; 821 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 822 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 823 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 824 825 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)); 826 827 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 828 npoints = pEnd - pStart; 829 830 ierr = PetscMalloc3(maxClosureSize,&tmpClosure,npoints,&lvisits,npoints,&visits);CHKERRQ(ierr); 831 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 832 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 833 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 834 for (c=cStart; c<cEnd; c++) { 835 PetscInt *support = tmpClosure; 836 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 837 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 838 } 839 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 840 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 841 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 842 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 843 844 ierr = PetscSFGetRanks();CHKERRQ(ierr); 845 846 847 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,&cellmat,npoints,&owner);CHKERRQ(ierr); 848 for (c=cStart; c<cEnd; c++) { 849 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 850 /* 851 Depth-first walk of transitive closure. 852 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 853 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 854 */ 855 } 856 857 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 858 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 859 PetscFunctionReturn(0); 860 } 861 #endif 862