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, ¢erDim);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, §ionAdj);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(§ionAdj);CHKERRQ(ierr); 5533d183407SMatthew G. Knepley ierr = PetscFree(cols);CHKERRQ(ierr); 5543d183407SMatthew G. Knepley PetscFunctionReturn(0); 5553d183407SMatthew G. Knepley } 556