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