xref: /petsc/src/dm/impls/da/dapreallocate.c (revision 854ce69b31eecaec02632e265405c6229e3f3488)
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, &centerDim);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, &sectionAdj);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(&sectionAdj);CHKERRQ(ierr);
5513d183407SMatthew G. Knepley   ierr = PetscFree(cols);CHKERRQ(ierr);
5523d183407SMatthew G. Knepley   PetscFunctionReturn(0);
5533d183407SMatthew G. Knepley }
554