Date: 2015-10-02T22:04:10+00:00

Actual source code: vsectionis.c
petsc-3.6.2 2015-10-02
Report Typos and Errors

      1: /*
      2:    This file contains routines for basic section object implementation.
      3: */

      5: #include <petsc/private/isimpl.h>   /*I  "petscvec.h"   I*/
      6: #include <petscsf.h>
      7: #include <petscviewer.h>

      9: PetscClassId PETSC_SECTION_CLASSID;

     13: /*@
     14:   PetscSectionCreate - Allocates PetscSection space and sets the map contents to the default.

     16:   Collective on MPI_Comm

     18:   Input Parameters:
     19: + comm - the MPI communicator
     20: - s    - pointer to the section

     22:   Level: developer

     24:   Notes: Typical calling sequence
     25: $       PetscSectionCreate(MPI_Comm,PetscSection *);
     26: $       PetscSectionSetNumFields(PetscSection, numFields);
     27: $       PetscSectionSetChart(PetscSection,low,high);
     28: $       PetscSectionSetDof(PetscSection,point,numdof);
     29: $       PetscSectionSetUp(PetscSection);
     30: $       PetscSectionGetOffset(PetscSection,point,PetscInt *);
     31: $       PetscSectionDestroy(PetscSection);

     33:        The PetscSection object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
     34:        recommended they not be used in user codes unless you really gain something in their use.

     36: .seealso: PetscSection, PetscSectionDestroy()
     37: @*/
     38: PetscErrorCode PetscSectionCreate(MPI_Comm comm, PetscSection *s)
     39: {

     44:   ISInitializePackage();

     46:   PetscHeaderCreate(*s,PETSC_SECTION_CLASSID,"PetscSection","Section","IS",comm,PetscSectionDestroy,PetscSectionView);

     48:   (*s)->pStart             = -1;
     49:   (*s)->pEnd               = -1;
     50:   (*s)->perm               = NULL;
     51:   (*s)->maxDof             = 0;
     52:   (*s)->atlasDof           = NULL;
     53:   (*s)->atlasOff           = NULL;
     54:   (*s)->bc                 = NULL;
     55:   (*s)->bcIndices          = NULL;
     56:   (*s)->setup              = PETSC_FALSE;
     57:   (*s)->numFields          = 0;
     58:   (*s)->fieldNames         = NULL;
     59:   (*s)->field              = NULL;
     60:   (*s)->clObj              = NULL;
     61:   (*s)->clSection          = NULL;
     62:   (*s)->clPoints          = NULL;
     63:   return(0);
     64: }

     68: /*@
     69:   PetscSectionCopy - Creates a shallow (if possible) copy of the PetscSection

     71:   Collective on MPI_Comm

     73:   Input Parameter:
     74: . section - the PetscSection

     76:   Output Parameter:
     77: . newSection - the copy

     79:   Level: developer

     81: .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
     82: @*/
     83: PetscErrorCode PetscSectionCopy(PetscSection section, PetscSection newSection)
     84: {
     85:   IS             perm;
     86:   PetscInt       numFields, f, pStart, pEnd, p;

     90:   PetscSectionGetNumFields(section, &numFields);
     91:   if (numFields) {PetscSectionSetNumFields(newSection, numFields);}
     92:   for (f = 0; f < numFields; ++f) {
     93:     const char *name   = NULL;
     94:     PetscInt   numComp = 0;

     96:     PetscSectionGetFieldName(section, f, &name);
     97:     PetscSectionSetFieldName(newSection, f, name);
     98:     PetscSectionGetFieldComponents(section, f, &numComp);
     99:     PetscSectionSetFieldComponents(newSection, f, numComp);
    100:   }
    101:   PetscSectionGetChart(section, &pStart, &pEnd);
    102:   PetscSectionSetChart(newSection, pStart, pEnd);
    103:   PetscSectionGetPermutation(section, &perm);
    104:   PetscSectionSetPermutation(newSection, perm);
    105:   for (p = pStart; p < pEnd; ++p) {
    106:     PetscInt dof, cdof, fcdof = 0;

    108:     PetscSectionGetDof(section, p, &dof);
    109:     PetscSectionSetDof(newSection, p, dof);
    110:     PetscSectionGetConstraintDof(section, p, &cdof);
    111:     if (cdof) {PetscSectionSetConstraintDof(newSection, p, cdof);}
    112:     for (f = 0; f < numFields; ++f) {
    113:       PetscSectionGetFieldDof(section, p, f, &dof);
    114:       PetscSectionSetFieldDof(newSection, p, f, dof);
    115:       if (cdof) {
    116:         PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
    117:         if (fcdof) {PetscSectionSetFieldConstraintDof(newSection, p, f, fcdof);}
    118:       }
    119:     }
    120:   }
    121:   PetscSectionSetUp(newSection);
    122:   for (p = pStart; p < pEnd; ++p) {
    123:     PetscInt       off, cdof, fcdof = 0;
    124:     const PetscInt *cInd;

    126:     /* Must set offsets in case they do not agree with the prefix sums */
    127:     PetscSectionGetOffset(section, p, &off);
    128:     PetscSectionSetOffset(newSection, p, off);
    129:     PetscSectionGetConstraintDof(section, p, &cdof);
    130:     if (cdof) {
    131:       PetscSectionGetConstraintIndices(section, p, &cInd);
    132:       PetscSectionSetConstraintIndices(newSection, p, cInd);
    133:       for (f = 0; f < numFields; ++f) {
    134:         PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
    135:         if (fcdof) {
    136:           PetscSectionGetFieldConstraintIndices(section, p, f, &cInd);
    137:           PetscSectionSetFieldConstraintIndices(newSection, p, f, cInd);
    138:         }
    139:       }
    140:     }
    141:   }
    142:   return(0);
    143: }

    147: /*@
    148:   PetscSectionClone - Creates a shallow (if possible) copy of the PetscSection

    150:   Collective on MPI_Comm

    152:   Input Parameter:
    153: . section - the PetscSection

    155:   Output Parameter:
    156: . newSection - the copy

    158:   Level: developer

    160: .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
    161: @*/
    162: PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection)
    163: {

    167:   PetscSectionCreate(PetscObjectComm((PetscObject) section), newSection);
    168:   PetscSectionCopy(section, *newSection);
    169:   return(0);
    170: }

    174: /*@
    175:   PetscSectionGetNumFields - Returns the number of fields, or 0 if no fields were defined.

    177:   Not collective

    179:   Input Parameter:
    180: . s - the PetscSection

    182:   Output Parameter:
    183: . numFields - the number of fields defined, or 0 if none were defined

    185:   Level: intermediate

    187: .seealso: PetscSectionSetNumFields()
    188: @*/
    189: PetscErrorCode PetscSectionGetNumFields(PetscSection s, PetscInt *numFields)
    190: {
    193:   *numFields = s->numFields;
    194:   return(0);
    195: }

    199: /*@
    200:   PetscSectionSetNumFields - Sets the number of fields.

    202:   Not collective

    204:   Input Parameters:
    205: + s - the PetscSection
    206: - numFields - the number of fields

    208:   Level: intermediate

    210: .seealso: PetscSectionGetNumFields()
    211: @*/
    212: PetscErrorCode PetscSectionSetNumFields(PetscSection s, PetscInt numFields)
    213: {
    214:   PetscInt       f;

    218:   if (numFields <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "The number of fields %d must be positive", numFields);
    219:   PetscSectionReset(s);

    221:   s->numFields = numFields;
    222:   PetscMalloc1(s->numFields, &s->numFieldComponents);
    223:   PetscMalloc1(s->numFields, &s->fieldNames);
    224:   PetscMalloc1(s->numFields, &s->field);
    225:   for (f = 0; f < s->numFields; ++f) {
    226:     char name[64];

    228:     s->numFieldComponents[f] = 1;

    230:     PetscSectionCreate(PetscObjectComm((PetscObject) s), &s->field[f]);
    231:     PetscSNPrintf(name, 64, "Field_%D", f);
    232:     PetscStrallocpy(name, (char **) &s->fieldNames[f]);
    233:   }
    234:   return(0);
    235: }

    239: /*@C
    240:   PetscSectionGetFieldName - Returns the name of a field in the PetscSection

    242:   Not Collective

    244:   Input Parameters:
    245: + s     - the PetscSection
    246: - field - the field number

    248:   Output Parameter:
    249: . fieldName - the field name

    251:   Level: developer

    253: .seealso: PetscSectionSetFieldName()
    254: @*/
    255: PetscErrorCode PetscSectionGetFieldName(PetscSection s, PetscInt field, const char *fieldName[])
    256: {
    259:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    260:   *fieldName = s->fieldNames[field];
    261:   return(0);
    262: }

    266: /*@C
    267:   PetscSectionSetFieldName - Sets the name of a field in the PetscSection

    269:   Not Collective

    271:   Input Parameters:
    272: + s     - the PetscSection
    273: . field - the field number
    274: - fieldName - the field name

    276:   Level: developer

    278: .seealso: PetscSectionGetFieldName()
    279: @*/
    280: PetscErrorCode PetscSectionSetFieldName(PetscSection s, PetscInt field, const char fieldName[])
    281: {

    286:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    287:   PetscFree(s->fieldNames[field]);
    288:   PetscStrallocpy(fieldName, (char**) &s->fieldNames[field]);
    289:   return(0);
    290: }

    294: /*@
    295:   PetscSectionGetFieldComponents - Returns the number of field components for the given field.

    297:   Not collective

    299:   Input Parameters:
    300: + s - the PetscSection
    301: - field - the field number

    303:   Output Parameter:
    304: . numComp - the number of field components

    306:   Level: intermediate

    308: .seealso: PetscSectionSetNumFieldComponents(), PetscSectionGetNumFields()
    309: @*/
    310: PetscErrorCode PetscSectionGetFieldComponents(PetscSection s, PetscInt field, PetscInt *numComp)
    311: {
    314:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    315:   *numComp = s->numFieldComponents[field];
    316:   return(0);
    317: }

    321: /*@
    322:   PetscSectionSetFieldComponents - Sets the number of field components for the given field.

    324:   Not collective

    326:   Input Parameters:
    327: + s - the PetscSection
    328: . field - the field number
    329: - numComp - the number of field components

    331:   Level: intermediate

    333: .seealso: PetscSectionGetNumFieldComponents(), PetscSectionGetNumFields()
    334: @*/
    335: PetscErrorCode PetscSectionSetFieldComponents(PetscSection s, PetscInt field, PetscInt numComp)
    336: {
    338:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    339:   s->numFieldComponents[field] = numComp;
    340:   return(0);
    341: }

    345: static PetscErrorCode PetscSectionCheckConstraints_Static(PetscSection s)
    346: {

    350:   if (!s->bc) {
    351:     PetscSectionCreate(PETSC_COMM_SELF, &s->bc);
    352:     PetscSectionSetChart(s->bc, s->pStart, s->pEnd);
    353:   }
    354:   return(0);
    355: }

    359: /*@
    360:   PetscSectionGetChart - Returns the range [pStart, pEnd) in which points in the lie.

    362:   Not collective

    364:   Input Parameter:
    365: . s - the PetscSection

    367:   Output Parameters:
    368: + pStart - the first point
    369: - pEnd - one past the last point

    371:   Level: intermediate

    373: .seealso: PetscSectionSetChart(), PetscSectionCreate()
    374: @*/
    375: PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd)
    376: {
    379:   if (pStart) *pStart = s->pStart;
    380:   if (pEnd)   *pEnd   = s->pEnd;
    381:   return(0);
    382: }

    386: /*@
    387:   PetscSectionSetChart - Sets the range [pStart, pEnd) in which points in the lie.

    389:   Not collective

    391:   Input Parameters:
    392: + s - the PetscSection
    393: . pStart - the first point
    394: - pEnd - one past the last point

    396:   Level: intermediate

    398: .seealso: PetscSectionGetChart(), PetscSectionCreate()
    399: @*/
    400: PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd)
    401: {
    402:   PetscInt       f;

    407:   /* Cannot Reset() because it destroys field information */
    408:   s->setup = PETSC_FALSE;
    409:   PetscSectionDestroy(&s->bc);
    410:   PetscFree(s->bcIndices);
    411:   PetscFree2(s->atlasDof, s->atlasOff);

    413:   s->pStart = pStart;
    414:   s->pEnd   = pEnd;
    415:   PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff);
    416:   PetscMemzero(s->atlasDof, (pEnd - pStart)*sizeof(PetscInt));
    417:   for (f = 0; f < s->numFields; ++f) {
    418:     PetscSectionSetChart(s->field[f], pStart, pEnd);
    419:   }
    420:   return(0);
    421: }

    425: /*@
    426:   PetscSectionGetPermutation - Returns the permutation of [0, pEnd-pStart) or NULL

    428:   Not collective

    430:   Input Parameter:
    431: . s - the PetscSection

    433:   Output Parameters:
    434: . perm - The permutation as an IS

    436:   Level: intermediate

    438: .seealso: PetscSectionSetPermutation(), PetscSectionCreate()
    439: @*/
    440: PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm)
    441: {
    445:   return(0);
    446: }

    450: /*@
    451:   PetscSectionSetPermutation - Sets the permutation for [0, pEnd-pStart)

    453:   Not collective

    455:   Input Parameters:
    456: + s - the PetscSection
    457: - perm - the permutation of points

    459:   Level: intermediate

    461: .seealso: PetscSectionGetPermutation(), PetscSectionCreate()
    462: @*/
    463: PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm)
    464: {

    468:   if (s->setup) SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup");
    469:   if (s->perm != perm) {
    470:     ISDestroy(&s->perm);
    471:     s->perm = perm;
    472:     PetscObjectReference((PetscObject) s->perm);
    473:   }
    474:   return(0);
    475: }

    479: /*@
    480:   PetscSectionGetDof - Return the number of degrees of freedom associated with a given point.

    482:   Not collective

    484:   Input Parameters:
    485: + s - the PetscSection
    486: - point - the point

    488:   Output Parameter:
    489: . numDof - the number of dof

    491:   Level: intermediate

    493: .seealso: PetscSectionSetDof(), PetscSectionCreate()
    494: @*/
    495: PetscErrorCode PetscSectionGetDof(PetscSection s, PetscInt point, PetscInt *numDof)
    496: {
    498: #if defined(PETSC_USE_DEBUG)
    499:   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
    500: #endif
    501:   *numDof = s->atlasDof[point - s->pStart];
    502:   return(0);
    503: }

    507: /*@
    508:   PetscSectionSetDof - Sets the number of degrees of freedom associated with a given point.

    510:   Not collective

    512:   Input Parameters:
    513: + s - the PetscSection
    514: . point - the point
    515: - numDof - the number of dof

    517:   Level: intermediate

    519: .seealso: PetscSectionGetDof(), PetscSectionAddDof(), PetscSectionCreate()
    520: @*/
    521: PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof)
    522: {
    524:   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
    525:   s->atlasDof[point - s->pStart] = numDof;
    526:   return(0);
    527: }

    531: /*@
    532:   PetscSectionAddDof - Adds to the number of degrees of freedom associated with a given point.

    534:   Not collective

    536:   Input Parameters:
    537: + s - the PetscSection
    538: . point - the point
    539: - numDof - the number of additional dof

    541:   Level: intermediate

    543: .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate()
    544: @*/
    545: PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof)
    546: {
    548:   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
    549:   s->atlasDof[point - s->pStart] += numDof;
    550:   return(0);
    551: }

    555: /*@
    556:   PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point.

    558:   Not collective

    560:   Input Parameters:
    561: + s - the PetscSection
    562: . point - the point
    563: - field - the field

    565:   Output Parameter:
    566: . numDof - the number of dof

    568:   Level: intermediate

    570: .seealso: PetscSectionSetFieldDof(), PetscSectionCreate()
    571: @*/
    572: PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
    573: {

    577:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    578:   PetscSectionGetDof(s->field[field], point, numDof);
    579:   return(0);
    580: }

    584: /*@
    585:   PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point.

    587:   Not collective

    589:   Input Parameters:
    590: + s - the PetscSection
    591: . point - the point
    592: . field - the field
    593: - numDof - the number of dof

    595:   Level: intermediate

    597: .seealso: PetscSectionGetFieldDof(), PetscSectionCreate()
    598: @*/
    599: PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
    600: {

    604:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    605:   PetscSectionSetDof(s->field[field], point, numDof);
    606:   return(0);
    607: }

    611: /*@
    612:   PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point.

    614:   Not collective

    616:   Input Parameters:
    617: + s - the PetscSection
    618: . point - the point
    619: . field - the field
    620: - numDof - the number of dof

    622:   Level: intermediate

    624: .seealso: PetscSectionSetFieldDof(), PetscSectionGetFieldDof(), PetscSectionCreate()
    625: @*/
    626: PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
    627: {

    631:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    632:   PetscSectionAddDof(s->field[field], point, numDof);
    633:   return(0);
    634: }

    638: /*@
    639:   PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point.

    641:   Not collective

    643:   Input Parameters:
    644: + s - the PetscSection
    645: - point - the point

    647:   Output Parameter:
    648: . numDof - the number of dof which are fixed by constraints

    650:   Level: intermediate

    652: .seealso: PetscSectionGetDof(), PetscSectionSetConstraintDof(), PetscSectionCreate()
    653: @*/
    654: PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof)
    655: {

    659:   if (s->bc) {
    660:     PetscSectionGetDof(s->bc, point, numDof);
    661:   } else *numDof = 0;
    662:   return(0);
    663: }

    667: /*@
    668:   PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point.

    670:   Not collective

    672:   Input Parameters:
    673: + s - the PetscSection
    674: . point - the point
    675: - numDof - the number of dof which are fixed by constraints

    677:   Level: intermediate

    679: .seealso: PetscSectionSetDof(), PetscSectionGetConstraintDof(), PetscSectionCreate()
    680: @*/
    681: PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
    682: {

    686:   if (numDof) {
    687:     PetscSectionCheckConstraints_Static(s);
    688:     PetscSectionSetDof(s->bc, point, numDof);
    689:   }
    690:   return(0);
    691: }

    695: /*@
    696:   PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point.

    698:   Not collective

    700:   Input Parameters:
    701: + s - the PetscSection
    702: . point - the point
    703: - numDof - the number of additional dof which are fixed by constraints

    705:   Level: intermediate

    707: .seealso: PetscSectionAddDof(), PetscSectionGetConstraintDof(), PetscSectionCreate()
    708: @*/
    709: PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
    710: {

    714:   if (numDof) {
    715:     PetscSectionCheckConstraints_Static(s);
    716:     PetscSectionAddDof(s->bc, point, numDof);
    717:   }
    718:   return(0);
    719: }

    723: /*@
    724:   PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point.

    726:   Not collective

    728:   Input Parameters:
    729: + s - the PetscSection
    730: . point - the point
    731: - field - the field

    733:   Output Parameter:
    734: . numDof - the number of dof which are fixed by constraints

    736:   Level: intermediate

    738: .seealso: PetscSectionGetDof(), PetscSectionSetFieldConstraintDof(), PetscSectionCreate()
    739: @*/
    740: PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
    741: {

    745:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    746:   PetscSectionGetConstraintDof(s->field[field], point, numDof);
    747:   return(0);
    748: }

    752: /*@
    753:   PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point.

    755:   Not collective

    757:   Input Parameters:
    758: + s - the PetscSection
    759: . point - the point
    760: . field - the field
    761: - numDof - the number of dof which are fixed by constraints

    763:   Level: intermediate

    765: .seealso: PetscSectionSetDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate()
    766: @*/
    767: PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
    768: {

    772:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    773:   PetscSectionSetConstraintDof(s->field[field], point, numDof);
    774:   return(0);
    775: }

    779: /*@
    780:   PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point.

    782:   Not collective

    784:   Input Parameters:
    785: + s - the PetscSection
    786: . point - the point
    787: . field - the field
    788: - numDof - the number of additional dof which are fixed by constraints

    790:   Level: intermediate

    792: .seealso: PetscSectionAddDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate()
    793: @*/
    794: PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
    795: {

    799:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    800:   PetscSectionAddConstraintDof(s->field[field], point, numDof);
    801:   return(0);
    802: }

    806: PetscErrorCode PetscSectionSetUpBC(PetscSection s)
    807: {

    811:   if (s->bc) {
    812:     const PetscInt last = (s->bc->pEnd-s->bc->pStart) - 1;

    814:     PetscSectionSetUp(s->bc);
    815:     PetscMalloc1(s->bc->atlasOff[last] + s->bc->atlasDof[last], &s->bcIndices);
    816:   }
    817:   return(0);
    818: }

    822: /*@
    823:   PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point.

    825:   Not collective

    827:   Input Parameter:
    828: . s - the PetscSection

    830:   Level: intermediate

    832: .seealso: PetscSectionCreate()
    833: @*/
    834: PetscErrorCode PetscSectionSetUp(PetscSection s)
    835: {
    836:   const PetscInt *pind   = NULL;
    837:   PetscInt        offset = 0, p, f;
    838:   PetscErrorCode  ierr;

    841:   if (s->setup) return(0);
    842:   s->setup = PETSC_TRUE;
    843:   if (s->perm) {ISGetIndices(s->perm, &pind);}
    844:   for (p = 0; p < s->pEnd - s->pStart; ++p) {
    845:     const PetscInt q = pind ? pind[p] : p;

    847:     s->atlasOff[q] = offset;
    848:     offset        += s->atlasDof[q];
    849:     s->maxDof      = PetscMax(s->maxDof, s->atlasDof[q]);
    850:   }
    851:   PetscSectionSetUpBC(s);
    852:   /* Assume that all fields have the same chart */
    853:   for (p = 0; p < s->pEnd - s->pStart; ++p) {
    854:     const PetscInt q   = pind ? pind[p] : p;
    855:     PetscInt       off = s->atlasOff[q];

    857:     for (f = 0; f < s->numFields; ++f) {
    858:       PetscSection sf = s->field[f];

    860:       sf->atlasOff[q] = off;
    861:       off += sf->atlasDof[q];
    862:     }
    863:   }
    864:   if (s->perm) {ISRestoreIndices(s->perm, &pind);}
    865:   for (f = 0; f < s->numFields; ++f) {
    866:     PetscSectionSetUpBC(s->field[f]);
    867:   }
    868:   return(0);
    869: }

    873: /*@
    874:   PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the chart

    876:   Not collective

    878:   Input Parameters:
    879: . s - the PetscSection

    881:   Output Parameter:
    882: . maxDof - the maximum dof

    884:   Level: intermediate

    886: .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate()
    887: @*/
    888: PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof)
    889: {
    891:   *maxDof = s->maxDof;
    892:   return(0);
    893: }

    897: /*@
    898:   PetscSectionGetStorageSize - Return the size of an array or local Vec capable of holding all the degrees of freedom.

    900:   Not collective

    902:   Input Parameters:
    903: + s - the PetscSection
    904: - point - the point

    906:   Output Parameter:
    907: . size - the size of an array which can hold all the dofs

    909:   Level: intermediate

    911: .seealso: PetscSectionGetOffset(), PetscSectionGetConstrainedStorageSize(), PetscSectionCreate()
    912: @*/
    913: PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size)
    914: {
    915:   PetscInt p, n = 0;

    918:   for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
    919:   *size = n;
    920:   return(0);
    921: }

    925: /*@
    926:   PetscSectionGetConstrainedStorageSize - Return the size of an array or local Vec capable of holding all unconstrained degrees of freedom.

    928:   Not collective

    930:   Input Parameters:
    931: + s - the PetscSection
    932: - point - the point

    934:   Output Parameter:
    935: . size - the size of an array which can hold all unconstrained dofs

    937:   Level: intermediate

    939: .seealso: PetscSectionGetStorageSize(), PetscSectionGetOffset(), PetscSectionCreate()
    940: @*/
    941: PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size)
    942: {
    943:   PetscInt p, n = 0;

    946:   for (p = 0; p < s->pEnd - s->pStart; ++p) {
    947:     const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0;
    948:     n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0;
    949:   }
    950:   *size = n;
    951:   return(0);
    952: }

    956: /*@
    957:   PetscSectionCreateGlobalSection - Create a section describing the global field layout using
    958:   the local section and an SF describing the section point overlap.

    960:   Input Parameters:
    961:   + s - The PetscSection for the local field layout
    962:   . sf - The SF describing parallel layout of the section points (leaves are unowned local points)
    963:   - includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs

    965:   Output Parameter:
    966:   . gsection - The PetscSection for the global field layout

    968:   Note: This gives negative sizes and offsets to points not owned by this process

    970:   Level: developer

    972: .seealso: PetscSectionCreate()
    973: @*/
    974: PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscSection *gsection)
    975: {
    976:   const PetscInt *pind = NULL;
    977:   PetscInt       *recv = NULL, *neg = NULL;
    978:   PetscInt        pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots, nlocal;
    979:   PetscErrorCode  ierr;

    982:   PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);
    983:   PetscSectionGetChart(s, &pStart, &pEnd);
    984:   PetscSectionSetChart(*gsection, pStart, pEnd);
    985:   PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);
    986:   nlocal = nroots;              /* The local/leaf space matches global/root space */
    987:   /* Must allocate for all points visible to SF, which may be more than this section */
    988:   if (nroots >= 0) {             /* nroots < 0 means that the graph has not been set, only happens in serial */
    989:     if (nroots < pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %d < pEnd %d", nroots, pEnd);
    990:     PetscMalloc2(nroots,&neg,nlocal,&recv);
    991:     PetscMemzero(neg,nroots*sizeof(PetscInt));
    992:   }
    993:   /* Mark all local points with negative dof */
    994:   for (p = pStart; p < pEnd; ++p) {
    995:     PetscSectionGetDof(s, p, &dof);
    996:     PetscSectionSetDof(*gsection, p, dof);
    997:     PetscSectionGetConstraintDof(s, p, &cdof);
    998:     if (!includeConstraints && cdof > 0) {PetscSectionSetConstraintDof(*gsection, p, cdof);}
    999:     if (neg) neg[p] = -(dof+1);
    1000:   }
    1001:   PetscSectionSetUpBC(*gsection);
    1002:   if (nroots >= 0) {
    1003:     PetscMemzero(recv,nlocal*sizeof(PetscInt));
    1004:     PetscSFBcastBegin(sf, MPIU_INT, neg, recv);
    1005:     PetscSFBcastEnd(sf, MPIU_INT, neg, recv);
    1006:     for (p = pStart; p < pEnd; ++p) {
    1007:       if (recv[p] < 0) {
    1008:         (*gsection)->atlasDof[p-pStart] = recv[p];
    1009:         PetscSectionGetDof(s, p, &dof);
    1010:         if (-(recv[p]+1) != dof) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is not the unconstrained %d", -(recv[p]+1), p, dof);
    1011:       }
    1012:     }
    1013:   }
    1014:   /* Calculate new sizes, get proccess offset, and calculate point offsets */
    1015:   if (s->perm) {ISGetIndices(s->perm, &pind);}
    1016:   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
    1017:     const PetscInt q = pind ? pind[p] : p;

    1019:     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
    1020:     (*gsection)->atlasOff[q] = off;
    1021:     off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
    1022:   }
    1023:   MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));
    1024:   globalOff -= off;
    1025:   for (p = pStart, off = 0; p < pEnd; ++p) {
    1026:     (*gsection)->atlasOff[p-pStart] += globalOff;
    1027:     if (neg) neg[p] = -((*gsection)->atlasOff[p-pStart]+1);
    1028:   }
    1029:   if (s->perm) {ISRestoreIndices(s->perm, &pind);}
    1030:   /* Put in negative offsets for ghost points */
    1031:   if (nroots >= 0) {
    1032:     PetscMemzero(recv,nlocal*sizeof(PetscInt));
    1033:     PetscSFBcastBegin(sf, MPIU_INT, neg, recv);
    1034:     PetscSFBcastEnd(sf, MPIU_INT, neg, recv);
    1035:     for (p = pStart; p < pEnd; ++p) {
    1036:       if (recv[p] < 0) (*gsection)->atlasOff[p-pStart] = recv[p];
    1037:     }
    1038:   }
    1039:   PetscFree2(neg,recv);
    1040:   PetscSectionViewFromOptions(*gsection,NULL,"-section_global_view");
    1041:   return(0);
    1042: }

    1046: /*@
    1047:   PetscSectionCreateGlobalSectionCensored - Create a section describing the global field layout using
    1048:   the local section and an SF describing the section point overlap.

    1050:   Input Parameters:
    1051:   + s - The PetscSection for the local field layout
    1052:   . sf - The SF describing parallel layout of the section points
    1053:   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
    1054:   . numExcludes - The number of exclusion ranges
    1055:   - excludes - An array [start_0, end_0, start_1, end_1, ...] where there are numExcludes pairs

    1057:   Output Parameter:
    1058:   . gsection - The PetscSection for the global field layout

    1060:   Note: This gives negative sizes and offsets to points not owned by this process

    1062:   Level: developer

    1064: .seealso: PetscSectionCreate()
    1065: @*/
    1066: PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection)
    1067: {
    1068:   const PetscInt *pind = NULL;
    1069:   PetscInt       *neg  = NULL, *tmpOff = NULL;
    1070:   PetscInt        pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
    1071:   PetscErrorCode  ierr;

    1074:   PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);
    1075:   PetscSectionGetChart(s, &pStart, &pEnd);
    1076:   PetscSectionSetChart(*gsection, pStart, pEnd);
    1077:   PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);
    1078:   if (nroots >= 0) {
    1079:     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
    1080:     PetscCalloc1(nroots, &neg);
    1081:     if (nroots > pEnd-pStart) {
    1082:       PetscCalloc1(nroots, &tmpOff);
    1083:     } else {
    1084:       tmpOff = &(*gsection)->atlasDof[-pStart];
    1085:     }
    1086:   }
    1087:   /* Mark ghost points with negative dof */
    1088:   for (p = pStart; p < pEnd; ++p) {
    1089:     for (e = 0; e < numExcludes; ++e) {
    1090:       if ((p >= excludes[e*2+0]) && (p < excludes[e*2+1])) {
    1091:         PetscSectionSetDof(*gsection, p, 0);
    1092:         break;
    1093:       }
    1094:     }
    1095:     if (e < numExcludes) continue;
    1096:     PetscSectionGetDof(s, p, &dof);
    1097:     PetscSectionSetDof(*gsection, p, dof);
    1098:     PetscSectionGetConstraintDof(s, p, &cdof);
    1099:     if (!includeConstraints && cdof > 0) {PetscSectionSetConstraintDof(*gsection, p, cdof);}
    1100:     if (neg) neg[p] = -(dof+1);
    1101:   }
    1102:   PetscSectionSetUpBC(*gsection);
    1103:   if (nroots >= 0) {
    1104:     PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);
    1105:     PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);
    1106:     if (nroots > pEnd - pStart) {
    1107:       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
    1108:     }
    1109:   }
    1110:   /* Calculate new sizes, get proccess offset, and calculate point offsets */
    1111:   if (s->perm) {ISGetIndices(s->perm, &pind);}
    1112:   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
    1113:     const PetscInt q = pind ? pind[p] : p;

    1115:     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
    1116:     (*gsection)->atlasOff[q] = off;
    1117:     off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
    1118:   }
    1119:   MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));
    1120:   globalOff -= off;
    1121:   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
    1122:     (*gsection)->atlasOff[p] += globalOff;
    1123:     if (neg) neg[p+pStart] = -((*gsection)->atlasOff[p]+1);
    1124:   }
    1125:   if (s->perm) {ISRestoreIndices(s->perm, &pind);}
    1126:   /* Put in negative offsets for ghost points */
    1127:   if (nroots >= 0) {
    1128:     if (nroots == pEnd-pStart) tmpOff = &(*gsection)->atlasOff[-pStart];
    1129:     PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);
    1130:     PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);
    1131:     if (nroots > pEnd - pStart) {
    1132:       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
    1133:     }
    1134:   }
    1135:   if (nroots >= 0 && nroots > pEnd-pStart) {PetscFree(tmpOff);}
    1136:   PetscFree(neg);
    1137:   return(0);
    1138: }

    1142: PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
    1143: {
    1144:   PetscInt       pStart, pEnd, p, localSize = 0;

    1148:   PetscSectionGetChart(s, &pStart, &pEnd);
    1149:   for (p = pStart; p < pEnd; ++p) {
    1150:     PetscInt dof;

    1152:     PetscSectionGetDof(s, p, &dof);
    1153:     if (dof > 0) ++localSize;
    1154:   }
    1155:   PetscLayoutCreate(comm, layout);
    1156:   PetscLayoutSetLocalSize(*layout, localSize);
    1157:   PetscLayoutSetBlockSize(*layout, 1);
    1158:   PetscLayoutSetUp(*layout);
    1159:   return(0);
    1160: }

    1164: PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
    1165: {
    1166:   PetscInt       pStart, pEnd, p, localSize = 0;

    1170:   PetscSectionGetChart(s, &pStart, &pEnd);
    1171:   for (p = pStart; p < pEnd; ++p) {
    1172:     PetscInt dof,cdof;

    1174:     PetscSectionGetDof(s, p, &dof);
    1175:     PetscSectionGetConstraintDof(s, p, &cdof);
    1176:     if (dof-cdof > 0) localSize += dof-cdof;
    1177:   }
    1178:   PetscLayoutCreate(comm, layout);
    1179:   PetscLayoutSetLocalSize(*layout, localSize);
    1180:   PetscLayoutSetBlockSize(*layout, 1);
    1181:   PetscLayoutSetUp(*layout);
    1182:   return(0);
    1183: }

    1187: /*@
    1188:   PetscSectionGetOffset - Return the offset into an array or local Vec for the dof associated with the given point.

    1190:   Not collective

    1192:   Input Parameters:
    1193: + s - the PetscSection
    1194: - point - the point

    1196:   Output Parameter:
    1197: . offset - the offset

    1199:   Level: intermediate

    1201: .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate()
    1202: @*/
    1203: PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset)
    1204: {
    1206: #if defined(PETSC_USE_DEBUG)
    1207:   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
    1208: #endif
    1209:   *offset = s->atlasOff[point - s->pStart];
    1210:   return(0);
    1211: }

    1215: /*@
    1216:   PetscSectionSetOffset - Set the offset into an array or local Vec for the dof associated with the given point.

    1218:   Not collective

    1220:   Input Parameters:
    1221: + s - the PetscSection
    1222: . point - the point
    1223: - offset - the offset

    1225:   Note: The user usually does not call this function, but uses PetscSectionSetUp()

    1227:   Level: intermediate

    1229: .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate(), PetscSectionSetUp()
    1230: @*/
    1231: PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset)
    1232: {
    1234:   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
    1235:   s->atlasOff[point - s->pStart] = offset;
    1236:   return(0);
    1237: }

    1241: /*@
    1242:   PetscSectionGetFieldOffset - Return the offset into an array or local Vec for the dof associated with the given point.

    1244:   Not collective

    1246:   Input Parameters:
    1247: + s - the PetscSection
    1248: . point - the point
    1249: - field - the field

    1251:   Output Parameter:
    1252: . offset - the offset

    1254:   Level: intermediate

    1256: .seealso: PetscSectionGetOffset(), PetscSectionCreate()
    1257: @*/
    1258: PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
    1259: {

    1263:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    1264:   PetscSectionGetOffset(s->field[field], point, offset);
    1265:   return(0);
    1266: }

    1270: /*@
    1271:   PetscSectionSetFieldOffset - Set the offset into an array or local Vec for the dof associated with the given point.

    1273:   Not collective

    1275:   Input Parameters:
    1276: + s - the PetscSection
    1277: . point - the point
    1278: . field - the field
    1279: - offset - the offset

    1281:   Note: The user usually does not call this function, but uses PetscSectionSetUp()

    1283:   Level: intermediate

    1285: .seealso: PetscSectionGetOffset(), PetscSectionCreate(), PetscSectionSetUp()
    1286: @*/
    1287: PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset)
    1288: {

    1292:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    1293:   PetscSectionSetOffset(s->field[field], point, offset);
    1294:   return(0);
    1295: }

    1299: /* This gives the offset on a point of the field, ignoring constraints */
    1300: PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
    1301: {
    1302:   PetscInt       off, foff;

    1306:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    1307:   PetscSectionGetOffset(s, point, &off);
    1308:   PetscSectionGetOffset(s->field[field], point, &foff);
    1309:   *offset = foff - off;
    1310:   return(0);
    1311: }

    1315: /*@
    1316:   PetscSectionGetOffsetRange - Return the full range of offsets [start, end)

    1318:   Not collective

    1320:   Input Parameter:
    1321: . s - the PetscSection

    1323:   Output Parameters:
    1324: + start - the minimum offset
    1325: - end   - one more than the maximum offset

    1327:   Level: intermediate

    1329: .seealso: PetscSectionGetOffset(), PetscSectionCreate()
    1330: @*/
    1331: PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end)
    1332: {
    1333:   PetscInt       os = 0, oe = 0, pStart, pEnd, p;

    1337:   if (s->atlasOff) {os = s->atlasOff[0]; oe = s->atlasOff[0];}
    1338:   PetscSectionGetChart(s, &pStart, &pEnd);
    1339:   for (p = 0; p < pEnd-pStart; ++p) {
    1340:     PetscInt dof = s->atlasDof[p], off = s->atlasOff[p];

    1342:     if (off >= 0) {
    1343:       os = PetscMin(os, off);
    1344:       oe = PetscMax(oe, off+dof);
    1345:     }
    1346:   }
    1347:   if (start) *start = os;
    1348:   if (end)   *end   = oe;
    1349:   return(0);
    1350: }

    1354: PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt numFields, PetscInt fields[], PetscSection *subs)
    1355: {
    1356:   PetscInt       nF, f, pStart, pEnd, p, maxCdof = 0;

    1360:   if (!numFields) return(0);
    1361:   PetscSectionGetNumFields(s, &nF);
    1362:   if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of fields %d", numFields, nF);
    1363:   PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);
    1364:   PetscSectionSetNumFields(*subs, numFields);
    1365:   for (f = 0; f < numFields; ++f) {
    1366:     const char *name   = NULL;
    1367:     PetscInt   numComp = 0;

    1369:     PetscSectionGetFieldName(s, fields[f], &name);
    1370:     PetscSectionSetFieldName(*subs, f, name);
    1371:     PetscSectionGetFieldComponents(s, fields[f], &numComp);
    1372:     PetscSectionSetFieldComponents(*subs, f, numComp);
    1373:   }
    1374:   PetscSectionGetChart(s, &pStart, &pEnd);
    1375:   PetscSectionSetChart(*subs, pStart, pEnd);
    1376:   for (p = pStart; p < pEnd; ++p) {
    1377:     PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0;

    1379:     for (f = 0; f < numFields; ++f) {
    1380:       PetscSectionGetFieldDof(s, p, fields[f], &fdof);
    1381:       PetscSectionSetFieldDof(*subs, p, f, fdof);
    1382:       PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof);
    1383:       if (cfdof) {PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof);}
    1384:       dof  += fdof;
    1385:       cdof += cfdof;
    1386:     }
    1387:     PetscSectionSetDof(*subs, p, dof);
    1388:     if (cdof) {PetscSectionSetConstraintDof(*subs, p, cdof);}
    1389:     maxCdof = PetscMax(cdof, maxCdof);
    1390:   }
    1391:   PetscSectionSetUp(*subs);
    1392:   if (maxCdof) {
    1393:     PetscInt *indices;

    1395:     PetscMalloc1(maxCdof, &indices);
    1396:     for (p = pStart; p < pEnd; ++p) {
    1397:       PetscInt cdof;

    1399:       PetscSectionGetConstraintDof(*subs, p, &cdof);
    1400:       if (cdof) {
    1401:         const PetscInt *oldIndices = NULL;
    1402:         PetscInt       fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0;

    1404:         for (f = 0; f < numFields; ++f) {
    1405:           PetscInt oldFoff = 0, oldf;

    1407:           PetscSectionGetFieldDof(s, p, fields[f], &fdof);
    1408:           PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof);
    1409:           PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices);
    1410:           /* This can be sped up if we assume sorted fields */
    1411:           for (oldf = 0; oldf < fields[f]; ++oldf) {
    1412:             PetscInt oldfdof = 0;
    1413:             PetscSectionGetFieldDof(s, p, oldf, &oldfdof);
    1414:             oldFoff += oldfdof;
    1415:           }
    1416:           for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] = oldIndices[fc] + (fOff - oldFoff);
    1417:           PetscSectionSetFieldConstraintIndices(*subs, p, f, &indices[numConst]);
    1418:           numConst += cfdof;
    1419:           fOff     += fdof;
    1420:         }
    1421:         PetscSectionSetConstraintIndices(*subs, p, indices);
    1422:       }
    1423:     }
    1424:     PetscFree(indices);
    1425:   }
    1426:   return(0);
    1427: }

    1431: PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs)
    1432: {
    1433:   const PetscInt *points = NULL, *indices = NULL;
    1434:   PetscInt       numFields, f, numSubpoints = 0, pStart, pEnd, p, subp;

    1438:   PetscSectionGetNumFields(s, &numFields);
    1439:   PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);
    1440:   if (numFields) {PetscSectionSetNumFields(*subs, numFields);}
    1441:   for (f = 0; f < numFields; ++f) {
    1442:     const char *name   = NULL;
    1443:     PetscInt   numComp = 0;

    1445:     PetscSectionGetFieldName(s, f, &name);
    1446:     PetscSectionSetFieldName(*subs, f, name);
    1447:     PetscSectionGetFieldComponents(s, f, &numComp);
    1448:     PetscSectionSetFieldComponents(*subs, f, numComp);
    1449:   }
    1450:   /* For right now, we do not try to squeeze the subchart */
    1451:   if (subpointMap) {
    1452:     ISGetSize(subpointMap, &numSubpoints);
    1453:     ISGetIndices(subpointMap, &points);
    1454:   }
    1455:   PetscSectionGetChart(s, &pStart, &pEnd);
    1456:   PetscSectionSetChart(*subs, 0, numSubpoints);
    1457:   for (p = pStart; p < pEnd; ++p) {
    1458:     PetscInt dof, cdof, fdof = 0, cfdof = 0;

    1460:     PetscFindInt(p, numSubpoints, points, &subp);
    1461:     if (subp < 0) continue;
    1462:     for (f = 0; f < numFields; ++f) {
    1463:       PetscSectionGetFieldDof(s, p, f, &fdof);
    1464:       PetscSectionSetFieldDof(*subs, subp, f, fdof);
    1465:       PetscSectionGetFieldConstraintDof(s, p, f, &cfdof);
    1466:       if (cfdof) {PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof);}
    1467:     }
    1468:     PetscSectionGetDof(s, p, &dof);
    1469:     PetscSectionSetDof(*subs, subp, dof);
    1470:     PetscSectionGetConstraintDof(s, p, &cdof);
    1471:     if (cdof) {PetscSectionSetConstraintDof(*subs, subp, cdof);}
    1472:   }
    1473:   PetscSectionSetUp(*subs);
    1474:   /* Change offsets to original offsets */
    1475:   for (p = pStart; p < pEnd; ++p) {
    1476:     PetscInt off, foff = 0;

    1478:     PetscFindInt(p, numSubpoints, points, &subp);
    1479:     if (subp < 0) continue;
    1480:     for (f = 0; f < numFields; ++f) {
    1481:       PetscSectionGetFieldOffset(s, p, f, &foff);
    1482:       PetscSectionSetFieldOffset(*subs, subp, f, foff);
    1483:     }
    1484:     PetscSectionGetOffset(s, p, &off);
    1485:     PetscSectionSetOffset(*subs, subp, off);
    1486:   }
    1487:   /* Copy constraint indices */
    1488:   for (subp = 0; subp < numSubpoints; ++subp) {
    1489:     PetscInt cdof;

    1491:     PetscSectionGetConstraintDof(*subs, subp, &cdof);
    1492:     if (cdof) {
    1493:       for (f = 0; f < numFields; ++f) {
    1494:         PetscSectionGetFieldConstraintIndices(s, points[subp], f, &indices);
    1495:         PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices);
    1496:       }
    1497:       PetscSectionGetConstraintIndices(s, points[subp], &indices);
    1498:       PetscSectionSetConstraintIndices(*subs, subp, indices);
    1499:     }
    1500:   }
    1501:   if (subpointMap) {ISRestoreIndices(subpointMap, &points);}
    1502:   return(0);
    1503: }

    1507: PetscErrorCode  PetscSectionView_ASCII(PetscSection s, PetscViewer viewer)
    1508: {
    1509:   PetscInt       p;
    1510:   PetscMPIInt    rank;

    1514:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
    1515:   PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);
    1516:   PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);
    1517:   for (p = 0; p < s->pEnd - s->pStart; ++p) {
    1518:     if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
    1519:       PetscInt b;

    1521:       PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d constrained", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);
    1522:       for (b = 0; b < s->bc->atlasDof[p]; ++b) {
    1523:         PetscViewerASCIISynchronizedPrintf(viewer, " %d", s->bcIndices[s->bc->atlasOff[p]+b]);
    1524:       }
    1525:       PetscViewerASCIISynchronizedPrintf(viewer, "\n");
    1526:     } else {
    1527:       PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d\n", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);
    1528:     }
    1529:   }
    1530:   PetscViewerFlush(viewer);
    1531:   return(0);
    1532: }

    1536: /*@C
    1537:   PetscSectionView - Views a PetscSection

    1539:   Collective on PetscSection

    1541:   Input Parameters:
    1542: + s - the PetscSection object to view
    1543: - v - the viewer

    1545:   Level: developer

    1547: .seealso PetscSectionCreate(), PetscSectionDestroy()
    1548: @*/
    1549: PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer)
    1550: {
    1551:   PetscBool      isascii;
    1552:   PetscInt       f;

    1556:   if (!viewer) {PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer);}
    1558:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);
    1559:   if (isascii) {
    1560:     PetscObjectPrintClassNamePrefixType((PetscObject)s,viewer);
    1561:     if (s->numFields) {
    1562:       PetscViewerASCIIPrintf(viewer, "%D fields\n", s->numFields);
    1563:       for (f = 0; f < s->numFields; ++f) {
    1564:         PetscViewerASCIIPrintf(viewer, "  field %D with %D components\n", f, s->numFieldComponents[f]);
    1565:         PetscSectionView_ASCII(s->field[f], viewer);
    1566:       }
    1567:     } else {
    1568:       PetscSectionView_ASCII(s, viewer);
    1569:     }
    1570:   }
    1571:   return(0);
    1572: }

    1576: /*@
    1577:   PetscSectionReset - Frees all section data.

    1579:   Not collective

    1581:   Input Parameters:
    1582: . s - the PetscSection

    1584:   Level: developer

    1586: .seealso: PetscSection, PetscSectionCreate()
    1587: @*/
    1588: PetscErrorCode PetscSectionReset(PetscSection s)
    1589: {
    1590:   PetscInt       f;

    1594:   PetscFree(s->numFieldComponents);
    1595:   for (f = 0; f < s->numFields; ++f) {
    1596:     PetscSectionDestroy(&s->field[f]);
    1597:     PetscFree(s->fieldNames[f]);
    1598:   }
    1599:   PetscFree(s->fieldNames);
    1600:   PetscFree(s->field);
    1601:   PetscSectionDestroy(&s->bc);
    1602:   PetscFree(s->bcIndices);
    1603:   PetscFree2(s->atlasDof, s->atlasOff);
    1604:   PetscSectionDestroy(&s->clSection);
    1605:   ISDestroy(&s->clPoints);
    1606:   ISDestroy(&s->perm);

    1608:   s->pStart    = -1;
    1609:   s->pEnd      = -1;
    1610:   s->maxDof    = 0;
    1611:   s->setup     = PETSC_FALSE;
    1612:   s->numFields = 0;
    1613:   s->clObj     = NULL;
    1614:   return(0);
    1615: }

    1619: /*@
    1620:   PetscSectionDestroy - Frees a section object and frees its range if that exists.

    1622:   Not collective

    1624:   Input Parameters:
    1625: . s - the PetscSection

    1627:   Level: developer

    1629:     The PetscSection object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
    1630:     recommended they not be used in user codes unless you really gain something in their use.

    1632: .seealso: PetscSection, PetscSectionCreate()
    1633: @*/
    1634: PetscErrorCode PetscSectionDestroy(PetscSection *s)
    1635: {

    1639:   if (!*s) return(0);
    1641:   if (--((PetscObject)(*s))->refct > 0) {
    1642:     *s = NULL;
    1643:     return(0);
    1644:   }
    1645:   PetscSectionReset(*s);
    1646:   PetscHeaderDestroy(s);
    1647:   return(0);
    1648: }

    1652: PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values)
    1653: {
    1654:   const PetscInt p = point - s->pStart;

    1657:   *values = &baseArray[s->atlasOff[p]];
    1658:   return(0);
    1659: }

    1663: PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode)
    1664: {
    1665:   PetscInt       *array;
    1666:   const PetscInt p           = point - s->pStart;
    1667:   const PetscInt orientation = 0; /* Needs to be included for use in closure operations */
    1668:   PetscInt       cDim        = 0;

    1672:   PetscSectionGetConstraintDof(s, p, &cDim);
    1673:   array = &baseArray[s->atlasOff[p]];
    1674:   if (!cDim) {
    1675:     if (orientation >= 0) {
    1676:       const PetscInt dim = s->atlasDof[p];
    1677:       PetscInt       i;

    1679:       if (mode == INSERT_VALUES) {
    1680:         for (i = 0; i < dim; ++i) array[i] = values[i];
    1681:       } else {
    1682:         for (i = 0; i < dim; ++i) array[i] += values[i];
    1683:       }
    1684:     } else {
    1685:       PetscInt offset = 0;
    1686:       PetscInt j      = -1, field, i;

    1688:       for (field = 0; field < s->numFields; ++field) {
    1689:         const PetscInt dim = s->field[field]->atlasDof[p];

    1691:         for (i = dim-1; i >= 0; --i) array[++j] = values[i+offset];
    1692:         offset += dim;
    1693:       }
    1694:     }
    1695:   } else {
    1696:     if (orientation >= 0) {
    1697:       const PetscInt dim  = s->atlasDof[p];
    1698:       PetscInt       cInd = 0, i;
    1699:       const PetscInt *cDof;

    1701:       PetscSectionGetConstraintIndices(s, point, &cDof);
    1702:       if (mode == INSERT_VALUES) {
    1703:         for (i = 0; i < dim; ++i) {
    1704:           if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
    1705:           array[i] = values[i];
    1706:         }
    1707:       } else {
    1708:         for (i = 0; i < dim; ++i) {
    1709:           if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
    1710:           array[i] += values[i];
    1711:         }
    1712:       }
    1713:     } else {
    1714:       const PetscInt *cDof;
    1715:       PetscInt       offset  = 0;
    1716:       PetscInt       cOffset = 0;
    1717:       PetscInt       j       = 0, field;

    1719:       PetscSectionGetConstraintIndices(s, point, &cDof);
    1720:       for (field = 0; field < s->numFields; ++field) {
    1721:         const PetscInt dim  = s->field[field]->atlasDof[p];     /* PetscSectionGetFieldDof() */
    1722:         const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */
    1723:         const PetscInt sDim = dim - tDim;
    1724:         PetscInt       cInd = 0, i,k;

    1726:         for (i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
    1727:           if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
    1728:           array[j] = values[k];
    1729:         }
    1730:         offset  += dim;
    1731:         cOffset += dim - tDim;
    1732:       }
    1733:     }
    1734:   }
    1735:   return(0);
    1736: }

    1740: PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints)
    1741: {
    1745:   *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE;
    1746:   return(0);
    1747: }

    1751: /*@C
    1752:   PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained

    1754:   Input Parameters:
    1755: + s     - The PetscSection
    1756: - point - The point

    1758:   Output Parameter:
    1759: . indices - The constrained dofs

    1761:   Note: In Fortran, you call PetscSectionGetConstraintIndicesF90() and PetscSectionRestoreConstraintIndicesF90()

    1763:   Level: advanced

    1765: .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
    1766: @*/
    1767: PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices)
    1768: {

    1772:   if (s->bc) {
    1773:     VecIntGetValuesSection(s->bcIndices, s->bc, point, indices);
    1774:   } else *indices = NULL;
    1775:   return(0);
    1776: }

    1780: /*@C
    1781:   PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained

    1783:   Input Parameters:
    1784: + s     - The PetscSection
    1785: . point - The point
    1786: - indices - The constrained dofs

    1788:   Note: The Fortran is PetscSectionSetConstraintIndicesF90()

    1790:   Level: advanced

    1792: .seealso: PetscSectionGetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
    1793: @*/
    1794: PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[])
    1795: {

    1799:   if (s->bc) {
    1800:     VecIntSetValuesSection(s->bcIndices, s->bc, point, indices, INSERT_VALUES);
    1801:   }
    1802:   return(0);
    1803: }

    1807: PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices)
    1808: {

    1812:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    1813:   PetscSectionGetConstraintIndices(s->field[field], point, indices);
    1814:   return(0);
    1815: }

    1819: PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[])
    1820: {

    1824:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    1825:   PetscSectionSetConstraintIndices(s->field[field], point, indices);
    1826:   return(0);
    1827: }

    1831: /*@
    1832:   PetscSectionPermute - Reorder the section according to the input point permutation

    1834:   Collective on PetscSection

    1836:   Input Parameter:
    1837: + section - The PetscSection object
    1838: - perm - The point permutation, old point p becomes new point perm[p]

    1840:   Output Parameter:
    1841: . sectionNew - The permuted PetscSection

    1843:   Level: intermediate

    1845: .keywords: mesh
    1846: .seealso: MatPermute()
    1847: @*/
    1848: PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew)
    1849: {
    1850:   PetscSection    s = section, sNew;
    1851:   const PetscInt *perm;
    1852:   PetscInt        numFields, f, numPoints, pStart, pEnd, p;
    1853:   PetscErrorCode  ierr;

    1859:   PetscSectionCreate(PetscObjectComm((PetscObject) s), &sNew);
    1860:   PetscSectionGetNumFields(s, &numFields);
    1861:   if (numFields) {PetscSectionSetNumFields(sNew, numFields);}
    1862:   for (f = 0; f < numFields; ++f) {
    1863:     const char *name;
    1864:     PetscInt    numComp;

    1866:     PetscSectionGetFieldName(s, f, &name);
    1867:     PetscSectionSetFieldName(sNew, f, name);
    1868:     PetscSectionGetFieldComponents(s, f, &numComp);
    1869:     PetscSectionSetFieldComponents(sNew, f, numComp);
    1870:   }
    1871:   ISGetLocalSize(permutation, &numPoints);
    1872:   ISGetIndices(permutation, &perm);
    1873:   PetscSectionGetChart(s, &pStart, &pEnd);
    1874:   PetscSectionSetChart(sNew, pStart, pEnd);
    1875:   if (numPoints < pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %d is less than largest Section point %d", numPoints, pEnd);
    1876:   for (p = pStart; p < pEnd; ++p) {
    1877:     PetscInt dof, cdof;

    1879:     PetscSectionGetDof(s, p, &dof);
    1880:     PetscSectionSetDof(sNew, perm[p], dof);
    1881:     PetscSectionGetConstraintDof(s, p, &cdof);
    1882:     if (cdof) {PetscSectionSetConstraintDof(sNew, perm[p], cdof);}
    1883:     for (f = 0; f < numFields; ++f) {
    1884:       PetscSectionGetFieldDof(s, p, f, &dof);
    1885:       PetscSectionSetFieldDof(sNew, perm[p], f, dof);
    1886:       PetscSectionGetFieldConstraintDof(s, p, f, &cdof);
    1887:       if (cdof) {PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof);}
    1888:     }
    1889:   }
    1890:   PetscSectionSetUp(sNew);
    1891:   for (p = pStart; p < pEnd; ++p) {
    1892:     const PetscInt *cind;
    1893:     PetscInt        cdof;

    1895:     PetscSectionGetConstraintDof(s, p, &cdof);
    1896:     if (cdof) {
    1897:       PetscSectionGetConstraintIndices(s, p, &cind);
    1898:       PetscSectionSetConstraintIndices(sNew, perm[p], cind);
    1899:     }
    1900:     for (f = 0; f < numFields; ++f) {
    1901:       PetscSectionGetFieldConstraintDof(s, p, f, &cdof);
    1902:       if (cdof) {
    1903:         PetscSectionGetFieldConstraintIndices(s, p, f, &cind);
    1904:         PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind);
    1905:       }
    1906:     }
    1907:   }
    1908:   ISRestoreIndices(permutation, &perm);
    1909:   *sectionNew = sNew;
    1910:   return(0);
    1911: }

    1915: /*@C
    1916:   PetscSFDistributeSection - Create a new PetscSection reorganized, moving from the root to the leaves of the SF

    1918:   Collective

    1920:   Input Parameters:
    1921: + sf - The SF
    1922: - rootSection - Section defined on root space

    1924:   Output Parameters:
    1925: + remoteOffsets - root offsets in leaf storage, or NULL
    1926: - leafSection - Section defined on the leaf space

    1928:   Level: intermediate

    1930: .seealso: PetscSFCreate()
    1931: @*/
    1932: PetscErrorCode PetscSFDistributeSection(PetscSF sf, PetscSection rootSection, PetscInt **remoteOffsets, PetscSection leafSection)
    1933: {
    1934:   PetscSF        embedSF;
    1935:   const PetscInt *ilocal, *indices;
    1936:   IS             selected;
    1937:   PetscInt       numFields, nleaves, rpStart, rpEnd, lpStart = PETSC_MAX_INT, lpEnd = -1, i, f;

    1941:   PetscSectionGetNumFields(rootSection, &numFields);
    1942:   if (numFields) {PetscSectionSetNumFields(leafSection, numFields);}
    1943:   for (f = 0; f < numFields; ++f) {
    1944:     PetscInt numComp = 0;
    1945:     PetscSectionGetFieldComponents(rootSection, f, &numComp);
    1946:     PetscSectionSetFieldComponents(leafSection, f, numComp);
    1947:   }
    1948:   PetscSectionGetChart(rootSection, &rpStart, &rpEnd);
    1949:   ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected);
    1950:   ISGetIndices(selected, &indices);
    1951:   PetscSFCreateEmbeddedSF(sf, rpEnd - rpStart, indices, &embedSF);
    1952:   ISRestoreIndices(selected, &indices);
    1953:   ISDestroy(&selected);
    1954:   PetscSFGetGraph(embedSF, NULL, &nleaves, &ilocal, NULL);
    1955:   if (nleaves && ilocal) {
    1956:     for (i = 0; i < nleaves; ++i) {
    1957:       lpStart = PetscMin(lpStart, ilocal[i]);
    1958:       lpEnd   = PetscMax(lpEnd,   ilocal[i]);
    1959:     }
    1960:     ++lpEnd;
    1961:   } else {
    1962:     lpStart = 0;
    1963:     lpEnd   = nleaves;
    1964:   }
    1965:   PetscSectionSetChart(leafSection, lpStart, lpEnd);
    1966:   /* Could fuse these at the cost of a copy and extra allocation */
    1967:   PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart]);
    1968:   PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart]);
    1969:   for (f = 0; f < numFields; ++f) {
    1970:     PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart]);
    1971:     PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart]);
    1972:   }
    1973:   if (remoteOffsets) {
    1974:     PetscMalloc1(lpEnd - lpStart, remoteOffsets);
    1975:     PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
    1976:     PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
    1977:   }
    1978:   PetscSFDestroy(&embedSF);
    1979:   PetscSectionSetUp(leafSection);
    1980:   return(0);
    1981: }

    1985: PetscErrorCode PetscSFCreateRemoteOffsets(PetscSF sf, PetscSection rootSection, PetscSection leafSection, PetscInt **remoteOffsets)
    1986: {
    1987:   PetscSF         embedSF;
    1988:   const PetscInt *indices;
    1989:   IS              selected;
    1990:   PetscInt        numRoots, rpStart = 0, rpEnd = 0, lpStart = 0, lpEnd = 0;
    1991:   PetscErrorCode  ierr;

    1994:   *remoteOffsets = NULL;
    1995:   PetscSFGetGraph(sf, &numRoots, NULL, NULL, NULL);
    1996:   if (numRoots < 0) return(0);
    1997:   PetscSectionGetChart(rootSection, &rpStart, &rpEnd);
    1998:   PetscSectionGetChart(leafSection, &lpStart, &lpEnd);
    1999:   ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected);
    2000:   ISGetIndices(selected, &indices);
    2001:   PetscSFCreateEmbeddedSF(sf, rpEnd - rpStart, indices, &embedSF);
    2002:   ISRestoreIndices(selected, &indices);
    2003:   ISDestroy(&selected);
    2004:   PetscCalloc1(lpEnd - lpStart, remoteOffsets);
    2005:   PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
    2006:   PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
    2007:   PetscSFDestroy(&embedSF);
    2008:   return(0);
    2009: }

    2013: /*@C
    2014:   PetscSFCreateSectionSF - Create an expanded SF of dofs, assuming the input SF relates points

    2016:   Input Parameters:
    2017: + sf - The SF
    2018: . rootSection - Data layout of remote points for outgoing data (this is usually the serial section), or NULL
    2019: - remoteOffsets - Offsets for point data on remote processes (these are offsets from the root section), or NULL

    2021:   Output Parameters:
    2022: + leafSection - Data layout of local points for incoming data  (this is the distributed section)
    2023: - sectionSF - The new SF

    2025:   Note: Either rootSection or remoteOffsets can be specified

    2027:   Level: intermediate

    2029: .seealso: PetscSFCreate()
    2030: @*/
    2031: PetscErrorCode PetscSFCreateSectionSF(PetscSF sf, PetscSection rootSection, PetscInt remoteOffsets[], PetscSection leafSection, PetscSF *sectionSF)
    2032: {
    2033:   MPI_Comm          comm;
    2034:   const PetscInt    *localPoints;
    2035:   const PetscSFNode *remotePoints;
    2036:   PetscInt          lpStart, lpEnd;
    2037:   PetscInt          numRoots, numSectionRoots, numPoints, numIndices = 0;
    2038:   PetscInt          *localIndices;
    2039:   PetscSFNode       *remoteIndices;
    2040:   PetscInt          i, ind;
    2041:   PetscErrorCode    ierr;

    2049:   PetscObjectGetComm((PetscObject)sf,&comm);
    2050:   PetscSFCreate(comm, sectionSF);
    2051:   PetscSectionGetChart(leafSection, &lpStart, &lpEnd);
    2052:   PetscSectionGetStorageSize(rootSection, &numSectionRoots);
    2053:   PetscSFGetGraph(sf, &numRoots, &numPoints, &localPoints, &remotePoints);
    2054:   if (numRoots < 0) return(0);
    2055:   for (i = 0; i < numPoints; ++i) {
    2056:     PetscInt localPoint = localPoints ? localPoints[i] : i;
    2057:     PetscInt dof;

    2059:     if ((localPoint >= lpStart) && (localPoint < lpEnd)) {
    2060:       PetscSectionGetDof(leafSection, localPoint, &dof);
    2061:       numIndices += dof;
    2062:     }
    2063:   }
    2064:   PetscMalloc1(numIndices, &localIndices);
    2065:   PetscMalloc1(numIndices, &remoteIndices);
    2066:   /* Create new index graph */
    2067:   for (i = 0, ind = 0; i < numPoints; ++i) {
    2068:     PetscInt localPoint = localPoints ? localPoints[i] : i;
    2069:     PetscInt rank       = remotePoints[i].rank;

    2071:     if ((localPoint >= lpStart) && (localPoint < lpEnd)) {
    2072:       PetscInt remoteOffset = remoteOffsets[localPoint-lpStart];
    2073:       PetscInt loff, dof, d;

    2075:       PetscSectionGetOffset(leafSection, localPoint, &loff);
    2076:       PetscSectionGetDof(leafSection, localPoint, &dof);
    2077:       for (d = 0; d < dof; ++d, ++ind) {
    2078:         localIndices[ind]        = loff+d;
    2079:         remoteIndices[ind].rank  = rank;
    2080:         remoteIndices[ind].index = remoteOffset+d;
    2081:       }
    2082:     }
    2083:   }
    2084:   PetscFree(remoteOffsets);
    2085:   if (numIndices != ind) SETERRQ2(comm, PETSC_ERR_PLIB, "Inconsistency in indices, %d should be %d", ind, numIndices);
    2086:   PetscSFSetGraph(*sectionSF, numSectionRoots, numIndices, localIndices, PETSC_OWN_POINTER, remoteIndices, PETSC_OWN_POINTER);
    2087:   return(0);
    2088: }

    2092: /*@
    2093:   PetscSectionSetClosureIndex - Set a cache of points in the closure of each point in the section

    2095:   Input Parameters:
    2096: + section   - The PetscSection
    2097: . obj       - A PetscObject which serves as the key for this index
    2098: . clSection - Section giving the size of the closure of each point
    2099: - clPoints  - IS giving the points in each closure

    2101:   Note: We compress out closure points with no dofs in this section

    2103:   Level: intermediate

    2105: .seealso: PetscSectionGetClosureIndex(), DMPlexCreateClosureIndex()
    2106: @*/
    2107: PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints)
    2108: {

    2112:   section->clObj     = obj;
    2113:   PetscSectionDestroy(&section->clSection);
    2114:   ISDestroy(&section->clPoints);
    2115:   section->clSection = clSection;
    2116:   section->clPoints  = clPoints;
    2117:   return(0);
    2118: }

    2122: /*@
    2123:   PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section

    2125:   Input Parameters:
    2126: + section   - The PetscSection
    2127: - obj       - A PetscObject which serves as the key for this index

    2129:   Output Parameters:
    2130: + clSection - Section giving the size of the closure of each point
    2131: - clPoints  - IS giving the points in each closure

    2133:   Note: We compress out closure points with no dofs in this section

    2135:   Level: intermediate

    2137: .seealso: PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex()
    2138: @*/
    2139: PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints)
    2140: {
    2142:   if (section->clObj == obj) {
    2143:     if (clSection) *clSection = section->clSection;
    2144:     if (clPoints)  *clPoints  = section->clPoints;
    2145:   } else {
    2146:     if (clSection) *clSection = NULL;
    2147:     if (clPoints)  *clPoints  = NULL;
    2148:   }
    2149:   return(0);
    2150: }

    2154: /*@
    2155:   PetscSectionGetField - Get the subsection associated with a single field

    2157:   Input Parameters:
    2158: + s     - The PetscSection
    2159: - field - The field number

    2161:   Output Parameter:
    2162: . subs  - The subsection for the given field

    2164:   Level: intermediate

    2166: .seealso: PetscSectionSetNumFields()
    2167: @*/
    2168: PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs)
    2169: {

    2175:   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
    2176:   PetscObjectReference((PetscObject) s->field[field]);
    2177:   *subs = s->field[field];
    2178:   return(0);
    2179: }