xref: /petsc/src/vec/is/section/interface/section.c (revision 40196513abc1c283dec5d376af352f834a500ea9)
1ea844a1aSMatthew Knepley /*
2ea844a1aSMatthew Knepley    This file contains routines for basic section object implementation.
3ea844a1aSMatthew Knepley */
4ea844a1aSMatthew Knepley 
5ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h> /*I  "petscsection.h"   I*/
6ea844a1aSMatthew Knepley #include <petscsf.h>
7ea844a1aSMatthew Knepley 
8ea844a1aSMatthew Knepley PetscClassId PETSC_SECTION_CLASSID;
9ea844a1aSMatthew Knepley 
10ea844a1aSMatthew Knepley /*@
1120662ed9SBarry Smith   PetscSectionCreate - Allocates a `PetscSection` and sets the map contents to the default.
12ea844a1aSMatthew Knepley 
13ea844a1aSMatthew Knepley   Collective
14ea844a1aSMatthew Knepley 
15ea844a1aSMatthew Knepley   Input Parameters:
16ea844a1aSMatthew Knepley + comm - the MPI communicator
17ea844a1aSMatthew Knepley - s    - pointer to the section
18ea844a1aSMatthew Knepley 
19ea844a1aSMatthew Knepley   Level: beginner
20ea844a1aSMatthew Knepley 
21ea844a1aSMatthew Knepley   Notes:
22ea844a1aSMatthew Knepley   Typical calling sequence
23cab54364SBarry Smith .vb
24cab54364SBarry Smith        PetscSectionCreate(MPI_Comm,PetscSection *);!
25cab54364SBarry Smith        PetscSectionSetNumFields(PetscSection, numFields);
26cab54364SBarry Smith        PetscSectionSetChart(PetscSection,low,high);
27cab54364SBarry Smith        PetscSectionSetDof(PetscSection,point,numdof);
28cab54364SBarry Smith        PetscSectionSetUp(PetscSection);
29cab54364SBarry Smith        PetscSectionGetOffset(PetscSection,point,PetscInt *);
30cab54364SBarry Smith        PetscSectionDestroy(PetscSection);
31cab54364SBarry Smith .ve
32ea844a1aSMatthew Knepley 
3335cb6cd3SPierre Jolivet   The `PetscSection` object and methods are intended to be used in the PETSc `Vec` and `Mat` implementations. The indices returned by the `PetscSection` are appropriate for the kind of `Vec` it is associated with. For example, if the vector being indexed is a local vector, we call the section a local section. If the section indexes a global vector, we call it a global section. For parallel vectors, like global vectors, we use negative indices to indicate dofs owned by other processes.
34ea844a1aSMatthew Knepley 
35583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetChart()`, `PetscSectionDestroy()`, `PetscSectionCreateGlobalSection()`
36ea844a1aSMatthew Knepley @*/
37d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreate(MPI_Comm comm, PetscSection *s)
38d71ae5a4SJacob Faibussowitsch {
39ea844a1aSMatthew Knepley   PetscFunctionBegin;
404f572ea9SToby Isaac   PetscAssertPointer(s, 2);
419566063dSJacob Faibussowitsch   PetscCall(ISInitializePackage());
42ea844a1aSMatthew Knepley 
439566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*s, PETSC_SECTION_CLASSID, "PetscSection", "Section", "IS", comm, PetscSectionDestroy, PetscSectionView));
44ea844a1aSMatthew Knepley 
45ea844a1aSMatthew Knepley   (*s)->pStart              = -1;
46ea844a1aSMatthew Knepley   (*s)->pEnd                = -1;
47ea844a1aSMatthew Knepley   (*s)->perm                = NULL;
48ea844a1aSMatthew Knepley   (*s)->pointMajor          = PETSC_TRUE;
4987e637c6Sksagiyam   (*s)->includesConstraints = PETSC_TRUE;
50ea844a1aSMatthew Knepley   (*s)->atlasDof            = NULL;
51ea844a1aSMatthew Knepley   (*s)->atlasOff            = NULL;
52ea844a1aSMatthew Knepley   (*s)->bc                  = NULL;
53ea844a1aSMatthew Knepley   (*s)->bcIndices           = NULL;
54ea844a1aSMatthew Knepley   (*s)->setup               = PETSC_FALSE;
55ea844a1aSMatthew Knepley   (*s)->numFields           = 0;
56ea844a1aSMatthew Knepley   (*s)->fieldNames          = NULL;
57ea844a1aSMatthew Knepley   (*s)->field               = NULL;
58ea844a1aSMatthew Knepley   (*s)->useFieldOff         = PETSC_FALSE;
59b778fa18SValeria Barra   (*s)->compNames           = NULL;
60ea844a1aSMatthew Knepley   (*s)->clObj               = NULL;
61c459fbc1SJed Brown   (*s)->clHash              = NULL;
62ea844a1aSMatthew Knepley   (*s)->clSection           = NULL;
63ea844a1aSMatthew Knepley   (*s)->clPoints            = NULL;
6469c11d05SVaclav Hapla   PetscCall(PetscSectionInvalidateMaxDof_Internal(*s));
653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66ea844a1aSMatthew Knepley }
67ea844a1aSMatthew Knepley 
68ea844a1aSMatthew Knepley /*@
69cab54364SBarry Smith   PetscSectionCopy - Creates a shallow (if possible) copy of the `PetscSection`
70ea844a1aSMatthew Knepley 
71ea844a1aSMatthew Knepley   Collective
72ea844a1aSMatthew Knepley 
73ea844a1aSMatthew Knepley   Input Parameter:
74cab54364SBarry Smith . section - the `PetscSection`
75ea844a1aSMatthew Knepley 
76ea844a1aSMatthew Knepley   Output Parameter:
77ea844a1aSMatthew Knepley . newSection - the copy
78ea844a1aSMatthew Knepley 
79ea844a1aSMatthew Knepley   Level: intermediate
80ea844a1aSMatthew Knepley 
8138b5cf2dSJacob Faibussowitsch   Developer Notes:
82cab54364SBarry Smith   What exactly does shallow mean in this context?
83cab54364SBarry Smith 
84cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`
85ea844a1aSMatthew Knepley @*/
86d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCopy(PetscSection section, PetscSection newSection)
87d71ae5a4SJacob Faibussowitsch {
88ea844a1aSMatthew Knepley   PetscSectionSym sym;
89ea844a1aSMatthew Knepley   IS              perm;
90b778fa18SValeria Barra   PetscInt        numFields, f, c, pStart, pEnd, p;
91ea844a1aSMatthew Knepley 
92ea844a1aSMatthew Knepley   PetscFunctionBegin;
93ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
94ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(newSection, PETSC_SECTION_CLASSID, 2);
959566063dSJacob Faibussowitsch   PetscCall(PetscSectionReset(newSection));
969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
979566063dSJacob Faibussowitsch   if (numFields) PetscCall(PetscSectionSetNumFields(newSection, numFields));
98ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
99b778fa18SValeria Barra     const char *fieldName = NULL, *compName = NULL;
100ea844a1aSMatthew Knepley     PetscInt    numComp = 0;
101ea844a1aSMatthew Knepley 
1029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
1039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldName(newSection, f, fieldName));
1049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
1059566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(newSection, f, numComp));
106b778fa18SValeria Barra     for (c = 0; c < numComp; ++c) {
1079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetComponentName(section, f, c, &compName));
1089566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetComponentName(newSection, f, c, compName));
109b778fa18SValeria Barra     }
1109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldSym(section, f, &sym));
1119566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldSym(newSection, f, sym));
112ea844a1aSMatthew Knepley   }
1139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(newSection, pStart, pEnd));
1159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPermutation(section, &perm));
1169566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetPermutation(newSection, perm));
1179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetSym(section, &sym));
1189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetSym(newSection, sym));
119ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
120ea844a1aSMatthew Knepley     PetscInt dof, cdof, fcdof = 0;
121ea844a1aSMatthew Knepley 
1229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, p, &dof));
1239566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(newSection, p, dof));
1249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
1259566063dSJacob Faibussowitsch     if (cdof) PetscCall(PetscSectionSetConstraintDof(newSection, p, cdof));
126ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
1279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
1289566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(newSection, p, f, dof));
129ea844a1aSMatthew Knepley       if (cdof) {
1309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
1319566063dSJacob Faibussowitsch         if (fcdof) PetscCall(PetscSectionSetFieldConstraintDof(newSection, p, f, fcdof));
132ea844a1aSMatthew Knepley       }
133ea844a1aSMatthew Knepley     }
134ea844a1aSMatthew Knepley   }
1359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(newSection));
136ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
137ea844a1aSMatthew Knepley     PetscInt        off, cdof, fcdof = 0;
138ea844a1aSMatthew Knepley     const PetscInt *cInd;
139ea844a1aSMatthew Knepley 
140ea844a1aSMatthew Knepley     /* Must set offsets in case they do not agree with the prefix sums */
1419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, p, &off));
1429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetOffset(newSection, p, off));
1439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
144ea844a1aSMatthew Knepley     if (cdof) {
1459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintIndices(section, p, &cInd));
1469566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetConstraintIndices(newSection, p, cInd));
147ea844a1aSMatthew Knepley       for (f = 0; f < numFields; ++f) {
1489566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
149ea844a1aSMatthew Knepley         if (fcdof) {
1509566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintIndices(section, p, f, &cInd));
1519566063dSJacob Faibussowitsch           PetscCall(PetscSectionSetFieldConstraintIndices(newSection, p, f, cInd));
152ea844a1aSMatthew Knepley         }
153ea844a1aSMatthew Knepley       }
154ea844a1aSMatthew Knepley     }
155ea844a1aSMatthew Knepley   }
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
157ea844a1aSMatthew Knepley }
158ea844a1aSMatthew Knepley 
159ea844a1aSMatthew Knepley /*@
160cab54364SBarry Smith   PetscSectionClone - Creates a shallow (if possible) copy of the `PetscSection`
161ea844a1aSMatthew Knepley 
162ea844a1aSMatthew Knepley   Collective
163ea844a1aSMatthew Knepley 
164ea844a1aSMatthew Knepley   Input Parameter:
165cab54364SBarry Smith . section - the `PetscSection`
166ea844a1aSMatthew Knepley 
167ea844a1aSMatthew Knepley   Output Parameter:
168ea844a1aSMatthew Knepley . newSection - the copy
169ea844a1aSMatthew Knepley 
170ea844a1aSMatthew Knepley   Level: beginner
171ea844a1aSMatthew Knepley 
17238b5cf2dSJacob Faibussowitsch   Developer Notes:
173cab54364SBarry Smith   With standard PETSc terminology this should be called `PetscSectionDuplicate()`
174cab54364SBarry Smith 
175cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionCopy()`
176ea844a1aSMatthew Knepley @*/
177d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection)
178d71ae5a4SJacob Faibussowitsch {
179ea844a1aSMatthew Knepley   PetscFunctionBegin;
180ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
1814f572ea9SToby Isaac   PetscAssertPointer(newSection, 2);
1829566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), newSection));
1839566063dSJacob Faibussowitsch   PetscCall(PetscSectionCopy(section, *newSection));
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185ea844a1aSMatthew Knepley }
186ea844a1aSMatthew Knepley 
187ea844a1aSMatthew Knepley /*@
188cab54364SBarry Smith   PetscSectionSetFromOptions - sets parameters in a `PetscSection` from the options database
189ea844a1aSMatthew Knepley 
19040750d41SVaclav Hapla   Collective
191ea844a1aSMatthew Knepley 
192ea844a1aSMatthew Knepley   Input Parameter:
19338b5cf2dSJacob Faibussowitsch . s - the `PetscSection`
194ea844a1aSMatthew Knepley 
19520662ed9SBarry Smith   Options Database Key:
196cab54364SBarry Smith . -petscsection_point_major - `PETSC_TRUE` for point-major order
197ea844a1aSMatthew Knepley 
198ea844a1aSMatthew Knepley   Level: intermediate
199ea844a1aSMatthew Knepley 
200cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`
201ea844a1aSMatthew Knepley @*/
202d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFromOptions(PetscSection s)
203d71ae5a4SJacob Faibussowitsch {
204ea844a1aSMatthew Knepley   PetscFunctionBegin;
205ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
206d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)s);
2079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-petscsection_point_major", "The for ordering, either point major or field major", "PetscSectionSetPointMajor", s->pointMajor, &s->pointMajor, NULL));
208ea844a1aSMatthew Knepley   /* process any options handlers added with PetscObjectAddOptionsHandler() */
209dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)s, PetscOptionsObject));
210d0609cedSBarry Smith   PetscOptionsEnd();
2119566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)s, NULL, "-petscsection_view"));
2123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213ea844a1aSMatthew Knepley }
214ea844a1aSMatthew Knepley 
215ea844a1aSMatthew Knepley /*@
216ea844a1aSMatthew Knepley   PetscSectionCompare - Compares two sections
217ea844a1aSMatthew Knepley 
21840750d41SVaclav Hapla   Collective
219ea844a1aSMatthew Knepley 
2207a7aea1fSJed Brown   Input Parameters:
221cab54364SBarry Smith + s1 - the first `PetscSection`
222cab54364SBarry Smith - s2 - the second `PetscSection`
223ea844a1aSMatthew Knepley 
224ea844a1aSMatthew Knepley   Output Parameter:
225cab54364SBarry Smith . congruent - `PETSC_TRUE` if the two sections are congruent, `PETSC_FALSE` otherwise
226ea844a1aSMatthew Knepley 
227ea844a1aSMatthew Knepley   Level: intermediate
228ea844a1aSMatthew Knepley 
229cab54364SBarry Smith   Note:
230ea844a1aSMatthew Knepley   Field names are disregarded.
231ea844a1aSMatthew Knepley 
232cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionCopy()`, `PetscSectionClone()`
233ea844a1aSMatthew Knepley @*/
234d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCompare(PetscSection s1, PetscSection s2, PetscBool *congruent)
235d71ae5a4SJacob Faibussowitsch {
236ea844a1aSMatthew Knepley   PetscInt        pStart, pEnd, nfields, ncdof, nfcdof, p, f, n1, n2;
237ea844a1aSMatthew Knepley   const PetscInt *idx1, *idx2;
238ea844a1aSMatthew Knepley   IS              perm1, perm2;
239ea844a1aSMatthew Knepley   PetscBool       flg;
240ea844a1aSMatthew Knepley   PetscMPIInt     mflg;
241ea844a1aSMatthew Knepley 
242ea844a1aSMatthew Knepley   PetscFunctionBegin;
243ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s1, PETSC_SECTION_CLASSID, 1);
244ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s2, PETSC_SECTION_CLASSID, 2);
2454f572ea9SToby Isaac   PetscAssertPointer(congruent, 3);
246ea844a1aSMatthew Knepley   flg = PETSC_FALSE;
247ea844a1aSMatthew Knepley 
2489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)s1), PetscObjectComm((PetscObject)s2), &mflg));
249ea844a1aSMatthew Knepley   if (mflg != MPI_CONGRUENT && mflg != MPI_IDENT) {
250ea844a1aSMatthew Knepley     *congruent = PETSC_FALSE;
2513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
252ea844a1aSMatthew Knepley   }
253ea844a1aSMatthew Knepley 
2549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s1, &pStart, &pEnd));
2559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s2, &n1, &n2));
256ea844a1aSMatthew Knepley   if (pStart != n1 || pEnd != n2) goto not_congruent;
257ea844a1aSMatthew Knepley 
2589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPermutation(s1, &perm1));
2599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPermutation(s2, &perm2));
260ea844a1aSMatthew Knepley   if (perm1 && perm2) {
2619566063dSJacob Faibussowitsch     PetscCall(ISEqual(perm1, perm2, congruent));
262ea844a1aSMatthew Knepley     if (!(*congruent)) goto not_congruent;
263ea844a1aSMatthew Knepley   } else if (perm1 != perm2) goto not_congruent;
264ea844a1aSMatthew Knepley 
265ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(s1, p, &n1));
2679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(s2, p, &n2));
268ea844a1aSMatthew Knepley     if (n1 != n2) goto not_congruent;
269ea844a1aSMatthew Knepley 
2709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s1, p, &n1));
2719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s2, p, &n2));
272ea844a1aSMatthew Knepley     if (n1 != n2) goto not_congruent;
273ea844a1aSMatthew Knepley 
2749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s1, p, &ncdof));
2759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s2, p, &n2));
276ea844a1aSMatthew Knepley     if (ncdof != n2) goto not_congruent;
277ea844a1aSMatthew Knepley 
2789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(s1, p, &idx1));
2799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(s2, p, &idx2));
2809566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(idx1, idx2, ncdof, congruent));
281ea844a1aSMatthew Knepley     if (!(*congruent)) goto not_congruent;
282ea844a1aSMatthew Knepley   }
283ea844a1aSMatthew Knepley 
2849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s1, &nfields));
2859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s2, &n2));
286ea844a1aSMatthew Knepley   if (nfields != n2) goto not_congruent;
287ea844a1aSMatthew Knepley 
288ea844a1aSMatthew Knepley   for (f = 0; f < nfields; ++f) {
2899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s1, f, &n1));
2909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s2, f, &n2));
291ea844a1aSMatthew Knepley     if (n1 != n2) goto not_congruent;
292ea844a1aSMatthew Knepley 
293ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
2949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(s1, p, f, &n1));
2959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(s2, p, f, &n2));
296ea844a1aSMatthew Knepley       if (n1 != n2) goto not_congruent;
297ea844a1aSMatthew Knepley 
2989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s1, p, f, &n1));
2999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s2, p, f, &n2));
300ea844a1aSMatthew Knepley       if (n1 != n2) goto not_congruent;
301ea844a1aSMatthew Knepley 
3029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s1, p, f, &nfcdof));
3039566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s2, p, f, &n2));
304ea844a1aSMatthew Knepley       if (nfcdof != n2) goto not_congruent;
305ea844a1aSMatthew Knepley 
3069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(s1, p, f, &idx1));
3079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(s2, p, f, &idx2));
3089566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(idx1, idx2, nfcdof, congruent));
309ea844a1aSMatthew Knepley       if (!(*congruent)) goto not_congruent;
310ea844a1aSMatthew Knepley     }
311ea844a1aSMatthew Knepley   }
312ea844a1aSMatthew Knepley 
313ea844a1aSMatthew Knepley   flg = PETSC_TRUE;
314ea844a1aSMatthew Knepley not_congruent:
3151c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&flg, congruent, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)s1)));
3163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
317ea844a1aSMatthew Knepley }
318ea844a1aSMatthew Knepley 
319ea844a1aSMatthew Knepley /*@
320cab54364SBarry Smith   PetscSectionGetNumFields - Returns the number of fields in a `PetscSection`, or 0 if no fields were defined.
321ea844a1aSMatthew Knepley 
32240750d41SVaclav Hapla   Not Collective
323ea844a1aSMatthew Knepley 
324ea844a1aSMatthew Knepley   Input Parameter:
325cab54364SBarry Smith . s - the `PetscSection`
326ea844a1aSMatthew Knepley 
327ea844a1aSMatthew Knepley   Output Parameter:
328ea844a1aSMatthew Knepley . numFields - the number of fields defined, or 0 if none were defined
329ea844a1aSMatthew Knepley 
330ea844a1aSMatthew Knepley   Level: intermediate
331ea844a1aSMatthew Knepley 
332cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetNumFields()`
333ea844a1aSMatthew Knepley @*/
334d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetNumFields(PetscSection s, PetscInt *numFields)
335d71ae5a4SJacob Faibussowitsch {
336ea844a1aSMatthew Knepley   PetscFunctionBegin;
337ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
3384f572ea9SToby Isaac   PetscAssertPointer(numFields, 2);
339ea844a1aSMatthew Knepley   *numFields = s->numFields;
3403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
341ea844a1aSMatthew Knepley }
342ea844a1aSMatthew Knepley 
343ea844a1aSMatthew Knepley /*@
344cab54364SBarry Smith   PetscSectionSetNumFields - Sets the number of fields in a `PetscSection`
345ea844a1aSMatthew Knepley 
34640750d41SVaclav Hapla   Not Collective
347ea844a1aSMatthew Knepley 
348ea844a1aSMatthew Knepley   Input Parameters:
34920662ed9SBarry Smith + s         - the `PetscSection`
350ea844a1aSMatthew Knepley - numFields - the number of fields
351ea844a1aSMatthew Knepley 
352ea844a1aSMatthew Knepley   Level: intermediate
353ea844a1aSMatthew Knepley 
354583308b6SBarry Smith   Notes:
355583308b6SBarry Smith   Calling this destroys all the information in the `PetscSection` including the chart.
356583308b6SBarry Smith 
357583308b6SBarry Smith   You must call `PetscSectionSetChart()` after calling this.
358583308b6SBarry Smith 
359583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetNumFields()`, `PetscSectionSetChart()`, `PetscSectionReset()`
360ea844a1aSMatthew Knepley @*/
361d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetNumFields(PetscSection s, PetscInt numFields)
362d71ae5a4SJacob Faibussowitsch {
363ea844a1aSMatthew Knepley   PetscInt f;
364ea844a1aSMatthew Knepley 
365ea844a1aSMatthew Knepley   PetscFunctionBegin;
366ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
36708401ef6SPierre Jolivet   PetscCheck(numFields > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "The number of fields %" PetscInt_FMT " must be positive", numFields);
3689566063dSJacob Faibussowitsch   PetscCall(PetscSectionReset(s));
369ea844a1aSMatthew Knepley 
370ea844a1aSMatthew Knepley   s->numFields = numFields;
3719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(s->numFields, &s->numFieldComponents));
3729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(s->numFields, &s->fieldNames));
3739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(s->numFields, &s->compNames));
3749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(s->numFields, &s->field));
375ea844a1aSMatthew Knepley   for (f = 0; f < s->numFields; ++f) {
376ea844a1aSMatthew Knepley     char name[64];
377ea844a1aSMatthew Knepley 
378ea844a1aSMatthew Knepley     s->numFieldComponents[f] = 1;
379ea844a1aSMatthew Knepley 
3809566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &s->field[f]));
3819566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(name, 64, "Field_%" PetscInt_FMT, f));
3829566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, (char **)&s->fieldNames[f]));
3839566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(name, 64, "Component_0"));
3849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(s->numFieldComponents[f], &s->compNames[f]));
3859566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, (char **)&s->compNames[f][0]));
386ea844a1aSMatthew Knepley   }
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388ea844a1aSMatthew Knepley }
389ea844a1aSMatthew Knepley 
390ea844a1aSMatthew Knepley /*@C
391cab54364SBarry Smith   PetscSectionGetFieldName - Returns the name of a field in the `PetscSection`
392ea844a1aSMatthew Knepley 
393ea844a1aSMatthew Knepley   Not Collective
394ea844a1aSMatthew Knepley 
395ea844a1aSMatthew Knepley   Input Parameters:
396cab54364SBarry Smith + s     - the `PetscSection`
397ea844a1aSMatthew Knepley - field - the field number
398ea844a1aSMatthew Knepley 
399ea844a1aSMatthew Knepley   Output Parameter:
400ea844a1aSMatthew Knepley . fieldName - the field name
401ea844a1aSMatthew Knepley 
402ea844a1aSMatthew Knepley   Level: intermediate
403ea844a1aSMatthew Knepley 
404cab54364SBarry Smith   Note:
405cab54364SBarry Smith   Will error if the field number is out of range
406cab54364SBarry Smith 
407cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`
408ea844a1aSMatthew Knepley @*/
409d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldName(PetscSection s, PetscInt field, const char *fieldName[])
410d71ae5a4SJacob Faibussowitsch {
411ea844a1aSMatthew Knepley   PetscFunctionBegin;
412ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
4134f572ea9SToby Isaac   PetscAssertPointer(fieldName, 3);
4142abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
415ea844a1aSMatthew Knepley   *fieldName = s->fieldNames[field];
4163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
417ea844a1aSMatthew Knepley }
418ea844a1aSMatthew Knepley 
419ea844a1aSMatthew Knepley /*@C
420cab54364SBarry Smith   PetscSectionSetFieldName - Sets the name of a field in the `PetscSection`
421ea844a1aSMatthew Knepley 
422ea844a1aSMatthew Knepley   Not Collective
423ea844a1aSMatthew Knepley 
424ea844a1aSMatthew Knepley   Input Parameters:
425cab54364SBarry Smith + s         - the `PetscSection`
426ea844a1aSMatthew Knepley . field     - the field number
427ea844a1aSMatthew Knepley - fieldName - the field name
428ea844a1aSMatthew Knepley 
429ea844a1aSMatthew Knepley   Level: intermediate
430ea844a1aSMatthew Knepley 
431cab54364SBarry Smith   Note:
432cab54364SBarry Smith   Will error if the field number is out of range
433cab54364SBarry Smith 
434cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionGetFieldName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`
435ea844a1aSMatthew Knepley @*/
436d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldName(PetscSection s, PetscInt field, const char fieldName[])
437d71ae5a4SJacob Faibussowitsch {
438ea844a1aSMatthew Knepley   PetscFunctionBegin;
439ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
4404f572ea9SToby Isaac   if (fieldName) PetscAssertPointer(fieldName, 3);
4412abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
4429566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->fieldNames[field]));
4439566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(fieldName, (char **)&s->fieldNames[field]));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445ea844a1aSMatthew Knepley }
446ea844a1aSMatthew Knepley 
447b778fa18SValeria Barra /*@C
448cab54364SBarry Smith   PetscSectionGetComponentName - Gets the name of a field component in the `PetscSection`
449b778fa18SValeria Barra 
450b778fa18SValeria Barra   Not Collective
451b778fa18SValeria Barra 
452b778fa18SValeria Barra   Input Parameters:
453cab54364SBarry Smith + s     - the `PetscSection`
454b778fa18SValeria Barra . field - the field number
455cab54364SBarry Smith - comp  - the component number
456cab54364SBarry Smith 
457d5b43468SJose E. Roman   Output Parameter:
458cab54364SBarry Smith . compName - the component name
459b778fa18SValeria Barra 
460b778fa18SValeria Barra   Level: intermediate
461b778fa18SValeria Barra 
462cab54364SBarry Smith   Note:
463cab54364SBarry Smith   Will error if the field or component number do not exist
464cab54364SBarry Smith 
46538b5cf2dSJacob Faibussowitsch   Developer Notes:
466583308b6SBarry Smith   The function name should have Field in it since they are field components.
467583308b6SBarry Smith 
468cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`,
469cab54364SBarry Smith           `PetscSectionSetComponentName()`, `PetscSectionSetFieldName()`, `PetscSectionGetFieldComponents()`, `PetscSectionSetFieldComponents()`
470b778fa18SValeria Barra @*/
471d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetComponentName(PetscSection s, PetscInt field, PetscInt comp, const char *compName[])
472d71ae5a4SJacob Faibussowitsch {
473b778fa18SValeria Barra   PetscFunctionBegin;
474b778fa18SValeria Barra   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
4754f572ea9SToby Isaac   PetscAssertPointer(compName, 4);
4762abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
4772abc8c78SJacob Faibussowitsch   PetscSectionCheckValidFieldComponent(comp, s->numFieldComponents[field]);
478b778fa18SValeria Barra   *compName = s->compNames[field][comp];
4793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
480b778fa18SValeria Barra }
481b778fa18SValeria Barra 
482b778fa18SValeria Barra /*@C
483cab54364SBarry Smith   PetscSectionSetComponentName - Sets the name of a field component in the `PetscSection`
484b778fa18SValeria Barra 
485b778fa18SValeria Barra   Not Collective
486b778fa18SValeria Barra 
487b778fa18SValeria Barra   Input Parameters:
48820662ed9SBarry Smith + s        - the `PetscSection`
489b778fa18SValeria Barra . field    - the field number
490b778fa18SValeria Barra . comp     - the component number
491b778fa18SValeria Barra - compName - the component name
492b778fa18SValeria Barra 
493583308b6SBarry Smith   Level: advanced
494b778fa18SValeria Barra 
495cab54364SBarry Smith   Note:
496cab54364SBarry Smith   Will error if the field or component number do not exist
497cab54364SBarry Smith 
49838b5cf2dSJacob Faibussowitsch   Developer Notes:
499583308b6SBarry Smith   The function name should have Field in it since they are field components.
500583308b6SBarry Smith 
501cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetComponentName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`,
50242747ad1SJacob Faibussowitsch           `PetscSectionSetFieldName()`, `PetscSectionGetFieldComponents()`, `PetscSectionSetFieldComponents()`
503b778fa18SValeria Barra @*/
504d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetComponentName(PetscSection s, PetscInt field, PetscInt comp, const char compName[])
505d71ae5a4SJacob Faibussowitsch {
506b778fa18SValeria Barra   PetscFunctionBegin;
507b778fa18SValeria Barra   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
5084f572ea9SToby Isaac   if (compName) PetscAssertPointer(compName, 4);
5092abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
5102abc8c78SJacob Faibussowitsch   PetscSectionCheckValidFieldComponent(comp, s->numFieldComponents[field]);
5119566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->compNames[field][comp]));
5129566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(compName, (char **)&s->compNames[field][comp]));
5133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
514b778fa18SValeria Barra }
515b778fa18SValeria Barra 
516ea844a1aSMatthew Knepley /*@
517ea844a1aSMatthew Knepley   PetscSectionGetFieldComponents - Returns the number of field components for the given field.
518ea844a1aSMatthew Knepley 
51940750d41SVaclav Hapla   Not Collective
520ea844a1aSMatthew Knepley 
521ea844a1aSMatthew Knepley   Input Parameters:
522cab54364SBarry Smith + s     - the `PetscSection`
523ea844a1aSMatthew Knepley - field - the field number
524ea844a1aSMatthew Knepley 
525ea844a1aSMatthew Knepley   Output Parameter:
526ea844a1aSMatthew Knepley . numComp - the number of field components
527ea844a1aSMatthew Knepley 
528583308b6SBarry Smith   Level: advanced
529ea844a1aSMatthew Knepley 
53038b5cf2dSJacob Faibussowitsch   Developer Notes:
531cab54364SBarry Smith   This function is misnamed. There is a Num in `PetscSectionGetNumFields()` but not in this name
532cab54364SBarry Smith 
533583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldComponents()`, `PetscSectionGetNumFields()`,
534583308b6SBarry Smith           `PetscSectionSetComponentName()`, `PetscSectionGetComponentName()`
535ea844a1aSMatthew Knepley @*/
536d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldComponents(PetscSection s, PetscInt field, PetscInt *numComp)
537d71ae5a4SJacob Faibussowitsch {
538ea844a1aSMatthew Knepley   PetscFunctionBegin;
539ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
5404f572ea9SToby Isaac   PetscAssertPointer(numComp, 3);
5412abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
542ea844a1aSMatthew Knepley   *numComp = s->numFieldComponents[field];
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
544ea844a1aSMatthew Knepley }
545ea844a1aSMatthew Knepley 
546ea844a1aSMatthew Knepley /*@
547ea844a1aSMatthew Knepley   PetscSectionSetFieldComponents - Sets the number of field components for the given field.
548ea844a1aSMatthew Knepley 
54940750d41SVaclav Hapla   Not Collective
550ea844a1aSMatthew Knepley 
551ea844a1aSMatthew Knepley   Input Parameters:
55220662ed9SBarry Smith + s       - the `PetscSection`
553ea844a1aSMatthew Knepley . field   - the field number
554ea844a1aSMatthew Knepley - numComp - the number of field components
555ea844a1aSMatthew Knepley 
556583308b6SBarry Smith   Level: advanced
557ea844a1aSMatthew Knepley 
558583308b6SBarry Smith   Note:
559583308b6SBarry Smith   This number can be different than the values set with `PetscSectionSetFieldDof()`. It can be used to indicate the number of
560583308b6SBarry Smith   components in the field of the underlying physical model which may be different than the number of degrees of freedom needed
561583308b6SBarry Smith   at a point in a discretization. For example, if in three dimensions the field is velocity, it will have 3 components, u, v, and w but
562583308b6SBarry Smith   an face based model for velocity (where the velocity normal to the face is stored) there is only 1 dof for each face point.
563583308b6SBarry Smith 
564583308b6SBarry Smith   The value set with this function are not needed or used in `PetscSectionSetUp()`.
565583308b6SBarry Smith 
56638b5cf2dSJacob Faibussowitsch   Developer Notes:
567583308b6SBarry Smith   This function is misnamed. There is a Num in `PetscSectionSetNumFields()` but not in this name
568583308b6SBarry Smith 
569583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldComponents()`, `PetscSectionSetComponentName()`,
570583308b6SBarry Smith           `PetscSectionGetComponentName()`, `PetscSectionGetNumFields()`
571ea844a1aSMatthew Knepley @*/
572d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldComponents(PetscSection s, PetscInt field, PetscInt numComp)
573d71ae5a4SJacob Faibussowitsch {
574b778fa18SValeria Barra   PetscInt c;
575b778fa18SValeria Barra 
576ea844a1aSMatthew Knepley   PetscFunctionBegin;
577ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
5782abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
579b778fa18SValeria Barra   if (s->compNames) {
58048a46eb9SPierre Jolivet     for (c = 0; c < s->numFieldComponents[field]; ++c) PetscCall(PetscFree(s->compNames[field][c]));
5819566063dSJacob Faibussowitsch     PetscCall(PetscFree(s->compNames[field]));
582b778fa18SValeria Barra   }
583b778fa18SValeria Barra 
584ea844a1aSMatthew Knepley   s->numFieldComponents[field] = numComp;
585b778fa18SValeria Barra   if (numComp) {
5869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numComp, (char ***)&s->compNames[field]));
587b778fa18SValeria Barra     for (c = 0; c < numComp; ++c) {
5882abc8c78SJacob Faibussowitsch       char name[64];
5892abc8c78SJacob Faibussowitsch 
5909566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(name, 64, "%" PetscInt_FMT, c));
5919566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(name, (char **)&s->compNames[field][c]));
592b778fa18SValeria Barra     }
593b778fa18SValeria Barra   }
5943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
595ea844a1aSMatthew Knepley }
596ea844a1aSMatthew Knepley 
597ea844a1aSMatthew Knepley /*@
598583308b6SBarry Smith   PetscSectionGetChart - Returns the range [`pStart`, `pEnd`) in which points (indices) lie for this `PetscSection` on this MPI process
599ea844a1aSMatthew Knepley 
60040750d41SVaclav Hapla   Not Collective
601ea844a1aSMatthew Knepley 
602ea844a1aSMatthew Knepley   Input Parameter:
603cab54364SBarry Smith . s - the `PetscSection`
604ea844a1aSMatthew Knepley 
605ea844a1aSMatthew Knepley   Output Parameters:
606ea844a1aSMatthew Knepley + pStart - the first point
607ea844a1aSMatthew Knepley - pEnd   - one past the last point
608ea844a1aSMatthew Knepley 
609ea844a1aSMatthew Knepley   Level: intermediate
610ea844a1aSMatthew Knepley 
611cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetChart()`, `PetscSectionCreate()`
612ea844a1aSMatthew Knepley @*/
613d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd)
614d71ae5a4SJacob Faibussowitsch {
615ea844a1aSMatthew Knepley   PetscFunctionBegin;
616ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
617ea844a1aSMatthew Knepley   if (pStart) *pStart = s->pStart;
618ea844a1aSMatthew Knepley   if (pEnd) *pEnd = s->pEnd;
6193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
620ea844a1aSMatthew Knepley }
621ea844a1aSMatthew Knepley 
622ea844a1aSMatthew Knepley /*@
623583308b6SBarry Smith   PetscSectionSetChart - Sets the range [`pStart`, `pEnd`) in which points (indices) lie for this `PetscSection` on this MPI process
624ea844a1aSMatthew Knepley 
62540750d41SVaclav Hapla   Not Collective
626ea844a1aSMatthew Knepley 
627ea844a1aSMatthew Knepley   Input Parameters:
62820662ed9SBarry Smith + s      - the `PetscSection`
629ea844a1aSMatthew Knepley . pStart - the first point
630ea844a1aSMatthew Knepley - pEnd   - one past the last point
631ea844a1aSMatthew Knepley 
632ea844a1aSMatthew Knepley   Level: intermediate
633ea844a1aSMatthew Knepley 
634583308b6SBarry Smith   Notes:
635583308b6SBarry Smith   The charts on different MPI processes may (and often do) overlap
636583308b6SBarry Smith 
637583308b6SBarry Smith   If you intend to use `PetscSectionSetNumFields()` it must be called before this call.
638583308b6SBarry Smith 
639583308b6SBarry Smith   The chart for all fields created with `PetscSectionSetNumFields()` is the same as this chart.
640583308b6SBarry Smith 
641583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetChart()`, `PetscSectionCreate()`, `PetscSectionSetNumFields()`
642ea844a1aSMatthew Knepley @*/
643d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd)
644d71ae5a4SJacob Faibussowitsch {
645ea844a1aSMatthew Knepley   PetscInt f;
646ea844a1aSMatthew Knepley 
647ea844a1aSMatthew Knepley   PetscFunctionBegin;
648ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
649*40196513SBarry Smith   PetscCheck(pEnd >= pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Chart pEnd %" PetscInt_FMT " cannot be smaller than chart pStart %" PetscInt_FMT, pEnd, pStart);
6503ba16761SJacob Faibussowitsch   if (pStart == s->pStart && pEnd == s->pEnd) PetscFunctionReturn(PETSC_SUCCESS);
651ea844a1aSMatthew Knepley   /* Cannot Reset() because it destroys field information */
652ea844a1aSMatthew Knepley   s->setup = PETSC_FALSE;
6539566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s->bc));
6549566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->bcIndices));
6559566063dSJacob Faibussowitsch   PetscCall(PetscFree2(s->atlasDof, s->atlasOff));
656ea844a1aSMatthew Knepley 
657ea844a1aSMatthew Knepley   s->pStart = pStart;
658ea844a1aSMatthew Knepley   s->pEnd   = pEnd;
6599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff));
6609566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(s->atlasDof, pEnd - pStart));
66148a46eb9SPierre Jolivet   for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetChart(s->field[f], pStart, pEnd));
6623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
663ea844a1aSMatthew Knepley }
664ea844a1aSMatthew Knepley 
665ea844a1aSMatthew Knepley /*@
66620662ed9SBarry Smith   PetscSectionGetPermutation - Returns the permutation of [0, `pEnd` - `pStart`) or `NULL` that was set with `PetscSectionSetPermutation()`
667ea844a1aSMatthew Knepley 
66840750d41SVaclav Hapla   Not Collective
669ea844a1aSMatthew Knepley 
670ea844a1aSMatthew Knepley   Input Parameter:
671cab54364SBarry Smith . s - the `PetscSection`
672ea844a1aSMatthew Knepley 
6732fe279fdSBarry Smith   Output Parameter:
674cab54364SBarry Smith . perm - The permutation as an `IS`
675ea844a1aSMatthew Knepley 
676ea844a1aSMatthew Knepley   Level: intermediate
677ea844a1aSMatthew Knepley 
678cab54364SBarry Smith .seealso: [](sec_scatter), `IS`, `PetscSection`, `PetscSectionSetPermutation()`, `PetscSectionCreate()`
679ea844a1aSMatthew Knepley @*/
680d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm)
681d71ae5a4SJacob Faibussowitsch {
682ea844a1aSMatthew Knepley   PetscFunctionBegin;
683ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
6849371c9d4SSatish Balay   if (perm) {
6854f572ea9SToby Isaac     PetscAssertPointer(perm, 2);
6869371c9d4SSatish Balay     *perm = s->perm;
6879371c9d4SSatish Balay   }
6883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
689ea844a1aSMatthew Knepley }
690ea844a1aSMatthew Knepley 
691ea844a1aSMatthew Knepley /*@
692583308b6SBarry Smith   PetscSectionSetPermutation - Sets a permutation of the chart for this section, [0, `pEnd` - `pStart`), which determines the order to store the `PetscSection` information
693ea844a1aSMatthew Knepley 
69440750d41SVaclav Hapla   Not Collective
695ea844a1aSMatthew Knepley 
696ea844a1aSMatthew Knepley   Input Parameters:
69720662ed9SBarry Smith + s    - the `PetscSection`
698ea844a1aSMatthew Knepley - perm - the permutation of points
699ea844a1aSMatthew Knepley 
700ea844a1aSMatthew Knepley   Level: intermediate
701ea844a1aSMatthew Knepley 
702583308b6SBarry Smith   Notes:
703583308b6SBarry Smith   The permutation must be provided before `PetscSectionSetUp()`.
704cab54364SBarry Smith 
705583308b6SBarry Smith   The data in the `PetscSection` are permuted but the access via `PetscSectionGetFieldOffset()` and `PetscSectionGetOffset()` is not changed
706583308b6SBarry Smith 
707583308b6SBarry Smith   Compart to `PetscSectionPermute()`
708583308b6SBarry Smith 
709583308b6SBarry Smith .seealso: [](sec_scatter), `IS`, `PetscSection`, `PetscSectionSetUp()`, `PetscSectionGetPermutation()`, `PetscSectionPermute()`, `PetscSectionCreate()`
710ea844a1aSMatthew Knepley @*/
711d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm)
712d71ae5a4SJacob Faibussowitsch {
713ea844a1aSMatthew Knepley   PetscFunctionBegin;
714ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
715ea844a1aSMatthew Knepley   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
71628b400f6SJacob Faibussowitsch   PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup");
717ea844a1aSMatthew Knepley   if (s->perm != perm) {
7189566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&s->perm));
719ea844a1aSMatthew Knepley     if (perm) {
720ea844a1aSMatthew Knepley       s->perm = perm;
7219566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)s->perm));
722ea844a1aSMatthew Knepley     }
723ea844a1aSMatthew Knepley   }
7243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
725ea844a1aSMatthew Knepley }
726ea844a1aSMatthew Knepley 
727ea844a1aSMatthew Knepley /*@
728cab54364SBarry Smith   PetscSectionGetPointMajor - Returns the flag for dof ordering, `PETSC_TRUE` if it is point major, `PETSC_FALSE` if it is field major
729ea844a1aSMatthew Knepley 
73040750d41SVaclav Hapla   Not Collective
731ea844a1aSMatthew Knepley 
732ea844a1aSMatthew Knepley   Input Parameter:
733cab54364SBarry Smith . s - the `PetscSection`
734ea844a1aSMatthew Knepley 
735ea844a1aSMatthew Knepley   Output Parameter:
736ea844a1aSMatthew Knepley . pm - the flag for point major ordering
737ea844a1aSMatthew Knepley 
738ea844a1aSMatthew Knepley   Level: intermediate
739ea844a1aSMatthew Knepley 
74038b5cf2dSJacob Faibussowitsch .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetPointMajor()`
741ea844a1aSMatthew Knepley @*/
742d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetPointMajor(PetscSection s, PetscBool *pm)
743d71ae5a4SJacob Faibussowitsch {
744ea844a1aSMatthew Knepley   PetscFunctionBegin;
745ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
7464f572ea9SToby Isaac   PetscAssertPointer(pm, 2);
747ea844a1aSMatthew Knepley   *pm = s->pointMajor;
7483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
749ea844a1aSMatthew Knepley }
750ea844a1aSMatthew Knepley 
751ea844a1aSMatthew Knepley /*@
752cab54364SBarry Smith   PetscSectionSetPointMajor - Sets the flag for dof ordering, `PETSC_TRUE` for point major, otherwise it will be field major
753ea844a1aSMatthew Knepley 
75440750d41SVaclav Hapla   Not Collective
755ea844a1aSMatthew Knepley 
756ea844a1aSMatthew Knepley   Input Parameters:
757cab54364SBarry Smith + s  - the `PetscSection`
758ea844a1aSMatthew Knepley - pm - the flag for point major ordering
759ea844a1aSMatthew Knepley 
760ea844a1aSMatthew Knepley   Level: intermediate
761ea844a1aSMatthew Knepley 
762583308b6SBarry Smith   Note:
763583308b6SBarry Smith   Field-major order is not recommended unless you are managing the entire problem yourself, since many higher-level functions in PETSc depend on point-major order.
764583308b6SBarry Smith 
765583308b6SBarry Smith   Point major order means the degrees of freedom are stored as follows
766583308b6SBarry Smith .vb
767583308b6SBarry Smith     all the degrees of freedom for each point are stored contiquously, one point after another (respecting a permutation set with `PetscSectionSetPermutation()`)
768583308b6SBarry Smith     for each point
769583308b6SBarry Smith        the degrees of freedom for each field (starting with the unnamed default field) are listed in order by field
770583308b6SBarry Smith .ve
771583308b6SBarry Smith 
772583308b6SBarry Smith   Field major order means the degrees of freedom are stored as follows
773583308b6SBarry Smith .vb
774583308b6SBarry Smith     all degrees of freedom for each field (including the unnamed default field) are stored contiquously, one field after another
775583308b6SBarry Smith     for each field (started with unnamed default field)
776583308b6SBarry Smith       the degrees of freedom for each point are listed in order by point (respecting a permutation set with `PetscSectionSetPermutation()`)
777583308b6SBarry Smith .ve
778583308b6SBarry Smith 
779583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetPointMajor()`, `PetscSectionSetPermutation()`
780ea844a1aSMatthew Knepley @*/
781d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetPointMajor(PetscSection s, PetscBool pm)
782d71ae5a4SJacob Faibussowitsch {
783ea844a1aSMatthew Knepley   PetscFunctionBegin;
784ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
78528b400f6SJacob Faibussowitsch   PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set the dof ordering after the section is setup");
786ea844a1aSMatthew Knepley   s->pointMajor = pm;
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
788ea844a1aSMatthew Knepley }
789ea844a1aSMatthew Knepley 
790ea844a1aSMatthew Knepley /*@
791cab54364SBarry Smith   PetscSectionGetIncludesConstraints - Returns the flag indicating if constrained dofs were included when computing offsets in the `PetscSection`.
792cab54364SBarry Smith   The value is set with `PetscSectionSetIncludesConstraints()`
79387e637c6Sksagiyam 
79440750d41SVaclav Hapla   Not Collective
79587e637c6Sksagiyam 
79687e637c6Sksagiyam   Input Parameter:
797cab54364SBarry Smith . s - the `PetscSection`
79887e637c6Sksagiyam 
79987e637c6Sksagiyam   Output Parameter:
80087e637c6Sksagiyam . includesConstraints - the flag indicating if constrained dofs were included when computing offsets
80187e637c6Sksagiyam 
80287e637c6Sksagiyam   Level: intermediate
80387e637c6Sksagiyam 
804cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetIncludesConstraints()`
80587e637c6Sksagiyam @*/
806d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetIncludesConstraints(PetscSection s, PetscBool *includesConstraints)
807d71ae5a4SJacob Faibussowitsch {
80887e637c6Sksagiyam   PetscFunctionBegin;
80987e637c6Sksagiyam   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
8104f572ea9SToby Isaac   PetscAssertPointer(includesConstraints, 2);
81187e637c6Sksagiyam   *includesConstraints = s->includesConstraints;
8123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81387e637c6Sksagiyam }
81487e637c6Sksagiyam 
81587e637c6Sksagiyam /*@
81687e637c6Sksagiyam   PetscSectionSetIncludesConstraints - Sets the flag indicating if constrained dofs are to be included when computing offsets
81787e637c6Sksagiyam 
81840750d41SVaclav Hapla   Not Collective
81987e637c6Sksagiyam 
82087e637c6Sksagiyam   Input Parameters:
82120662ed9SBarry Smith + s                   - the `PetscSection`
82287e637c6Sksagiyam - includesConstraints - the flag indicating if constrained dofs are to be included when computing offsets
82387e637c6Sksagiyam 
82487e637c6Sksagiyam   Level: intermediate
82587e637c6Sksagiyam 
826cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetIncludesConstraints()`
82787e637c6Sksagiyam @*/
828d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetIncludesConstraints(PetscSection s, PetscBool includesConstraints)
829d71ae5a4SJacob Faibussowitsch {
83087e637c6Sksagiyam   PetscFunctionBegin;
83187e637c6Sksagiyam   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
83228b400f6SJacob Faibussowitsch   PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set includesConstraints after the section is set up");
83387e637c6Sksagiyam   s->includesConstraints = includesConstraints;
8343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83587e637c6Sksagiyam }
83687e637c6Sksagiyam 
83787e637c6Sksagiyam /*@
838583308b6SBarry Smith   PetscSectionGetDof - Return the total number of degrees of freedom associated with a given point.
839ea844a1aSMatthew Knepley 
84040750d41SVaclav Hapla   Not Collective
841ea844a1aSMatthew Knepley 
842ea844a1aSMatthew Knepley   Input Parameters:
843cab54364SBarry Smith + s     - the `PetscSection`
844ea844a1aSMatthew Knepley - point - the point
845ea844a1aSMatthew Knepley 
846ea844a1aSMatthew Knepley   Output Parameter:
847ea844a1aSMatthew Knepley . numDof - the number of dof
848ea844a1aSMatthew Knepley 
849583308b6SBarry Smith   Level: intermediate
850583308b6SBarry Smith 
851583308b6SBarry Smith   Notes:
852db527f05SMatthew G. Knepley   In a global section, this size will be negative for points not owned by this process.
853db527f05SMatthew G. Knepley 
854583308b6SBarry Smith   This number is for the unnamed default field at the given point plus all degrees of freedom associated with all fields at that point
855ea844a1aSMatthew Knepley 
856cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetDof()`, `PetscSectionCreate()`
857ea844a1aSMatthew Knepley @*/
858d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetDof(PetscSection s, PetscInt point, PetscInt *numDof)
859d71ae5a4SJacob Faibussowitsch {
86076bd3646SJed Brown   PetscFunctionBeginHot;
861ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
8624f572ea9SToby Isaac   PetscAssertPointer(numDof, 3);
863b498ca8aSPierre Jolivet   PetscAssert(point >= s->pStart && point < s->pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd);
864ea844a1aSMatthew Knepley   *numDof = s->atlasDof[point - s->pStart];
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
866ea844a1aSMatthew Knepley }
867ea844a1aSMatthew Knepley 
868ea844a1aSMatthew Knepley /*@
869583308b6SBarry Smith   PetscSectionSetDof - Sets the total number of degrees of freedom associated with a given point.
870ea844a1aSMatthew Knepley 
87140750d41SVaclav Hapla   Not Collective
872ea844a1aSMatthew Knepley 
873ea844a1aSMatthew Knepley   Input Parameters:
874cab54364SBarry Smith + s      - the `PetscSection`
875ea844a1aSMatthew Knepley . point  - the point
876ea844a1aSMatthew Knepley - numDof - the number of dof
877ea844a1aSMatthew Knepley 
878ea844a1aSMatthew Knepley   Level: intermediate
879ea844a1aSMatthew Knepley 
880583308b6SBarry Smith   Note:
881583308b6SBarry Smith   This number is for the unnamed default field at the given point plus all degrees of freedom associated with all fields at that point
882583308b6SBarry Smith 
883cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionAddDof()`, `PetscSectionCreate()`
884ea844a1aSMatthew Knepley @*/
885d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof)
886d71ae5a4SJacob Faibussowitsch {
887ea844a1aSMatthew Knepley   PetscFunctionBegin;
888ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
889c8bf3acbSVaclav Hapla   PetscAssert(point >= s->pStart && point < s->pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd);
890ea844a1aSMatthew Knepley   s->atlasDof[point - s->pStart] = numDof;
89169c11d05SVaclav Hapla   PetscCall(PetscSectionInvalidateMaxDof_Internal(s));
8923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
893ea844a1aSMatthew Knepley }
894ea844a1aSMatthew Knepley 
895ea844a1aSMatthew Knepley /*@
896583308b6SBarry Smith   PetscSectionAddDof - Adds to the total number of degrees of freedom associated with a given point.
897ea844a1aSMatthew Knepley 
89840750d41SVaclav Hapla   Not Collective
899ea844a1aSMatthew Knepley 
900ea844a1aSMatthew Knepley   Input Parameters:
901cab54364SBarry Smith + s      - the `PetscSection`
902ea844a1aSMatthew Knepley . point  - the point
903ea844a1aSMatthew Knepley - numDof - the number of additional dof
904ea844a1aSMatthew Knepley 
905ea844a1aSMatthew Knepley   Level: intermediate
906ea844a1aSMatthew Knepley 
907583308b6SBarry Smith   Note:
908583308b6SBarry Smith   This number is for the unnamed default field at the given point plus all degrees of freedom associated with all fields at that point
909583308b6SBarry Smith 
910cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetDof()`, `PetscSectionCreate()`
911ea844a1aSMatthew Knepley @*/
912d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof)
913d71ae5a4SJacob Faibussowitsch {
91476bd3646SJed Brown   PetscFunctionBeginHot;
915ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
916b498ca8aSPierre Jolivet   PetscAssert(point >= s->pStart && point < s->pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd);
917*40196513SBarry Smith   PetscCheck(numDof >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "numDof %" PetscInt_FMT " should not be negative", numDof);
918ea844a1aSMatthew Knepley   s->atlasDof[point - s->pStart] += numDof;
91969c11d05SVaclav Hapla   PetscCall(PetscSectionInvalidateMaxDof_Internal(s));
9203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
921ea844a1aSMatthew Knepley }
922ea844a1aSMatthew Knepley 
923ea844a1aSMatthew Knepley /*@
924ea844a1aSMatthew Knepley   PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point.
925ea844a1aSMatthew Knepley 
92640750d41SVaclav Hapla   Not Collective
927ea844a1aSMatthew Knepley 
928ea844a1aSMatthew Knepley   Input Parameters:
929cab54364SBarry Smith + s     - the `PetscSection`
930ea844a1aSMatthew Knepley . point - the point
931ea844a1aSMatthew Knepley - field - the field
932ea844a1aSMatthew Knepley 
933ea844a1aSMatthew Knepley   Output Parameter:
934ea844a1aSMatthew Knepley . numDof - the number of dof
935ea844a1aSMatthew Knepley 
936ea844a1aSMatthew Knepley   Level: intermediate
937ea844a1aSMatthew Knepley 
938cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldDof()`, `PetscSectionCreate()`
939ea844a1aSMatthew Knepley @*/
940d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
941d71ae5a4SJacob Faibussowitsch {
942ea844a1aSMatthew Knepley   PetscFunctionBegin;
943ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
9444f572ea9SToby Isaac   PetscAssertPointer(numDof, 4);
9452abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
9469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(s->field[field], point, numDof));
9473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
948ea844a1aSMatthew Knepley }
949ea844a1aSMatthew Knepley 
950ea844a1aSMatthew Knepley /*@
951ea844a1aSMatthew Knepley   PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point.
952ea844a1aSMatthew Knepley 
95340750d41SVaclav Hapla   Not Collective
954ea844a1aSMatthew Knepley 
955ea844a1aSMatthew Knepley   Input Parameters:
956cab54364SBarry Smith + s      - the `PetscSection`
957ea844a1aSMatthew Knepley . point  - the point
958ea844a1aSMatthew Knepley . field  - the field
959ea844a1aSMatthew Knepley - numDof - the number of dof
960ea844a1aSMatthew Knepley 
961ea844a1aSMatthew Knepley   Level: intermediate
962ea844a1aSMatthew Knepley 
963583308b6SBarry Smith   Note:
964583308b6SBarry Smith   When setting the number of dof for a field at a point one must also ensure the count of the total number of dof at the point (summed over
965583308b6SBarry Smith   the fields and the unnamed default field) is correct by also calling `PetscSectionAddDof()` or `PetscSectionSetDof()`
966583308b6SBarry Smith 
967583308b6SBarry Smith   This is equivalent to
968583308b6SBarry Smith .vb
969583308b6SBarry Smith      PetscSection fs;
970583308b6SBarry Smith      PetscSectionGetField(s,field,&fs)
971583308b6SBarry Smith      PetscSectionSetDof(fs,numDof)
972583308b6SBarry Smith .ve
973583308b6SBarry Smith 
974583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldDof()`, `PetscSectionCreate()`, `PetscSectionAddDof()`, `PetscSectionSetDof()`
975ea844a1aSMatthew Knepley @*/
976d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
977d71ae5a4SJacob Faibussowitsch {
978ea844a1aSMatthew Knepley   PetscFunctionBegin;
979ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
9802abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
9819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(s->field[field], point, numDof));
9823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
983ea844a1aSMatthew Knepley }
984ea844a1aSMatthew Knepley 
985ea844a1aSMatthew Knepley /*@
986ea844a1aSMatthew Knepley   PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point.
987ea844a1aSMatthew Knepley 
98840750d41SVaclav Hapla   Not Collective
989ea844a1aSMatthew Knepley 
990ea844a1aSMatthew Knepley   Input Parameters:
991cab54364SBarry Smith + s      - the `PetscSection`
992ea844a1aSMatthew Knepley . point  - the point
993ea844a1aSMatthew Knepley . field  - the field
994ea844a1aSMatthew Knepley - numDof - the number of dof
995ea844a1aSMatthew Knepley 
996ea844a1aSMatthew Knepley   Level: intermediate
997ea844a1aSMatthew Knepley 
998583308b6SBarry Smith   Notes:
999583308b6SBarry Smith   When adding to the number of dof for a field at a point one must also ensure the count of the total number of dof at the point (summed over
1000583308b6SBarry Smith   the fields and the unnamed default field) is correct by also calling `PetscSectionAddDof()` or `PetscSectionSetDof()`
1001583308b6SBarry Smith 
1002583308b6SBarry Smith   This is equivalent to
1003583308b6SBarry Smith .vb
1004583308b6SBarry Smith      PetscSection fs;
1005583308b6SBarry Smith      PetscSectionGetField(s,field,&fs)
1006583308b6SBarry Smith      PetscSectionAddDof(fs,numDof)
1007583308b6SBarry Smith .ve
1008583308b6SBarry Smith 
1009cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldDof()`, `PetscSectionGetFieldDof()`, `PetscSectionCreate()`
1010ea844a1aSMatthew Knepley @*/
1011d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
1012d71ae5a4SJacob Faibussowitsch {
1013ea844a1aSMatthew Knepley   PetscFunctionBegin;
1014ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
10152abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
10169566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(s->field[field], point, numDof));
10173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1018ea844a1aSMatthew Knepley }
1019ea844a1aSMatthew Knepley 
1020ea844a1aSMatthew Knepley /*@
1021ea844a1aSMatthew Knepley   PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point.
1022ea844a1aSMatthew Knepley 
102340750d41SVaclav Hapla   Not Collective
1024ea844a1aSMatthew Knepley 
1025ea844a1aSMatthew Knepley   Input Parameters:
1026cab54364SBarry Smith + s     - the `PetscSection`
1027ea844a1aSMatthew Knepley - point - the point
1028ea844a1aSMatthew Knepley 
1029ea844a1aSMatthew Knepley   Output Parameter:
1030ea844a1aSMatthew Knepley . numDof - the number of dof which are fixed by constraints
1031ea844a1aSMatthew Knepley 
1032ea844a1aSMatthew Knepley   Level: intermediate
1033ea844a1aSMatthew Knepley 
1034cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetConstraintDof()`, `PetscSectionCreate()`
1035ea844a1aSMatthew Knepley @*/
1036d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof)
1037d71ae5a4SJacob Faibussowitsch {
1038ea844a1aSMatthew Knepley   PetscFunctionBegin;
1039ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
10404f572ea9SToby Isaac   PetscAssertPointer(numDof, 3);
1041ea844a1aSMatthew Knepley   if (s->bc) {
10429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s->bc, point, numDof));
1043ea844a1aSMatthew Knepley   } else *numDof = 0;
10443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1045ea844a1aSMatthew Knepley }
1046ea844a1aSMatthew Knepley 
1047ea844a1aSMatthew Knepley /*@
1048ea844a1aSMatthew Knepley   PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point.
1049ea844a1aSMatthew Knepley 
105040750d41SVaclav Hapla   Not Collective
1051ea844a1aSMatthew Knepley 
1052ea844a1aSMatthew Knepley   Input Parameters:
1053cab54364SBarry Smith + s      - the `PetscSection`
1054ea844a1aSMatthew Knepley . point  - the point
1055ea844a1aSMatthew Knepley - numDof - the number of dof which are fixed by constraints
1056ea844a1aSMatthew Knepley 
1057ea844a1aSMatthew Knepley   Level: intermediate
1058ea844a1aSMatthew Knepley 
1059cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetDof()`, `PetscSectionGetConstraintDof()`, `PetscSectionCreate()`
1060ea844a1aSMatthew Knepley @*/
1061d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
1062d71ae5a4SJacob Faibussowitsch {
1063ea844a1aSMatthew Knepley   PetscFunctionBegin;
1064ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1065ea844a1aSMatthew Knepley   if (numDof) {
10667c0883d5SVaclav Hapla     PetscCall(PetscSectionCheckConstraints_Private(s));
10679566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(s->bc, point, numDof));
1068ea844a1aSMatthew Knepley   }
10693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1070ea844a1aSMatthew Knepley }
1071ea844a1aSMatthew Knepley 
1072ea844a1aSMatthew Knepley /*@
1073ea844a1aSMatthew Knepley   PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point.
1074ea844a1aSMatthew Knepley 
107540750d41SVaclav Hapla   Not Collective
1076ea844a1aSMatthew Knepley 
1077ea844a1aSMatthew Knepley   Input Parameters:
1078cab54364SBarry Smith + s      - the `PetscSection`
1079ea844a1aSMatthew Knepley . point  - the point
1080ea844a1aSMatthew Knepley - numDof - the number of additional dof which are fixed by constraints
1081ea844a1aSMatthew Knepley 
1082ea844a1aSMatthew Knepley   Level: intermediate
1083ea844a1aSMatthew Knepley 
1084cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionAddDof()`, `PetscSectionGetConstraintDof()`, `PetscSectionCreate()`
1085ea844a1aSMatthew Knepley @*/
1086d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
1087d71ae5a4SJacob Faibussowitsch {
1088ea844a1aSMatthew Knepley   PetscFunctionBegin;
1089ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1090ea844a1aSMatthew Knepley   if (numDof) {
10917c0883d5SVaclav Hapla     PetscCall(PetscSectionCheckConstraints_Private(s));
10929566063dSJacob Faibussowitsch     PetscCall(PetscSectionAddDof(s->bc, point, numDof));
1093ea844a1aSMatthew Knepley   }
10943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1095ea844a1aSMatthew Knepley }
1096ea844a1aSMatthew Knepley 
1097ea844a1aSMatthew Knepley /*@
1098ea844a1aSMatthew Knepley   PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point.
1099ea844a1aSMatthew Knepley 
110040750d41SVaclav Hapla   Not Collective
1101ea844a1aSMatthew Knepley 
1102ea844a1aSMatthew Knepley   Input Parameters:
1103cab54364SBarry Smith + s     - the `PetscSection`
1104ea844a1aSMatthew Knepley . point - the point
1105ea844a1aSMatthew Knepley - field - the field
1106ea844a1aSMatthew Knepley 
1107ea844a1aSMatthew Knepley   Output Parameter:
1108ea844a1aSMatthew Knepley . numDof - the number of dof which are fixed by constraints
1109ea844a1aSMatthew Knepley 
1110ea844a1aSMatthew Knepley   Level: intermediate
1111ea844a1aSMatthew Knepley 
1112cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetFieldConstraintDof()`, `PetscSectionCreate()`
1113ea844a1aSMatthew Knepley @*/
1114d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
1115d71ae5a4SJacob Faibussowitsch {
1116ea844a1aSMatthew Knepley   PetscFunctionBegin;
1117ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
11184f572ea9SToby Isaac   PetscAssertPointer(numDof, 4);
11192abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
11209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(s->field[field], point, numDof));
11213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1122ea844a1aSMatthew Knepley }
1123ea844a1aSMatthew Knepley 
1124ea844a1aSMatthew Knepley /*@
1125ea844a1aSMatthew Knepley   PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point.
1126ea844a1aSMatthew Knepley 
112740750d41SVaclav Hapla   Not Collective
1128ea844a1aSMatthew Knepley 
1129ea844a1aSMatthew Knepley   Input Parameters:
1130cab54364SBarry Smith + s      - the `PetscSection`
1131ea844a1aSMatthew Knepley . point  - the point
1132ea844a1aSMatthew Knepley . field  - the field
1133ea844a1aSMatthew Knepley - numDof - the number of dof which are fixed by constraints
1134ea844a1aSMatthew Knepley 
1135ea844a1aSMatthew Knepley   Level: intermediate
1136ea844a1aSMatthew Knepley 
1137cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetDof()`, `PetscSectionGetFieldConstraintDof()`, `PetscSectionCreate()`
1138ea844a1aSMatthew Knepley @*/
1139d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
1140d71ae5a4SJacob Faibussowitsch {
1141ea844a1aSMatthew Knepley   PetscFunctionBegin;
1142ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
11432abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
11449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetConstraintDof(s->field[field], point, numDof));
11453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1146ea844a1aSMatthew Knepley }
1147ea844a1aSMatthew Knepley 
1148ea844a1aSMatthew Knepley /*@
1149ea844a1aSMatthew Knepley   PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point.
1150ea844a1aSMatthew Knepley 
115140750d41SVaclav Hapla   Not Collective
1152ea844a1aSMatthew Knepley 
1153ea844a1aSMatthew Knepley   Input Parameters:
1154cab54364SBarry Smith + s      - the `PetscSection`
1155ea844a1aSMatthew Knepley . point  - the point
1156ea844a1aSMatthew Knepley . field  - the field
1157ea844a1aSMatthew Knepley - numDof - the number of additional dof which are fixed by constraints
1158ea844a1aSMatthew Knepley 
1159ea844a1aSMatthew Knepley   Level: intermediate
1160ea844a1aSMatthew Knepley 
1161cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionAddDof()`, `PetscSectionGetFieldConstraintDof()`, `PetscSectionCreate()`
1162ea844a1aSMatthew Knepley @*/
1163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
1164d71ae5a4SJacob Faibussowitsch {
1165ea844a1aSMatthew Knepley   PetscFunctionBegin;
1166ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
11672abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
11689566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddConstraintDof(s->field[field], point, numDof));
11693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1170ea844a1aSMatthew Knepley }
1171ea844a1aSMatthew Knepley 
1172ea844a1aSMatthew Knepley /*@
1173ea844a1aSMatthew Knepley   PetscSectionSetUpBC - Setup the subsections describing boundary conditions.
1174ea844a1aSMatthew Knepley 
117540750d41SVaclav Hapla   Not Collective
1176ea844a1aSMatthew Knepley 
1177ea844a1aSMatthew Knepley   Input Parameter:
1178cab54364SBarry Smith . s - the `PetscSection`
1179ea844a1aSMatthew Knepley 
1180ea844a1aSMatthew Knepley   Level: advanced
1181ea844a1aSMatthew Knepley 
1182cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetUp()`, `PetscSectionCreate()`
1183ea844a1aSMatthew Knepley @*/
1184d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetUpBC(PetscSection s)
1185d71ae5a4SJacob Faibussowitsch {
1186ea844a1aSMatthew Knepley   PetscFunctionBegin;
1187ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1188ea844a1aSMatthew Knepley   if (s->bc) {
1189ea844a1aSMatthew Knepley     const PetscInt last = (s->bc->pEnd - s->bc->pStart) - 1;
1190ea844a1aSMatthew Knepley 
11919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(s->bc));
11928da24d32SBarry Smith     PetscCall(PetscMalloc1((last >= 0 ? s->bc->atlasOff[last] + s->bc->atlasDof[last] : 0), &s->bcIndices));
1193ea844a1aSMatthew Knepley   }
11943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1195ea844a1aSMatthew Knepley }
1196ea844a1aSMatthew Knepley 
1197ea844a1aSMatthew Knepley /*@
1198583308b6SBarry Smith   PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point in preparation for use of the `PetscSection`
1199ea844a1aSMatthew Knepley 
120040750d41SVaclav Hapla   Not Collective
1201ea844a1aSMatthew Knepley 
1202ea844a1aSMatthew Knepley   Input Parameter:
1203cab54364SBarry Smith . s - the `PetscSection`
1204ea844a1aSMatthew Knepley 
1205ea844a1aSMatthew Knepley   Level: intermediate
1206ea844a1aSMatthew Knepley 
1207583308b6SBarry Smith   Notes:
1208583308b6SBarry Smith   If used, `PetscSectionSetPermutation()` must be called before this routine.
1209583308b6SBarry Smith 
1210583308b6SBarry Smith   `PetscSectionSetPointMajor()`, cannot be called after this routine.
1211583308b6SBarry Smith 
1212583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionSetPermutation()`
1213ea844a1aSMatthew Knepley @*/
1214d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetUp(PetscSection s)
1215d71ae5a4SJacob Faibussowitsch {
1216ea844a1aSMatthew Knepley   const PetscInt *pind   = NULL;
1217ea844a1aSMatthew Knepley   PetscInt        offset = 0, foff, p, f;
1218ea844a1aSMatthew Knepley 
1219ea844a1aSMatthew Knepley   PetscFunctionBegin;
1220ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
12213ba16761SJacob Faibussowitsch   if (s->setup) PetscFunctionReturn(PETSC_SUCCESS);
1222ea844a1aSMatthew Knepley   s->setup = PETSC_TRUE;
1223ea844a1aSMatthew Knepley   /* Set offsets and field offsets for all points */
1224ea844a1aSMatthew Knepley   /*   Assume that all fields have the same chart */
122528b400f6SJacob Faibussowitsch   PetscCheck(s->includesConstraints, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscSectionSetUp is currently unsupported for includesConstraints = PETSC_TRUE");
12269566063dSJacob Faibussowitsch   if (s->perm) PetscCall(ISGetIndices(s->perm, &pind));
1227ea844a1aSMatthew Knepley   if (s->pointMajor) {
1228ea844a1aSMatthew Knepley     for (p = 0; p < s->pEnd - s->pStart; ++p) {
1229ea844a1aSMatthew Knepley       const PetscInt q = pind ? pind[p] : p;
1230ea844a1aSMatthew Knepley 
1231ea844a1aSMatthew Knepley       /* Set point offset */
1232ea844a1aSMatthew Knepley       s->atlasOff[q] = offset;
1233ea844a1aSMatthew Knepley       offset += s->atlasDof[q];
1234ea844a1aSMatthew Knepley       /* Set field offset */
1235ea844a1aSMatthew Knepley       for (f = 0, foff = s->atlasOff[q]; f < s->numFields; ++f) {
1236ea844a1aSMatthew Knepley         PetscSection sf = s->field[f];
1237ea844a1aSMatthew Knepley 
1238ea844a1aSMatthew Knepley         sf->atlasOff[q] = foff;
1239ea844a1aSMatthew Knepley         foff += sf->atlasDof[q];
1240ea844a1aSMatthew Knepley       }
1241ea844a1aSMatthew Knepley     }
1242ea844a1aSMatthew Knepley   } else {
1243ea844a1aSMatthew Knepley     /* Set field offsets for all points */
1244ea844a1aSMatthew Knepley     for (f = 0; f < s->numFields; ++f) {
1245ea844a1aSMatthew Knepley       PetscSection sf = s->field[f];
1246ea844a1aSMatthew Knepley 
1247ea844a1aSMatthew Knepley       for (p = 0; p < s->pEnd - s->pStart; ++p) {
1248ea844a1aSMatthew Knepley         const PetscInt q = pind ? pind[p] : p;
1249ea844a1aSMatthew Knepley 
1250ea844a1aSMatthew Knepley         sf->atlasOff[q] = offset;
1251ea844a1aSMatthew Knepley         offset += sf->atlasDof[q];
1252ea844a1aSMatthew Knepley       }
1253ea844a1aSMatthew Knepley     }
1254ea844a1aSMatthew Knepley     /* Disable point offsets since these are unused */
1255ad540459SPierre Jolivet     for (p = 0; p < s->pEnd - s->pStart; ++p) s->atlasOff[p] = -1;
1256ea844a1aSMatthew Knepley   }
12579566063dSJacob Faibussowitsch   if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind));
1258ea844a1aSMatthew Knepley   /* Setup BC sections */
12599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(s));
12609566063dSJacob Faibussowitsch   for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetUpBC(s->field[f]));
12613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1262ea844a1aSMatthew Knepley }
1263ea844a1aSMatthew Knepley 
1264ea844a1aSMatthew Knepley /*@
126520662ed9SBarry Smith   PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the `PetscSection`
1266ea844a1aSMatthew Knepley 
126740750d41SVaclav Hapla   Not Collective
1268ea844a1aSMatthew Knepley 
12692fe279fdSBarry Smith   Input Parameter:
1270cab54364SBarry Smith . s - the `PetscSection`
1271ea844a1aSMatthew Knepley 
1272ea844a1aSMatthew Knepley   Output Parameter:
1273ea844a1aSMatthew Knepley . maxDof - the maximum dof
1274ea844a1aSMatthew Knepley 
1275ea844a1aSMatthew Knepley   Level: intermediate
1276ea844a1aSMatthew Knepley 
1277583308b6SBarry Smith   Notes:
1278cab54364SBarry Smith   The returned number is up-to-date without need for `PetscSectionSetUp()`.
127969c11d05SVaclav Hapla 
1280583308b6SBarry Smith   This is the maximum over all points of the sum of the number of dof in the unnamed default field plus all named fields. This is equivalent to
1281583308b6SBarry Smith   the maximum over all points of the value returned by `PetscSectionGetDof()` on this MPI process
1282583308b6SBarry Smith 
1283583308b6SBarry Smith   Developer Notes:
128469c11d05SVaclav Hapla   The returned number is calculated lazily and stashed.
1285cab54364SBarry Smith 
1286cab54364SBarry Smith   A call to `PetscSectionInvalidateMaxDof_Internal()` invalidates the stashed value.
1287cab54364SBarry Smith 
1288cab54364SBarry Smith   `PetscSectionInvalidateMaxDof_Internal()` is called in `PetscSectionSetDof()`, `PetscSectionAddDof()` and `PetscSectionReset()`
1289cab54364SBarry Smith 
129020662ed9SBarry Smith   It should also be called every time `atlasDof` is modified directly.
129169c11d05SVaclav Hapla 
1292cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetDof()`, `PetscSectionAddDof()`, `PetscSectionCreate()`
1293ea844a1aSMatthew Knepley @*/
1294d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof)
1295d71ae5a4SJacob Faibussowitsch {
129669c11d05SVaclav Hapla   PetscInt p;
129769c11d05SVaclav Hapla 
1298ea844a1aSMatthew Knepley   PetscFunctionBegin;
1299ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
13004f572ea9SToby Isaac   PetscAssertPointer(maxDof, 2);
130169c11d05SVaclav Hapla   if (s->maxDof == PETSC_MIN_INT) {
130269c11d05SVaclav Hapla     s->maxDof = 0;
1303ad540459SPierre Jolivet     for (p = 0; p < s->pEnd - s->pStart; ++p) s->maxDof = PetscMax(s->maxDof, s->atlasDof[p]);
130469c11d05SVaclav Hapla   }
1305ea844a1aSMatthew Knepley   *maxDof = s->maxDof;
13063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1307ea844a1aSMatthew Knepley }
1308ea844a1aSMatthew Knepley 
1309ea844a1aSMatthew Knepley /*@
131020662ed9SBarry Smith   PetscSectionGetStorageSize - Return the size of an array or local `Vec` capable of holding all the degrees of freedom defined in a `PetscSection`
1311ea844a1aSMatthew Knepley 
131240750d41SVaclav Hapla   Not Collective
1313ea844a1aSMatthew Knepley 
1314ea844a1aSMatthew Knepley   Input Parameter:
1315cab54364SBarry Smith . s - the `PetscSection`
1316ea844a1aSMatthew Knepley 
1317ea844a1aSMatthew Knepley   Output Parameter:
1318ea844a1aSMatthew Knepley . size - the size of an array which can hold all the dofs
1319ea844a1aSMatthew Knepley 
1320ea844a1aSMatthew Knepley   Level: intermediate
1321ea844a1aSMatthew Knepley 
1322cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionGetConstrainedStorageSize()`, `PetscSectionCreate()`
1323ea844a1aSMatthew Knepley @*/
1324d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size)
1325d71ae5a4SJacob Faibussowitsch {
1326ea844a1aSMatthew Knepley   PetscInt p, n = 0;
1327ea844a1aSMatthew Knepley 
1328ea844a1aSMatthew Knepley   PetscFunctionBegin;
1329ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
13304f572ea9SToby Isaac   PetscAssertPointer(size, 2);
1331ea844a1aSMatthew Knepley   for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
1332ea844a1aSMatthew Knepley   *size = n;
13333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1334ea844a1aSMatthew Knepley }
1335ea844a1aSMatthew Knepley 
1336ea844a1aSMatthew Knepley /*@
133720662ed9SBarry Smith   PetscSectionGetConstrainedStorageSize - Return the size of an array or local `Vec` capable of holding all unconstrained degrees of freedom in a `PetscSection`
1338ea844a1aSMatthew Knepley 
133940750d41SVaclav Hapla   Not Collective
1340ea844a1aSMatthew Knepley 
1341064ec1f3Sprj-   Input Parameter:
1342cab54364SBarry Smith . s - the `PetscSection`
1343ea844a1aSMatthew Knepley 
1344ea844a1aSMatthew Knepley   Output Parameter:
1345ea844a1aSMatthew Knepley . size - the size of an array which can hold all unconstrained dofs
1346ea844a1aSMatthew Knepley 
1347ea844a1aSMatthew Knepley   Level: intermediate
1348ea844a1aSMatthew Knepley 
1349cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetStorageSize()`, `PetscSectionGetOffset()`, `PetscSectionCreate()`
1350ea844a1aSMatthew Knepley @*/
1351d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size)
1352d71ae5a4SJacob Faibussowitsch {
1353ea844a1aSMatthew Knepley   PetscInt p, n = 0;
1354ea844a1aSMatthew Knepley 
1355ea844a1aSMatthew Knepley   PetscFunctionBegin;
1356ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
13574f572ea9SToby Isaac   PetscAssertPointer(size, 2);
1358ea844a1aSMatthew Knepley   for (p = 0; p < s->pEnd - s->pStart; ++p) {
1359ea844a1aSMatthew Knepley     const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0;
1360ea844a1aSMatthew Knepley     n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0;
1361ea844a1aSMatthew Knepley   }
1362ea844a1aSMatthew Knepley   *size = n;
13633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1364ea844a1aSMatthew Knepley }
1365ea844a1aSMatthew Knepley 
1366ea844a1aSMatthew Knepley /*@
1367583308b6SBarry Smith   PetscSectionCreateGlobalSection - Create a parallel section describing the global layout using
1368583308b6SBarry Smith   a local (sequential) `PetscSection` on each MPI process and a `PetscSF` describing the section point overlap.
1369ea844a1aSMatthew Knepley 
1370ea844a1aSMatthew Knepley   Input Parameters:
1371cab54364SBarry Smith + s                  - The `PetscSection` for the local field layout
1372cab54364SBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points (leaves are unowned local points)
1373cab54364SBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
1374cab54364SBarry Smith - localOffsets       - If `PETSC_TRUE`, use local rather than global offsets for the points
1375ea844a1aSMatthew Knepley 
1376ea844a1aSMatthew Knepley   Output Parameter:
1377cab54364SBarry Smith . gsection - The `PetscSection` for the global field layout
1378ea844a1aSMatthew Knepley 
1379ea844a1aSMatthew Knepley   Level: intermediate
1380ea844a1aSMatthew Knepley 
1381db527f05SMatthew G. Knepley   Notes:
1382583308b6SBarry Smith   On each MPI process `gsection` inherits the chart of the `s` on that process.
1383db527f05SMatthew G. Knepley 
1384583308b6SBarry Smith   This sets negative sizes and offsets to points not owned by this process as defined by `sf` but that are within the local value of the chart of `gsection`.
1385583308b6SBarry Smith   In those locations the value of size is -(size+1) and the value of the offset on the remote process is -(off+1).
1386cab54364SBarry Smith 
138720662ed9SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionCreateGlobalSectionCensored()`
1388ea844a1aSMatthew Knepley @*/
1389d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscBool localOffsets, PetscSection *gsection)
1390d71ae5a4SJacob Faibussowitsch {
1391ea844a1aSMatthew Knepley   PetscSection    gs;
1392ea844a1aSMatthew Knepley   const PetscInt *pind = NULL;
1393ea844a1aSMatthew Knepley   PetscInt       *recv = NULL, *neg = NULL;
1394046d2115Sksagiyam   PetscInt        pStart, pEnd, p, dof, cdof, off, foff, globalOff = 0, nroots, nlocal, maxleaf;
1395046d2115Sksagiyam   PetscInt        numFields, f, numComponents;
1396ea844a1aSMatthew Knepley 
1397ea844a1aSMatthew Knepley   PetscFunctionBegin;
1398ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1399ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1400ea844a1aSMatthew Knepley   PetscValidLogicalCollectiveBool(s, includeConstraints, 3);
1401ea844a1aSMatthew Knepley   PetscValidLogicalCollectiveBool(s, localOffsets, 4);
14024f572ea9SToby Isaac   PetscAssertPointer(gsection, 5);
140328b400f6SJacob Faibussowitsch   PetscCheck(s->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering");
14049566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &gs));
14059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &numFields));
14069566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(PetscSectionSetNumFields(gs, numFields));
14079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
14089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(gs, pStart, pEnd));
140987e637c6Sksagiyam   gs->includesConstraints = includeConstraints;
14109566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
1411ea844a1aSMatthew Knepley   nlocal = nroots; /* The local/leaf space matches global/root space */
1412ea844a1aSMatthew Knepley   /* Must allocate for all points visible to SF, which may be more than this section */
1413ea844a1aSMatthew Knepley   if (nroots >= 0) { /* nroots < 0 means that the graph has not been set, only happens in serial */
14149566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRange(sf, NULL, &maxleaf));
141508401ef6SPierre Jolivet     PetscCheck(nroots >= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %" PetscInt_FMT " < pEnd %" PetscInt_FMT, nroots, pEnd);
141608401ef6SPierre Jolivet     PetscCheck(maxleaf < nroots, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Max local leaf %" PetscInt_FMT " >= nroots %" PetscInt_FMT, maxleaf, nroots);
14179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nroots, &neg, nlocal, &recv));
14189566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(neg, nroots));
1419ea844a1aSMatthew Knepley   }
1420ea844a1aSMatthew Knepley   /* Mark all local points with negative dof */
1421ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
14229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
14239566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(gs, p, dof));
14249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
14259566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(gs, p, cdof));
1426ea844a1aSMatthew Knepley     if (neg) neg[p] = -(dof + 1);
1427ea844a1aSMatthew Knepley   }
14289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(gs));
14299566063dSJacob Faibussowitsch   if (gs->bcIndices) PetscCall(PetscArraycpy(gs->bcIndices, s->bcIndices, gs->bc->atlasOff[gs->bc->pEnd - gs->bc->pStart - 1] + gs->bc->atlasDof[gs->bc->pEnd - gs->bc->pStart - 1]));
1430ea844a1aSMatthew Knepley   if (nroots >= 0) {
14319566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(recv, nlocal));
14329566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv, MPI_REPLACE));
14339566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv, MPI_REPLACE));
1434ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1435ea844a1aSMatthew Knepley       if (recv[p] < 0) {
1436ea844a1aSMatthew Knepley         gs->atlasDof[p - pStart] = recv[p];
14379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(s, p, &dof));
143808401ef6SPierre Jolivet         PetscCheck(-(recv[p] + 1) == dof, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global dof %" PetscInt_FMT " for point %" PetscInt_FMT " is not the unconstrained %" PetscInt_FMT, -(recv[p] + 1), p, dof);
1439ea844a1aSMatthew Knepley       }
1440ea844a1aSMatthew Knepley     }
1441ea844a1aSMatthew Knepley   }
1442ea844a1aSMatthew Knepley   /* Calculate new sizes, get process offset, and calculate point offsets */
14439566063dSJacob Faibussowitsch   if (s->perm) PetscCall(ISGetIndices(s->perm, &pind));
1444ea844a1aSMatthew Knepley   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
1445ea844a1aSMatthew Knepley     const PetscInt q = pind ? pind[p] : p;
1446ea844a1aSMatthew Knepley 
1447ea844a1aSMatthew Knepley     cdof            = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1448ea844a1aSMatthew Knepley     gs->atlasOff[q] = off;
1449ea844a1aSMatthew Knepley     off += gs->atlasDof[q] > 0 ? gs->atlasDof[q] - cdof : 0;
1450ea844a1aSMatthew Knepley   }
1451ea844a1aSMatthew Knepley   if (!localOffsets) {
14529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
1453ea844a1aSMatthew Knepley     globalOff -= off;
1454ea844a1aSMatthew Knepley   }
1455ea844a1aSMatthew Knepley   for (p = pStart, off = 0; p < pEnd; ++p) {
1456ea844a1aSMatthew Knepley     gs->atlasOff[p - pStart] += globalOff;
1457ea844a1aSMatthew Knepley     if (neg) neg[p] = -(gs->atlasOff[p - pStart] + 1);
1458ea844a1aSMatthew Knepley   }
14599566063dSJacob Faibussowitsch   if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind));
1460ea844a1aSMatthew Knepley   /* Put in negative offsets for ghost points */
1461ea844a1aSMatthew Knepley   if (nroots >= 0) {
14629566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(recv, nlocal));
14639566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv, MPI_REPLACE));
14649566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv, MPI_REPLACE));
1465ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1466ea844a1aSMatthew Knepley       if (recv[p] < 0) gs->atlasOff[p - pStart] = recv[p];
1467ea844a1aSMatthew Knepley     }
1468ea844a1aSMatthew Knepley   }
14699566063dSJacob Faibussowitsch   PetscCall(PetscFree2(neg, recv));
1470046d2115Sksagiyam   /* Set field dofs/offsets/constraints */
1471046d2115Sksagiyam   for (f = 0; f < numFields; ++f) {
1472046d2115Sksagiyam     gs->field[f]->includesConstraints = includeConstraints;
14739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &numComponents));
14749566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(gs, f, numComponents));
1475046d2115Sksagiyam   }
1476046d2115Sksagiyam   for (p = pStart; p < pEnd; ++p) {
14779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(gs, p, &off));
1478046d2115Sksagiyam     for (f = 0, foff = off; f < numFields; ++f) {
14799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof));
14809566063dSJacob Faibussowitsch       if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetFieldConstraintDof(gs, p, f, cdof));
14819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
14829566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(gs, p, f, off < 0 ? -(dof + 1) : dof));
14839566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldOffset(gs, p, f, foff));
14849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(gs, p, f, &cdof));
1485046d2115Sksagiyam       foff = off < 0 ? foff - (dof - cdof) : foff + (dof - cdof);
1486046d2115Sksagiyam     }
1487046d2115Sksagiyam   }
1488046d2115Sksagiyam   for (f = 0; f < numFields; ++f) {
1489046d2115Sksagiyam     PetscSection gfs = gs->field[f];
1490046d2115Sksagiyam 
14919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUpBC(gfs));
14929566063dSJacob Faibussowitsch     if (gfs->bcIndices) PetscCall(PetscArraycpy(gfs->bcIndices, s->field[f]->bcIndices, gfs->bc->atlasOff[gfs->bc->pEnd - gfs->bc->pStart - 1] + gfs->bc->atlasDof[gfs->bc->pEnd - gfs->bc->pStart - 1]));
1493046d2115Sksagiyam   }
1494046d2115Sksagiyam   gs->setup = PETSC_TRUE;
14959566063dSJacob Faibussowitsch   PetscCall(PetscSectionViewFromOptions(gs, NULL, "-global_section_view"));
1496ea844a1aSMatthew Knepley   *gsection = gs;
14973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1498ea844a1aSMatthew Knepley }
1499ea844a1aSMatthew Knepley 
1500ea844a1aSMatthew Knepley /*@
1501583308b6SBarry Smith   PetscSectionCreateGlobalSectionCensored - Create a `PetscSection` describing the globallayout using
1502583308b6SBarry Smith   a local (sequential) `PetscSection` on each MPI process and an `PetscSF` describing the section point overlap.
1503ea844a1aSMatthew Knepley 
1504ea844a1aSMatthew Knepley   Input Parameters:
1505cab54364SBarry Smith + s                  - The `PetscSection` for the local field layout
1506cab54364SBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points
1507583308b6SBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global vector will not possess constrained dofs
1508583308b6SBarry Smith . numExcludes        - The number of exclusion ranges, this must have the same value on all MPI processes
1509583308b6SBarry Smith - excludes           - An array [start_0, end_0, start_1, end_1, ...] where there are `numExcludes` pairs and must have the same values on all MPI processes
1510ea844a1aSMatthew Knepley 
1511ea844a1aSMatthew Knepley   Output Parameter:
1512cab54364SBarry Smith . gsection - The `PetscSection` for the global field layout
1513ea844a1aSMatthew Knepley 
1514ea844a1aSMatthew Knepley   Level: advanced
1515ea844a1aSMatthew Knepley 
1516583308b6SBarry Smith   Notes:
1517583308b6SBarry Smith   On each MPI process `gsection` inherits the chart of the `s` on that process.
151820662ed9SBarry Smith 
1519583308b6SBarry Smith   This sets negative sizes and offsets to points not owned by this process as defined by `sf` but that are within the local value of the chart of `gsection`.
1520583308b6SBarry Smith   In those locations the value of size is -(size+1) and the value of the offset on the remote process is -(off+1).
1521583308b6SBarry Smith 
1522583308b6SBarry Smith   This routine augments `PetscSectionCreateGlobalSection()` by allowing one to exclude certain ranges in the chart of the `PetscSection`
1523cab54364SBarry Smith 
152438b5cf2dSJacob Faibussowitsch   Developer Notes:
152520662ed9SBarry Smith   This is a terrible function name
152620662ed9SBarry Smith 
152742747ad1SJacob Faibussowitsch .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`
1528ea844a1aSMatthew Knepley @*/
1529d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection)
1530d71ae5a4SJacob Faibussowitsch {
1531ea844a1aSMatthew Knepley   const PetscInt *pind = NULL;
1532ea844a1aSMatthew Knepley   PetscInt       *neg = NULL, *tmpOff = NULL;
1533ea844a1aSMatthew Knepley   PetscInt        pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
1534ea844a1aSMatthew Knepley 
1535ea844a1aSMatthew Knepley   PetscFunctionBegin;
1536ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1537ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
15384f572ea9SToby Isaac   PetscAssertPointer(gsection, 6);
15399566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
15409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
15419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
15429566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
1543ea844a1aSMatthew Knepley   if (nroots >= 0) {
154408401ef6SPierre Jolivet     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
15459566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
1546ea844a1aSMatthew Knepley     if (nroots > pEnd - pStart) {
15479566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
1548ea844a1aSMatthew Knepley     } else {
1549ea844a1aSMatthew Knepley       tmpOff = &(*gsection)->atlasDof[-pStart];
1550ea844a1aSMatthew Knepley     }
1551ea844a1aSMatthew Knepley   }
1552ea844a1aSMatthew Knepley   /* Mark ghost points with negative dof */
1553ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1554ea844a1aSMatthew Knepley     for (e = 0; e < numExcludes; ++e) {
1555ea844a1aSMatthew Knepley       if ((p >= excludes[e * 2 + 0]) && (p < excludes[e * 2 + 1])) {
15569566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(*gsection, p, 0));
1557ea844a1aSMatthew Knepley         break;
1558ea844a1aSMatthew Knepley       }
1559ea844a1aSMatthew Knepley     }
1560ea844a1aSMatthew Knepley     if (e < numExcludes) continue;
15619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
15629566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
15639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
15649566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
1565ea844a1aSMatthew Knepley     if (neg) neg[p] = -(dof + 1);
1566ea844a1aSMatthew Knepley   }
15679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
1568ea844a1aSMatthew Knepley   if (nroots >= 0) {
15699566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
15709566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
1571ea844a1aSMatthew Knepley     if (nroots > pEnd - pStart) {
15729371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
15739371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
15749371c9d4SSatish Balay       }
1575ea844a1aSMatthew Knepley     }
1576ea844a1aSMatthew Knepley   }
157735cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
15789566063dSJacob Faibussowitsch   if (s->perm) PetscCall(ISGetIndices(s->perm, &pind));
1579ea844a1aSMatthew Knepley   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
1580ea844a1aSMatthew Knepley     const PetscInt q = pind ? pind[p] : p;
1581ea844a1aSMatthew Knepley 
1582ea844a1aSMatthew Knepley     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1583ea844a1aSMatthew Knepley     (*gsection)->atlasOff[q] = off;
1584ea844a1aSMatthew Knepley     off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q] - cdof : 0;
1585ea844a1aSMatthew Knepley   }
15869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
1587ea844a1aSMatthew Knepley   globalOff -= off;
1588ea844a1aSMatthew Knepley   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
1589ea844a1aSMatthew Knepley     (*gsection)->atlasOff[p] += globalOff;
1590ea844a1aSMatthew Knepley     if (neg) neg[p + pStart] = -((*gsection)->atlasOff[p] + 1);
1591ea844a1aSMatthew Knepley   }
15929566063dSJacob Faibussowitsch   if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind));
1593ea844a1aSMatthew Knepley   /* Put in negative offsets for ghost points */
1594ea844a1aSMatthew Knepley   if (nroots >= 0) {
1595ea844a1aSMatthew Knepley     if (nroots == pEnd - pStart) tmpOff = &(*gsection)->atlasOff[-pStart];
15969566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
15979566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
1598ea844a1aSMatthew Knepley     if (nroots > pEnd - pStart) {
15999371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
16009371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
16019371c9d4SSatish Balay       }
1602ea844a1aSMatthew Knepley     }
1603ea844a1aSMatthew Knepley   }
16049566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
16059566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
16063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1607ea844a1aSMatthew Knepley }
1608ea844a1aSMatthew Knepley 
1609ea844a1aSMatthew Knepley /*@
1610583308b6SBarry Smith   PetscSectionGetPointLayout - Get a `PetscLayout` for the points with nonzero dof counts of the unnamed default field within this `PetscSection`s local chart
1611ea844a1aSMatthew Knepley 
1612cab54364SBarry Smith   Collective
1613ea844a1aSMatthew Knepley 
1614ea844a1aSMatthew Knepley   Input Parameters:
1615cab54364SBarry Smith + comm - The `MPI_Comm`
1616cab54364SBarry Smith - s    - The `PetscSection`
1617ea844a1aSMatthew Knepley 
1618ea844a1aSMatthew Knepley   Output Parameter:
161920662ed9SBarry Smith . layout - The point layout for the data that defines the section
1620ea844a1aSMatthew Knepley 
1621ea844a1aSMatthew Knepley   Level: advanced
1622ea844a1aSMatthew Knepley 
162320662ed9SBarry Smith   Notes:
1624583308b6SBarry Smith   `PetscSectionGetValueLayout()` provides similar information but counting the total number of degrees of freedom on the MPI process (excluding constrained
1625583308b6SBarry Smith   degrees of freedom).
162620662ed9SBarry Smith 
1627583308b6SBarry Smith   This count includes constrained degrees of freedom
1628583308b6SBarry Smith 
1629583308b6SBarry Smith   This is usually called on the default global section.
1630583308b6SBarry Smith 
1631583308b6SBarry Smith   Example:
1632583308b6SBarry Smith .vb
1633583308b6SBarry Smith      The chart is [2,5), point 2 has 2 dof, point 3 has 0 dof, point 4 has 1 dof
1634583308b6SBarry Smith      The local size of the `PetscLayout` is 2 since 2 points have a non-zero number of dof
1635583308b6SBarry Smith .ve
1636583308b6SBarry Smith 
163738b5cf2dSJacob Faibussowitsch   Developer Notes:
1638583308b6SBarry Smith   I find the names of these two functions extremely non-informative
1639cab54364SBarry Smith 
1640cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetValueLayout()`, `PetscSectionCreate()`
1641ea844a1aSMatthew Knepley @*/
1642d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1643d71ae5a4SJacob Faibussowitsch {
1644ea844a1aSMatthew Knepley   PetscInt pStart, pEnd, p, localSize = 0;
1645ea844a1aSMatthew Knepley 
1646ea844a1aSMatthew Knepley   PetscFunctionBegin;
16479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1648ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1649ea844a1aSMatthew Knepley     PetscInt dof;
1650ea844a1aSMatthew Knepley 
16519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
16529120ba30SVaclav Hapla     if (dof >= 0) ++localSize;
1653ea844a1aSMatthew Knepley   }
16549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, layout));
16559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(*layout, localSize));
16569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(*layout, 1));
16579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(*layout));
16583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1659ea844a1aSMatthew Knepley }
1660ea844a1aSMatthew Knepley 
1661ea844a1aSMatthew Knepley /*@
166220662ed9SBarry Smith   PetscSectionGetValueLayout - Get the `PetscLayout` associated with the section dofs of a `PetscSection`
1663ea844a1aSMatthew Knepley 
1664cab54364SBarry Smith   Collective
1665ea844a1aSMatthew Knepley 
1666ea844a1aSMatthew Knepley   Input Parameters:
1667cab54364SBarry Smith + comm - The `MPI_Comm`
1668cab54364SBarry Smith - s    - The `PetscSection`
1669ea844a1aSMatthew Knepley 
1670ea844a1aSMatthew Knepley   Output Parameter:
1671ea844a1aSMatthew Knepley . layout - The dof layout for the section
1672ea844a1aSMatthew Knepley 
1673ea844a1aSMatthew Knepley   Level: advanced
1674ea844a1aSMatthew Knepley 
167520662ed9SBarry Smith   Notes:
1676583308b6SBarry Smith   `PetscSectionGetPointLayout()` provides similar information but only counting the number of points with nonzero degrees of freedom and
1677583308b6SBarry Smith   including the constrained degrees of freedom
167820662ed9SBarry Smith 
1679cab54364SBarry Smith   This is usually called for the default global section.
1680cab54364SBarry Smith 
1681583308b6SBarry Smith   Example:
1682583308b6SBarry Smith .vb
1683583308b6SBarry Smith      The chart is [2,5), point 2 has 4 dof (2 constrained), point 3 has 0 dof, point 4 has 1 dof (not constrained)
1684583308b6SBarry Smith      The local size of the `PetscLayout` is 3 since there are 3 unconstrained degrees of freedom on this MPI process
1685583308b6SBarry Smith .ve
1686583308b6SBarry Smith 
1687cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetPointLayout()`, `PetscSectionCreate()`
1688ea844a1aSMatthew Knepley @*/
1689d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1690d71ae5a4SJacob Faibussowitsch {
1691ea844a1aSMatthew Knepley   PetscInt pStart, pEnd, p, localSize = 0;
1692ea844a1aSMatthew Knepley 
1693ea844a1aSMatthew Knepley   PetscFunctionBegin;
1694ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2);
16954f572ea9SToby Isaac   PetscAssertPointer(layout, 3);
16969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1697ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1698ea844a1aSMatthew Knepley     PetscInt dof, cdof;
1699ea844a1aSMatthew Knepley 
17009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
17019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
1702ea844a1aSMatthew Knepley     if (dof - cdof > 0) localSize += dof - cdof;
1703ea844a1aSMatthew Knepley   }
17049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, layout));
17059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(*layout, localSize));
17069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(*layout, 1));
17079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(*layout));
17083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1709ea844a1aSMatthew Knepley }
1710ea844a1aSMatthew Knepley 
1711ea844a1aSMatthew Knepley /*@
1712db527f05SMatthew G. Knepley   PetscSectionGetOffset - Return the offset into an array or `Vec` for the dof associated with the given point.
1713ea844a1aSMatthew Knepley 
171440750d41SVaclav Hapla   Not Collective
1715ea844a1aSMatthew Knepley 
1716ea844a1aSMatthew Knepley   Input Parameters:
1717cab54364SBarry Smith + s     - the `PetscSection`
1718ea844a1aSMatthew Knepley - point - the point
1719ea844a1aSMatthew Knepley 
1720ea844a1aSMatthew Knepley   Output Parameter:
1721ea844a1aSMatthew Knepley . offset - the offset
1722ea844a1aSMatthew Knepley 
1723ea844a1aSMatthew Knepley   Level: intermediate
1724ea844a1aSMatthew Knepley 
1725583308b6SBarry Smith   Notes:
1726583308b6SBarry Smith   In a global section, this offset will be negative for points not owned by this process.
1727583308b6SBarry Smith 
1728583308b6SBarry Smith   This is for the unnamed default field in the `PetscSection` not the named fields
1729583308b6SBarry Smith 
1730583308b6SBarry Smith   The `offset` values are different depending on a value set with `PetscSectionSetPointMajor()`
1731583308b6SBarry Smith 
1732583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldOffset()`, `PetscSectionCreate()`, `PetscSectionSetPointMajor()`
1733ea844a1aSMatthew Knepley @*/
1734d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset)
1735d71ae5a4SJacob Faibussowitsch {
1736ea844a1aSMatthew Knepley   PetscFunctionBegin;
1737ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
17384f572ea9SToby Isaac   PetscAssertPointer(offset, 3);
1739b498ca8aSPierre Jolivet   PetscAssert(!(point < s->pStart) && !(point >= s->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd);
1740ea844a1aSMatthew Knepley   *offset = s->atlasOff[point - s->pStart];
17413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1742ea844a1aSMatthew Knepley }
1743ea844a1aSMatthew Knepley 
1744ea844a1aSMatthew Knepley /*@
1745db527f05SMatthew G. Knepley   PetscSectionSetOffset - Set the offset into an array or `Vec` for the dof associated with the given point.
1746ea844a1aSMatthew Knepley 
174740750d41SVaclav Hapla   Not Collective
1748ea844a1aSMatthew Knepley 
1749ea844a1aSMatthew Knepley   Input Parameters:
1750cab54364SBarry Smith + s      - the `PetscSection`
1751ea844a1aSMatthew Knepley . point  - the point
1752ea844a1aSMatthew Knepley - offset - the offset
1753ea844a1aSMatthew Knepley 
1754583308b6SBarry Smith   Level: developer
1755ea844a1aSMatthew Knepley 
1756cab54364SBarry Smith   Note:
1757cab54364SBarry Smith   The user usually does not call this function, but uses `PetscSectionSetUp()`
1758cab54364SBarry Smith 
1759cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldOffset()`, `PetscSectionCreate()`, `PetscSectionSetUp()`
1760ea844a1aSMatthew Knepley @*/
1761d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset)
1762d71ae5a4SJacob Faibussowitsch {
1763ea844a1aSMatthew Knepley   PetscFunctionBegin;
1764ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
176508401ef6SPierre Jolivet   PetscCheck(!(point < s->pStart) && !(point >= s->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd);
1766ea844a1aSMatthew Knepley   s->atlasOff[point - s->pStart] = offset;
17673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1768ea844a1aSMatthew Knepley }
1769ea844a1aSMatthew Knepley 
1770ea844a1aSMatthew Knepley /*@
1771db527f05SMatthew G. Knepley   PetscSectionGetFieldOffset - Return the offset into an array or `Vec` for the field dof associated with the given point.
1772ea844a1aSMatthew Knepley 
177340750d41SVaclav Hapla   Not Collective
1774ea844a1aSMatthew Knepley 
1775ea844a1aSMatthew Knepley   Input Parameters:
1776cab54364SBarry Smith + s     - the `PetscSection`
1777ea844a1aSMatthew Knepley . point - the point
1778ea844a1aSMatthew Knepley - field - the field
1779ea844a1aSMatthew Knepley 
1780ea844a1aSMatthew Knepley   Output Parameter:
1781ea844a1aSMatthew Knepley . offset - the offset
1782ea844a1aSMatthew Knepley 
1783ea844a1aSMatthew Knepley   Level: intermediate
1784ea844a1aSMatthew Knepley 
1785583308b6SBarry Smith   Notes:
1786583308b6SBarry Smith   In a global section, this offset will be negative for points not owned by this process.
1787583308b6SBarry Smith 
1788583308b6SBarry Smith   The `offset` values are different depending on a value set with `PetscSectionSetPointMajor()`
1789583308b6SBarry Smith 
1790583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionCreate()`, `PetscSectionGetFieldPointOffset()`
1791ea844a1aSMatthew Knepley @*/
1792d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1793d71ae5a4SJacob Faibussowitsch {
1794ea844a1aSMatthew Knepley   PetscFunctionBegin;
1795ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
17964f572ea9SToby Isaac   PetscAssertPointer(offset, 4);
17972abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
17989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(s->field[field], point, offset));
17993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1800ea844a1aSMatthew Knepley }
1801ea844a1aSMatthew Knepley 
1802ea844a1aSMatthew Knepley /*@
1803db527f05SMatthew G. Knepley   PetscSectionSetFieldOffset - Set the offset into an array or `Vec` for the dof associated with the given field at a point.
1804ea844a1aSMatthew Knepley 
180540750d41SVaclav Hapla   Not Collective
1806ea844a1aSMatthew Knepley 
1807ea844a1aSMatthew Knepley   Input Parameters:
180820662ed9SBarry Smith + s      - the `PetscSection`
1809ea844a1aSMatthew Knepley . point  - the point
1810ea844a1aSMatthew Knepley . field  - the field
1811ea844a1aSMatthew Knepley - offset - the offset
1812ea844a1aSMatthew Knepley 
1813cab54364SBarry Smith   Level: developer
1814ea844a1aSMatthew Knepley 
1815cab54364SBarry Smith   Note:
1816cab54364SBarry Smith   The user usually does not call this function, but uses `PetscSectionSetUp()`
1817ea844a1aSMatthew Knepley 
1818cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldOffset()`, `PetscSectionSetOffset()`, `PetscSectionCreate()`, `PetscSectionSetUp()`
1819ea844a1aSMatthew Knepley @*/
1820d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset)
1821d71ae5a4SJacob Faibussowitsch {
1822ea844a1aSMatthew Knepley   PetscFunctionBegin;
1823ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
18242abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
18259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetOffset(s->field[field], point, offset));
18263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1827ea844a1aSMatthew Knepley }
1828ea844a1aSMatthew Knepley 
1829ea844a1aSMatthew Knepley /*@
1830583308b6SBarry Smith   PetscSectionGetFieldPointOffset - Return the offset for the first field dof associated with the given point relative to the offset for that point for the
1831583308b6SBarry Smith   unnamed default field's first dof
1832ea844a1aSMatthew Knepley 
183340750d41SVaclav Hapla   Not Collective
1834ea844a1aSMatthew Knepley 
1835ea844a1aSMatthew Knepley   Input Parameters:
1836cab54364SBarry Smith + s     - the `PetscSection`
1837ea844a1aSMatthew Knepley . point - the point
1838ea844a1aSMatthew Knepley - field - the field
1839ea844a1aSMatthew Knepley 
1840ea844a1aSMatthew Knepley   Output Parameter:
1841ea844a1aSMatthew Knepley . offset - the offset
1842ea844a1aSMatthew Knepley 
1843ea844a1aSMatthew Knepley   Level: advanced
1844ea844a1aSMatthew Knepley 
1845cab54364SBarry Smith   Note:
1846583308b6SBarry Smith   This ignores constraints
1847cab54364SBarry Smith 
1848583308b6SBarry Smith   Example:
1849583308b6SBarry Smith .vb
1850583308b6SBarry Smith   if PetscSectionSetPointMajor(s,PETSC_TRUE)
1851583308b6SBarry Smith   The unnamed default field has 3 dof at `point`
1852583308b6SBarry Smith   Field 0 has 2 dof at `point`
1853583308b6SBarry Smith   Then PetscSectionGetFieldPointOffset(s,point,1,&offset) returns and offset of 5
1854583308b6SBarry Smith .ve
1855583308b6SBarry Smith 
1856583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionCreate()`, `PetscSectionGetFieldOffset()`
1857ea844a1aSMatthew Knepley @*/
1858d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1859d71ae5a4SJacob Faibussowitsch {
1860ea844a1aSMatthew Knepley   PetscInt off, foff;
1861ea844a1aSMatthew Knepley 
1862ea844a1aSMatthew Knepley   PetscFunctionBegin;
1863ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
18644f572ea9SToby Isaac   PetscAssertPointer(offset, 4);
18652abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
18669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(s, point, &off));
18679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(s->field[field], point, &foff));
1868ea844a1aSMatthew Knepley   *offset = foff - off;
18693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1870ea844a1aSMatthew Knepley }
1871ea844a1aSMatthew Knepley 
1872ea844a1aSMatthew Knepley /*@
187320662ed9SBarry Smith   PetscSectionGetOffsetRange - Return the full range of offsets [`start`, `end`) for a `PetscSection`
1874ea844a1aSMatthew Knepley 
187540750d41SVaclav Hapla   Not Collective
1876ea844a1aSMatthew Knepley 
1877ea844a1aSMatthew Knepley   Input Parameter:
1878cab54364SBarry Smith . s - the `PetscSection`
1879ea844a1aSMatthew Knepley 
1880ea844a1aSMatthew Knepley   Output Parameters:
1881ea844a1aSMatthew Knepley + start - the minimum offset
1882ea844a1aSMatthew Knepley - end   - one more than the maximum offset
1883ea844a1aSMatthew Knepley 
1884ea844a1aSMatthew Knepley   Level: intermediate
1885ea844a1aSMatthew Knepley 
1886cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionCreate()`
1887ea844a1aSMatthew Knepley @*/
1888d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end)
1889d71ae5a4SJacob Faibussowitsch {
1890ea844a1aSMatthew Knepley   PetscInt os = 0, oe = 0, pStart, pEnd, p;
1891ea844a1aSMatthew Knepley 
1892ea844a1aSMatthew Knepley   PetscFunctionBegin;
1893ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
18949371c9d4SSatish Balay   if (s->atlasOff) {
18959371c9d4SSatish Balay     os = s->atlasOff[0];
18969371c9d4SSatish Balay     oe = s->atlasOff[0];
18979371c9d4SSatish Balay   }
18989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1899ea844a1aSMatthew Knepley   for (p = 0; p < pEnd - pStart; ++p) {
1900ea844a1aSMatthew Knepley     PetscInt dof = s->atlasDof[p], off = s->atlasOff[p];
1901ea844a1aSMatthew Knepley 
1902ea844a1aSMatthew Knepley     if (off >= 0) {
1903ea844a1aSMatthew Knepley       os = PetscMin(os, off);
1904ea844a1aSMatthew Knepley       oe = PetscMax(oe, off + dof);
1905ea844a1aSMatthew Knepley     }
1906ea844a1aSMatthew Knepley   }
1907ea844a1aSMatthew Knepley   if (start) *start = os;
1908ea844a1aSMatthew Knepley   if (end) *end = oe;
19093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1910ea844a1aSMatthew Knepley }
1911ea844a1aSMatthew Knepley 
1912ea844a1aSMatthew Knepley /*@
1913583308b6SBarry Smith   PetscSectionCreateSubsection - Create a new, smaller `PetscSection` composed of only selected fields
1914ea844a1aSMatthew Knepley 
191540750d41SVaclav Hapla   Collective
1916ea844a1aSMatthew Knepley 
1917d8d19677SJose E. Roman   Input Parameters:
1918cab54364SBarry Smith + s      - the `PetscSection`
1919ea844a1aSMatthew Knepley . len    - the number of subfields
1920ea844a1aSMatthew Knepley - fields - the subfield numbers
1921ea844a1aSMatthew Knepley 
1922ea844a1aSMatthew Knepley   Output Parameter:
1923ea844a1aSMatthew Knepley . subs - the subsection
1924ea844a1aSMatthew Knepley 
1925ea844a1aSMatthew Knepley   Level: advanced
1926ea844a1aSMatthew Knepley 
1927cab54364SBarry Smith   Notes:
1928583308b6SBarry Smith   The chart of `subs` is the same as the chart of `s`
1929cab54364SBarry Smith 
1930cab54364SBarry Smith   This will error if a fieldnumber is out of range
1931cab54364SBarry Smith 
1932cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSupersection()`, `PetscSectionCreate()`
1933ea844a1aSMatthew Knepley @*/
1934d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt len, const PetscInt fields[], PetscSection *subs)
1935d71ae5a4SJacob Faibussowitsch {
1936b778fa18SValeria Barra   PetscInt nF, f, c, pStart, pEnd, p, maxCdof = 0;
1937ea844a1aSMatthew Knepley 
1938ea844a1aSMatthew Knepley   PetscFunctionBegin;
19393ba16761SJacob Faibussowitsch   if (!len) PetscFunctionReturn(PETSC_SUCCESS);
1940ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
19414f572ea9SToby Isaac   PetscAssertPointer(fields, 3);
19424f572ea9SToby Isaac   PetscAssertPointer(subs, 4);
19439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &nF));
194408401ef6SPierre Jolivet   PetscCheck(len <= nF, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONG, "Number of requested fields %" PetscInt_FMT " greater than number of fields %" PetscInt_FMT, len, nF);
19459566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), subs));
19469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(*subs, len));
1947ea844a1aSMatthew Knepley   for (f = 0; f < len; ++f) {
1948ea844a1aSMatthew Knepley     const char     *name    = NULL;
1949ea844a1aSMatthew Knepley     PetscInt        numComp = 0;
195042a52479SJed Brown     PetscSectionSym sym;
1951ea844a1aSMatthew Knepley 
19529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, fields[f], &name));
19539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldName(*subs, f, name));
19549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, fields[f], &numComp));
19559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp));
1956b778fa18SValeria Barra     for (c = 0; c < s->numFieldComponents[fields[f]]; ++c) {
19579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetComponentName(s, fields[f], c, &name));
19589566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetComponentName(*subs, f, c, name));
1959b778fa18SValeria Barra     }
196042a52479SJed Brown     PetscCall(PetscSectionGetFieldSym(s, fields[f], &sym));
196142a52479SJed Brown     PetscCall(PetscSectionSetFieldSym(*subs, f, sym));
1962ea844a1aSMatthew Knepley   }
19639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
19649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*subs, pStart, pEnd));
1965ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1966ea844a1aSMatthew Knepley     PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0;
1967ea844a1aSMatthew Knepley 
1968ea844a1aSMatthew Knepley     for (f = 0; f < len; ++f) {
19699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof));
19709566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(*subs, p, f, fdof));
19719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof));
19729566063dSJacob Faibussowitsch       if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof));
1973ea844a1aSMatthew Knepley       dof += fdof;
1974ea844a1aSMatthew Knepley       cdof += cfdof;
1975ea844a1aSMatthew Knepley     }
19769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*subs, p, dof));
19779566063dSJacob Faibussowitsch     if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, p, cdof));
1978ea844a1aSMatthew Knepley     maxCdof = PetscMax(cdof, maxCdof);
1979ea844a1aSMatthew Knepley   }
19809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*subs));
1981ea844a1aSMatthew Knepley   if (maxCdof) {
1982ea844a1aSMatthew Knepley     PetscInt *indices;
1983ea844a1aSMatthew Knepley 
19849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxCdof, &indices));
1985ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1986ea844a1aSMatthew Knepley       PetscInt cdof;
1987ea844a1aSMatthew Knepley 
19889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(*subs, p, &cdof));
1989ea844a1aSMatthew Knepley       if (cdof) {
1990ea844a1aSMatthew Knepley         const PetscInt *oldIndices = NULL;
1991ea844a1aSMatthew Knepley         PetscInt        fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0;
1992ea844a1aSMatthew Knepley 
1993ea844a1aSMatthew Knepley         for (f = 0; f < len; ++f) {
19949566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof));
19959566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof));
19969566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices));
19979566063dSJacob Faibussowitsch           PetscCall(PetscSectionSetFieldConstraintIndices(*subs, p, f, oldIndices));
19989574d0f0SMatthew G. Knepley           for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] = oldIndices[fc] + fOff;
1999ea844a1aSMatthew Knepley           numConst += cfdof;
2000ea844a1aSMatthew Knepley           fOff += fdof;
2001ea844a1aSMatthew Knepley         }
20029566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetConstraintIndices(*subs, p, indices));
2003ea844a1aSMatthew Knepley       }
2004ea844a1aSMatthew Knepley     }
20059566063dSJacob Faibussowitsch     PetscCall(PetscFree(indices));
2006ea844a1aSMatthew Knepley   }
20073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2008ea844a1aSMatthew Knepley }
2009ea844a1aSMatthew Knepley 
2010ea844a1aSMatthew Knepley /*@
2011583308b6SBarry Smith   PetscSectionCreateSupersection - Create a new, larger section composed of multiple `PetscSection`s
2012ea844a1aSMatthew Knepley 
201340750d41SVaclav Hapla   Collective
2014ea844a1aSMatthew Knepley 
2015ea844a1aSMatthew Knepley   Input Parameters:
2016ea844a1aSMatthew Knepley + s   - the input sections
2017ea844a1aSMatthew Knepley - len - the number of input sections
2018ea844a1aSMatthew Knepley 
2019ea844a1aSMatthew Knepley   Output Parameter:
2020ea844a1aSMatthew Knepley . supers - the supersection
2021ea844a1aSMatthew Knepley 
2022ea844a1aSMatthew Knepley   Level: advanced
2023ea844a1aSMatthew Knepley 
2024583308b6SBarry Smith   Notes:
2025cab54364SBarry Smith   The section offsets now refer to a new, larger vector.
2026cab54364SBarry Smith 
202738b5cf2dSJacob Faibussowitsch   Developer Notes:
2028cab54364SBarry Smith   Needs to explain how the sections are composed
2029cab54364SBarry Smith 
2030cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSubsection()`, `PetscSectionCreate()`
2031ea844a1aSMatthew Knepley @*/
2032d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateSupersection(PetscSection s[], PetscInt len, PetscSection *supers)
2033d71ae5a4SJacob Faibussowitsch {
2034ea844a1aSMatthew Knepley   PetscInt Nf = 0, f, pStart = PETSC_MAX_INT, pEnd = 0, p, maxCdof = 0, i;
2035ea844a1aSMatthew Knepley 
2036ea844a1aSMatthew Knepley   PetscFunctionBegin;
20373ba16761SJacob Faibussowitsch   if (!len) PetscFunctionReturn(PETSC_SUCCESS);
2038ea844a1aSMatthew Knepley   for (i = 0; i < len; ++i) {
2039ea844a1aSMatthew Knepley     PetscInt nf, pStarti, pEndi;
2040ea844a1aSMatthew Knepley 
20419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(s[i], &nf));
20429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi));
2043ea844a1aSMatthew Knepley     pStart = PetscMin(pStart, pStarti);
2044ea844a1aSMatthew Knepley     pEnd   = PetscMax(pEnd, pEndi);
2045ea844a1aSMatthew Knepley     Nf += nf;
2046ea844a1aSMatthew Knepley   }
20479566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s[0]), supers));
20489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(*supers, Nf));
2049ea844a1aSMatthew Knepley   for (i = 0, f = 0; i < len; ++i) {
2050b778fa18SValeria Barra     PetscInt nf, fi, ci;
2051ea844a1aSMatthew Knepley 
20529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(s[i], &nf));
2053ea844a1aSMatthew Knepley     for (fi = 0; fi < nf; ++fi, ++f) {
2054ea844a1aSMatthew Knepley       const char *name    = NULL;
2055ea844a1aSMatthew Knepley       PetscInt    numComp = 0;
2056ea844a1aSMatthew Knepley 
20579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(s[i], fi, &name));
20589566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldName(*supers, f, name));
20599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(s[i], fi, &numComp));
20609566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*supers, f, numComp));
2061b778fa18SValeria Barra       for (ci = 0; ci < s[i]->numFieldComponents[fi]; ++ci) {
20629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetComponentName(s[i], fi, ci, &name));
20639566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetComponentName(*supers, f, ci, name));
2064b778fa18SValeria Barra       }
2065ea844a1aSMatthew Knepley     }
2066ea844a1aSMatthew Knepley   }
20679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*supers, pStart, pEnd));
2068ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2069ea844a1aSMatthew Knepley     PetscInt dof = 0, cdof = 0;
2070ea844a1aSMatthew Knepley 
2071ea844a1aSMatthew Knepley     for (i = 0, f = 0; i < len; ++i) {
2072ea844a1aSMatthew Knepley       PetscInt nf, fi, pStarti, pEndi;
2073ea844a1aSMatthew Knepley       PetscInt fdof = 0, cfdof = 0;
2074ea844a1aSMatthew Knepley 
20759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(s[i], &nf));
20769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi));
2077ea844a1aSMatthew Knepley       if ((p < pStarti) || (p >= pEndi)) continue;
2078ea844a1aSMatthew Knepley       for (fi = 0; fi < nf; ++fi, ++f) {
20799566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof));
20809566063dSJacob Faibussowitsch         PetscCall(PetscSectionAddFieldDof(*supers, p, f, fdof));
20819566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof));
20829566063dSJacob Faibussowitsch         if (cfdof) PetscCall(PetscSectionAddFieldConstraintDof(*supers, p, f, cfdof));
2083ea844a1aSMatthew Knepley         dof += fdof;
2084ea844a1aSMatthew Knepley         cdof += cfdof;
2085ea844a1aSMatthew Knepley       }
2086ea844a1aSMatthew Knepley     }
20879566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*supers, p, dof));
20889566063dSJacob Faibussowitsch     if (cdof) PetscCall(PetscSectionSetConstraintDof(*supers, p, cdof));
2089ea844a1aSMatthew Knepley     maxCdof = PetscMax(cdof, maxCdof);
2090ea844a1aSMatthew Knepley   }
20919566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*supers));
2092ea844a1aSMatthew Knepley   if (maxCdof) {
2093ea844a1aSMatthew Knepley     PetscInt *indices;
2094ea844a1aSMatthew Knepley 
20959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxCdof, &indices));
2096ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
2097ea844a1aSMatthew Knepley       PetscInt cdof;
2098ea844a1aSMatthew Knepley 
20999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(*supers, p, &cdof));
2100ea844a1aSMatthew Knepley       if (cdof) {
2101ea844a1aSMatthew Knepley         PetscInt dof, numConst = 0, fOff = 0;
2102ea844a1aSMatthew Knepley 
2103ea844a1aSMatthew Knepley         for (i = 0, f = 0; i < len; ++i) {
2104ea844a1aSMatthew Knepley           const PetscInt *oldIndices = NULL;
2105ea844a1aSMatthew Knepley           PetscInt        nf, fi, pStarti, pEndi, fdof, cfdof, fc;
2106ea844a1aSMatthew Knepley 
21079566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetNumFields(s[i], &nf));
21089566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi));
2109ea844a1aSMatthew Knepley           if ((p < pStarti) || (p >= pEndi)) continue;
2110ea844a1aSMatthew Knepley           for (fi = 0; fi < nf; ++fi, ++f) {
21119566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof));
21129566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof));
21139566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintIndices(s[i], p, fi, &oldIndices));
2114fcd2503dSMatthew G. Knepley             for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] = oldIndices[fc];
21159566063dSJacob Faibussowitsch             PetscCall(PetscSectionSetFieldConstraintIndices(*supers, p, f, &indices[numConst]));
2116fcd2503dSMatthew G. Knepley             for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] += fOff;
2117ea844a1aSMatthew Knepley             numConst += cfdof;
2118ea844a1aSMatthew Knepley           }
21199566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(s[i], p, &dof));
2120ea844a1aSMatthew Knepley           fOff += dof;
2121ea844a1aSMatthew Knepley         }
21229566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetConstraintIndices(*supers, p, indices));
2123ea844a1aSMatthew Knepley       }
2124ea844a1aSMatthew Knepley     }
21259566063dSJacob Faibussowitsch     PetscCall(PetscFree(indices));
2126ea844a1aSMatthew Knepley   }
21273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128ea844a1aSMatthew Knepley }
2129ea844a1aSMatthew Knepley 
2130da8c939bSJacob Faibussowitsch static PetscErrorCode PetscSectionCreateSubplexSection_Private(PetscSection s, IS subpointMap, PetscBool renumberPoints, PetscSection *subs)
2131d71ae5a4SJacob Faibussowitsch {
2132ea844a1aSMatthew Knepley   const PetscInt *points = NULL, *indices = NULL;
213341f23ed0SMatthew G. Knepley   PetscInt        numFields, f, c, numSubpoints = 0, pStart, pEnd, p, spStart, spEnd, subp;
2134ea844a1aSMatthew Knepley 
2135ea844a1aSMatthew Knepley   PetscFunctionBegin;
2136ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2137ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2);
21384f572ea9SToby Isaac   PetscAssertPointer(subs, 4);
21399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &numFields));
21409566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), subs));
21419566063dSJacob Faibussowitsch   if (numFields) PetscCall(PetscSectionSetNumFields(*subs, numFields));
2142ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
2143ea844a1aSMatthew Knepley     const char *name    = NULL;
2144ea844a1aSMatthew Knepley     PetscInt    numComp = 0;
2145ea844a1aSMatthew Knepley 
21469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &name));
21479566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldName(*subs, f, name));
21489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &numComp));
21499566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp));
2150b778fa18SValeria Barra     for (c = 0; c < s->numFieldComponents[f]; ++c) {
21519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetComponentName(s, f, c, &name));
21529566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetComponentName(*subs, f, c, name));
2153b778fa18SValeria Barra     }
2154ea844a1aSMatthew Knepley   }
2155ea844a1aSMatthew Knepley   /* For right now, we do not try to squeeze the subchart */
2156ea844a1aSMatthew Knepley   if (subpointMap) {
21579566063dSJacob Faibussowitsch     PetscCall(ISGetSize(subpointMap, &numSubpoints));
21589566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(subpointMap, &points));
2159ea844a1aSMatthew Knepley   }
21609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
216141f23ed0SMatthew G. Knepley   if (renumberPoints) {
216241f23ed0SMatthew G. Knepley     spStart = 0;
216341f23ed0SMatthew G. Knepley     spEnd   = numSubpoints;
216441f23ed0SMatthew G. Knepley   } else {
216541f23ed0SMatthew G. Knepley     PetscCall(ISGetMinMax(subpointMap, &spStart, &spEnd));
216641f23ed0SMatthew G. Knepley     ++spEnd;
216741f23ed0SMatthew G. Knepley   }
216841f23ed0SMatthew G. Knepley   PetscCall(PetscSectionSetChart(*subs, spStart, spEnd));
2169ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2170ea844a1aSMatthew Knepley     PetscInt dof, cdof, fdof = 0, cfdof = 0;
2171ea844a1aSMatthew Knepley 
21729566063dSJacob Faibussowitsch     PetscCall(PetscFindInt(p, numSubpoints, points, &subp));
2173ea844a1aSMatthew Knepley     if (subp < 0) continue;
217441f23ed0SMatthew G. Knepley     if (!renumberPoints) subp = p;
2175ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
21769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof));
21779566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(*subs, subp, f, fdof));
21789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cfdof));
21799566063dSJacob Faibussowitsch       if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof));
2180ea844a1aSMatthew Knepley     }
21819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
21829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*subs, subp, dof));
21839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
21849566063dSJacob Faibussowitsch     if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, subp, cdof));
2185ea844a1aSMatthew Knepley   }
21869566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*subs));
2187ea844a1aSMatthew Knepley   /* Change offsets to original offsets */
2188ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2189ea844a1aSMatthew Knepley     PetscInt off, foff = 0;
2190ea844a1aSMatthew Knepley 
21919566063dSJacob Faibussowitsch     PetscCall(PetscFindInt(p, numSubpoints, points, &subp));
2192ea844a1aSMatthew Knepley     if (subp < 0) continue;
219341f23ed0SMatthew G. Knepley     if (!renumberPoints) subp = p;
2194ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
21959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(s, p, f, &foff));
21969566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldOffset(*subs, subp, f, foff));
2197ea844a1aSMatthew Knepley     }
21989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(s, p, &off));
21999566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetOffset(*subs, subp, off));
2200ea844a1aSMatthew Knepley   }
2201ea844a1aSMatthew Knepley   /* Copy constraint indices */
220241f23ed0SMatthew G. Knepley   for (subp = spStart; subp < spEnd; ++subp) {
2203ea844a1aSMatthew Knepley     PetscInt cdof;
2204ea844a1aSMatthew Knepley 
22059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(*subs, subp, &cdof));
2206ea844a1aSMatthew Knepley     if (cdof) {
2207ea844a1aSMatthew Knepley       for (f = 0; f < numFields; ++f) {
220841f23ed0SMatthew G. Knepley         PetscCall(PetscSectionGetFieldConstraintIndices(s, points[subp - spStart], f, &indices));
22099566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices));
2210ea844a1aSMatthew Knepley       }
221141f23ed0SMatthew G. Knepley       PetscCall(PetscSectionGetConstraintIndices(s, points[subp - spStart], &indices));
22129566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetConstraintIndices(*subs, subp, indices));
2213ea844a1aSMatthew Knepley     }
2214ea844a1aSMatthew Knepley   }
22159566063dSJacob Faibussowitsch   if (subpointMap) PetscCall(ISRestoreIndices(subpointMap, &points));
22163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2217ea844a1aSMatthew Knepley }
2218ea844a1aSMatthew Knepley 
221941f23ed0SMatthew G. Knepley /*@
222041f23ed0SMatthew G. Knepley   PetscSectionCreateSubmeshSection - Create a new, smaller section with support on the submesh
222141f23ed0SMatthew G. Knepley 
2222c3339decSBarry Smith   Collective
222341f23ed0SMatthew G. Knepley 
222441f23ed0SMatthew G. Knepley   Input Parameters:
2225cab54364SBarry Smith + s           - the `PetscSection`
222641f23ed0SMatthew G. Knepley - subpointMap - a sorted list of points in the original mesh which are in the submesh
222741f23ed0SMatthew G. Knepley 
222841f23ed0SMatthew G. Knepley   Output Parameter:
222941f23ed0SMatthew G. Knepley . subs - the subsection
223041f23ed0SMatthew G. Knepley 
2231cab54364SBarry Smith   Level: advanced
2232cab54364SBarry Smith 
2233583308b6SBarry Smith   Notes:
2234583308b6SBarry Smith   The points are renumbered from 0, and the section offsets now refer to a new, smaller vector. That is the chart of `subs` is `[0,sizeof(subpointmap))`
2235583308b6SBarry Smith 
223620662ed9SBarry Smith   Compare this with `PetscSectionCreateSubdomainSection()` that does not map the points numbers to start at zero but leaves them as before
223741f23ed0SMatthew G. Knepley 
223838b5cf2dSJacob Faibussowitsch   Developer Notes:
223920662ed9SBarry Smith   The use of the term Submesh is confusing and needs clarification, it is not specific to meshes. It appears to be just a subset of the chart of the original `PetscSection`
224041f23ed0SMatthew G. Knepley 
2241cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSubdomainSection()`, `PetscSectionCreateSubsection()`, `DMPlexGetSubpointMap()`, `PetscSectionCreate()`
224241f23ed0SMatthew G. Knepley @*/
2243d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs)
2244d71ae5a4SJacob Faibussowitsch {
224541f23ed0SMatthew G. Knepley   PetscFunctionBegin;
2246da8c939bSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubplexSection_Private(s, subpointMap, PETSC_TRUE, subs));
22473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224841f23ed0SMatthew G. Knepley }
224941f23ed0SMatthew G. Knepley 
225041f23ed0SMatthew G. Knepley /*@
225141f23ed0SMatthew G. Knepley   PetscSectionCreateSubdomainSection - Create a new, smaller section with support on a subdomain of the mesh
225241f23ed0SMatthew G. Knepley 
2253c3339decSBarry Smith   Collective
225441f23ed0SMatthew G. Knepley 
225541f23ed0SMatthew G. Knepley   Input Parameters:
2256cab54364SBarry Smith + s           - the `PetscSection`
225741f23ed0SMatthew G. Knepley - subpointMap - a sorted list of points in the original mesh which are in the subdomain
225841f23ed0SMatthew G. Knepley 
225941f23ed0SMatthew G. Knepley   Output Parameter:
226041f23ed0SMatthew G. Knepley . subs - the subsection
226141f23ed0SMatthew G. Knepley 
2262cab54364SBarry Smith   Level: advanced
2263cab54364SBarry Smith 
2264583308b6SBarry Smith   Notes:
2265583308b6SBarry Smith   The point numbers remain the same as in the larger `PetscSection`, but the section offsets now refer to a new, smaller vector. The chart of `subs`
2266583308b6SBarry Smith   is `[min(subpointMap),max(subpointMap)+1)`
2267583308b6SBarry Smith 
226820662ed9SBarry Smith   Compare this with `PetscSectionCreateSubmeshSection()` that maps the point numbers to start at zero
226941f23ed0SMatthew G. Knepley 
2270cab54364SBarry Smith   Developer Notes:
227120662ed9SBarry Smith   The use of the term Subdomain is unneeded and needs clarification, it is not specific to meshes. It appears to be just a subset of the chart of the original `PetscSection`
2272cab54364SBarry Smith 
2273cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSubmeshSection()`, `PetscSectionCreateSubsection()`, `DMPlexGetSubpointMap()`, `PetscSectionCreate()`
227441f23ed0SMatthew G. Knepley @*/
2275d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateSubdomainSection(PetscSection s, IS subpointMap, PetscSection *subs)
2276d71ae5a4SJacob Faibussowitsch {
227741f23ed0SMatthew G. Knepley   PetscFunctionBegin;
2278da8c939bSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubplexSection_Private(s, subpointMap, PETSC_FALSE, subs));
22793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
228041f23ed0SMatthew G. Knepley }
228141f23ed0SMatthew G. Knepley 
2282d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionView_ASCII(PetscSection s, PetscViewer viewer)
2283d71ae5a4SJacob Faibussowitsch {
2284ea844a1aSMatthew Knepley   PetscInt    p;
2285ea844a1aSMatthew Knepley   PetscMPIInt rank;
2286ea844a1aSMatthew Knepley 
2287ea844a1aSMatthew Knepley   PetscFunctionBegin;
22889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
22899566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
22909566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
2291ea844a1aSMatthew Knepley   for (p = 0; p < s->pEnd - s->pStart; ++p) {
2292ea844a1aSMatthew Knepley     if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
2293ea844a1aSMatthew Knepley       PetscInt b;
2294ea844a1aSMatthew Knepley 
22959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT " constrained", p + s->pStart, s->atlasDof[p], s->atlasOff[p]));
2296083401c6SMatthew G. Knepley       if (s->bcIndices) {
229748a46eb9SPierre Jolivet         for (b = 0; b < s->bc->atlasDof[p]; ++b) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, s->bcIndices[s->bc->atlasOff[p] + b]));
2298083401c6SMatthew G. Knepley       }
22999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
2300ea844a1aSMatthew Knepley     } else {
23019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT "\n", p + s->pStart, s->atlasDof[p], s->atlasOff[p]));
2302ea844a1aSMatthew Knepley     }
2303ea844a1aSMatthew Knepley   }
23049566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
23059566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
2306ea844a1aSMatthew Knepley   if (s->sym) {
23079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
23089566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymView(s->sym, viewer));
23099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
2310ea844a1aSMatthew Knepley   }
23113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2312ea844a1aSMatthew Knepley }
2313ea844a1aSMatthew Knepley 
2314ea844a1aSMatthew Knepley /*@C
2315cab54364SBarry Smith   PetscSectionViewFromOptions - View the `PetscSection` based on values in the options database
2316fe2efc57SMark 
231740750d41SVaclav Hapla   Collective
2318fe2efc57SMark 
2319fe2efc57SMark   Input Parameters:
232020662ed9SBarry Smith + A    - the `PetscSection` object to view
2321cab54364SBarry Smith . obj  - Optional object that provides the options prefix used for the options
2322736c3998SJose E. Roman - name - command line option
2323fe2efc57SMark 
2324fe2efc57SMark   Level: intermediate
2325cab54364SBarry Smith 
232620662ed9SBarry Smith   Note:
232720662ed9SBarry Smith   See `PetscObjectViewFromOptions()` for available values of `PetscViewer` and `PetscViewerFormat`
232820662ed9SBarry Smith 
2329cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionView`, `PetscObjectViewFromOptions()`, `PetscSectionCreate()`, `PetscSectionView()`
2330fe2efc57SMark @*/
2331d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionViewFromOptions(PetscSection A, PetscObject obj, const char name[])
2332d71ae5a4SJacob Faibussowitsch {
2333fe2efc57SMark   PetscFunctionBegin;
2334fe2efc57SMark   PetscValidHeaderSpecific(A, PETSC_SECTION_CLASSID, 1);
23359566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
23363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2337fe2efc57SMark }
2338fe2efc57SMark 
2339fe2efc57SMark /*@C
2340cab54364SBarry Smith   PetscSectionView - Views a `PetscSection`
2341ea844a1aSMatthew Knepley 
234240750d41SVaclav Hapla   Collective
2343ea844a1aSMatthew Knepley 
2344ea844a1aSMatthew Knepley   Input Parameters:
2345cab54364SBarry Smith + s      - the `PetscSection` object to view
234638b5cf2dSJacob Faibussowitsch - viewer - the viewer
2347ea844a1aSMatthew Knepley 
2348cab54364SBarry Smith   Level: beginner
2349cab54364SBarry Smith 
23501ddd528eSksagiyam   Note:
2351cab54364SBarry Smith   `PetscSectionView()`, when viewer is of type `PETSCVIEWERHDF5`, only saves
23521ddd528eSksagiyam   distribution independent data, such as dofs, offsets, constraint dofs,
23531ddd528eSksagiyam   and constraint indices. Points that have negative dofs, for instance,
23541ddd528eSksagiyam   are not saved as they represent points owned by other processes.
23551ddd528eSksagiyam   Point numbering and rank assignment is currently not stored.
2356cab54364SBarry Smith   The saved section can be loaded with `PetscSectionLoad()`.
23571ddd528eSksagiyam 
2358cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionLoad()`, `PetscViewer`
2359ea844a1aSMatthew Knepley @*/
2360d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer)
2361d71ae5a4SJacob Faibussowitsch {
23621ddd528eSksagiyam   PetscBool isascii, ishdf5;
2363ea844a1aSMatthew Knepley   PetscInt  f;
2364ea844a1aSMatthew Knepley 
2365ea844a1aSMatthew Knepley   PetscFunctionBegin;
2366ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
23679566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)s), &viewer));
2368ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
23709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2371ea844a1aSMatthew Knepley   if (isascii) {
23729566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)s, viewer));
2373ea844a1aSMatthew Knepley     if (s->numFields) {
23749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " fields\n", s->numFields));
2375ea844a1aSMatthew Knepley       for (f = 0; f < s->numFields; ++f) {
23769566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  field %" PetscInt_FMT " with %" PetscInt_FMT " components\n", f, s->numFieldComponents[f]));
23779566063dSJacob Faibussowitsch         PetscCall(PetscSectionView_ASCII(s->field[f], viewer));
2378ea844a1aSMatthew Knepley       }
2379ea844a1aSMatthew Knepley     } else {
23809566063dSJacob Faibussowitsch       PetscCall(PetscSectionView_ASCII(s, viewer));
2381ea844a1aSMatthew Knepley     }
23821ddd528eSksagiyam   } else if (ishdf5) {
23831ddd528eSksagiyam #if PetscDefined(HAVE_HDF5)
23849566063dSJacob Faibussowitsch     PetscCall(PetscSectionView_HDF5_Internal(s, viewer));
23851ddd528eSksagiyam #else
23861ddd528eSksagiyam     SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23871ddd528eSksagiyam #endif
2388ea844a1aSMatthew Knepley   }
23893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2390ea844a1aSMatthew Knepley }
2391ea844a1aSMatthew Knepley 
2392fde5e3acSksagiyam /*@C
2393cab54364SBarry Smith   PetscSectionLoad - Loads a `PetscSection`
2394fde5e3acSksagiyam 
239540750d41SVaclav Hapla   Collective
2396fde5e3acSksagiyam 
2397fde5e3acSksagiyam   Input Parameters:
2398cab54364SBarry Smith + s      - the `PetscSection` object to load
239938b5cf2dSJacob Faibussowitsch - viewer - the viewer
2400fde5e3acSksagiyam 
2401cab54364SBarry Smith   Level: beginner
2402cab54364SBarry Smith 
2403fde5e3acSksagiyam   Note:
2404cab54364SBarry Smith   `PetscSectionLoad()`, when viewer is of type `PETSCVIEWERHDF5`, loads
2405cab54364SBarry Smith   a section saved with `PetscSectionView()`. The number of processes
2406fde5e3acSksagiyam   used here (N) does not need to be the same as that used when saving.
2407fde5e3acSksagiyam   After calling this function, the chart of s on rank i will be set
2408fde5e3acSksagiyam   to [0, E_i), where \sum_{i=0}^{N-1}E_i equals to the total number of
2409fde5e3acSksagiyam   saved section points.
2410fde5e3acSksagiyam 
2411cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionView()`
2412fde5e3acSksagiyam @*/
2413d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionLoad(PetscSection s, PetscViewer viewer)
2414d71ae5a4SJacob Faibussowitsch {
2415fde5e3acSksagiyam   PetscBool ishdf5;
2416fde5e3acSksagiyam 
2417fde5e3acSksagiyam   PetscFunctionBegin;
2418fde5e3acSksagiyam   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2419fde5e3acSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2421fde5e3acSksagiyam   if (ishdf5) {
2422fde5e3acSksagiyam #if PetscDefined(HAVE_HDF5)
24239566063dSJacob Faibussowitsch     PetscCall(PetscSectionLoad_HDF5_Internal(s, viewer));
24243ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2425fde5e3acSksagiyam #else
2426fde5e3acSksagiyam     SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2427fde5e3acSksagiyam #endif
242898921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "Viewer type %s not yet supported for PetscSection loading", ((PetscObject)viewer)->type_name);
2429fde5e3acSksagiyam }
2430fde5e3acSksagiyam 
2431d4a1ad33SMatthew G. Knepley /*@
2432d4a1ad33SMatthew G. Knepley   PetscSectionResetClosurePermutation - Remove any existing closure permutation
2433d4a1ad33SMatthew G. Knepley 
2434d4a1ad33SMatthew G. Knepley   Input Parameter:
2435e8e188d2SZach Atkins . section - The `PetscSection`
2436d4a1ad33SMatthew G. Knepley 
2437d4a1ad33SMatthew G. Knepley   Level: intermediate
2438d4a1ad33SMatthew G. Knepley 
2439e8e188d2SZach Atkins .seealso: `PetscSectionSetClosurePermutation()`, `PetscSectionSetClosureIndex()`, `PetscSectionReset()`
2440d4a1ad33SMatthew G. Knepley @*/
2441d4a1ad33SMatthew G. Knepley PetscErrorCode PetscSectionResetClosurePermutation(PetscSection section)
2442d71ae5a4SJacob Faibussowitsch {
2443c459fbc1SJed Brown   PetscSectionClosurePermVal clVal;
2444c459fbc1SJed Brown 
2445c459fbc1SJed Brown   PetscFunctionBegin;
24463ba16761SJacob Faibussowitsch   if (!section->clHash) PetscFunctionReturn(PETSC_SUCCESS);
2447c459fbc1SJed Brown   kh_foreach_value(section->clHash, clVal, {
24489566063dSJacob Faibussowitsch     PetscCall(PetscFree(clVal.perm));
24499566063dSJacob Faibussowitsch     PetscCall(PetscFree(clVal.invPerm));
2450c459fbc1SJed Brown   });
2451c459fbc1SJed Brown   kh_destroy(ClPerm, section->clHash);
2452c459fbc1SJed Brown   section->clHash = NULL;
24533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2454c459fbc1SJed Brown }
2455c459fbc1SJed Brown 
2456ea844a1aSMatthew Knepley /*@
2457583308b6SBarry Smith   PetscSectionReset - Frees all section data, the section is then as if `PetscSectionCreate()` had just been called.
2458ea844a1aSMatthew Knepley 
245940750d41SVaclav Hapla   Not Collective
2460ea844a1aSMatthew Knepley 
24612fe279fdSBarry Smith   Input Parameter:
2462cab54364SBarry Smith . s - the `PetscSection`
2463ea844a1aSMatthew Knepley 
2464ea844a1aSMatthew Knepley   Level: beginner
2465ea844a1aSMatthew Knepley 
2466cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`
2467ea844a1aSMatthew Knepley @*/
2468d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionReset(PetscSection s)
2469d71ae5a4SJacob Faibussowitsch {
2470b778fa18SValeria Barra   PetscInt f, c;
2471ea844a1aSMatthew Knepley 
2472ea844a1aSMatthew Knepley   PetscFunctionBegin;
2473ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2474ea844a1aSMatthew Knepley   for (f = 0; f < s->numFields; ++f) {
24759566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&s->field[f]));
24769566063dSJacob Faibussowitsch     PetscCall(PetscFree(s->fieldNames[f]));
247748a46eb9SPierre Jolivet     for (c = 0; c < s->numFieldComponents[f]; ++c) PetscCall(PetscFree(s->compNames[f][c]));
24789566063dSJacob Faibussowitsch     PetscCall(PetscFree(s->compNames[f]));
2479ea844a1aSMatthew Knepley   }
24809566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->numFieldComponents));
24819566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->fieldNames));
24829566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->compNames));
24839566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->field));
24849566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s->bc));
24859566063dSJacob Faibussowitsch   PetscCall(PetscFree(s->bcIndices));
24869566063dSJacob Faibussowitsch   PetscCall(PetscFree2(s->atlasDof, s->atlasOff));
24879566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s->clSection));
24889566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&s->clPoints));
24899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&s->perm));
2490d4a1ad33SMatthew G. Knepley   PetscCall(PetscSectionResetClosurePermutation(s));
24919566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymDestroy(&s->sym));
24929566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s->clSection));
24939566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&s->clPoints));
249469c11d05SVaclav Hapla   PetscCall(PetscSectionInvalidateMaxDof_Internal(s));
2495ea844a1aSMatthew Knepley   s->pStart    = -1;
2496ea844a1aSMatthew Knepley   s->pEnd      = -1;
2497ea844a1aSMatthew Knepley   s->maxDof    = 0;
2498ea844a1aSMatthew Knepley   s->setup     = PETSC_FALSE;
2499ea844a1aSMatthew Knepley   s->numFields = 0;
2500ea844a1aSMatthew Knepley   s->clObj     = NULL;
25013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2502ea844a1aSMatthew Knepley }
2503ea844a1aSMatthew Knepley 
2504ea844a1aSMatthew Knepley /*@
2505583308b6SBarry Smith   PetscSectionDestroy - Frees a `PetscSection`
2506ea844a1aSMatthew Knepley 
250740750d41SVaclav Hapla   Not Collective
2508ea844a1aSMatthew Knepley 
25092fe279fdSBarry Smith   Input Parameter:
2510cab54364SBarry Smith . s - the `PetscSection`
2511ea844a1aSMatthew Knepley 
2512ea844a1aSMatthew Knepley   Level: beginner
2513ea844a1aSMatthew Knepley 
2514cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionReset()`
2515ea844a1aSMatthew Knepley @*/
2516d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionDestroy(PetscSection *s)
2517d71ae5a4SJacob Faibussowitsch {
2518ea844a1aSMatthew Knepley   PetscFunctionBegin;
25193ba16761SJacob Faibussowitsch   if (!*s) PetscFunctionReturn(PETSC_SUCCESS);
252062f17a49SStefano Zampini   PetscValidHeaderSpecific(*s, PETSC_SECTION_CLASSID, 1);
2521ea844a1aSMatthew Knepley   if (--((PetscObject)(*s))->refct > 0) {
2522ea844a1aSMatthew Knepley     *s = NULL;
25233ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2524ea844a1aSMatthew Knepley   }
25259566063dSJacob Faibussowitsch   PetscCall(PetscSectionReset(*s));
25269566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(s));
25273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2528ea844a1aSMatthew Knepley }
2529ea844a1aSMatthew Knepley 
2530da8c939bSJacob Faibussowitsch static PetscErrorCode VecIntGetValuesSection_Private(const PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values)
2531d71ae5a4SJacob Faibussowitsch {
2532ea844a1aSMatthew Knepley   const PetscInt p = point - s->pStart;
2533ea844a1aSMatthew Knepley 
2534ea844a1aSMatthew Knepley   PetscFunctionBegin;
2535ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2);
2536ea844a1aSMatthew Knepley   *values = &baseArray[s->atlasOff[p]];
25373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2538ea844a1aSMatthew Knepley }
2539ea844a1aSMatthew Knepley 
2540da8c939bSJacob Faibussowitsch static PetscErrorCode VecIntSetValuesSection_Private(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode)
2541d71ae5a4SJacob Faibussowitsch {
2542ea844a1aSMatthew Knepley   PetscInt      *array;
2543ea844a1aSMatthew Knepley   const PetscInt p           = point - s->pStart;
2544ea844a1aSMatthew Knepley   const PetscInt orientation = 0; /* Needs to be included for use in closure operations */
2545ea844a1aSMatthew Knepley   PetscInt       cDim        = 0;
2546ea844a1aSMatthew Knepley 
2547ea844a1aSMatthew Knepley   PetscFunctionBegin;
2548ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2);
25499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(s, p, &cDim));
2550ea844a1aSMatthew Knepley   array = &baseArray[s->atlasOff[p]];
2551ea844a1aSMatthew Knepley   if (!cDim) {
2552ea844a1aSMatthew Knepley     if (orientation >= 0) {
2553ea844a1aSMatthew Knepley       const PetscInt dim = s->atlasDof[p];
2554ea844a1aSMatthew Knepley       PetscInt       i;
2555ea844a1aSMatthew Knepley 
2556ea844a1aSMatthew Knepley       if (mode == INSERT_VALUES) {
2557ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) array[i] = values[i];
2558ea844a1aSMatthew Knepley       } else {
2559ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) array[i] += values[i];
2560ea844a1aSMatthew Knepley       }
2561ea844a1aSMatthew Knepley     } else {
2562ea844a1aSMatthew Knepley       PetscInt offset = 0;
2563ea844a1aSMatthew Knepley       PetscInt j      = -1, field, i;
2564ea844a1aSMatthew Knepley 
2565ea844a1aSMatthew Knepley       for (field = 0; field < s->numFields; ++field) {
2566ea844a1aSMatthew Knepley         const PetscInt dim = s->field[field]->atlasDof[p];
2567ea844a1aSMatthew Knepley 
2568ea844a1aSMatthew Knepley         for (i = dim - 1; i >= 0; --i) array[++j] = values[i + offset];
2569ea844a1aSMatthew Knepley         offset += dim;
2570ea844a1aSMatthew Knepley       }
2571ea844a1aSMatthew Knepley     }
2572ea844a1aSMatthew Knepley   } else {
2573ea844a1aSMatthew Knepley     if (orientation >= 0) {
2574ea844a1aSMatthew Knepley       const PetscInt  dim  = s->atlasDof[p];
2575ea844a1aSMatthew Knepley       PetscInt        cInd = 0, i;
2576ea844a1aSMatthew Knepley       const PetscInt *cDof;
2577ea844a1aSMatthew Knepley 
25789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof));
2579ea844a1aSMatthew Knepley       if (mode == INSERT_VALUES) {
2580ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) {
25819371c9d4SSatish Balay           if ((cInd < cDim) && (i == cDof[cInd])) {
25829371c9d4SSatish Balay             ++cInd;
25839371c9d4SSatish Balay             continue;
25849371c9d4SSatish Balay           }
2585ea844a1aSMatthew Knepley           array[i] = values[i];
2586ea844a1aSMatthew Knepley         }
2587ea844a1aSMatthew Knepley       } else {
2588ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) {
25899371c9d4SSatish Balay           if ((cInd < cDim) && (i == cDof[cInd])) {
25909371c9d4SSatish Balay             ++cInd;
25919371c9d4SSatish Balay             continue;
25929371c9d4SSatish Balay           }
2593ea844a1aSMatthew Knepley           array[i] += values[i];
2594ea844a1aSMatthew Knepley         }
2595ea844a1aSMatthew Knepley       }
2596ea844a1aSMatthew Knepley     } else {
2597ea844a1aSMatthew Knepley       const PetscInt *cDof;
2598ea844a1aSMatthew Knepley       PetscInt        offset  = 0;
2599ea844a1aSMatthew Knepley       PetscInt        cOffset = 0;
2600ea844a1aSMatthew Knepley       PetscInt        j       = 0, field;
2601ea844a1aSMatthew Knepley 
26029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof));
2603ea844a1aSMatthew Knepley       for (field = 0; field < s->numFields; ++field) {
2604ea844a1aSMatthew Knepley         const PetscInt dim  = s->field[field]->atlasDof[p];     /* PetscSectionGetFieldDof() */
2605ea844a1aSMatthew Knepley         const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */
2606ea844a1aSMatthew Knepley         const PetscInt sDim = dim - tDim;
2607ea844a1aSMatthew Knepley         PetscInt       cInd = 0, i, k;
2608ea844a1aSMatthew Knepley 
2609ea844a1aSMatthew Knepley         for (i = 0, k = dim + offset - 1; i < dim; ++i, ++j, --k) {
26109371c9d4SSatish Balay           if ((cInd < sDim) && (j == cDof[cInd + cOffset])) {
26119371c9d4SSatish Balay             ++cInd;
26129371c9d4SSatish Balay             continue;
26139371c9d4SSatish Balay           }
2614ea844a1aSMatthew Knepley           array[j] = values[k];
2615ea844a1aSMatthew Knepley         }
2616ea844a1aSMatthew Knepley         offset += dim;
2617ea844a1aSMatthew Knepley         cOffset += dim - tDim;
2618ea844a1aSMatthew Knepley       }
2619ea844a1aSMatthew Knepley     }
2620ea844a1aSMatthew Knepley   }
26213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2622ea844a1aSMatthew Knepley }
2623ea844a1aSMatthew Knepley 
2624ea844a1aSMatthew Knepley /*@C
262520662ed9SBarry Smith   PetscSectionHasConstraints - Determine whether a `PetscSection` has constrained dofs
2626ea844a1aSMatthew Knepley 
262740750d41SVaclav Hapla   Not Collective
2628ea844a1aSMatthew Knepley 
2629ea844a1aSMatthew Knepley   Input Parameter:
2630cab54364SBarry Smith . s - The `PetscSection`
2631ea844a1aSMatthew Knepley 
2632ea844a1aSMatthew Knepley   Output Parameter:
2633ea844a1aSMatthew Knepley . hasConstraints - flag indicating that the section has constrained dofs
2634ea844a1aSMatthew Knepley 
2635ea844a1aSMatthew Knepley   Level: intermediate
2636ea844a1aSMatthew Knepley 
2637cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2638ea844a1aSMatthew Knepley @*/
2639d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints)
2640d71ae5a4SJacob Faibussowitsch {
2641ea844a1aSMatthew Knepley   PetscFunctionBegin;
2642ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
26434f572ea9SToby Isaac   PetscAssertPointer(hasConstraints, 2);
2644ea844a1aSMatthew Knepley   *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE;
26453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2646ea844a1aSMatthew Knepley }
2647ea844a1aSMatthew Knepley 
2648ea844a1aSMatthew Knepley /*@C
264920662ed9SBarry Smith   PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained for a given point
2650ea844a1aSMatthew Knepley 
265140750d41SVaclav Hapla   Not Collective
2652ea844a1aSMatthew Knepley 
2653ea844a1aSMatthew Knepley   Input Parameters:
2654cab54364SBarry Smith + s     - The `PetscSection`
2655ea844a1aSMatthew Knepley - point - The point
2656ea844a1aSMatthew Knepley 
2657ea844a1aSMatthew Knepley   Output Parameter:
2658ea844a1aSMatthew Knepley . indices - The constrained dofs
2659ea844a1aSMatthew Knepley 
2660ea844a1aSMatthew Knepley   Level: intermediate
2661ea844a1aSMatthew Knepley 
266238b5cf2dSJacob Faibussowitsch   Fortran Notes:
266320662ed9SBarry Smith   Use `PetscSectionGetConstraintIndicesF90()` and `PetscSectionRestoreConstraintIndicesF90()`
2664cab54364SBarry Smith 
2665cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2666ea844a1aSMatthew Knepley @*/
2667d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices)
2668d71ae5a4SJacob Faibussowitsch {
2669ea844a1aSMatthew Knepley   PetscFunctionBegin;
2670ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2671ea844a1aSMatthew Knepley   if (s->bc) {
2672da8c939bSJacob Faibussowitsch     PetscCall(VecIntGetValuesSection_Private(s->bcIndices, s->bc, point, indices));
2673ea844a1aSMatthew Knepley   } else *indices = NULL;
26743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2675ea844a1aSMatthew Knepley }
2676ea844a1aSMatthew Knepley 
2677ea844a1aSMatthew Knepley /*@C
2678ea844a1aSMatthew Knepley   PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained
2679ea844a1aSMatthew Knepley 
268040750d41SVaclav Hapla   Not Collective
2681ea844a1aSMatthew Knepley 
2682ea844a1aSMatthew Knepley   Input Parameters:
2683cab54364SBarry Smith + s       - The `PetscSection`
2684ea844a1aSMatthew Knepley . point   - The point
2685ea844a1aSMatthew Knepley - indices - The constrained dofs
2686ea844a1aSMatthew Knepley 
2687ea844a1aSMatthew Knepley   Level: intermediate
2688ea844a1aSMatthew Knepley 
268938b5cf2dSJacob Faibussowitsch   Fortran Notes:
2690cab54364SBarry Smith   Use `PetscSectionSetConstraintIndicesF90()`
2691cab54364SBarry Smith 
2692cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionGetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2693ea844a1aSMatthew Knepley @*/
2694d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[])
2695d71ae5a4SJacob Faibussowitsch {
2696ea844a1aSMatthew Knepley   PetscFunctionBegin;
2697ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2698ea844a1aSMatthew Knepley   if (s->bc) {
2699d57bb9dbSMatthew G. Knepley     const PetscInt dof  = s->atlasDof[point];
2700d57bb9dbSMatthew G. Knepley     const PetscInt cdof = s->bc->atlasDof[point];
2701d57bb9dbSMatthew G. Knepley     PetscInt       d;
2702d57bb9dbSMatthew G. Knepley 
2703ad540459SPierre Jolivet     for (d = 0; d < cdof; ++d) PetscCheck(indices[d] < dof, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " dof %" PetscInt_FMT ", invalid constraint index[%" PetscInt_FMT "]: %" PetscInt_FMT, point, dof, d, indices[d]);
2704da8c939bSJacob Faibussowitsch     PetscCall(VecIntSetValuesSection_Private(s->bcIndices, s->bc, point, indices, INSERT_VALUES));
2705ea844a1aSMatthew Knepley   }
27063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2707ea844a1aSMatthew Knepley }
2708ea844a1aSMatthew Knepley 
2709ea844a1aSMatthew Knepley /*@C
2710ea844a1aSMatthew Knepley   PetscSectionGetFieldConstraintIndices - Get the field dof numbers, in [0, fdof), which are constrained
2711ea844a1aSMatthew Knepley 
271240750d41SVaclav Hapla   Not Collective
2713ea844a1aSMatthew Knepley 
2714ea844a1aSMatthew Knepley   Input Parameters:
2715cab54364SBarry Smith + s     - The `PetscSection`
2716ea844a1aSMatthew Knepley . field - The field number
2717ea844a1aSMatthew Knepley - point - The point
2718ea844a1aSMatthew Knepley 
2719ea844a1aSMatthew Knepley   Output Parameter:
27209759eb26SJed Brown . indices - The constrained dofs sorted in ascending order
2721ea844a1aSMatthew Knepley 
2722ea844a1aSMatthew Knepley   Level: intermediate
2723ea844a1aSMatthew Knepley 
2724cab54364SBarry Smith   Note:
2725cab54364SBarry Smith   The indices array, which is provided by the caller, must have capacity to hold the number of constrained dofs, e.g., as returned by `PetscSectionGetConstraintDof()`.
2726cab54364SBarry Smith 
272738b5cf2dSJacob Faibussowitsch   Fortran Notes:
272820662ed9SBarry Smith   Use `PetscSectionGetFieldConstraintIndicesF90()` and `PetscSectionRestoreFieldConstraintIndicesF90()`
2729cab54364SBarry Smith 
2730cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSetFieldConstraintIndices()`, `PetscSectionGetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2731ea844a1aSMatthew Knepley @*/
2732d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices)
2733d71ae5a4SJacob Faibussowitsch {
2734ea844a1aSMatthew Knepley   PetscFunctionBegin;
2735ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
27364f572ea9SToby Isaac   PetscAssertPointer(indices, 4);
27372abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
27389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintIndices(s->field[field], point, indices));
27393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2740ea844a1aSMatthew Knepley }
2741ea844a1aSMatthew Knepley 
2742ea844a1aSMatthew Knepley /*@C
2743ea844a1aSMatthew Knepley   PetscSectionSetFieldConstraintIndices - Set the field dof numbers, in [0, fdof), which are constrained
2744ea844a1aSMatthew Knepley 
274540750d41SVaclav Hapla   Not Collective
2746ea844a1aSMatthew Knepley 
2747ea844a1aSMatthew Knepley   Input Parameters:
2748cab54364SBarry Smith + s       - The `PetscSection`
2749ea844a1aSMatthew Knepley . point   - The point
2750ea844a1aSMatthew Knepley . field   - The field number
2751ea844a1aSMatthew Knepley - indices - The constrained dofs
2752ea844a1aSMatthew Knepley 
2753ea844a1aSMatthew Knepley   Level: intermediate
2754ea844a1aSMatthew Knepley 
275538b5cf2dSJacob Faibussowitsch   Fortran Notes:
2756cab54364SBarry Smith   Use `PetscSectionSetFieldConstraintIndicesF90()`
2757cab54364SBarry Smith 
2758cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSetConstraintIndices()`, `PetscSectionGetFieldConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2759ea844a1aSMatthew Knepley @*/
2760d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[])
2761d71ae5a4SJacob Faibussowitsch {
2762ea844a1aSMatthew Knepley   PetscFunctionBegin;
2763ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
27642abc8c78SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
2765e2bfaee7SMatthew G. Knepley     PetscInt nfdof;
27662abc8c78SJacob Faibussowitsch 
27679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(s, point, field, &nfdof));
27684f572ea9SToby Isaac     if (nfdof) PetscAssertPointer(indices, 4);
27692abc8c78SJacob Faibussowitsch   }
27702abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
27719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetConstraintIndices(s->field[field], point, indices));
27723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2773ea844a1aSMatthew Knepley }
2774ea844a1aSMatthew Knepley 
2775ea844a1aSMatthew Knepley /*@
2776ea844a1aSMatthew Knepley   PetscSectionPermute - Reorder the section according to the input point permutation
2777ea844a1aSMatthew Knepley 
277840750d41SVaclav Hapla   Collective
2779ea844a1aSMatthew Knepley 
2780d8d19677SJose E. Roman   Input Parameters:
2781cab54364SBarry Smith + section     - The `PetscSection` object
278238b5cf2dSJacob Faibussowitsch - permutation - The point permutation, old point p becomes new point perm[p]
2783ea844a1aSMatthew Knepley 
2784ea844a1aSMatthew Knepley   Output Parameter:
2785cab54364SBarry Smith . sectionNew - The permuted `PetscSection`
2786ea844a1aSMatthew Knepley 
2787ea844a1aSMatthew Knepley   Level: intermediate
2788ea844a1aSMatthew Knepley 
2789583308b6SBarry Smith   Note:
2790583308b6SBarry Smith   The data and the access to the data via `PetscSectionGetFieldOffset()` and `PetscSectionGetOffset()` are both changed in `sectionNew`
2791583308b6SBarry Smith 
2792583308b6SBarry Smith   Compare to `PetscSectionSetPermutation()`
2793583308b6SBarry Smith 
2794583308b6SBarry Smith .seealso: [PetscSection](sec_petscsection), `IS`, `PetscSection`, `MatPermute()`, `PetscSectionSetPermutation()`
2795ea844a1aSMatthew Knepley @*/
2796d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew)
2797d71ae5a4SJacob Faibussowitsch {
2798ea844a1aSMatthew Knepley   PetscSection    s = section, sNew;
2799ea844a1aSMatthew Knepley   const PetscInt *perm;
2800b778fa18SValeria Barra   PetscInt        numFields, f, c, numPoints, pStart, pEnd, p;
2801ea844a1aSMatthew Knepley 
2802ea844a1aSMatthew Knepley   PetscFunctionBegin;
2803ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
2804ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
28054f572ea9SToby Isaac   PetscAssertPointer(sectionNew, 3);
28069566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &sNew));
28079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &numFields));
28089566063dSJacob Faibussowitsch   if (numFields) PetscCall(PetscSectionSetNumFields(sNew, numFields));
2809ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
2810ea844a1aSMatthew Knepley     const char *name;
2811ea844a1aSMatthew Knepley     PetscInt    numComp;
2812ea844a1aSMatthew Knepley 
28139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &name));
28149566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldName(sNew, f, name));
28159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &numComp));
28169566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(sNew, f, numComp));
2817b778fa18SValeria Barra     for (c = 0; c < s->numFieldComponents[f]; ++c) {
28189566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetComponentName(s, f, c, &name));
28199566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetComponentName(sNew, f, c, name));
2820b778fa18SValeria Barra     }
2821ea844a1aSMatthew Knepley   }
28229566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
28239566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
28249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
28259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(sNew, pStart, pEnd));
282608401ef6SPierre Jolivet   PetscCheck(numPoints >= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %" PetscInt_FMT " is less than largest Section point %" PetscInt_FMT, numPoints, pEnd);
2827ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2828ea844a1aSMatthew Knepley     PetscInt dof, cdof;
2829ea844a1aSMatthew Knepley 
28309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
28319566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(sNew, perm[p], dof));
28329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
28339566063dSJacob Faibussowitsch     if (cdof) PetscCall(PetscSectionSetConstraintDof(sNew, perm[p], cdof));
2834ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
28359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
28369566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(sNew, perm[p], f, dof));
28379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof));
28389566063dSJacob Faibussowitsch       if (cdof) PetscCall(PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof));
2839ea844a1aSMatthew Knepley     }
2840ea844a1aSMatthew Knepley   }
28419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(sNew));
2842ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2843ea844a1aSMatthew Knepley     const PetscInt *cind;
2844ea844a1aSMatthew Knepley     PetscInt        cdof;
2845ea844a1aSMatthew Knepley 
28469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
2847ea844a1aSMatthew Knepley     if (cdof) {
28489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintIndices(s, p, &cind));
28499566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetConstraintIndices(sNew, perm[p], cind));
2850ea844a1aSMatthew Knepley     }
2851ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
28529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof));
2853ea844a1aSMatthew Knepley       if (cdof) {
28549566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldConstraintIndices(s, p, f, &cind));
28559566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind));
2856ea844a1aSMatthew Knepley       }
2857ea844a1aSMatthew Knepley     }
2858ea844a1aSMatthew Knepley   }
28599566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
2860ea844a1aSMatthew Knepley   *sectionNew = sNew;
28613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2862ea844a1aSMatthew Knepley }
2863ea844a1aSMatthew Knepley 
2864ea844a1aSMatthew Knepley /*@
286520662ed9SBarry Smith   PetscSectionSetClosureIndex - Create an internal data structure to speed up closure queries.
2866ea844a1aSMatthew Knepley 
286740750d41SVaclav Hapla   Collective
2868ea844a1aSMatthew Knepley 
2869ea844a1aSMatthew Knepley   Input Parameters:
2870cab54364SBarry Smith + section   - The `PetscSection`
2871cab54364SBarry Smith . obj       - A `PetscObject` which serves as the key for this index
2872cab54364SBarry Smith . clSection - `PetscSection` giving the size of the closure of each point
2873cab54364SBarry Smith - clPoints  - `IS` giving the points in each closure
2874ea844a1aSMatthew Knepley 
2875ea844a1aSMatthew Knepley   Level: advanced
2876ea844a1aSMatthew Knepley 
2877cab54364SBarry Smith   Note:
287820662ed9SBarry Smith   This function creates an internal map from each point to its closure. We compress out closure points with no dofs in this section.
287920662ed9SBarry Smith 
288038b5cf2dSJacob Faibussowitsch   Developer Notes:
288120662ed9SBarry Smith   The information provided here is completely opaque
2882cab54364SBarry Smith 
2883cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetClosureIndex()`, `DMPlexCreateClosureIndex()`
2884ea844a1aSMatthew Knepley @*/
2885d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints)
2886d71ae5a4SJacob Faibussowitsch {
2887ea844a1aSMatthew Knepley   PetscFunctionBegin;
28883e03ebd8SStefano Zampini   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
28893e03ebd8SStefano Zampini   PetscValidHeaderSpecific(clSection, PETSC_SECTION_CLASSID, 3);
28903e03ebd8SStefano Zampini   PetscValidHeaderSpecific(clPoints, IS_CLASSID, 4);
2891d4a1ad33SMatthew G. Knepley   if (section->clObj != obj) PetscCall(PetscSectionResetClosurePermutation(section));
2892ea844a1aSMatthew Knepley   section->clObj = obj;
28939566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)clSection));
28949566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)clPoints));
28959566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section->clSection));
28969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&section->clPoints));
2897ea844a1aSMatthew Knepley   section->clSection = clSection;
2898ea844a1aSMatthew Knepley   section->clPoints  = clPoints;
28993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2900ea844a1aSMatthew Knepley }
2901ea844a1aSMatthew Knepley 
2902ea844a1aSMatthew Knepley /*@
2903cab54364SBarry Smith   PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section set with `PetscSectionSetClosureIndex()`
2904ea844a1aSMatthew Knepley 
290540750d41SVaclav Hapla   Collective
2906ea844a1aSMatthew Knepley 
2907ea844a1aSMatthew Knepley   Input Parameters:
2908cab54364SBarry Smith + section - The `PetscSection`
2909cab54364SBarry Smith - obj     - A `PetscObject` which serves as the key for this index
2910ea844a1aSMatthew Knepley 
2911ea844a1aSMatthew Knepley   Output Parameters:
2912cab54364SBarry Smith + clSection - `PetscSection` giving the size of the closure of each point
2913cab54364SBarry Smith - clPoints  - `IS` giving the points in each closure
2914ea844a1aSMatthew Knepley 
2915ea844a1aSMatthew Knepley   Level: advanced
2916ea844a1aSMatthew Knepley 
2917cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()`
2918ea844a1aSMatthew Knepley @*/
2919d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints)
2920d71ae5a4SJacob Faibussowitsch {
2921ea844a1aSMatthew Knepley   PetscFunctionBegin;
2922ea844a1aSMatthew Knepley   if (section->clObj == obj) {
2923ea844a1aSMatthew Knepley     if (clSection) *clSection = section->clSection;
2924ea844a1aSMatthew Knepley     if (clPoints) *clPoints = section->clPoints;
2925ea844a1aSMatthew Knepley   } else {
2926ea844a1aSMatthew Knepley     if (clSection) *clSection = NULL;
2927ea844a1aSMatthew Knepley     if (clPoints) *clPoints = NULL;
2928ea844a1aSMatthew Knepley   }
29293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2930ea844a1aSMatthew Knepley }
2931ea844a1aSMatthew Knepley 
2932d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, PetscCopyMode mode, PetscInt *clPerm)
2933d71ae5a4SJacob Faibussowitsch {
2934ea844a1aSMatthew Knepley   PetscInt                    i;
2935c459fbc1SJed Brown   khiter_t                    iter;
2936c459fbc1SJed Brown   int                         new_entry;
2937c459fbc1SJed Brown   PetscSectionClosurePermKey  key = {depth, clSize};
2938c459fbc1SJed Brown   PetscSectionClosurePermVal *val;
2939ea844a1aSMatthew Knepley 
2940ea844a1aSMatthew Knepley   PetscFunctionBegin;
2941ea844a1aSMatthew Knepley   if (section->clObj != obj) {
29429566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&section->clSection));
29439566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&section->clPoints));
2944ea844a1aSMatthew Knepley   }
2945ea844a1aSMatthew Knepley   section->clObj = obj;
29469566063dSJacob Faibussowitsch   if (!section->clHash) PetscCall(PetscClPermCreate(&section->clHash));
2947c459fbc1SJed Brown   iter = kh_put(ClPerm, section->clHash, key, &new_entry);
2948c459fbc1SJed Brown   val  = &kh_val(section->clHash, iter);
2949c459fbc1SJed Brown   if (!new_entry) {
29509566063dSJacob Faibussowitsch     PetscCall(PetscFree(val->perm));
29519566063dSJacob Faibussowitsch     PetscCall(PetscFree(val->invPerm));
2952c459fbc1SJed Brown   }
2953ea844a1aSMatthew Knepley   if (mode == PETSC_COPY_VALUES) {
29549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(clSize, &val->perm));
29559566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(val->perm, clPerm, clSize));
2956ea844a1aSMatthew Knepley   } else if (mode == PETSC_OWN_POINTER) {
2957c459fbc1SJed Brown     val->perm = clPerm;
2958ea844a1aSMatthew Knepley   } else SETERRQ(PetscObjectComm(obj), PETSC_ERR_SUP, "Do not support borrowed arrays");
29599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(clSize, &val->invPerm));
2960c459fbc1SJed Brown   for (i = 0; i < clSize; ++i) val->invPerm[clPerm[i]] = i;
29613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2962ea844a1aSMatthew Knepley }
2963ea844a1aSMatthew Knepley 
2964ea844a1aSMatthew Knepley /*@
2965c459fbc1SJed Brown   PetscSectionSetClosurePermutation - Set the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex.
2966ea844a1aSMatthew Knepley 
2967ea844a1aSMatthew Knepley   Not Collective
2968ea844a1aSMatthew Knepley 
2969ea844a1aSMatthew Knepley   Input Parameters:
2970cab54364SBarry Smith + section - The `PetscSection`
2971cab54364SBarry Smith . obj     - A `PetscObject` which serves as the key for this index (usually a `DM`)
2972c459fbc1SJed Brown . depth   - Depth of points on which to apply the given permutation
2973ea844a1aSMatthew Knepley - perm    - Permutation of the cell dof closure
2974ea844a1aSMatthew Knepley 
2975cab54364SBarry Smith   Level: intermediate
2976cab54364SBarry Smith 
2977cab54364SBarry Smith   Notes:
2978c459fbc1SJed Brown   The specified permutation will only be applied to points at depth whose closure size matches the length of perm.  In a
2979c459fbc1SJed Brown   mixed-topology or variable-degree finite element space, this function can be called multiple times at each depth for
2980c459fbc1SJed Brown   each topology and degree.
2981c459fbc1SJed Brown 
2982c459fbc1SJed Brown   This approach assumes that (depth, len(perm)) uniquely identifies the desired permutation; this might not be true for
2983c459fbc1SJed Brown   exotic/enriched spaces on mixed topology meshes.
2984ea844a1aSMatthew Knepley 
2985cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionGetClosurePermutation()`, `PetscSectionGetClosureIndex()`, `DMPlexCreateClosureIndex()`, `PetscCopyMode`
2986ea844a1aSMatthew Knepley @*/
2987d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, IS perm)
2988d71ae5a4SJacob Faibussowitsch {
2989ea844a1aSMatthew Knepley   const PetscInt *clPerm = NULL;
2990ea844a1aSMatthew Knepley   PetscInt        clSize = 0;
2991ea844a1aSMatthew Knepley 
2992ea844a1aSMatthew Knepley   PetscFunctionBegin;
2993ea844a1aSMatthew Knepley   if (perm) {
29949566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(perm, &clSize));
29959566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(perm, &clPerm));
2996ea844a1aSMatthew Knepley   }
29979566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetClosurePermutation_Internal(section, obj, depth, clSize, PETSC_COPY_VALUES, (PetscInt *)clPerm));
29989566063dSJacob Faibussowitsch   if (perm) PetscCall(ISRestoreIndices(perm, &clPerm));
29993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3000ea844a1aSMatthew Knepley }
3001ea844a1aSMatthew Knepley 
3002da8c939bSJacob Faibussowitsch static PetscErrorCode PetscSectionGetClosurePermutation_Private(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[])
3003d71ae5a4SJacob Faibussowitsch {
3004ea844a1aSMatthew Knepley   PetscFunctionBegin;
3005ea844a1aSMatthew Knepley   if (section->clObj == obj) {
3006c459fbc1SJed Brown     PetscSectionClosurePermKey k = {depth, size};
3007c459fbc1SJed Brown     PetscSectionClosurePermVal v;
3008da8c939bSJacob Faibussowitsch 
30099566063dSJacob Faibussowitsch     PetscCall(PetscClPermGet(section->clHash, k, &v));
3010c459fbc1SJed Brown     if (perm) *perm = v.perm;
3011ea844a1aSMatthew Knepley   } else {
3012ea844a1aSMatthew Knepley     if (perm) *perm = NULL;
3013ea844a1aSMatthew Knepley   }
30143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3015ea844a1aSMatthew Knepley }
3016ea844a1aSMatthew Knepley 
3017ea844a1aSMatthew Knepley /*@
3018ea844a1aSMatthew Knepley   PetscSectionGetClosurePermutation - Get the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex.
3019ea844a1aSMatthew Knepley 
302040750d41SVaclav Hapla   Not Collective
3021ea844a1aSMatthew Knepley 
3022ea844a1aSMatthew Knepley   Input Parameters:
3023cab54364SBarry Smith + section - The `PetscSection`
3024cab54364SBarry Smith . obj     - A `PetscObject` which serves as the key for this index (usually a DM)
3025c459fbc1SJed Brown . depth   - Depth stratum on which to obtain closure permutation
3026c459fbc1SJed Brown - clSize  - Closure size to be permuted (e.g., may vary with element topology and degree)
3027ea844a1aSMatthew Knepley 
3028ea844a1aSMatthew Knepley   Output Parameter:
3029ea844a1aSMatthew Knepley . perm - The dof closure permutation
3030ea844a1aSMatthew Knepley 
3031ea844a1aSMatthew Knepley   Level: intermediate
3032ea844a1aSMatthew Knepley 
3033cab54364SBarry Smith   Note:
3034cab54364SBarry Smith   The user must destroy the `IS` that is returned.
3035cab54364SBarry Smith 
3036cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionSetClosurePermutation()`, `PetscSectionGetClosureInversePermutation()`, `PetscSectionGetClosureIndex()`, `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()`
3037ea844a1aSMatthew Knepley @*/
3038d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm)
3039d71ae5a4SJacob Faibussowitsch {
3040da8c939bSJacob Faibussowitsch   const PetscInt *clPerm = NULL;
3041ea844a1aSMatthew Knepley 
3042ea844a1aSMatthew Knepley   PetscFunctionBegin;
3043da8c939bSJacob Faibussowitsch   PetscCall(PetscSectionGetClosurePermutation_Private(section, obj, depth, clSize, &clPerm));
30449566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm));
30453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3046ea844a1aSMatthew Knepley }
3047ea844a1aSMatthew Knepley 
3048d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetClosureInversePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[])
3049d71ae5a4SJacob Faibussowitsch {
3050ea844a1aSMatthew Knepley   PetscFunctionBegin;
3051c459fbc1SJed Brown   if (section->clObj == obj && section->clHash) {
3052c459fbc1SJed Brown     PetscSectionClosurePermKey k = {depth, size};
3053c459fbc1SJed Brown     PetscSectionClosurePermVal v;
30549566063dSJacob Faibussowitsch     PetscCall(PetscClPermGet(section->clHash, k, &v));
3055c459fbc1SJed Brown     if (perm) *perm = v.invPerm;
3056ea844a1aSMatthew Knepley   } else {
3057ea844a1aSMatthew Knepley     if (perm) *perm = NULL;
3058ea844a1aSMatthew Knepley   }
30593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3060ea844a1aSMatthew Knepley }
3061ea844a1aSMatthew Knepley 
3062ea844a1aSMatthew Knepley /*@
3063ea844a1aSMatthew Knepley   PetscSectionGetClosureInversePermutation - Get the inverse dof permutation for the closure of each cell in the section, meaning clPerm[oldIndex] = newIndex.
3064ea844a1aSMatthew Knepley 
306540750d41SVaclav Hapla   Not Collective
3066ea844a1aSMatthew Knepley 
3067ea844a1aSMatthew Knepley   Input Parameters:
3068cab54364SBarry Smith + section - The `PetscSection`
3069cab54364SBarry Smith . obj     - A `PetscObject` which serves as the key for this index (usually a `DM`)
3070c459fbc1SJed Brown . depth   - Depth stratum on which to obtain closure permutation
3071c459fbc1SJed Brown - clSize  - Closure size to be permuted (e.g., may vary with element topology and degree)
3072ea844a1aSMatthew Knepley 
30732fe279fdSBarry Smith   Output Parameter:
3074c459fbc1SJed Brown . perm - The dof closure permutation
3075ea844a1aSMatthew Knepley 
3076ea844a1aSMatthew Knepley   Level: intermediate
3077ea844a1aSMatthew Knepley 
3078cab54364SBarry Smith   Note:
3079cab54364SBarry Smith   The user must destroy the `IS` that is returned.
3080cab54364SBarry Smith 
3081cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionSetClosurePermutation()`, `PetscSectionGetClosureIndex()`, `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()`
3082ea844a1aSMatthew Knepley @*/
3083d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetClosureInversePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm)
3084d71ae5a4SJacob Faibussowitsch {
3085da8c939bSJacob Faibussowitsch   const PetscInt *clPerm = NULL;
3086ea844a1aSMatthew Knepley 
3087ea844a1aSMatthew Knepley   PetscFunctionBegin;
30889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, obj, depth, clSize, &clPerm));
30899566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm));
30903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3091ea844a1aSMatthew Knepley }
3092ea844a1aSMatthew Knepley 
3093ea844a1aSMatthew Knepley /*@
3094583308b6SBarry Smith   PetscSectionGetField - Get the `PetscSection` associated with a single field
3095ea844a1aSMatthew Knepley 
3096ea844a1aSMatthew Knepley   Input Parameters:
3097cab54364SBarry Smith + s     - The `PetscSection`
3098ea844a1aSMatthew Knepley - field - The field number
3099ea844a1aSMatthew Knepley 
3100ea844a1aSMatthew Knepley   Output Parameter:
3101583308b6SBarry Smith . subs - The `PetscSection` for the given field, note the chart of `subs` is not set
3102ea844a1aSMatthew Knepley 
3103ea844a1aSMatthew Knepley   Level: intermediate
3104ea844a1aSMatthew Knepley 
3105cab54364SBarry Smith   Note:
3106cab54364SBarry Smith   Does not increase the reference count of the selected sub-section. There is no matching `PetscSectionRestoreField()`
3107cab54364SBarry Smith 
3108cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionSetNumFields()`
3109ea844a1aSMatthew Knepley @*/
3110d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs)
3111d71ae5a4SJacob Faibussowitsch {
3112ea844a1aSMatthew Knepley   PetscFunctionBegin;
3113ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
31144f572ea9SToby Isaac   PetscAssertPointer(subs, 3);
31152abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, s->numFields);
3116ea844a1aSMatthew Knepley   *subs = s->field[field];
31173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3118ea844a1aSMatthew Knepley }
3119ea844a1aSMatthew Knepley 
3120ea844a1aSMatthew Knepley PetscClassId      PETSC_SECTION_SYM_CLASSID;
3121ea844a1aSMatthew Knepley PetscFunctionList PetscSectionSymList = NULL;
3122ea844a1aSMatthew Knepley 
3123ea844a1aSMatthew Knepley /*@
3124cab54364SBarry Smith   PetscSectionSymCreate - Creates an empty `PetscSectionSym` object.
3125ea844a1aSMatthew Knepley 
3126ea844a1aSMatthew Knepley   Collective
3127ea844a1aSMatthew Knepley 
3128ea844a1aSMatthew Knepley   Input Parameter:
3129ea844a1aSMatthew Knepley . comm - the MPI communicator
3130ea844a1aSMatthew Knepley 
3131ea844a1aSMatthew Knepley   Output Parameter:
3132ea844a1aSMatthew Knepley . sym - pointer to the new set of symmetries
3133ea844a1aSMatthew Knepley 
3134ea844a1aSMatthew Knepley   Level: developer
3135ea844a1aSMatthew Knepley 
3136cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSym`, `PetscSectionSymDestroy()`
3137ea844a1aSMatthew Knepley @*/
3138d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate(MPI_Comm comm, PetscSectionSym *sym)
3139d71ae5a4SJacob Faibussowitsch {
3140ea844a1aSMatthew Knepley   PetscFunctionBegin;
31414f572ea9SToby Isaac   PetscAssertPointer(sym, 2);
31429566063dSJacob Faibussowitsch   PetscCall(ISInitializePackage());
31439566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*sym, PETSC_SECTION_SYM_CLASSID, "PetscSectionSym", "Section Symmetry", "IS", comm, PetscSectionSymDestroy, PetscSectionSymView));
31443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3145ea844a1aSMatthew Knepley }
3146ea844a1aSMatthew Knepley 
3147ea844a1aSMatthew Knepley /*@C
3148cab54364SBarry Smith   PetscSectionSymSetType - Builds a `PetscSectionSym`, for a particular implementation.
3149ea844a1aSMatthew Knepley 
315040750d41SVaclav Hapla   Collective
3151ea844a1aSMatthew Knepley 
3152ea844a1aSMatthew Knepley   Input Parameters:
3153ea844a1aSMatthew Knepley + sym    - The section symmetry object
3154ea844a1aSMatthew Knepley - method - The name of the section symmetry type
3155ea844a1aSMatthew Knepley 
3156ea844a1aSMatthew Knepley   Level: developer
3157ea844a1aSMatthew Knepley 
3158cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymType`, `PetscSectionSymGetType()`, `PetscSectionSymCreate()`
3159ea844a1aSMatthew Knepley @*/
3160d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymSetType(PetscSectionSym sym, PetscSectionSymType method)
3161d71ae5a4SJacob Faibussowitsch {
3162ea844a1aSMatthew Knepley   PetscErrorCode (*r)(PetscSectionSym);
3163ea844a1aSMatthew Knepley   PetscBool match;
3164ea844a1aSMatthew Knepley 
3165ea844a1aSMatthew Knepley   PetscFunctionBegin;
3166ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
31679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)sym, method, &match));
31683ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
3169ea844a1aSMatthew Knepley 
31709566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(PetscSectionSymList, method, &r));
31716adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscSectionSym type: %s", method);
3172dbbe0bcdSBarry Smith   PetscTryTypeMethod(sym, destroy);
3173ea844a1aSMatthew Knepley   sym->ops->destroy = NULL;
3174dbbe0bcdSBarry Smith 
31759566063dSJacob Faibussowitsch   PetscCall((*r)(sym));
31769566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)sym, method));
31773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3178ea844a1aSMatthew Knepley }
3179ea844a1aSMatthew Knepley 
3180ea844a1aSMatthew Knepley /*@C
3181cab54364SBarry Smith   PetscSectionSymGetType - Gets the section symmetry type name (as a string) from the `PetscSectionSym`.
3182ea844a1aSMatthew Knepley 
3183ea844a1aSMatthew Knepley   Not Collective
3184ea844a1aSMatthew Knepley 
3185ea844a1aSMatthew Knepley   Input Parameter:
3186ea844a1aSMatthew Knepley . sym - The section symmetry
3187ea844a1aSMatthew Knepley 
3188ea844a1aSMatthew Knepley   Output Parameter:
3189ea844a1aSMatthew Knepley . type - The index set type name
3190ea844a1aSMatthew Knepley 
3191ea844a1aSMatthew Knepley   Level: developer
3192ea844a1aSMatthew Knepley 
3193cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymType`, `PetscSectionSymSetType()`, `PetscSectionSymCreate()`
3194ea844a1aSMatthew Knepley @*/
3195d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymGetType(PetscSectionSym sym, PetscSectionSymType *type)
3196d71ae5a4SJacob Faibussowitsch {
3197ea844a1aSMatthew Knepley   PetscFunctionBegin;
3198ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
31994f572ea9SToby Isaac   PetscAssertPointer(type, 2);
3200ea844a1aSMatthew Knepley   *type = ((PetscObject)sym)->type_name;
32013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3202ea844a1aSMatthew Knepley }
3203ea844a1aSMatthew Knepley 
3204ea844a1aSMatthew Knepley /*@C
3205cab54364SBarry Smith   PetscSectionSymRegister - Registers a new section symmetry implementation
3206ea844a1aSMatthew Knepley 
3207ea844a1aSMatthew Knepley   Not Collective
3208ea844a1aSMatthew Knepley 
3209ea844a1aSMatthew Knepley   Input Parameters:
32102fe279fdSBarry Smith + sname    - The name of a new user-defined creation routine
32112fe279fdSBarry Smith - function - The creation routine itself
3212ea844a1aSMatthew Knepley 
3213ea844a1aSMatthew Knepley   Level: developer
3214ea844a1aSMatthew Knepley 
3215cab54364SBarry Smith   Notes:
3216cab54364SBarry Smith   `PetscSectionSymRegister()` may be called multiple times to add several user-defined vectors
3217cab54364SBarry Smith 
3218cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymType`, `PetscSectionSymCreate()`, `PetscSectionSymSetType()`
3219ea844a1aSMatthew Knepley @*/
3220d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymRegister(const char sname[], PetscErrorCode (*function)(PetscSectionSym))
3221d71ae5a4SJacob Faibussowitsch {
3222ea844a1aSMatthew Knepley   PetscFunctionBegin;
32239566063dSJacob Faibussowitsch   PetscCall(ISInitializePackage());
32249566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PetscSectionSymList, sname, function));
32253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3226ea844a1aSMatthew Knepley }
3227ea844a1aSMatthew Knepley 
3228ea844a1aSMatthew Knepley /*@
3229ea844a1aSMatthew Knepley   PetscSectionSymDestroy - Destroys a section symmetry.
3230ea844a1aSMatthew Knepley 
323140750d41SVaclav Hapla   Collective
3232ea844a1aSMatthew Knepley 
32332fe279fdSBarry Smith   Input Parameter:
3234ea844a1aSMatthew Knepley . sym - the section symmetry
3235ea844a1aSMatthew Knepley 
3236ea844a1aSMatthew Knepley   Level: developer
3237ea844a1aSMatthew Knepley 
323842747ad1SJacob Faibussowitsch .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymCreate()`
3239ea844a1aSMatthew Knepley @*/
3240d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymDestroy(PetscSectionSym *sym)
3241d71ae5a4SJacob Faibussowitsch {
3242ea844a1aSMatthew Knepley   SymWorkLink link, next;
3243ea844a1aSMatthew Knepley 
3244ea844a1aSMatthew Knepley   PetscFunctionBegin;
32453ba16761SJacob Faibussowitsch   if (!*sym) PetscFunctionReturn(PETSC_SUCCESS);
3246ea844a1aSMatthew Knepley   PetscValidHeaderSpecific((*sym), PETSC_SECTION_SYM_CLASSID, 1);
32479371c9d4SSatish Balay   if (--((PetscObject)(*sym))->refct > 0) {
32489371c9d4SSatish Balay     *sym = NULL;
32493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3250ea844a1aSMatthew Knepley   }
325148a46eb9SPierre Jolivet   if ((*sym)->ops->destroy) PetscCall((*(*sym)->ops->destroy)(*sym));
3252c9cc58a2SBarry Smith   PetscCheck(!(*sym)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out");
3253ea844a1aSMatthew Knepley   for (link = (*sym)->workin; link; link = next) {
32540c99d500SBarry Smith     PetscInt    **perms = (PetscInt **)link->perms;
32550c99d500SBarry Smith     PetscScalar **rots  = (PetscScalar **)link->rots;
32560c99d500SBarry Smith     PetscCall(PetscFree2(perms, rots));
3257ea844a1aSMatthew Knepley     next = link->next;
32589566063dSJacob Faibussowitsch     PetscCall(PetscFree(link));
3259ea844a1aSMatthew Knepley   }
3260ea844a1aSMatthew Knepley   (*sym)->workin = NULL;
32619566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(sym));
32623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3263ea844a1aSMatthew Knepley }
3264ea844a1aSMatthew Knepley 
3265ea844a1aSMatthew Knepley /*@C
3266ea844a1aSMatthew Knepley   PetscSectionSymView - Displays a section symmetry
3267ea844a1aSMatthew Knepley 
326840750d41SVaclav Hapla   Collective
3269ea844a1aSMatthew Knepley 
3270ea844a1aSMatthew Knepley   Input Parameters:
3271ea844a1aSMatthew Knepley + sym    - the index set
3272cab54364SBarry Smith - viewer - viewer used to display the set, for example `PETSC_VIEWER_STDOUT_SELF`.
3273ea844a1aSMatthew Knepley 
3274ea844a1aSMatthew Knepley   Level: developer
3275ea844a1aSMatthew Knepley 
3276cab54364SBarry Smith .seealso: `PetscSectionSym`, `PetscViewer`, `PetscViewerASCIIOpen()`
3277ea844a1aSMatthew Knepley @*/
3278d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymView(PetscSectionSym sym, PetscViewer viewer)
3279d71ae5a4SJacob Faibussowitsch {
3280ea844a1aSMatthew Knepley   PetscFunctionBegin;
3281ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
328248a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sym), &viewer));
3283ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3284ea844a1aSMatthew Knepley   PetscCheckSameComm(sym, 1, viewer, 2);
32859566063dSJacob Faibussowitsch   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sym, viewer));
3286dbbe0bcdSBarry Smith   PetscTryTypeMethod(sym, view, viewer);
32873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3288ea844a1aSMatthew Knepley }
3289ea844a1aSMatthew Knepley 
3290ea844a1aSMatthew Knepley /*@
3291ea844a1aSMatthew Knepley   PetscSectionSetSym - Set the symmetries for the data referred to by the section
3292ea844a1aSMatthew Knepley 
329340750d41SVaclav Hapla   Collective
3294ea844a1aSMatthew Knepley 
3295ea844a1aSMatthew Knepley   Input Parameters:
3296ea844a1aSMatthew Knepley + section - the section describing data layout
3297ea844a1aSMatthew Knepley - sym     - the symmetry describing the affect of orientation on the access of the data
3298ea844a1aSMatthew Knepley 
3299ea844a1aSMatthew Knepley   Level: developer
3300ea844a1aSMatthew Knepley 
3301cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetSym()`, `PetscSectionSymCreate()`
3302ea844a1aSMatthew Knepley @*/
3303d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetSym(PetscSection section, PetscSectionSym sym)
3304d71ae5a4SJacob Faibussowitsch {
3305ea844a1aSMatthew Knepley   PetscFunctionBegin;
3306ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
33079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymDestroy(&(section->sym)));
3308ea844a1aSMatthew Knepley   if (sym) {
3309ea844a1aSMatthew Knepley     PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 2);
3310ea844a1aSMatthew Knepley     PetscCheckSameComm(section, 1, sym, 2);
33119566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)sym));
3312ea844a1aSMatthew Knepley   }
3313ea844a1aSMatthew Knepley   section->sym = sym;
33143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3315ea844a1aSMatthew Knepley }
3316ea844a1aSMatthew Knepley 
3317ea844a1aSMatthew Knepley /*@
3318ea844a1aSMatthew Knepley   PetscSectionGetSym - Get the symmetries for the data referred to by the section
3319ea844a1aSMatthew Knepley 
332040750d41SVaclav Hapla   Not Collective
3321ea844a1aSMatthew Knepley 
33222fe279fdSBarry Smith   Input Parameter:
3323ea844a1aSMatthew Knepley . section - the section describing data layout
3324ea844a1aSMatthew Knepley 
33252fe279fdSBarry Smith   Output Parameter:
332620662ed9SBarry Smith . sym - the symmetry describing the affect of orientation on the access of the data, provided previously by `PetscSectionSetSym()`
3327ea844a1aSMatthew Knepley 
3328ea844a1aSMatthew Knepley   Level: developer
3329ea844a1aSMatthew Knepley 
3330cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSetSym()`, `PetscSectionSymCreate()`
3331ea844a1aSMatthew Knepley @*/
3332d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetSym(PetscSection section, PetscSectionSym *sym)
3333d71ae5a4SJacob Faibussowitsch {
3334ea844a1aSMatthew Knepley   PetscFunctionBegin;
3335ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
3336ea844a1aSMatthew Knepley   *sym = section->sym;
33373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3338ea844a1aSMatthew Knepley }
3339ea844a1aSMatthew Knepley 
3340ea844a1aSMatthew Knepley /*@
3341ea844a1aSMatthew Knepley   PetscSectionSetFieldSym - Set the symmetries for the data referred to by a field of the section
3342ea844a1aSMatthew Knepley 
334340750d41SVaclav Hapla   Collective
3344ea844a1aSMatthew Knepley 
3345ea844a1aSMatthew Knepley   Input Parameters:
3346ea844a1aSMatthew Knepley + section - the section describing data layout
3347ea844a1aSMatthew Knepley . field   - the field number
3348ea844a1aSMatthew Knepley - sym     - the symmetry describing the affect of orientation on the access of the data
3349ea844a1aSMatthew Knepley 
3350ea844a1aSMatthew Knepley   Level: developer
3351ea844a1aSMatthew Knepley 
3352cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetFieldSym()`, `PetscSectionSymCreate()`
3353ea844a1aSMatthew Knepley @*/
3354d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetFieldSym(PetscSection section, PetscInt field, PetscSectionSym sym)
3355d71ae5a4SJacob Faibussowitsch {
3356ea844a1aSMatthew Knepley   PetscFunctionBegin;
3357ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
33582abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, section->numFields);
33599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetSym(section->field[field], sym));
33603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3361ea844a1aSMatthew Knepley }
3362ea844a1aSMatthew Knepley 
3363ea844a1aSMatthew Knepley /*@
3364ea844a1aSMatthew Knepley   PetscSectionGetFieldSym - Get the symmetries for the data referred to by a field of the section
3365ea844a1aSMatthew Knepley 
336640750d41SVaclav Hapla   Collective
3367ea844a1aSMatthew Knepley 
3368ea844a1aSMatthew Knepley   Input Parameters:
3369ea844a1aSMatthew Knepley + section - the section describing data layout
3370ea844a1aSMatthew Knepley - field   - the field number
3371ea844a1aSMatthew Knepley 
33722fe279fdSBarry Smith   Output Parameter:
3373ea844a1aSMatthew Knepley . sym - the symmetry describing the affect of orientation on the access of the data
3374ea844a1aSMatthew Knepley 
3375ea844a1aSMatthew Knepley   Level: developer
3376ea844a1aSMatthew Knepley 
3377cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSetFieldSym()`, `PetscSectionSymCreate()`
3378ea844a1aSMatthew Knepley @*/
3379d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldSym(PetscSection section, PetscInt field, PetscSectionSym *sym)
3380d71ae5a4SJacob Faibussowitsch {
3381ea844a1aSMatthew Knepley   PetscFunctionBegin;
3382ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
33832abc8c78SJacob Faibussowitsch   PetscSectionCheckValidField(field, section->numFields);
3384ea844a1aSMatthew Knepley   *sym = section->field[field]->sym;
33853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3386ea844a1aSMatthew Knepley }
3387ea844a1aSMatthew Knepley 
3388ea844a1aSMatthew Knepley /*@C
3389cab54364SBarry Smith   PetscSectionGetPointSyms - Get the symmetries for a set of points in a `PetscSection` under specific orientations.
3390ea844a1aSMatthew Knepley 
339140750d41SVaclav Hapla   Not Collective
3392ea844a1aSMatthew Knepley 
3393ea844a1aSMatthew Knepley   Input Parameters:
3394ea844a1aSMatthew Knepley + section   - the section
3395ea844a1aSMatthew Knepley . numPoints - the number of points
339620662ed9SBarry Smith - points    - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
339720662ed9SBarry Smith     arbitrary integer: its interpretation is up to sym.  Orientations are used by `DM`: for their interpretation in that
339820662ed9SBarry Smith     context, see `DMPlexGetConeOrientation()`).
3399ea844a1aSMatthew Knepley 
3400d8d19677SJose E. Roman   Output Parameters:
340120662ed9SBarry Smith + perms - The permutations for the given orientations (or `NULL` if there is no symmetry or the permutation is the identity).
340220662ed9SBarry Smith - rots  - The field rotations symmetries for the given orientations (or `NULL` if there is no symmetry or the rotations are all
3403ea844a1aSMatthew Knepley     identity).
3404ea844a1aSMatthew Knepley 
3405ea844a1aSMatthew Knepley   Example of usage, gathering dofs into a local array (lArray) from a section array (sArray):
3406ea844a1aSMatthew Knepley .vb
3407ea844a1aSMatthew Knepley      const PetscInt    **perms;
3408ea844a1aSMatthew Knepley      const PetscScalar **rots;
3409ea844a1aSMatthew Knepley      PetscInt            lOffset;
3410ea844a1aSMatthew Knepley 
3411ea844a1aSMatthew Knepley      PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots);
3412ea844a1aSMatthew Knepley      for (i = 0, lOffset = 0; i < numPoints; i++) {
3413ea844a1aSMatthew Knepley        PetscInt           point = points[2*i], dof, sOffset;
3414ea844a1aSMatthew Knepley        const PetscInt    *perm  = perms ? perms[i] : NULL;
3415ea844a1aSMatthew Knepley        const PetscScalar *rot   = rots  ? rots[i]  : NULL;
3416ea844a1aSMatthew Knepley 
3417ea844a1aSMatthew Knepley        PetscSectionGetDof(section,point,&dof);
3418ea844a1aSMatthew Knepley        PetscSectionGetOffset(section,point,&sOffset);
3419ea844a1aSMatthew Knepley 
3420ea844a1aSMatthew Knepley        if (perm) {for (j = 0; j < dof; j++) {lArray[lOffset + perm[j]]  = sArray[sOffset + j];}}
3421ea844a1aSMatthew Knepley        else      {for (j = 0; j < dof; j++) {lArray[lOffset +      j ]  = sArray[sOffset + j];}}
3422ea844a1aSMatthew Knepley        if (rot)  {for (j = 0; j < dof; j++) {lArray[lOffset +      j ] *= rot[j];             }}
3423ea844a1aSMatthew Knepley        lOffset += dof;
3424ea844a1aSMatthew Knepley      }
3425ea844a1aSMatthew Knepley      PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots);
3426ea844a1aSMatthew Knepley .ve
3427ea844a1aSMatthew Knepley 
3428ea844a1aSMatthew Knepley   Example of usage, adding dofs into a section array (sArray) from a local array (lArray):
3429ea844a1aSMatthew Knepley .vb
3430ea844a1aSMatthew Knepley      const PetscInt    **perms;
3431ea844a1aSMatthew Knepley      const PetscScalar **rots;
3432ea844a1aSMatthew Knepley      PetscInt            lOffset;
3433ea844a1aSMatthew Knepley 
3434ea844a1aSMatthew Knepley      PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots);
3435ea844a1aSMatthew Knepley      for (i = 0, lOffset = 0; i < numPoints; i++) {
3436ea844a1aSMatthew Knepley        PetscInt           point = points[2*i], dof, sOffset;
3437ea844a1aSMatthew Knepley        const PetscInt    *perm  = perms ? perms[i] : NULL;
3438ea844a1aSMatthew Knepley        const PetscScalar *rot   = rots  ? rots[i]  : NULL;
3439ea844a1aSMatthew Knepley 
3440ea844a1aSMatthew Knepley        PetscSectionGetDof(section,point,&dof);
3441ea844a1aSMatthew Knepley        PetscSectionGetOffset(section,point,&sOff);
3442ea844a1aSMatthew Knepley 
3443ea844a1aSMatthew Knepley        if (perm) {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + perm[j]] * (rot ? PetscConj(rot[perm[j]]) : 1.);}}
3444ea844a1aSMatthew Knepley        else      {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset +      j ] * (rot ? PetscConj(rot[     j ]) : 1.);}}
3445ea844a1aSMatthew Knepley        offset += dof;
3446ea844a1aSMatthew Knepley      }
3447ea844a1aSMatthew Knepley      PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots);
3448ea844a1aSMatthew Knepley .ve
3449ea844a1aSMatthew Knepley 
3450ea844a1aSMatthew Knepley   Level: developer
3451ea844a1aSMatthew Knepley 
3452583308b6SBarry Smith   Notes:
345320662ed9SBarry Smith   `PetscSectionSetSym()` must have been previously called to provide the symmetries to the `PetscSection`
345420662ed9SBarry Smith 
345520662ed9SBarry Smith   Use `PetscSectionRestorePointSyms()` when finished with the data
345620662ed9SBarry Smith 
3457cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionRestorePointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`
3458ea844a1aSMatthew Knepley @*/
3459d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetPointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3460d71ae5a4SJacob Faibussowitsch {
3461ea844a1aSMatthew Knepley   PetscSectionSym sym;
3462ea844a1aSMatthew Knepley 
3463ea844a1aSMatthew Knepley   PetscFunctionBegin;
3464ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
34654f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(points, 3);
3466ea844a1aSMatthew Knepley   if (perms) *perms = NULL;
3467ea844a1aSMatthew Knepley   if (rots) *rots = NULL;
3468ea844a1aSMatthew Knepley   sym = section->sym;
3469ea844a1aSMatthew Knepley   if (sym && (perms || rots)) {
3470ea844a1aSMatthew Knepley     SymWorkLink link;
3471ea844a1aSMatthew Knepley 
3472ea844a1aSMatthew Knepley     if (sym->workin) {
3473ea844a1aSMatthew Knepley       link        = sym->workin;
3474ea844a1aSMatthew Knepley       sym->workin = sym->workin->next;
3475ea844a1aSMatthew Knepley     } else {
34764dfa11a4SJacob Faibussowitsch       PetscCall(PetscNew(&link));
3477ea844a1aSMatthew Knepley     }
3478ea844a1aSMatthew Knepley     if (numPoints > link->numPoints) {
34790c99d500SBarry Smith       PetscInt    **perms = (PetscInt **)link->perms;
34800c99d500SBarry Smith       PetscScalar **rots  = (PetscScalar **)link->rots;
34810c99d500SBarry Smith       PetscCall(PetscFree2(perms, rots));
34820c99d500SBarry Smith       PetscCall(PetscMalloc2(numPoints, (PetscInt ***)&link->perms, numPoints, (PetscScalar ***)&link->rots));
3483ea844a1aSMatthew Knepley       link->numPoints = numPoints;
3484ea844a1aSMatthew Knepley     }
3485ea844a1aSMatthew Knepley     link->next   = sym->workout;
3486ea844a1aSMatthew Knepley     sym->workout = link;
34879566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero((PetscInt **)link->perms, numPoints));
34889566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero((PetscInt **)link->rots, numPoints));
34899566063dSJacob Faibussowitsch     PetscCall((*sym->ops->getpoints)(sym, section, numPoints, points, link->perms, link->rots));
3490ea844a1aSMatthew Knepley     if (perms) *perms = link->perms;
3491ea844a1aSMatthew Knepley     if (rots) *rots = link->rots;
3492ea844a1aSMatthew Knepley   }
34933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3494ea844a1aSMatthew Knepley }
3495ea844a1aSMatthew Knepley 
3496ea844a1aSMatthew Knepley /*@C
3497cab54364SBarry Smith   PetscSectionRestorePointSyms - Restore the symmetries returned by `PetscSectionGetPointSyms()`
3498ea844a1aSMatthew Knepley 
349940750d41SVaclav Hapla   Not Collective
3500ea844a1aSMatthew Knepley 
3501ea844a1aSMatthew Knepley   Input Parameters:
3502ea844a1aSMatthew Knepley + section   - the section
3503ea844a1aSMatthew Knepley . numPoints - the number of points
350438b5cf2dSJacob Faibussowitsch . points    - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3505cab54364SBarry Smith     arbitrary integer: its interpretation is up to sym.  Orientations are used by `DM`: for their interpretation in that
3506cab54364SBarry Smith     context, see `DMPlexGetConeOrientation()`).
350720662ed9SBarry Smith . perms     - The permutations for the given orientations: set to `NULL` at conclusion
350820662ed9SBarry Smith - rots      - The field rotations symmetries for the given orientations: set to `NULL` at conclusion
3509ea844a1aSMatthew Knepley 
3510ea844a1aSMatthew Knepley   Level: developer
3511ea844a1aSMatthew Knepley 
3512cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`
3513ea844a1aSMatthew Knepley @*/
3514d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionRestorePointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3515d71ae5a4SJacob Faibussowitsch {
3516ea844a1aSMatthew Knepley   PetscSectionSym sym;
3517ea844a1aSMatthew Knepley 
3518ea844a1aSMatthew Knepley   PetscFunctionBegin;
3519ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
3520ea844a1aSMatthew Knepley   sym = section->sym;
3521ea844a1aSMatthew Knepley   if (sym && (perms || rots)) {
3522ea844a1aSMatthew Knepley     SymWorkLink *p, link;
3523ea844a1aSMatthew Knepley 
3524ea844a1aSMatthew Knepley     for (p = &sym->workout; (link = *p); p = &link->next) {
3525ea844a1aSMatthew Knepley       if ((perms && link->perms == *perms) || (rots && link->rots == *rots)) {
3526ea844a1aSMatthew Knepley         *p          = link->next;
3527ea844a1aSMatthew Knepley         link->next  = sym->workin;
3528ea844a1aSMatthew Knepley         sym->workin = link;
3529ea844a1aSMatthew Knepley         if (perms) *perms = NULL;
3530ea844a1aSMatthew Knepley         if (rots) *rots = NULL;
35313ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
3532ea844a1aSMatthew Knepley       }
3533ea844a1aSMatthew Knepley     }
3534ea844a1aSMatthew Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
3535ea844a1aSMatthew Knepley   }
35363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3537ea844a1aSMatthew Knepley }
3538ea844a1aSMatthew Knepley 
3539ea844a1aSMatthew Knepley /*@C
3540cab54364SBarry Smith   PetscSectionGetFieldPointSyms - Get the symmetries for a set of points in a field of a `PetscSection` under specific orientations.
3541ea844a1aSMatthew Knepley 
354240750d41SVaclav Hapla   Not Collective
3543ea844a1aSMatthew Knepley 
3544ea844a1aSMatthew Knepley   Input Parameters:
3545ea844a1aSMatthew Knepley + section   - the section
3546ea844a1aSMatthew Knepley . field     - the field of the section
3547ea844a1aSMatthew Knepley . numPoints - the number of points
354820662ed9SBarry Smith - points    - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3549cab54364SBarry Smith     arbitrary integer: its interpretation is up to sym.  Orientations are used by `DM`: for their interpretation in that
3550cab54364SBarry Smith     context, see `DMPlexGetConeOrientation()`).
3551ea844a1aSMatthew Knepley 
3552d8d19677SJose E. Roman   Output Parameters:
355320662ed9SBarry Smith + perms - The permutations for the given orientations (or `NULL` if there is no symmetry or the permutation is the identity).
355420662ed9SBarry Smith - rots  - The field rotations symmetries for the given orientations (or `NULL` if there is no symmetry or the rotations are all
3555ea844a1aSMatthew Knepley     identity).
3556ea844a1aSMatthew Knepley 
3557ea844a1aSMatthew Knepley   Level: developer
3558ea844a1aSMatthew Knepley 
355920662ed9SBarry Smith   Notes:
356020662ed9SBarry Smith   `PetscSectionSetFieldSym()` must have been previously called to provide the symmetries to the `PetscSection`
356120662ed9SBarry Smith 
356220662ed9SBarry Smith   Use `PetscSectionRestoreFieldPointSyms()` when finished with the data
356320662ed9SBarry Smith 
3564cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetPointSyms()`, `PetscSectionRestoreFieldPointSyms()`
3565ea844a1aSMatthew Knepley @*/
3566d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3567d71ae5a4SJacob Faibussowitsch {
3568ea844a1aSMatthew Knepley   PetscFunctionBegin;
3569ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
357008401ef6SPierre Jolivet   PetscCheck(field <= section->numFields, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "field %" PetscInt_FMT " greater than number of fields (%" PetscInt_FMT ") in section", field, section->numFields);
35719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section->field[field], numPoints, points, perms, rots));
35723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3573ea844a1aSMatthew Knepley }
3574ea844a1aSMatthew Knepley 
3575ea844a1aSMatthew Knepley /*@C
3576cab54364SBarry Smith   PetscSectionRestoreFieldPointSyms - Restore the symmetries returned by `PetscSectionGetFieldPointSyms()`
3577ea844a1aSMatthew Knepley 
357840750d41SVaclav Hapla   Not Collective
3579ea844a1aSMatthew Knepley 
3580ea844a1aSMatthew Knepley   Input Parameters:
3581ea844a1aSMatthew Knepley + section   - the section
3582ea844a1aSMatthew Knepley . field     - the field number
3583ea844a1aSMatthew Knepley . numPoints - the number of points
358438b5cf2dSJacob Faibussowitsch . points    - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3585cab54364SBarry Smith     arbitrary integer: its interpretation is up to sym.  Orientations are used by `DM`: for their interpretation in that
3586cab54364SBarry Smith     context, see `DMPlexGetConeOrientation()`).
358720662ed9SBarry Smith . perms     - The permutations for the given orientations: set to NULL at conclusion
3588ea844a1aSMatthew Knepley - rots      - The field rotations symmetries for the given orientations: set to NULL at conclusion
3589ea844a1aSMatthew Knepley 
3590ea844a1aSMatthew Knepley   Level: developer
3591ea844a1aSMatthew Knepley 
3592cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionRestorePointSyms()`, `petscSectionGetFieldPointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`
3593ea844a1aSMatthew Knepley @*/
3594d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionRestoreFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3595d71ae5a4SJacob Faibussowitsch {
3596ea844a1aSMatthew Knepley   PetscFunctionBegin;
3597ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
359808401ef6SPierre Jolivet   PetscCheck(field <= section->numFields, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "field %" PetscInt_FMT " greater than number of fields (%" PetscInt_FMT ") in section", field, section->numFields);
35999566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section->field[field], numPoints, points, perms, rots));
36003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3601ea844a1aSMatthew Knepley }
3602ea844a1aSMatthew Knepley 
3603ea844a1aSMatthew Knepley /*@
3604b004864fSMatthew G. Knepley   PetscSectionSymCopy - Copy the symmetries, assuming that the point structure is compatible
3605b004864fSMatthew G. Knepley 
360640750d41SVaclav Hapla   Not Collective
3607b004864fSMatthew G. Knepley 
3608b004864fSMatthew G. Knepley   Input Parameter:
3609cab54364SBarry Smith . sym - the `PetscSectionSym`
3610b004864fSMatthew G. Knepley 
3611b004864fSMatthew G. Knepley   Output Parameter:
3612b004864fSMatthew G. Knepley . nsym - the equivalent symmetries
3613b004864fSMatthew G. Knepley 
3614b004864fSMatthew G. Knepley   Level: developer
3615b004864fSMatthew G. Knepley 
3616cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
3617b004864fSMatthew G. Knepley @*/
3618d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCopy(PetscSectionSym sym, PetscSectionSym nsym)
3619d71ae5a4SJacob Faibussowitsch {
3620b004864fSMatthew G. Knepley   PetscFunctionBegin;
3621b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
3622b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(nsym, PETSC_SECTION_SYM_CLASSID, 2);
3623dbbe0bcdSBarry Smith   PetscTryTypeMethod(sym, copy, nsym);
36243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3625b004864fSMatthew G. Knepley }
3626b004864fSMatthew G. Knepley 
3627b004864fSMatthew G. Knepley /*@
3628cab54364SBarry Smith   PetscSectionSymDistribute - Distribute the symmetries in accordance with the input `PetscSF`
3629b004864fSMatthew G. Knepley 
3630b004864fSMatthew G. Knepley   Collective
3631b004864fSMatthew G. Knepley 
3632b004864fSMatthew G. Knepley   Input Parameters:
3633cab54364SBarry Smith + sym         - the `PetscSectionSym`
3634b004864fSMatthew G. Knepley - migrationSF - the distribution map from roots to leaves
3635b004864fSMatthew G. Knepley 
36362fe279fdSBarry Smith   Output Parameter:
3637b004864fSMatthew G. Knepley . dsym - the redistributed symmetries
3638b004864fSMatthew G. Knepley 
3639b004864fSMatthew G. Knepley   Level: developer
3640b004864fSMatthew G. Knepley 
3641cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
3642b004864fSMatthew G. Knepley @*/
3643d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymDistribute(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
3644d71ae5a4SJacob Faibussowitsch {
3645b004864fSMatthew G. Knepley   PetscFunctionBegin;
3646b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
3647b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(migrationSF, PETSCSF_CLASSID, 2);
36484f572ea9SToby Isaac   PetscAssertPointer(dsym, 3);
3649dbbe0bcdSBarry Smith   PetscTryTypeMethod(sym, distribute, migrationSF, dsym);
36503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3651b004864fSMatthew G. Knepley }
3652b004864fSMatthew G. Knepley 
3653b004864fSMatthew G. Knepley /*@
365420662ed9SBarry Smith   PetscSectionGetUseFieldOffsets - Get the flag indicating if field offsets are used directly in a global section, rather than just the point offset
3655ea844a1aSMatthew Knepley 
365640750d41SVaclav Hapla   Not Collective
3657ea844a1aSMatthew Knepley 
3658ea844a1aSMatthew Knepley   Input Parameter:
3659cab54364SBarry Smith . s - the global `PetscSection`
3660ea844a1aSMatthew Knepley 
36612fe279fdSBarry Smith   Output Parameter:
3662ea844a1aSMatthew Knepley . flg - the flag
3663ea844a1aSMatthew Knepley 
3664ea844a1aSMatthew Knepley   Level: developer
3665ea844a1aSMatthew Knepley 
3666cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSetChart()`, `PetscSectionCreate()`
3667ea844a1aSMatthew Knepley @*/
3668d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionGetUseFieldOffsets(PetscSection s, PetscBool *flg)
3669d71ae5a4SJacob Faibussowitsch {
3670ea844a1aSMatthew Knepley   PetscFunctionBegin;
3671ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
3672ea844a1aSMatthew Knepley   *flg = s->useFieldOff;
36733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3674ea844a1aSMatthew Knepley }
3675ea844a1aSMatthew Knepley 
3676ea844a1aSMatthew Knepley /*@
3677ea844a1aSMatthew Knepley   PetscSectionSetUseFieldOffsets - Set the flag to use field offsets directly in a global section, rather than just the point offset
3678ea844a1aSMatthew Knepley 
367940750d41SVaclav Hapla   Not Collective
3680ea844a1aSMatthew Knepley 
3681ea844a1aSMatthew Knepley   Input Parameters:
3682cab54364SBarry Smith + s   - the global `PetscSection`
3683ea844a1aSMatthew Knepley - flg - the flag
3684ea844a1aSMatthew Knepley 
3685ea844a1aSMatthew Knepley   Level: developer
3686ea844a1aSMatthew Knepley 
3687cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetUseFieldOffsets()`, `PetscSectionSetChart()`, `PetscSectionCreate()`
3688ea844a1aSMatthew Knepley @*/
3689d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSetUseFieldOffsets(PetscSection s, PetscBool flg)
3690d71ae5a4SJacob Faibussowitsch {
3691ea844a1aSMatthew Knepley   PetscFunctionBegin;
3692ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
3693ea844a1aSMatthew Knepley   s->useFieldOff = flg;
36943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3695ea844a1aSMatthew Knepley }
3696ea844a1aSMatthew Knepley 
3697ea844a1aSMatthew Knepley #define PetscSectionExpandPoints_Loop(TYPE) \
3698a8f51744SPierre Jolivet   do { \
3699ea844a1aSMatthew Knepley     PetscInt i, n, o0, o1, size; \
3700ea844a1aSMatthew Knepley     TYPE    *a0 = (TYPE *)origArray, *a1; \
37019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(s, &size)); \
37029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &a1)); \
3703ea844a1aSMatthew Knepley     for (i = 0; i < npoints; i++) { \
37049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(origSection, points_[i], &o0)); \
37059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(s, i, &o1)); \
37069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(s, i, &n)); \
37079566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(&a1[o1], &a0[o0], n *unitsize)); \
3708ea844a1aSMatthew Knepley     } \
3709ea844a1aSMatthew Knepley     *newArray = (void *)a1; \
3710a8f51744SPierre Jolivet   } while (0)
3711ea844a1aSMatthew Knepley 
3712ea844a1aSMatthew Knepley /*@
3713ea844a1aSMatthew Knepley   PetscSectionExtractDofsFromArray - Extracts elements of an array corresponding to DOFs of specified points.
3714ea844a1aSMatthew Knepley 
371540750d41SVaclav Hapla   Not Collective
3716ea844a1aSMatthew Knepley 
3717ea844a1aSMatthew Knepley   Input Parameters:
3718cab54364SBarry Smith + origSection - the `PetscSection` describing the layout of the array
3719cab54364SBarry Smith . dataType    - `MPI_Datatype` describing the data type of the array (currently only `MPIU_INT`, `MPIU_SCALAR`, `MPIU_REAL`)
372020662ed9SBarry Smith . origArray   - the array; its size must be equal to the storage size of `origSection`
372120662ed9SBarry Smith - points      - `IS` with points to extract; its indices must lie in the chart of `origSection`
3722ea844a1aSMatthew Knepley 
3723ea844a1aSMatthew Knepley   Output Parameters:
3724da81f932SPierre Jolivet + newSection - the new `PetscSection` describing the layout of the new array (with points renumbered 0,1,... but preserving numbers of DOFs)
372520662ed9SBarry Smith - newArray   - the array of the extracted DOFs; its size is the storage size of `newSection`
3726ea844a1aSMatthew Knepley 
3727ea844a1aSMatthew Knepley   Level: developer
3728ea844a1aSMatthew Knepley 
3729cab54364SBarry Smith .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetChart()`, `PetscSectionGetDof()`, `PetscSectionGetStorageSize()`, `PetscSectionCreate()`
3730ea844a1aSMatthew Knepley @*/
3731d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionExtractDofsFromArray(PetscSection origSection, MPI_Datatype dataType, const void *origArray, IS points, PetscSection *newSection, void *newArray[])
3732d71ae5a4SJacob Faibussowitsch {
3733ea844a1aSMatthew Knepley   PetscSection    s;
3734ea844a1aSMatthew Knepley   const PetscInt *points_;
3735ea844a1aSMatthew Knepley   PetscInt        i, n, npoints, pStart, pEnd;
3736ea844a1aSMatthew Knepley   PetscMPIInt     unitsize;
3737ea844a1aSMatthew Knepley 
3738ea844a1aSMatthew Knepley   PetscFunctionBegin;
3739ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(origSection, PETSC_SECTION_CLASSID, 1);
37404f572ea9SToby Isaac   PetscAssertPointer(origArray, 3);
3741ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(points, IS_CLASSID, 4);
37424f572ea9SToby Isaac   if (newSection) PetscAssertPointer(newSection, 5);
37434f572ea9SToby Isaac   if (newArray) PetscAssertPointer(newArray, 6);
37449566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_size(dataType, &unitsize));
37459566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &npoints));
37469566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &points_));
37479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(origSection, &pStart, &pEnd));
37489566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
37499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(s, 0, npoints));
3750ea844a1aSMatthew Knepley   for (i = 0; i < npoints; i++) {
3751c9cc58a2SBarry Smith     PetscCheck(points_[i] >= pStart && points_[i] < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "point %" PetscInt_FMT " (index %" PetscInt_FMT ") in input IS out of input section's chart", points_[i], i);
37529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(origSection, points_[i], &n));
37539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(s, i, n));
3754ea844a1aSMatthew Knepley   }
37559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(s));
3756ea844a1aSMatthew Knepley   if (newArray) {
37579371c9d4SSatish Balay     if (dataType == MPIU_INT) {
37589371c9d4SSatish Balay       PetscSectionExpandPoints_Loop(PetscInt);
37599371c9d4SSatish Balay     } else if (dataType == MPIU_SCALAR) {
37609371c9d4SSatish Balay       PetscSectionExpandPoints_Loop(PetscScalar);
37619371c9d4SSatish Balay     } else if (dataType == MPIU_REAL) {
37629371c9d4SSatish Balay       PetscSectionExpandPoints_Loop(PetscReal);
37639371c9d4SSatish Balay     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "not implemented for this MPI_Datatype");
3764ea844a1aSMatthew Knepley   }
3765ea844a1aSMatthew Knepley   if (newSection) {
3766ea844a1aSMatthew Knepley     *newSection = s;
3767ea844a1aSMatthew Knepley   } else {
37689566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&s));
3769ea844a1aSMatthew Knepley   }
37709566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &points_));
37713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3772ea844a1aSMatthew Knepley }
3773