xref: /petsc/src/dm/impls/da/dapreallocate.c (revision 527e7439f081c131dbd8e092dc1bd45ed17f0bae)
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 #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) {
21*527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(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);
113c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,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);
1298a713f3bSLawrence Mitchell   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
1303d183407SMatthew G. Knepley   if (debug) {
1313d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr);
1323d183407SMatthew G. Knepley     ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr);
1333d183407SMatthew G. Knepley   }
1343d183407SMatthew G. Knepley   /* Create section for dof adjacency (dof ==> # adj dof) */
1353d183407SMatthew G. Knepley   /*   FEM:   Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim   */
1363d183407SMatthew G. Knepley   /*   FVM:   Two points p and q are adjacent if q \in star(cone(p)),    preallocCenterDim = dim-1 */
1373d183407SMatthew G. Knepley   /*   FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0     */
1383d183407SMatthew G. Knepley   ierr = DMDAGetPreallocationCenterDimension(dm, &centerDim);CHKERRQ(ierr);
1393d183407SMatthew G. Knepley   if (centerDim == dim) {
1403d183407SMatthew G. Knepley     useClosure = PETSC_FALSE;
1413d183407SMatthew G. Knepley   } else if (centerDim == 0) {
1423d183407SMatthew G. Knepley     useClosure = PETSC_TRUE;
1433d183407SMatthew G. Knepley   } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", centerDim);
1443d183407SMatthew G. Knepley 
1453d183407SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
1463d183407SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr);
1473d183407SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr);
1483d183407SMatthew G. Knepley   ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr);
1493d183407SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr);
1503d183407SMatthew G. Knepley   ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr);
1513d183407SMatthew G. Knepley   /*   Fill in the ghost dofs on the interface */
1523d183407SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr);
1533d183407SMatthew G. Knepley   maxConeSize    = 6;
1543d183407SMatthew G. Knepley   maxSupportSize = 6;
1553d183407SMatthew G. Knepley 
1563d183407SMatthew G. Knepley   maxClosureSize = 2*PetscMax(PetscPowInt(maxConeSize,depth+1),PetscPowInt(maxSupportSize,depth+1));
1573d183407SMatthew G. Knepley   maxAdjSize     = PetscPowInt(maxConeSize,depth+1) * PetscPowInt(maxSupportSize,depth+1) + 1;
1583d183407SMatthew G. Knepley 
159ed91c37eSMatthew G. Knepley   ierr = PetscMalloc2(maxClosureSize,&tmpClosure,maxAdjSize,&tmpAdj);CHKERRQ(ierr);
1603d183407SMatthew G. Knepley 
1613d183407SMatthew G. Knepley   /*
1623d183407SMatthew G. Knepley    ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point.
1633d183407SMatthew G. Knepley     1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj
1643d183407SMatthew G. Knepley        Reduce those counts to rootSectionAdj (now redundantly counting some interface points)
1653d183407SMatthew G. Knepley     2. Visit owned points on interface, count adjacencies placing in rootSectionAdj
1663d183407SMatthew G. Knepley        Create sfAdj connecting rootSectionAdj and leafSectionAdj
1673d183407SMatthew G. Knepley     3. Visit unowned points on interface, write adjacencies to adj
1683d183407SMatthew G. Knepley        Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies)
1693d183407SMatthew G. Knepley     4. Visit owned points on interface, write adjacencies to rootAdj
1703d183407SMatthew G. Knepley        Remove redundancy in rootAdj
1713d183407SMatthew G. Knepley    ** The last two traversals use transitive closure
1723d183407SMatthew G. Knepley     5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj)
1733d183407SMatthew G. Knepley        Allocate memory addressed by sectionAdj (cols)
1743d183407SMatthew G. Knepley     6. Visit all owned points in the subdomain, insert dof adjacencies into cols
1753d183407SMatthew G. Knepley    ** Knowing all the column adjacencies, check ownership and sum into dnz and onz
1763d183407SMatthew G. Knepley   */
1773d183407SMatthew G. Knepley 
1783d183407SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
1793d183407SMatthew G. Knepley     PetscInt dof, off, d, q;
1803d183407SMatthew G. Knepley     PetscInt p = leaves[l], numAdj = maxAdjSize;
1813d183407SMatthew G. Knepley 
1823d183407SMatthew G. Knepley     if ((p < pStart) || (p >= pEnd)) continue;
1833d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
1843d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
1853d183407SMatthew G. Knepley     ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
1863d183407SMatthew G. Knepley     for (q = 0; q < numAdj; ++q) {
1873d183407SMatthew G. Knepley       const PetscInt padj = tmpAdj[q];
1883d183407SMatthew G. Knepley       PetscInt ndof, ncdof;
1893d183407SMatthew G. Knepley 
1903d183407SMatthew G. Knepley       if ((padj < pStart) || (padj >= pEnd)) continue;
1913d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr);
1923d183407SMatthew G. Knepley       ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr);
1933d183407SMatthew G. Knepley       for (d = off; d < off+dof; ++d) {
1943d183407SMatthew G. Knepley         ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr);
1953d183407SMatthew G. Knepley       }
1963d183407SMatthew G. Knepley     }
1973d183407SMatthew G. Knepley   }
1983d183407SMatthew G. Knepley   ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr);
1993d183407SMatthew G. Knepley   if (debug) {
2003d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr);
2013d183407SMatthew G. Knepley     ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
2023d183407SMatthew G. Knepley   }
2033d183407SMatthew G. Knepley   /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */
2043d183407SMatthew G. Knepley   if (size > 1) {
2053d183407SMatthew G. Knepley     ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr);
2063d183407SMatthew G. Knepley     ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr);
2073d183407SMatthew G. Knepley   }
2083d183407SMatthew G. Knepley   if (debug) {
2093d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr);
2103d183407SMatthew G. Knepley     ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
2113d183407SMatthew G. Knepley   }
2123d183407SMatthew G. Knepley   /* Add in local adjacency sizes for owned dofs on interface (roots) */
2133d183407SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2143d183407SMatthew G. Knepley     PetscInt numAdj = maxAdjSize, adof, dof, off, d, q;
2153d183407SMatthew G. Knepley 
2163d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
2173d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
2183d183407SMatthew G. Knepley     if (!dof) continue;
2193d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr);
2203d183407SMatthew G. Knepley     if (adof <= 0) continue;
2213d183407SMatthew G. Knepley     ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
2223d183407SMatthew G. Knepley     for (q = 0; q < numAdj; ++q) {
2233d183407SMatthew G. Knepley       const PetscInt padj = tmpAdj[q];
2243d183407SMatthew G. Knepley       PetscInt ndof, ncdof;
2253d183407SMatthew G. Knepley 
2263d183407SMatthew G. Knepley       if ((padj < pStart) || (padj >= pEnd)) continue;
2273d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr);
2283d183407SMatthew G. Knepley       ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr);
2293d183407SMatthew G. Knepley       for (d = off; d < off+dof; ++d) {
2303d183407SMatthew G. Knepley         ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr);
2313d183407SMatthew G. Knepley       }
2323d183407SMatthew G. Knepley     }
2333d183407SMatthew G. Knepley   }
2343d183407SMatthew G. Knepley   ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr);
2353d183407SMatthew G. Knepley   if (debug) {
2363d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr);
2373d183407SMatthew G. Knepley     ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
2383d183407SMatthew G. Knepley   }
2393d183407SMatthew G. Knepley   /* Create adj SF based on dof SF */
2403d183407SMatthew G. Knepley   ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr);
2413d183407SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr);
2428a713f3bSLawrence Mitchell   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
2433d183407SMatthew G. Knepley   if (debug) {
2443d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr);
2453d183407SMatthew G. Knepley     ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr);
2463d183407SMatthew G. Knepley   }
2473d183407SMatthew G. Knepley   ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr);
2483d183407SMatthew G. Knepley   /* Create leaf adjacency */
2493d183407SMatthew G. Knepley   ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr);
2503d183407SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr);
251854ce69bSBarry Smith   ierr = PetscMalloc1(adjSize, &adj);CHKERRQ(ierr);
2523d183407SMatthew G. Knepley   ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr);
2533d183407SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
2543d183407SMatthew G. Knepley     PetscInt dof, off, d, q;
2553d183407SMatthew G. Knepley     PetscInt p = leaves[l], numAdj = maxAdjSize;
2563d183407SMatthew G. Knepley 
2573d183407SMatthew G. Knepley     if ((p < pStart) || (p >= pEnd)) continue;
2583d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
2593d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
2603d183407SMatthew G. Knepley     ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
2613d183407SMatthew G. Knepley     for (d = off; d < off+dof; ++d) {
2623d183407SMatthew G. Knepley       PetscInt aoff, i = 0;
2633d183407SMatthew G. Knepley 
2643d183407SMatthew G. Knepley       ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr);
2653d183407SMatthew G. Knepley       for (q = 0; q < numAdj; ++q) {
2663d183407SMatthew G. Knepley         const PetscInt padj = tmpAdj[q];
2673d183407SMatthew G. Knepley         PetscInt ndof, ncdof, ngoff, nd;
2683d183407SMatthew G. Knepley 
2693d183407SMatthew G. Knepley         if ((padj < pStart) || (padj >= pEnd)) continue;
2703d183407SMatthew G. Knepley         ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr);
2713d183407SMatthew G. Knepley         ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr);
2723d183407SMatthew G. Knepley         ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr);
2733d183407SMatthew G. Knepley         for (nd = 0; nd < ndof-ncdof; ++nd) {
2743d183407SMatthew G. Knepley           adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd;
2753d183407SMatthew G. Knepley           ++i;
2763d183407SMatthew G. Knepley         }
2773d183407SMatthew G. Knepley       }
2783d183407SMatthew G. Knepley     }
2793d183407SMatthew G. Knepley   }
2803d183407SMatthew G. Knepley   /* Debugging */
2813d183407SMatthew G. Knepley   if (debug) {
2823d183407SMatthew G. Knepley     IS tmp;
2833d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr);
2843d183407SMatthew G. Knepley     ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
2853d183407SMatthew G. Knepley     ierr = ISView(tmp, NULL);CHKERRQ(ierr);
2863d183407SMatthew G. Knepley     ierr = ISDestroy(&tmp);CHKERRQ(ierr);
2873d183407SMatthew G. Knepley   }
2883d183407SMatthew G. Knepley   /* Gather adjacenct indices to root */
2893d183407SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr);
290854ce69bSBarry Smith   ierr = PetscMalloc1(adjSize, &rootAdj);CHKERRQ(ierr);
2913d183407SMatthew G. Knepley   for (r = 0; r < adjSize; ++r) rootAdj[r] = -1;
2923d183407SMatthew G. Knepley   if (size > 1) {
2933d183407SMatthew G. Knepley     ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr);
2943d183407SMatthew G. Knepley     ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr);
2953d183407SMatthew G. Knepley   }
2963d183407SMatthew G. Knepley   ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr);
2973d183407SMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
2983d183407SMatthew G. Knepley   /* Debugging */
2993d183407SMatthew G. Knepley   if (debug) {
3003d183407SMatthew G. Knepley     IS tmp;
3013d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr);
3023d183407SMatthew G. Knepley     ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
3033d183407SMatthew G. Knepley     ierr = ISView(tmp, NULL);CHKERRQ(ierr);
3043d183407SMatthew G. Knepley     ierr = ISDestroy(&tmp);CHKERRQ(ierr);
3053d183407SMatthew G. Knepley   }
3063d183407SMatthew G. Knepley   /* Add in local adjacency indices for owned dofs on interface (roots) */
3073d183407SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3083d183407SMatthew G. Knepley     PetscInt numAdj = maxAdjSize, adof, dof, off, d, q;
3093d183407SMatthew G. Knepley 
3103d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
3113d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
3123d183407SMatthew G. Knepley     if (!dof) continue;
3133d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr);
3143d183407SMatthew G. Knepley     if (adof <= 0) continue;
3153d183407SMatthew G. Knepley     ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
3163d183407SMatthew G. Knepley     for (d = off; d < off+dof; ++d) {
3173d183407SMatthew G. Knepley       PetscInt adof, aoff, i;
3183d183407SMatthew G. Knepley 
3193d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr);
3203d183407SMatthew G. Knepley       ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr);
3213d183407SMatthew G. Knepley       i    = adof-1;
3223d183407SMatthew G. Knepley       for (q = 0; q < numAdj; ++q) {
3233d183407SMatthew G. Knepley         const PetscInt padj = tmpAdj[q];
3243d183407SMatthew G. Knepley         PetscInt ndof, ncdof, ngoff, nd;
3253d183407SMatthew G. Knepley 
3263d183407SMatthew G. Knepley         if ((padj < pStart) || (padj >= pEnd)) continue;
3273d183407SMatthew G. Knepley         ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr);
3283d183407SMatthew G. Knepley         ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr);
3293d183407SMatthew G. Knepley         ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr);
3303d183407SMatthew G. Knepley         for (nd = 0; nd < ndof-ncdof; ++nd) {
3313d183407SMatthew G. Knepley           rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd;
3323d183407SMatthew G. Knepley           --i;
3333d183407SMatthew G. Knepley         }
3343d183407SMatthew G. Knepley       }
3353d183407SMatthew G. Knepley     }
3363d183407SMatthew G. Knepley   }
3373d183407SMatthew G. Knepley   /* Debugging */
3383d183407SMatthew G. Knepley   if (debug) {
3393d183407SMatthew G. Knepley     IS tmp;
3403d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr);
3413d183407SMatthew G. Knepley     ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
3423d183407SMatthew G. Knepley     ierr = ISView(tmp, NULL);CHKERRQ(ierr);
3433d183407SMatthew G. Knepley     ierr = ISDestroy(&tmp);CHKERRQ(ierr);
3443d183407SMatthew G. Knepley   }
3453d183407SMatthew G. Knepley   /* Compress indices */
3463d183407SMatthew G. Knepley   ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr);
3473d183407SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3483d183407SMatthew G. Knepley     PetscInt dof, cdof, off, d;
3493d183407SMatthew G. Knepley     PetscInt adof, aoff;
3503d183407SMatthew G. Knepley 
3513d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
3523d183407SMatthew G. Knepley     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
3533d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
3543d183407SMatthew G. Knepley     if (!dof) continue;
3553d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr);
3563d183407SMatthew G. Knepley     if (adof <= 0) continue;
3573d183407SMatthew G. Knepley     for (d = off; d < off+dof-cdof; ++d) {
3583d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr);
3593d183407SMatthew G. Knepley       ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr);
3603d183407SMatthew G. Knepley       ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr);
3613d183407SMatthew G. Knepley       ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr);
3623d183407SMatthew G. Knepley     }
3633d183407SMatthew G. Knepley   }
3643d183407SMatthew G. Knepley   /* Debugging */
3653d183407SMatthew G. Knepley   if (debug) {
3663d183407SMatthew G. Knepley     IS tmp;
3673d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr);
3683d183407SMatthew G. Knepley     ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3693d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr);
3703d183407SMatthew G. Knepley     ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
3713d183407SMatthew G. Knepley     ierr = ISView(tmp, NULL);CHKERRQ(ierr);
3723d183407SMatthew G. Knepley     ierr = ISDestroy(&tmp);CHKERRQ(ierr);
3733d183407SMatthew G. Knepley   }
3743d183407SMatthew G. Knepley   /* Build adjacency section: Maps global indices to sets of adjacent global indices */
3753d183407SMatthew G. Knepley   ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr);
3763d183407SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &sectionAdj);CHKERRQ(ierr);
3773d183407SMatthew G. Knepley   ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr);
3783d183407SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3793d183407SMatthew G. Knepley     PetscInt  numAdj = maxAdjSize, dof, cdof, off, goff, d, q;
3803d183407SMatthew G. Knepley     PetscBool found  = PETSC_TRUE;
3813d183407SMatthew G. Knepley 
3823d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
3833d183407SMatthew G. Knepley     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
3843d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
3853d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
3863d183407SMatthew G. Knepley     for (d = 0; d < dof-cdof; ++d) {
3873d183407SMatthew G. Knepley       PetscInt ldof, rdof;
3883d183407SMatthew G. Knepley 
3893d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr);
3903d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr);
3913d183407SMatthew G. Knepley       if (ldof > 0) {
3923d183407SMatthew G. Knepley         /* We do not own this point */
3933d183407SMatthew G. Knepley       } else if (rdof > 0) {
3943d183407SMatthew G. Knepley         ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr);
3953d183407SMatthew G. Knepley       } else {
3963d183407SMatthew G. Knepley         found = PETSC_FALSE;
3973d183407SMatthew G. Knepley       }
3983d183407SMatthew G. Knepley     }
3993d183407SMatthew G. Knepley     if (found) continue;
4003d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
4013d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
4023d183407SMatthew G. Knepley     ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
4033d183407SMatthew G. Knepley     for (q = 0; q < numAdj; ++q) {
4043d183407SMatthew G. Knepley       const PetscInt padj = tmpAdj[q];
4053d183407SMatthew G. Knepley       PetscInt ndof, ncdof, noff;
4063d183407SMatthew G. Knepley 
4073d183407SMatthew G. Knepley       if ((padj < pStart) || (padj >= pEnd)) continue;
4083d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr);
4093d183407SMatthew G. Knepley       ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr);
4103d183407SMatthew G. Knepley       ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr);
4113d183407SMatthew G. Knepley       for (d = goff; d < goff+dof-cdof; ++d) {
4123d183407SMatthew G. Knepley         ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr);
4133d183407SMatthew G. Knepley       }
4143d183407SMatthew G. Knepley     }
4153d183407SMatthew G. Knepley   }
4163d183407SMatthew G. Knepley   ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr);
4173d183407SMatthew G. Knepley   if (debug) {
4183d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr);
4193d183407SMatthew G. Knepley     ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
4203d183407SMatthew G. Knepley   }
4213d183407SMatthew G. Knepley   /* Get adjacent indices */
4223d183407SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr);
423854ce69bSBarry Smith   ierr = PetscMalloc1(numCols, &cols);CHKERRQ(ierr);
4243d183407SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4253d183407SMatthew G. Knepley     PetscInt  numAdj = maxAdjSize, dof, cdof, off, goff, d, q;
4263d183407SMatthew G. Knepley     PetscBool found  = PETSC_TRUE;
4273d183407SMatthew G. Knepley 
4283d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
4293d183407SMatthew G. Knepley     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
4303d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
4313d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
4323d183407SMatthew G. Knepley     for (d = 0; d < dof-cdof; ++d) {
4333d183407SMatthew G. Knepley       PetscInt ldof, rdof;
4343d183407SMatthew G. Knepley 
4353d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr);
4363d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr);
4373d183407SMatthew G. Knepley       if (ldof > 0) {
4383d183407SMatthew G. Knepley         /* We do not own this point */
4393d183407SMatthew G. Knepley       } else if (rdof > 0) {
4403d183407SMatthew G. Knepley         PetscInt aoff, roff;
4413d183407SMatthew G. Knepley 
4423d183407SMatthew G. Knepley         ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr);
4433d183407SMatthew G. Knepley         ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr);
4443d183407SMatthew G. Knepley         ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr);
4453d183407SMatthew G. Knepley       } else {
4463d183407SMatthew G. Knepley         found = PETSC_FALSE;
4473d183407SMatthew G. Knepley       }
4483d183407SMatthew G. Knepley     }
4493d183407SMatthew G. Knepley     if (found) continue;
4503d183407SMatthew G. Knepley     ierr = DMDAGetAdjacency_Internal(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
4513d183407SMatthew G. Knepley     for (d = goff; d < goff+dof-cdof; ++d) {
4523d183407SMatthew G. Knepley       PetscInt adof, aoff, i = 0;
4533d183407SMatthew G. Knepley 
4543d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr);
4553d183407SMatthew G. Knepley       ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr);
4563d183407SMatthew G. Knepley       for (q = 0; q < numAdj; ++q) {
4573d183407SMatthew G. Knepley         const PetscInt  padj = tmpAdj[q];
4583d183407SMatthew G. Knepley         PetscInt        ndof, ncdof, ngoff, nd;
4593d183407SMatthew G. Knepley         const PetscInt *ncind;
4603d183407SMatthew G. Knepley 
4613d183407SMatthew G. Knepley         /* Adjacent points may not be in the section chart */
4623d183407SMatthew G. Knepley         if ((padj < pStart) || (padj >= pEnd)) continue;
4633d183407SMatthew G. Knepley         ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr);
4643d183407SMatthew G. Knepley         ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr);
4653d183407SMatthew G. Knepley         ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr);
4663d183407SMatthew G. Knepley         ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr);
4673d183407SMatthew G. Knepley         for (nd = 0; nd < ndof-ncdof; ++nd, ++i) {
4683d183407SMatthew G. Knepley           cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd;
4693d183407SMatthew G. Knepley         }
4703d183407SMatthew G. Knepley       }
4713d183407SMatthew 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);
4723d183407SMatthew G. Knepley     }
4733d183407SMatthew G. Knepley   }
4743d183407SMatthew G. Knepley   ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr);
4753d183407SMatthew G. Knepley   ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr);
4763d183407SMatthew G. Knepley   ierr = PetscFree(rootAdj);CHKERRQ(ierr);
4773d183407SMatthew G. Knepley   ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr);
4783d183407SMatthew G. Knepley   /* Debugging */
4793d183407SMatthew G. Knepley   if (debug) {
4803d183407SMatthew G. Knepley     IS tmp;
4813d183407SMatthew G. Knepley     ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr);
4823d183407SMatthew G. Knepley     ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
4833d183407SMatthew G. Knepley     ierr = ISView(tmp, NULL);CHKERRQ(ierr);
4843d183407SMatthew G. Knepley     ierr = ISDestroy(&tmp);CHKERRQ(ierr);
4853d183407SMatthew G. Knepley   }
4863d183407SMatthew G. Knepley   /* Create allocation vectors from adjacency graph */
4873d183407SMatthew G. Knepley   ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr);
4883d183407SMatthew G. Knepley   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr);
4893d183407SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
4903d183407SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
4913d183407SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
4923d183407SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
4933d183407SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
4943d183407SMatthew G. Knepley   /* Only loop over blocks of rows */
4953d183407SMatthew 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);
4963d183407SMatthew G. Knepley   for (r = rStart/bs; r < rEnd/bs; ++r) {
4973d183407SMatthew G. Knepley     const PetscInt row = r*bs;
4983d183407SMatthew G. Knepley     PetscInt       numCols, cStart, c;
4993d183407SMatthew G. Knepley 
5003d183407SMatthew G. Knepley     ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr);
5013d183407SMatthew G. Knepley     ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr);
5023d183407SMatthew G. Knepley     for (c = cStart; c < cStart+numCols; ++c) {
5033d183407SMatthew G. Knepley       if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) {
5043d183407SMatthew G. Knepley         ++dnz[r-rStart];
5053d183407SMatthew G. Knepley         if (cols[c] >= row) ++dnzu[r-rStart];
5063d183407SMatthew G. Knepley       } else {
5073d183407SMatthew G. Knepley         ++onz[r-rStart];
5083d183407SMatthew G. Knepley         if (cols[c] >= row) ++onzu[r-rStart];
5093d183407SMatthew G. Knepley       }
5103d183407SMatthew G. Knepley     }
5113d183407SMatthew G. Knepley   }
5123d183407SMatthew G. Knepley   if (bs > 1) {
5133d183407SMatthew G. Knepley     for (r = 0; r < locRows/bs; ++r) {
5143d183407SMatthew G. Knepley       dnz[r]  /= bs;
5153d183407SMatthew G. Knepley       onz[r]  /= bs;
5163d183407SMatthew G. Knepley       dnzu[r] /= bs;
5173d183407SMatthew G. Knepley       onzu[r] /= bs;
5183d183407SMatthew G. Knepley     }
5193d183407SMatthew G. Knepley   }
5203d183407SMatthew G. Knepley   /* Set matrix pattern */
5213d183407SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr);
5223d183407SMatthew G. Knepley   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
5233d183407SMatthew G. Knepley   /* Check for symmetric storage */
5243d183407SMatthew G. Knepley   ierr = MatGetType(A, &mtype);CHKERRQ(ierr);
5253d183407SMatthew G. Knepley   ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr);
5263d183407SMatthew G. Knepley   ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr);
5273d183407SMatthew G. Knepley   ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr);
5283d183407SMatthew G. Knepley   if (isSymBlock || isSymSeqBlock || isSymMPIBlock) {ierr = MatSetOption(A, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr);}
5293d183407SMatthew G. Knepley   /* Fill matrix with zeros */
5303d183407SMatthew G. Knepley   if (fillMatrix) {
5313d183407SMatthew G. Knepley     PetscScalar *values;
5323d183407SMatthew G. Knepley     PetscInt     maxRowLen = 0;
5333d183407SMatthew G. Knepley 
5343d183407SMatthew G. Knepley     for (r = rStart; r < rEnd; ++r) {
5353d183407SMatthew G. Knepley       PetscInt len;
5363d183407SMatthew G. Knepley 
5373d183407SMatthew G. Knepley       ierr      = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr);
5383d183407SMatthew G. Knepley       maxRowLen = PetscMax(maxRowLen, len);
5393d183407SMatthew G. Knepley     }
540854ce69bSBarry Smith     ierr = PetscCalloc1(maxRowLen, &values);CHKERRQ(ierr);
5413d183407SMatthew G. Knepley     for (r = rStart; r < rEnd; ++r) {
5423d183407SMatthew G. Knepley       PetscInt numCols, cStart;
5433d183407SMatthew G. Knepley 
5443d183407SMatthew G. Knepley       ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr);
5453d183407SMatthew G. Knepley       ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr);
5463d183407SMatthew G. Knepley       ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr);
5473d183407SMatthew G. Knepley     }
5483d183407SMatthew G. Knepley     ierr = PetscFree(values);CHKERRQ(ierr);
5493d183407SMatthew G. Knepley     ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5503d183407SMatthew G. Knepley     ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5513d183407SMatthew G. Knepley   }
5523d183407SMatthew G. Knepley   ierr = PetscSectionDestroy(&sectionAdj);CHKERRQ(ierr);
5533d183407SMatthew G. Knepley   ierr = PetscFree(cols);CHKERRQ(ierr);
5543d183407SMatthew G. Knepley   PetscFunctionReturn(0);
5553d183407SMatthew G. Knepley }
556