13d183407SMatthew G. Knepley #include <petsc-private/dmdaimpl.h> /*I "petscdmda.h" I*/ 23d183407SMatthew G. Knepley #include <petsc-private/isimpl.h> 33d183407SMatthew G. Knepley #include <petscsf.h> 43d183407SMatthew G. Knepley 53d183407SMatthew G. Knepley #undef __FUNCT__ 63d183407SMatthew G. Knepley #define __FUNCT__ "DMDAGetAdjacency_Internal" 73d183407SMatthew G. Knepley static PetscErrorCode DMDAGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 83d183407SMatthew G. Knepley { 93d183407SMatthew G. Knepley const PetscInt *star = tmpClosure; 103d183407SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 113d183407SMatthew G. Knepley PetscErrorCode ierr; 123d183407SMatthew G. Knepley 133d183407SMatthew G. Knepley PetscFunctionBegin; 143d183407SMatthew G. Knepley ierr = DMDAGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 153d183407SMatthew G. Knepley for (s = 2; s < starSize*2; s += 2) { 163d183407SMatthew G. Knepley const PetscInt *closure = NULL; 173d183407SMatthew G. Knepley PetscInt closureSize, c, q; 183d183407SMatthew G. Knepley 193d183407SMatthew G. Knepley ierr = DMDAGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 203d183407SMatthew G. Knepley for (c = 0; c < closureSize*2; c += 2) { 213d183407SMatthew G. Knepley for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 223d183407SMatthew G. Knepley if (closure[c] == adj[q]) break; 233d183407SMatthew G. Knepley } 243d183407SMatthew G. Knepley if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 253d183407SMatthew G. Knepley } 263d183407SMatthew G. Knepley ierr = DMDARestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 273d183407SMatthew G. Knepley } 283d183407SMatthew G. Knepley *adjSize = numAdj; 293d183407SMatthew G. Knepley PetscFunctionReturn(0); 303d183407SMatthew G. Knepley } 313d183407SMatthew G. Knepley 323d183407SMatthew G. Knepley #undef __FUNCT__ 333d183407SMatthew G. Knepley #define __FUNCT__ "DMDASetPreallocationCenterDimension" 343d183407SMatthew G. Knepley /*@ 353d183407SMatthew G. Knepley DMDASetPreallocationCenterDimension - Determine the topology used to determine adjacency 363d183407SMatthew G. Knepley 373d183407SMatthew G. Knepley Input Parameters: 383d183407SMatthew G. Knepley + dm - The DM object 393d183407SMatthew G. Knepley - preallocCenterDim - The dimension of points which connect adjacent entries 403d183407SMatthew G. Knepley 413d183407SMatthew G. Knepley Level: developer 423d183407SMatthew G. Knepley 433d183407SMatthew G. Knepley Notes: 443d183407SMatthew G. Knepley $ FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim 453d183407SMatthew G. Knepley $ FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 463d183407SMatthew G. Knepley $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 473d183407SMatthew G. Knepley 483d183407SMatthew G. Knepley .seealso: DMCreateMatrix(), DMDAPreallocateOperator() 493d183407SMatthew G. Knepley @*/ 503d183407SMatthew G. Knepley PetscErrorCode DMDASetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 513d183407SMatthew G. Knepley { 523d183407SMatthew G. Knepley DM_DA *mesh = (DM_DA*) dm->data; 533d183407SMatthew G. Knepley 543d183407SMatthew G. Knepley PetscFunctionBegin; 553d183407SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 563d183407SMatthew G. Knepley mesh->preallocCenterDim = preallocCenterDim; 573d183407SMatthew G. Knepley PetscFunctionReturn(0); 583d183407SMatthew G. Knepley } 593d183407SMatthew G. Knepley 603d183407SMatthew G. Knepley #undef __FUNCT__ 613d183407SMatthew G. Knepley #define __FUNCT__ "DMDAGetPreallocationCenterDimension" 623d183407SMatthew G. Knepley /*@ 633d183407SMatthew G. Knepley DMDAGetPreallocationCenterDimension - Return the topology used to determine adjacency 643d183407SMatthew G. Knepley 653d183407SMatthew G. Knepley Input Parameter: 663d183407SMatthew G. Knepley . dm - The DM object 673d183407SMatthew G. Knepley 683d183407SMatthew G. Knepley Output Parameter: 693d183407SMatthew G. Knepley . preallocCenterDim - The dimension of points which connect adjacent entries 703d183407SMatthew G. Knepley 713d183407SMatthew G. Knepley Level: developer 723d183407SMatthew G. Knepley 733d183407SMatthew G. Knepley Notes: 743d183407SMatthew G. Knepley $ FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim 753d183407SMatthew G. Knepley $ FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 763d183407SMatthew G. Knepley $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 773d183407SMatthew G. Knepley 783d183407SMatthew G. Knepley .seealso: DMCreateMatrix(), DMDAPreallocateOperator(), DMDASetPreallocationCenterDimension() 793d183407SMatthew G. Knepley @*/ 803d183407SMatthew G. Knepley PetscErrorCode DMDAGetPreallocationCenterDimension(DM dm, PetscInt *preallocCenterDim) 813d183407SMatthew G. Knepley { 823d183407SMatthew G. Knepley DM_DA *mesh = (DM_DA*) dm->data; 833d183407SMatthew G. Knepley 843d183407SMatthew G. Knepley PetscFunctionBegin; 853d183407SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 863d183407SMatthew G. Knepley PetscValidIntPointer(preallocCenterDim, 2); 873d183407SMatthew G. Knepley *preallocCenterDim = mesh->preallocCenterDim; 883d183407SMatthew G. Knepley PetscFunctionReturn(0); 893d183407SMatthew G. Knepley } 903d183407SMatthew G. Knepley 913d183407SMatthew G. Knepley #undef __FUNCT__ 923d183407SMatthew G. Knepley #define __FUNCT__ "DMDAPreallocateOperator" 933d183407SMatthew G. Knepley PetscErrorCode DMDAPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 943d183407SMatthew G. Knepley { 953d183407SMatthew G. Knepley MPI_Comm comm; 963d183407SMatthew G. Knepley MatType mtype; 973d183407SMatthew G. Knepley PetscSF sf, sfDof, sfAdj; 983d183407SMatthew G. Knepley PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 993d183407SMatthew G. Knepley PetscInt nleaves, l, p; 1003d183407SMatthew G. Knepley const PetscInt *leaves; 1013d183407SMatthew G. Knepley const PetscSFNode *remotes; 1023d183407SMatthew G. Knepley PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 1033d183407SMatthew G. Knepley PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 1043d183407SMatthew G. Knepley PetscInt depth, centerDim, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 1053d183407SMatthew G. Knepley PetscLayout rLayout; 1063d183407SMatthew G. Knepley PetscInt locRows, rStart, rEnd, r; 1073d183407SMatthew G. Knepley PetscMPIInt size; 1083d183407SMatthew G. Knepley PetscBool useClosure, debug = PETSC_FALSE, isSymBlock, isSymSeqBlock, isSymMPIBlock; 1093d183407SMatthew G. Knepley PetscErrorCode ierr; 1103d183407SMatthew G. Knepley 1113d183407SMatthew G. Knepley PetscFunctionBegin; 1123d183407SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1133d183407SMatthew G. Knepley ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 1143d183407SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1153d183407SMatthew G. Knepley ierr = DMDAGetInfo(dm, &dim,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 1163d183407SMatthew G. Knepley depth = dim; 1173d183407SMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 1183d183407SMatthew G. Knepley /* Create dof SF based on point SF */ 1193d183407SMatthew G. Knepley if (debug) { 1203d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 1213d183407SMatthew G. Knepley ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1223d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 1233d183407SMatthew G. Knepley ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1243d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 1253d183407SMatthew G. Knepley ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 1263d183407SMatthew G. Knepley } 1273d183407SMatthew G. Knepley ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 1283d183407SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 1293d183407SMatthew G. Knepley if (debug) { 1303d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 1313d183407SMatthew G. Knepley ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 1323d183407SMatthew G. Knepley } 1333d183407SMatthew G. Knepley /* Create section for dof adjacency (dof ==> # adj dof) */ 1343d183407SMatthew G. Knepley /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 1353d183407SMatthew G. Knepley /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 1363d183407SMatthew G. Knepley /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 1373d183407SMatthew G. Knepley ierr = DMDAGetPreallocationCenterDimension(dm, ¢erDim);CHKERRQ(ierr); 1383d183407SMatthew G. Knepley if (centerDim == dim) { 1393d183407SMatthew G. Knepley useClosure = PETSC_FALSE; 1403d183407SMatthew G. Knepley } else if (centerDim == 0) { 1413d183407SMatthew G. Knepley useClosure = PETSC_TRUE; 1423d183407SMatthew G. Knepley } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", centerDim); 1433d183407SMatthew G. Knepley 1443d183407SMatthew G. Knepley ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 1453d183407SMatthew G. Knepley ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 1463d183407SMatthew G. Knepley ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 1473d183407SMatthew G. Knepley ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 1483d183407SMatthew G. Knepley ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 1493d183407SMatthew G. Knepley ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 1503d183407SMatthew G. Knepley /* Fill in the ghost dofs on the interface */ 1513d183407SMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 1523d183407SMatthew G. Knepley maxConeSize = 6; 1533d183407SMatthew G. Knepley maxSupportSize = 6; 1543d183407SMatthew G. Knepley 1553d183407SMatthew G. Knepley maxClosureSize = 2*PetscMax(PetscPowInt(maxConeSize,depth+1),PetscPowInt(maxSupportSize,depth+1)); 1563d183407SMatthew G. Knepley maxAdjSize = PetscPowInt(maxConeSize,depth+1) * PetscPowInt(maxSupportSize,depth+1) + 1; 1573d183407SMatthew G. Knepley 158ed91c37eSMatthew G. Knepley ierr = PetscMalloc2(maxClosureSize,&tmpClosure,maxAdjSize,&tmpAdj);CHKERRQ(ierr); 1593d183407SMatthew G. Knepley 1603d183407SMatthew G. Knepley /* 1613d183407SMatthew G. Knepley ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 1623d183407SMatthew G. Knepley 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 1633d183407SMatthew G. Knepley Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 1643d183407SMatthew G. Knepley 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 1653d183407SMatthew G. Knepley Create sfAdj connecting rootSectionAdj and leafSectionAdj 1663d183407SMatthew G. Knepley 3. Visit unowned points on interface, write adjacencies to adj 1673d183407SMatthew G. Knepley Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 1683d183407SMatthew G. Knepley 4. Visit owned points on interface, write adjacencies to rootAdj 1693d183407SMatthew G. Knepley Remove redundancy in rootAdj 1703d183407SMatthew G. Knepley ** The last two traversals use transitive closure 1713d183407SMatthew G. Knepley 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 1723d183407SMatthew G. Knepley Allocate memory addressed by sectionAdj (cols) 1733d183407SMatthew G. Knepley 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 1743d183407SMatthew G. Knepley ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 1753d183407SMatthew G. Knepley */ 1763d183407SMatthew G. Knepley 1773d183407SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 1783d183407SMatthew G. Knepley PetscInt dof, off, d, q; 1793d183407SMatthew G. Knepley PetscInt p = leaves[l], numAdj = maxAdjSize; 1803d183407SMatthew G. Knepley 1813d183407SMatthew G. Knepley if ((p < pStart) || (p >= pEnd)) continue; 1823d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 1833d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 1843d183407SMatthew G. Knepley ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 1853d183407SMatthew G. Knepley for (q = 0; q < numAdj; ++q) { 1863d183407SMatthew G. Knepley const PetscInt padj = tmpAdj[q]; 1873d183407SMatthew G. Knepley PetscInt ndof, ncdof; 1883d183407SMatthew G. Knepley 1893d183407SMatthew G. Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 1903d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 1913d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 1923d183407SMatthew G. Knepley for (d = off; d < off+dof; ++d) { 1933d183407SMatthew G. Knepley ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 1943d183407SMatthew G. Knepley } 1953d183407SMatthew G. Knepley } 1963d183407SMatthew G. Knepley } 1973d183407SMatthew G. Knepley ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 1983d183407SMatthew G. Knepley if (debug) { 1993d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 2003d183407SMatthew G. Knepley ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2013d183407SMatthew G. Knepley } 2023d183407SMatthew G. Knepley /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 2033d183407SMatthew G. Knepley if (size > 1) { 2043d183407SMatthew G. Knepley ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 2053d183407SMatthew G. Knepley ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 2063d183407SMatthew G. Knepley } 2073d183407SMatthew G. Knepley if (debug) { 2083d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 2093d183407SMatthew G. Knepley ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2103d183407SMatthew G. Knepley } 2113d183407SMatthew G. Knepley /* Add in local adjacency sizes for owned dofs on interface (roots) */ 2123d183407SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 2133d183407SMatthew G. Knepley PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 2143d183407SMatthew G. Knepley 2153d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 2163d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 2173d183407SMatthew G. Knepley if (!dof) continue; 2183d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 2193d183407SMatthew G. Knepley if (adof <= 0) continue; 2203d183407SMatthew G. Knepley ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 2213d183407SMatthew G. Knepley for (q = 0; q < numAdj; ++q) { 2223d183407SMatthew G. Knepley const PetscInt padj = tmpAdj[q]; 2233d183407SMatthew G. Knepley PetscInt ndof, ncdof; 2243d183407SMatthew G. Knepley 2253d183407SMatthew G. Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 2263d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 2273d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 2283d183407SMatthew G. Knepley for (d = off; d < off+dof; ++d) { 2293d183407SMatthew G. Knepley ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 2303d183407SMatthew G. Knepley } 2313d183407SMatthew G. Knepley } 2323d183407SMatthew G. Knepley } 2333d183407SMatthew G. Knepley ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 2343d183407SMatthew G. Knepley if (debug) { 2353d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 2363d183407SMatthew G. Knepley ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2373d183407SMatthew G. Knepley } 2383d183407SMatthew G. Knepley /* Create adj SF based on dof SF */ 2393d183407SMatthew G. Knepley ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 2403d183407SMatthew G. Knepley ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 2413d183407SMatthew G. Knepley if (debug) { 2423d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 2433d183407SMatthew G. Knepley ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 2443d183407SMatthew G. Knepley } 2453d183407SMatthew G. Knepley ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 2463d183407SMatthew G. Knepley /* Create leaf adjacency */ 2473d183407SMatthew G. Knepley ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 2483d183407SMatthew G. Knepley ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 249*854ce69bSBarry Smith ierr = PetscMalloc1(adjSize, &adj);CHKERRQ(ierr); 2503d183407SMatthew G. Knepley ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 2513d183407SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 2523d183407SMatthew G. Knepley PetscInt dof, off, d, q; 2533d183407SMatthew G. Knepley PetscInt p = leaves[l], numAdj = maxAdjSize; 2543d183407SMatthew G. Knepley 2553d183407SMatthew G. Knepley if ((p < pStart) || (p >= pEnd)) continue; 2563d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 2573d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 2583d183407SMatthew G. Knepley ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 2593d183407SMatthew G. Knepley for (d = off; d < off+dof; ++d) { 2603d183407SMatthew G. Knepley PetscInt aoff, i = 0; 2613d183407SMatthew G. Knepley 2623d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 2633d183407SMatthew G. Knepley for (q = 0; q < numAdj; ++q) { 2643d183407SMatthew G. Knepley const PetscInt padj = tmpAdj[q]; 2653d183407SMatthew G. Knepley PetscInt ndof, ncdof, ngoff, nd; 2663d183407SMatthew G. Knepley 2673d183407SMatthew G. Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 2683d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 2693d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 2703d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 2713d183407SMatthew G. Knepley for (nd = 0; nd < ndof-ncdof; ++nd) { 2723d183407SMatthew G. Knepley adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 2733d183407SMatthew G. Knepley ++i; 2743d183407SMatthew G. Knepley } 2753d183407SMatthew G. Knepley } 2763d183407SMatthew G. Knepley } 2773d183407SMatthew G. Knepley } 2783d183407SMatthew G. Knepley /* Debugging */ 2793d183407SMatthew G. Knepley if (debug) { 2803d183407SMatthew G. Knepley IS tmp; 2813d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 2823d183407SMatthew G. Knepley ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 2833d183407SMatthew G. Knepley ierr = ISView(tmp, NULL);CHKERRQ(ierr); 2843d183407SMatthew G. Knepley ierr = ISDestroy(&tmp);CHKERRQ(ierr); 2853d183407SMatthew G. Knepley } 2863d183407SMatthew G. Knepley /* Gather adjacenct indices to root */ 2873d183407SMatthew G. Knepley ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 288*854ce69bSBarry Smith ierr = PetscMalloc1(adjSize, &rootAdj);CHKERRQ(ierr); 2893d183407SMatthew G. Knepley for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 2903d183407SMatthew G. Knepley if (size > 1) { 2913d183407SMatthew G. Knepley ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 2923d183407SMatthew G. Knepley ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 2933d183407SMatthew G. Knepley } 2943d183407SMatthew G. Knepley ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 2953d183407SMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 2963d183407SMatthew G. Knepley /* Debugging */ 2973d183407SMatthew G. Knepley if (debug) { 2983d183407SMatthew G. Knepley IS tmp; 2993d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 3003d183407SMatthew G. Knepley ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 3013d183407SMatthew G. Knepley ierr = ISView(tmp, NULL);CHKERRQ(ierr); 3023d183407SMatthew G. Knepley ierr = ISDestroy(&tmp);CHKERRQ(ierr); 3033d183407SMatthew G. Knepley } 3043d183407SMatthew G. Knepley /* Add in local adjacency indices for owned dofs on interface (roots) */ 3053d183407SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3063d183407SMatthew G. Knepley PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 3073d183407SMatthew G. Knepley 3083d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 3093d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 3103d183407SMatthew G. Knepley if (!dof) continue; 3113d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 3123d183407SMatthew G. Knepley if (adof <= 0) continue; 3133d183407SMatthew G. Knepley ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 3143d183407SMatthew G. Knepley for (d = off; d < off+dof; ++d) { 3153d183407SMatthew G. Knepley PetscInt adof, aoff, i; 3163d183407SMatthew G. Knepley 3173d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 3183d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 3193d183407SMatthew G. Knepley i = adof-1; 3203d183407SMatthew G. Knepley for (q = 0; q < numAdj; ++q) { 3213d183407SMatthew G. Knepley const PetscInt padj = tmpAdj[q]; 3223d183407SMatthew G. Knepley PetscInt ndof, ncdof, ngoff, nd; 3233d183407SMatthew G. Knepley 3243d183407SMatthew G. Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 3253d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 3263d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 3273d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 3283d183407SMatthew G. Knepley for (nd = 0; nd < ndof-ncdof; ++nd) { 3293d183407SMatthew G. Knepley rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 3303d183407SMatthew G. Knepley --i; 3313d183407SMatthew G. Knepley } 3323d183407SMatthew G. Knepley } 3333d183407SMatthew G. Knepley } 3343d183407SMatthew G. Knepley } 3353d183407SMatthew G. Knepley /* Debugging */ 3363d183407SMatthew G. Knepley if (debug) { 3373d183407SMatthew G. Knepley IS tmp; 3383d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 3393d183407SMatthew G. Knepley ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 3403d183407SMatthew G. Knepley ierr = ISView(tmp, NULL);CHKERRQ(ierr); 3413d183407SMatthew G. Knepley ierr = ISDestroy(&tmp);CHKERRQ(ierr); 3423d183407SMatthew G. Knepley } 3433d183407SMatthew G. Knepley /* Compress indices */ 3443d183407SMatthew G. Knepley ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 3453d183407SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3463d183407SMatthew G. Knepley PetscInt dof, cdof, off, d; 3473d183407SMatthew G. Knepley PetscInt adof, aoff; 3483d183407SMatthew G. Knepley 3493d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 3503d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3513d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 3523d183407SMatthew G. Knepley if (!dof) continue; 3533d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 3543d183407SMatthew G. Knepley if (adof <= 0) continue; 3553d183407SMatthew G. Knepley for (d = off; d < off+dof-cdof; ++d) { 3563d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 3573d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 3583d183407SMatthew G. Knepley ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 3593d183407SMatthew G. Knepley ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 3603d183407SMatthew G. Knepley } 3613d183407SMatthew G. Knepley } 3623d183407SMatthew G. Knepley /* Debugging */ 3633d183407SMatthew G. Knepley if (debug) { 3643d183407SMatthew G. Knepley IS tmp; 3653d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 3663d183407SMatthew G. Knepley ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3673d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 3683d183407SMatthew G. Knepley ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 3693d183407SMatthew G. Knepley ierr = ISView(tmp, NULL);CHKERRQ(ierr); 3703d183407SMatthew G. Knepley ierr = ISDestroy(&tmp);CHKERRQ(ierr); 3713d183407SMatthew G. Knepley } 3723d183407SMatthew G. Knepley /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 3733d183407SMatthew G. Knepley ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 3743d183407SMatthew G. Knepley ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 3753d183407SMatthew G. Knepley ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 3763d183407SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3773d183407SMatthew G. Knepley PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 3783d183407SMatthew G. Knepley PetscBool found = PETSC_TRUE; 3793d183407SMatthew G. Knepley 3803d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 3813d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3823d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 3833d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 3843d183407SMatthew G. Knepley for (d = 0; d < dof-cdof; ++d) { 3853d183407SMatthew G. Knepley PetscInt ldof, rdof; 3863d183407SMatthew G. Knepley 3873d183407SMatthew G. Knepley ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 3883d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 3893d183407SMatthew G. Knepley if (ldof > 0) { 3903d183407SMatthew G. Knepley /* We do not own this point */ 3913d183407SMatthew G. Knepley } else if (rdof > 0) { 3923d183407SMatthew G. Knepley ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 3933d183407SMatthew G. Knepley } else { 3943d183407SMatthew G. Knepley found = PETSC_FALSE; 3953d183407SMatthew G. Knepley } 3963d183407SMatthew G. Knepley } 3973d183407SMatthew G. Knepley if (found) continue; 3983d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 3993d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 4003d183407SMatthew G. Knepley ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 4013d183407SMatthew G. Knepley for (q = 0; q < numAdj; ++q) { 4023d183407SMatthew G. Knepley const PetscInt padj = tmpAdj[q]; 4033d183407SMatthew G. Knepley PetscInt ndof, ncdof, noff; 4043d183407SMatthew G. Knepley 4053d183407SMatthew G. Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 4063d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 4073d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 4083d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 4093d183407SMatthew G. Knepley for (d = goff; d < goff+dof-cdof; ++d) { 4103d183407SMatthew G. Knepley ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 4113d183407SMatthew G. Knepley } 4123d183407SMatthew G. Knepley } 4133d183407SMatthew G. Knepley } 4143d183407SMatthew G. Knepley ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 4153d183407SMatthew G. Knepley if (debug) { 4163d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 4173d183407SMatthew G. Knepley ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4183d183407SMatthew G. Knepley } 4193d183407SMatthew G. Knepley /* Get adjacent indices */ 4203d183407SMatthew G. Knepley ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 421*854ce69bSBarry Smith ierr = PetscMalloc1(numCols, &cols);CHKERRQ(ierr); 4223d183407SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4233d183407SMatthew G. Knepley PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 4243d183407SMatthew G. Knepley PetscBool found = PETSC_TRUE; 4253d183407SMatthew G. Knepley 4263d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 4273d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 4283d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 4293d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 4303d183407SMatthew G. Knepley for (d = 0; d < dof-cdof; ++d) { 4313d183407SMatthew G. Knepley PetscInt ldof, rdof; 4323d183407SMatthew G. Knepley 4333d183407SMatthew G. Knepley ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 4343d183407SMatthew G. Knepley ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 4353d183407SMatthew G. Knepley if (ldof > 0) { 4363d183407SMatthew G. Knepley /* We do not own this point */ 4373d183407SMatthew G. Knepley } else if (rdof > 0) { 4383d183407SMatthew G. Knepley PetscInt aoff, roff; 4393d183407SMatthew G. Knepley 4403d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 4413d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 4423d183407SMatthew G. Knepley ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 4433d183407SMatthew G. Knepley } else { 4443d183407SMatthew G. Knepley found = PETSC_FALSE; 4453d183407SMatthew G. Knepley } 4463d183407SMatthew G. Knepley } 4473d183407SMatthew G. Knepley if (found) continue; 4483d183407SMatthew G. Knepley ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 4493d183407SMatthew G. Knepley for (d = goff; d < goff+dof-cdof; ++d) { 4503d183407SMatthew G. Knepley PetscInt adof, aoff, i = 0; 4513d183407SMatthew G. Knepley 4523d183407SMatthew G. Knepley ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 4533d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 4543d183407SMatthew G. Knepley for (q = 0; q < numAdj; ++q) { 4553d183407SMatthew G. Knepley const PetscInt padj = tmpAdj[q]; 4563d183407SMatthew G. Knepley PetscInt ndof, ncdof, ngoff, nd; 4573d183407SMatthew G. Knepley const PetscInt *ncind; 4583d183407SMatthew G. Knepley 4593d183407SMatthew G. Knepley /* Adjacent points may not be in the section chart */ 4603d183407SMatthew G. Knepley if ((padj < pStart) || (padj >= pEnd)) continue; 4613d183407SMatthew G. Knepley ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 4623d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 4633d183407SMatthew G. Knepley ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 4643d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 4653d183407SMatthew G. Knepley for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 4663d183407SMatthew G. Knepley cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 4673d183407SMatthew G. Knepley } 4683d183407SMatthew G. Knepley } 4693d183407SMatthew G. Knepley 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); 4703d183407SMatthew G. Knepley } 4713d183407SMatthew G. Knepley } 4723d183407SMatthew G. Knepley ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 4733d183407SMatthew G. Knepley ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 4743d183407SMatthew G. Knepley ierr = PetscFree(rootAdj);CHKERRQ(ierr); 4753d183407SMatthew G. Knepley ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 4763d183407SMatthew G. Knepley /* Debugging */ 4773d183407SMatthew G. Knepley if (debug) { 4783d183407SMatthew G. Knepley IS tmp; 4793d183407SMatthew G. Knepley ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 4803d183407SMatthew G. Knepley ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 4813d183407SMatthew G. Knepley ierr = ISView(tmp, NULL);CHKERRQ(ierr); 4823d183407SMatthew G. Knepley ierr = ISDestroy(&tmp);CHKERRQ(ierr); 4833d183407SMatthew G. Knepley } 4843d183407SMatthew G. Knepley /* Create allocation vectors from adjacency graph */ 4853d183407SMatthew G. Knepley ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 4863d183407SMatthew G. Knepley ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 4873d183407SMatthew G. Knepley ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 4883d183407SMatthew G. Knepley ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 4893d183407SMatthew G. Knepley ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 4903d183407SMatthew G. Knepley ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 4913d183407SMatthew G. Knepley ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 4923d183407SMatthew G. Knepley /* Only loop over blocks of rows */ 4933d183407SMatthew G. Knepley 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); 4943d183407SMatthew G. Knepley for (r = rStart/bs; r < rEnd/bs; ++r) { 4953d183407SMatthew G. Knepley const PetscInt row = r*bs; 4963d183407SMatthew G. Knepley PetscInt numCols, cStart, c; 4973d183407SMatthew G. Knepley 4983d183407SMatthew G. Knepley ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 4993d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 5003d183407SMatthew G. Knepley for (c = cStart; c < cStart+numCols; ++c) { 5013d183407SMatthew G. Knepley if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 5023d183407SMatthew G. Knepley ++dnz[r-rStart]; 5033d183407SMatthew G. Knepley if (cols[c] >= row) ++dnzu[r-rStart]; 5043d183407SMatthew G. Knepley } else { 5053d183407SMatthew G. Knepley ++onz[r-rStart]; 5063d183407SMatthew G. Knepley if (cols[c] >= row) ++onzu[r-rStart]; 5073d183407SMatthew G. Knepley } 5083d183407SMatthew G. Knepley } 5093d183407SMatthew G. Knepley } 5103d183407SMatthew G. Knepley if (bs > 1) { 5113d183407SMatthew G. Knepley for (r = 0; r < locRows/bs; ++r) { 5123d183407SMatthew G. Knepley dnz[r] /= bs; 5133d183407SMatthew G. Knepley onz[r] /= bs; 5143d183407SMatthew G. Knepley dnzu[r] /= bs; 5153d183407SMatthew G. Knepley onzu[r] /= bs; 5163d183407SMatthew G. Knepley } 5173d183407SMatthew G. Knepley } 5183d183407SMatthew G. Knepley /* Set matrix pattern */ 5193d183407SMatthew G. Knepley ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 5203d183407SMatthew G. Knepley ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 5213d183407SMatthew G. Knepley /* Check for symmetric storage */ 5223d183407SMatthew G. Knepley ierr = MatGetType(A, &mtype);CHKERRQ(ierr); 5233d183407SMatthew G. Knepley ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 5243d183407SMatthew G. Knepley ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 5253d183407SMatthew G. Knepley ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 5263d183407SMatthew G. Knepley if (isSymBlock || isSymSeqBlock || isSymMPIBlock) {ierr = MatSetOption(A, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr);} 5273d183407SMatthew G. Knepley /* Fill matrix with zeros */ 5283d183407SMatthew G. Knepley if (fillMatrix) { 5293d183407SMatthew G. Knepley PetscScalar *values; 5303d183407SMatthew G. Knepley PetscInt maxRowLen = 0; 5313d183407SMatthew G. Knepley 5323d183407SMatthew G. Knepley for (r = rStart; r < rEnd; ++r) { 5333d183407SMatthew G. Knepley PetscInt len; 5343d183407SMatthew G. Knepley 5353d183407SMatthew G. Knepley ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 5363d183407SMatthew G. Knepley maxRowLen = PetscMax(maxRowLen, len); 5373d183407SMatthew G. Knepley } 538*854ce69bSBarry Smith ierr = PetscCalloc1(maxRowLen, &values);CHKERRQ(ierr); 5393d183407SMatthew G. Knepley for (r = rStart; r < rEnd; ++r) { 5403d183407SMatthew G. Knepley PetscInt numCols, cStart; 5413d183407SMatthew G. Knepley 5423d183407SMatthew G. Knepley ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 5433d183407SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 5443d183407SMatthew G. Knepley ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 5453d183407SMatthew G. Knepley } 5463d183407SMatthew G. Knepley ierr = PetscFree(values);CHKERRQ(ierr); 5473d183407SMatthew G. Knepley ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5483d183407SMatthew G. Knepley ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5493d183407SMatthew G. Knepley } 5503d183407SMatthew G. Knepley ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 5513d183407SMatthew G. Knepley ierr = PetscFree(cols);CHKERRQ(ierr); 5523d183407SMatthew G. Knepley PetscFunctionReturn(0); 5533d183407SMatthew G. Knepley } 554