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