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