Actual source code: plexindices.c

      1: #include <petsc/private/dmpleximpl.h>

      3: /*@
      4:   DMPlexCreateClosureIndex - Calculate an index for the given `PetscSection` for the closure operation on the `DM`

      6:   Not Collective

      8:   Input Parameters:
      9: + dm      - The `DM`
     10: - section - The section describing the layout in the local vector, or NULL to use the default section

     12:   Level: intermediate

     14:   Note:
     15:   This should greatly improve the performance of the closure operations, at the cost of additional memory.

     17: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`, `DMPlexVecGetClosure()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
     18: @*/
     19: PetscErrorCode DMPlexCreateClosureIndex(DM dm, PetscSection section)
     20: {
     21:   PetscSection closureSection;
     22:   IS           closureIS;
     23:   PetscInt    *clPoints;
     24:   PetscInt     pStart, pEnd, sStart, sEnd, point, clSize;

     26:   PetscFunctionBegin;
     28:   if (!section) PetscCall(DMGetLocalSection(dm, &section));
     30:   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
     31:   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
     32:   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &closureSection));
     33:   PetscCall(PetscSectionSetChart(closureSection, pStart, pEnd));
     34:   for (point = pStart; point < pEnd; ++point) {
     35:     PetscInt *points = NULL, numPoints, p, dof, cldof = 0;

     37:     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points));
     38:     for (p = 0; p < numPoints * 2; p += 2) {
     39:       if ((points[p] >= sStart) && (points[p] < sEnd)) {
     40:         PetscCall(PetscSectionGetDof(section, points[p], &dof));
     41:         if (dof) cldof += 2;
     42:       }
     43:     }
     44:     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points));
     45:     PetscCall(PetscSectionSetDof(closureSection, point, cldof));
     46:   }
     47:   PetscCall(PetscSectionSetUp(closureSection));
     48:   PetscCall(PetscSectionGetStorageSize(closureSection, &clSize));
     49:   PetscCall(PetscMalloc1(clSize, &clPoints));
     50:   for (point = pStart; point < pEnd; ++point) {
     51:     PetscInt *points = NULL, numPoints, p, q, dof, cldof, cloff;

     53:     PetscCall(PetscSectionGetDof(closureSection, point, &cldof));
     54:     PetscCall(PetscSectionGetOffset(closureSection, point, &cloff));
     55:     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points));
     56:     for (p = 0, q = 0; p < numPoints * 2; p += 2) {
     57:       if ((points[p] >= sStart) && (points[p] < sEnd)) {
     58:         PetscCall(PetscSectionGetDof(section, points[p], &dof));
     59:         if (dof) {
     60:           clPoints[cloff + q * 2]     = points[p];
     61:           clPoints[cloff + q * 2 + 1] = points[p + 1];
     62:           ++q;
     63:         }
     64:       }
     65:     }
     66:     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points));
     67:     PetscCheck(q * 2 == cldof, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, q * 2, cldof);
     68:   }
     69:   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPoints, PETSC_OWN_POINTER, &closureIS));
     70:   PetscCall(PetscSectionSetClosureIndex(section, (PetscObject)dm, closureSection, closureIS));
     71:   PetscCall(PetscSectionDestroy(&closureSection));
     72:   PetscCall(ISDestroy(&closureIS));
     73:   PetscFunctionReturn(PETSC_SUCCESS);
     74: }