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