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