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