1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc-private/isimpl.h> 3 #include <petscsf.h> 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DMPlexGetAdjacency_Internal" 7 static PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 8 { 9 const PetscInt *star = tmpClosure; 10 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 11 PetscErrorCode ierr; 12 13 PetscFunctionBegin; 14 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 15 for (s = 2; s < starSize*2; s += 2) { 16 const PetscInt *closure = NULL; 17 PetscInt closureSize, c, q; 18 19 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 20 for (c = 0; c < closureSize*2; c += 2) { 21 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 22 if (closure[c] == adj[q]) break; 23 } 24 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 25 } 26 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 27 } 28 *adjSize = numAdj; 29 PetscFunctionReturn(0); 30 } 31 32 #undef __FUNCT__ 33 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 34 /*@ 35 DMPlexSetPreallocationCenterDimension - Determine the topology used to determine adjacency 36 37 Input Parameters: 38 + dm - The DM object 39 - preallocCenterDim - The dimension of points which connect adjacent entries 40 41 Level: developer 42 43 Notes: 44 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim 45 $ FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 46 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 47 48 .seealso: DMCreateMatrix(), DMPlexPreallocateOperator() 49 @*/ 50 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 51 { 52 DM_Plex *mesh = (DM_Plex*) dm->data; 53 54 PetscFunctionBegin; 55 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56 mesh->preallocCenterDim = preallocCenterDim; 57 PetscFunctionReturn(0); 58 } 59 60 #undef __FUNCT__ 61 #define __FUNCT__ "DMPlexPreallocateOperator" 62 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 63 { 64 DM_Plex *mesh = (DM_Plex*) dm->data; 65 MPI_Comm comm; 66 MatType mtype; 67 PetscSF sf, sfDof, sfAdj; 68 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 69 PetscInt nroots, nleaves, l, p; 70 const PetscInt *leaves; 71 const PetscSFNode *remotes; 72 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 73 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 74 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 75 PetscLayout rLayout; 76 PetscInt locRows, rStart, rEnd, r; 77 PetscMPIInt size; 78 PetscBool useClosure, doCommLocal, doComm, debug = PETSC_FALSE, isSymBlock, isSymSeqBlock, isSymMPIBlock; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = PetscLogEventBegin(DMPLEX_Preallocate,dm,0,0,0);CHKERRQ(ierr); 83 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 84 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 85 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 86 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 87 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 88 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 89 doCommLocal = (size > 1) && (nroots >= 0) ? PETSC_TRUE : PETSC_FALSE; 90 ierr = MPI_Allreduce(&doCommLocal, &doComm, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 91 /* Create dof SF based on point SF */ 92 if (debug) { 93 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 94 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 95 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 96 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 97 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 98 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 99 } 100 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 101 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 102 if (debug) { 103 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 104 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 105 } 106 /* Create section for dof adjacency (dof ==> # adj dof) */ 107 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 108 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 109 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 110 if (mesh->preallocCenterDim == dim) { 111 useClosure = PETSC_FALSE; 112 } else if (mesh->preallocCenterDim == 0) { 113 useClosure = PETSC_TRUE; 114 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 115 116 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 117 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 118 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 119 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 120 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 121 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 122 /* Fill in the ghost dofs on the interface */ 123 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 124 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 125 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 126 127 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)); 128 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth+1) * PetscPowInt(mesh->maxSupportSize,depth+1) + 1; 129 130 ierr = PetscMalloc2(maxClosureSize,&tmpClosure,maxAdjSize,&tmpAdj);CHKERRQ(ierr); 131 132 /* 133 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 134 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 135 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 136 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 137 Create sfAdj connecting rootSectionAdj and leafSectionAdj 138 3. Visit unowned points on interface, write adjacencies to adj 139 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 140 4. Visit owned points on interface, write adjacencies to rootAdj 141 Remove redundancy in rootAdj 142 ** The last two traversals use transitive closure 143 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 144 Allocate memory addressed by sectionAdj (cols) 145 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 146 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 147 */ 148 149 for (l = 0; l < nleaves; ++l) { 150 PetscInt dof, off, d, q; 151 PetscInt p = leaves[l], numAdj = maxAdjSize; 152 153 if ((p < pStart) || (p >= pEnd)) continue; 154 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 155 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 156 ierr = DMPlexGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 157 for (q = 0; q < numAdj; ++q) { 158 const PetscInt padj = tmpAdj[q]; 159 PetscInt ndof, ncdof; 160 161 if ((padj < pStart) || (padj >= pEnd)) continue; 162 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 163 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 164 for (d = off; d < off+dof; ++d) { 165 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 166 } 167 } 168 } 169 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 170 if (debug) { 171 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 172 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 173 } 174 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 175 if (doComm) { 176 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 177 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 178 } 179 if (debug) { 180 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 181 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 182 } 183 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 184 for (p = pStart; p < pEnd; ++p) { 185 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 186 187 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 188 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 189 if (!dof) continue; 190 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 191 if (adof <= 0) continue; 192 ierr = DMPlexGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 193 for (q = 0; q < numAdj; ++q) { 194 const PetscInt padj = tmpAdj[q]; 195 PetscInt ndof, ncdof; 196 197 if ((padj < pStart) || (padj >= pEnd)) continue; 198 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 199 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 200 for (d = off; d < off+dof; ++d) { 201 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 202 } 203 } 204 } 205 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 206 if (debug) { 207 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 208 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 209 } 210 /* Create adj SF based on dof SF */ 211 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 212 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 213 if (debug) { 214 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 215 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 216 } 217 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 218 /* Create leaf adjacency */ 219 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 220 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 221 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 222 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 223 for (l = 0; l < nleaves; ++l) { 224 PetscInt dof, off, d, q; 225 PetscInt p = leaves[l], numAdj = maxAdjSize; 226 227 if ((p < pStart) || (p >= pEnd)) continue; 228 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 229 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 230 ierr = DMPlexGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 231 for (d = off; d < off+dof; ++d) { 232 PetscInt aoff, i = 0; 233 234 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 235 for (q = 0; q < numAdj; ++q) { 236 const PetscInt padj = tmpAdj[q]; 237 PetscInt ndof, ncdof, ngoff, nd; 238 239 if ((padj < pStart) || (padj >= pEnd)) continue; 240 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 241 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 243 for (nd = 0; nd < ndof-ncdof; ++nd) { 244 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 245 ++i; 246 } 247 } 248 } 249 } 250 /* Debugging */ 251 if (debug) { 252 IS tmp; 253 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 254 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 255 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 256 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 257 } 258 /* Gather adjacenct indices to root */ 259 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 260 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 261 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 262 if (doComm) { 263 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 264 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 265 } 266 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 267 ierr = PetscFree(adj);CHKERRQ(ierr); 268 /* Debugging */ 269 if (debug) { 270 IS tmp; 271 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 272 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 273 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 274 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 275 } 276 /* Add in local adjacency indices for owned dofs on interface (roots) */ 277 for (p = pStart; p < pEnd; ++p) { 278 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 279 280 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 281 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 282 if (!dof) continue; 283 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 284 if (adof <= 0) continue; 285 ierr = DMPlexGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 286 for (d = off; d < off+dof; ++d) { 287 PetscInt adof, aoff, i; 288 289 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 290 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 291 i = adof-1; 292 for (q = 0; q < numAdj; ++q) { 293 const PetscInt padj = tmpAdj[q]; 294 PetscInt ndof, ncdof, ngoff, nd; 295 296 if ((padj < pStart) || (padj >= pEnd)) continue; 297 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 298 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 299 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 300 for (nd = 0; nd < ndof-ncdof; ++nd) { 301 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 302 --i; 303 } 304 } 305 } 306 } 307 /* Debugging */ 308 if (debug) { 309 IS tmp; 310 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 311 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 312 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 313 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 314 } 315 /* Compress indices */ 316 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 317 for (p = pStart; p < pEnd; ++p) { 318 PetscInt dof, cdof, off, d; 319 PetscInt adof, aoff; 320 321 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 322 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 323 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 324 if (!dof) continue; 325 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 326 if (adof <= 0) continue; 327 for (d = off; d < off+dof-cdof; ++d) { 328 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 329 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 330 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 331 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 332 } 333 } 334 /* Debugging */ 335 if (debug) { 336 IS tmp; 337 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 338 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 339 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 340 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 341 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 342 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 343 } 344 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 345 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 346 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 347 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 348 for (p = pStart; p < pEnd; ++p) { 349 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 350 PetscBool found = PETSC_TRUE; 351 352 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 353 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 354 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 355 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 356 for (d = 0; d < dof-cdof; ++d) { 357 PetscInt ldof, rdof; 358 359 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 360 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 361 if (ldof > 0) { 362 /* We do not own this point */ 363 } else if (rdof > 0) { 364 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 365 } else { 366 found = PETSC_FALSE; 367 } 368 } 369 if (found) continue; 370 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 371 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 372 ierr = DMPlexGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 373 for (q = 0; q < numAdj; ++q) { 374 const PetscInt padj = tmpAdj[q]; 375 PetscInt ndof, ncdof, noff; 376 377 if ((padj < pStart) || (padj >= pEnd)) continue; 378 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 379 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 380 ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 381 for (d = goff; d < goff+dof-cdof; ++d) { 382 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 383 } 384 } 385 } 386 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 387 if (debug) { 388 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 389 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 390 } 391 /* Get adjacent indices */ 392 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 393 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 394 for (p = pStart; p < pEnd; ++p) { 395 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 396 PetscBool found = PETSC_TRUE; 397 398 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 399 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 400 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 401 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 402 for (d = 0; d < dof-cdof; ++d) { 403 PetscInt ldof, rdof; 404 405 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 406 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 407 if (ldof > 0) { 408 /* We do not own this point */ 409 } else if (rdof > 0) { 410 PetscInt aoff, roff; 411 412 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 413 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 414 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 415 } else { 416 found = PETSC_FALSE; 417 } 418 } 419 if (found) continue; 420 ierr = DMPlexGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 421 for (d = goff; d < goff+dof-cdof; ++d) { 422 PetscInt adof, aoff, i = 0; 423 424 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 425 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 426 for (q = 0; q < numAdj; ++q) { 427 const PetscInt padj = tmpAdj[q]; 428 PetscInt ndof, ncdof, ngoff, nd; 429 const PetscInt *ncind; 430 431 /* Adjacent points may not be in the section chart */ 432 if ((padj < pStart) || (padj >= pEnd)) continue; 433 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 434 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 435 ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 436 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 437 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 438 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 439 } 440 } 441 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); 442 } 443 } 444 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 445 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 446 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 447 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 448 /* Debugging */ 449 if (debug) { 450 IS tmp; 451 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 452 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 453 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 454 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 455 } 456 /* Create allocation vectors from adjacency graph */ 457 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 458 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 459 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 460 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 461 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 462 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 463 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 464 /* Only loop over blocks of rows */ 465 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 466 for (r = rStart/bs; r < rEnd/bs; ++r) { 467 const PetscInt row = r*bs; 468 PetscInt numCols, cStart, c; 469 470 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 471 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 472 for (c = cStart; c < cStart+numCols; ++c) { 473 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 474 ++dnz[r-rStart]; 475 if (cols[c] >= row) ++dnzu[r-rStart]; 476 } else { 477 ++onz[r-rStart]; 478 if (cols[c] >= row) ++onzu[r-rStart]; 479 } 480 } 481 } 482 if (bs > 1) { 483 for (r = 0; r < locRows/bs; ++r) { 484 dnz[r] /= bs; 485 onz[r] /= bs; 486 dnzu[r] /= bs; 487 onzu[r] /= bs; 488 } 489 } 490 /* Set matrix pattern */ 491 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 492 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 493 /* Check for symmetric storage */ 494 ierr = MatGetType(A, &mtype);CHKERRQ(ierr); 495 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 496 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 497 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 498 if (isSymBlock || isSymSeqBlock || isSymMPIBlock) {ierr = MatSetOption(A, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr);} 499 /* Fill matrix with zeros */ 500 if (fillMatrix) { 501 PetscScalar *values; 502 PetscInt maxRowLen = 0; 503 504 for (r = rStart; r < rEnd; ++r) { 505 PetscInt len; 506 507 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 508 maxRowLen = PetscMax(maxRowLen, len); 509 } 510 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 511 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 512 for (r = rStart; r < rEnd; ++r) { 513 PetscInt numCols, cStart; 514 515 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 516 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 517 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 518 } 519 ierr = PetscFree(values);CHKERRQ(ierr); 520 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 521 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 522 } 523 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 524 ierr = PetscFree(cols);CHKERRQ(ierr); 525 ierr = PetscLogEventEnd(DMPLEX_Preallocate,dm,0,0,0);CHKERRQ(ierr); 526 PetscFunctionReturn(0); 527 } 528 529 #if 0 530 #undef __FUNCT__ 531 #define __FUNCT__ "DMPlexPreallocateOperator_2" 532 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 533 { 534 PetscInt *tmpClosure,*tmpAdj,*visits; 535 PetscInt c,cStart,cEnd,pStart,pEnd; 536 PetscErrorCode ierr; 537 538 PetscFunctionBegin; 539 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 540 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 541 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 542 543 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)); 544 545 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 546 npoints = pEnd - pStart; 547 548 ierr = PetscMalloc3(maxClosureSize,&tmpClosure,npoints,&lvisits,npoints,&visits);CHKERRQ(ierr); 549 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 550 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 551 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 552 for (c=cStart; c<cEnd; c++) { 553 PetscInt *support = tmpClosure; 554 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 555 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 556 } 557 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 558 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 559 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 560 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 561 562 ierr = PetscSFGetRanks();CHKERRQ(ierr); 563 564 565 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,&cellmat,npoints,&owner);CHKERRQ(ierr); 566 for (c=cStart; c<cEnd; c++) { 567 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 568 /* 569 Depth-first walk of transitive closure. 570 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. 571 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 572 */ 573 } 574 575 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 576 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 577 PetscFunctionReturn(0); 578 } 579 #endif 580