Actual source code: section.c
1: /*
2: This file contains routines for basic section object implementation.
3: */
5: #include <petsc/private/sectionimpl.h>
6: #include <petscsf.h>
8: PetscClassId PETSC_SECTION_CLASSID;
10: /*@
11: PetscSectionCreate - Allocates a `PetscSection` and sets the map contents to the default.
13: Collective
15: Input Parameters:
16: + comm - the MPI communicator
17: - s - pointer to the section
19: Level: beginner
21: Notes:
22: Typical calling sequence
23: .vb
24: PetscSectionCreate(MPI_Comm,PetscSection *);!
25: PetscSectionSetNumFields(PetscSection, numFields);
26: PetscSectionSetChart(PetscSection,low,high);
27: PetscSectionSetDof(PetscSection,point,numdof);
28: PetscSectionSetUp(PetscSection);
29: PetscSectionGetOffset(PetscSection,point,PetscInt *);
30: PetscSectionDestroy(PetscSection);
31: .ve
33: 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.
35: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionDestroy()`, `PetscSectionCreateGlobalSection()`
36: @*/
37: PetscErrorCode PetscSectionCreate(MPI_Comm comm, PetscSection *s)
38: {
39: PetscFunctionBegin;
41: PetscCall(ISInitializePackage());
43: PetscCall(PetscHeaderCreate(*s, PETSC_SECTION_CLASSID, "PetscSection", "Section", "IS", comm, PetscSectionDestroy, PetscSectionView));
45: (*s)->pStart = -1;
46: (*s)->pEnd = -1;
47: (*s)->perm = NULL;
48: (*s)->pointMajor = PETSC_TRUE;
49: (*s)->includesConstraints = PETSC_TRUE;
50: (*s)->atlasDof = NULL;
51: (*s)->atlasOff = NULL;
52: (*s)->bc = NULL;
53: (*s)->bcIndices = NULL;
54: (*s)->setup = PETSC_FALSE;
55: (*s)->numFields = 0;
56: (*s)->fieldNames = NULL;
57: (*s)->field = NULL;
58: (*s)->useFieldOff = PETSC_FALSE;
59: (*s)->compNames = NULL;
60: (*s)->clObj = NULL;
61: (*s)->clHash = NULL;
62: (*s)->clSection = NULL;
63: (*s)->clPoints = NULL;
64: PetscCall(PetscSectionInvalidateMaxDof_Internal(*s));
65: PetscFunctionReturn(PETSC_SUCCESS);
66: }
68: /*@
69: PetscSectionCopy - Creates a shallow (if possible) copy of the `PetscSection`
71: Collective
73: Input Parameter:
74: . section - the `PetscSection`
76: Output Parameter:
77: . newSection - the copy
79: Level: intermediate
81: Developer Note:
82: What exactly does shallow mean in this context?
84: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`
85: @*/
86: PetscErrorCode PetscSectionCopy(PetscSection section, PetscSection newSection)
87: {
88: PetscSectionSym sym;
89: IS perm;
90: PetscInt numFields, f, c, pStart, pEnd, p;
92: PetscFunctionBegin;
95: PetscCall(PetscSectionReset(newSection));
96: PetscCall(PetscSectionGetNumFields(section, &numFields));
97: if (numFields) PetscCall(PetscSectionSetNumFields(newSection, numFields));
98: for (f = 0; f < numFields; ++f) {
99: const char *fieldName = NULL, *compName = NULL;
100: PetscInt numComp = 0;
102: PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
103: PetscCall(PetscSectionSetFieldName(newSection, f, fieldName));
104: PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
105: PetscCall(PetscSectionSetFieldComponents(newSection, f, numComp));
106: for (c = 0; c < numComp; ++c) {
107: PetscCall(PetscSectionGetComponentName(section, f, c, &compName));
108: PetscCall(PetscSectionSetComponentName(newSection, f, c, compName));
109: }
110: PetscCall(PetscSectionGetFieldSym(section, f, &sym));
111: PetscCall(PetscSectionSetFieldSym(newSection, f, sym));
112: }
113: PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
114: PetscCall(PetscSectionSetChart(newSection, pStart, pEnd));
115: PetscCall(PetscSectionGetPermutation(section, &perm));
116: PetscCall(PetscSectionSetPermutation(newSection, perm));
117: PetscCall(PetscSectionGetSym(section, &sym));
118: PetscCall(PetscSectionSetSym(newSection, sym));
119: for (p = pStart; p < pEnd; ++p) {
120: PetscInt dof, cdof, fcdof = 0;
122: PetscCall(PetscSectionGetDof(section, p, &dof));
123: PetscCall(PetscSectionSetDof(newSection, p, dof));
124: PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
125: if (cdof) PetscCall(PetscSectionSetConstraintDof(newSection, p, cdof));
126: for (f = 0; f < numFields; ++f) {
127: PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
128: PetscCall(PetscSectionSetFieldDof(newSection, p, f, dof));
129: if (cdof) {
130: PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
131: if (fcdof) PetscCall(PetscSectionSetFieldConstraintDof(newSection, p, f, fcdof));
132: }
133: }
134: }
135: PetscCall(PetscSectionSetUp(newSection));
136: for (p = pStart; p < pEnd; ++p) {
137: PetscInt off, cdof, fcdof = 0;
138: const PetscInt *cInd;
140: /* Must set offsets in case they do not agree with the prefix sums */
141: PetscCall(PetscSectionGetOffset(section, p, &off));
142: PetscCall(PetscSectionSetOffset(newSection, p, off));
143: PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
144: if (cdof) {
145: PetscCall(PetscSectionGetConstraintIndices(section, p, &cInd));
146: PetscCall(PetscSectionSetConstraintIndices(newSection, p, cInd));
147: for (f = 0; f < numFields; ++f) {
148: PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
149: if (fcdof) {
150: PetscCall(PetscSectionGetFieldConstraintIndices(section, p, f, &cInd));
151: PetscCall(PetscSectionSetFieldConstraintIndices(newSection, p, f, cInd));
152: }
153: }
154: }
155: }
156: PetscFunctionReturn(PETSC_SUCCESS);
157: }
159: /*@
160: PetscSectionClone - Creates a shallow (if possible) copy of the `PetscSection`
162: Collective
164: Input Parameter:
165: . section - the `PetscSection`
167: Output Parameter:
168: . newSection - the copy
170: Level: beginner
172: Developer Note:
173: With standard PETSc terminology this should be called `PetscSectionDuplicate()`
175: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionCopy()`
176: @*/
177: PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection)
178: {
179: PetscFunctionBegin;
182: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), newSection));
183: PetscCall(PetscSectionCopy(section, *newSection));
184: PetscFunctionReturn(PETSC_SUCCESS);
185: }
187: /*@
188: PetscSectionSetFromOptions - sets parameters in a `PetscSection` from the options database
190: Collective
192: Input Parameter:
193: . section - the `PetscSection`
195: Options Database Key:
196: . -petscsection_point_major - `PETSC_TRUE` for point-major order
198: Level: intermediate
200: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`
201: @*/
202: PetscErrorCode PetscSectionSetFromOptions(PetscSection s)
203: {
204: PetscFunctionBegin;
206: PetscObjectOptionsBegin((PetscObject)s);
207: PetscCall(PetscOptionsBool("-petscsection_point_major", "The for ordering, either point major or field major", "PetscSectionSetPointMajor", s->pointMajor, &s->pointMajor, NULL));
208: /* process any options handlers added with PetscObjectAddOptionsHandler() */
209: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)s, PetscOptionsObject));
210: PetscOptionsEnd();
211: PetscCall(PetscObjectViewFromOptions((PetscObject)s, NULL, "-petscsection_view"));
212: PetscFunctionReturn(PETSC_SUCCESS);
213: }
215: /*@
216: PetscSectionCompare - Compares two sections
218: Collective
220: Input Parameters:
221: + s1 - the first `PetscSection`
222: - s2 - the second `PetscSection`
224: Output Parameter:
225: . congruent - `PETSC_TRUE` if the two sections are congruent, `PETSC_FALSE` otherwise
227: Level: intermediate
229: Note:
230: Field names are disregarded.
232: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionCopy()`, `PetscSectionClone()`
233: @*/
234: PetscErrorCode PetscSectionCompare(PetscSection s1, PetscSection s2, PetscBool *congruent)
235: {
236: PetscInt pStart, pEnd, nfields, ncdof, nfcdof, p, f, n1, n2;
237: const PetscInt *idx1, *idx2;
238: IS perm1, perm2;
239: PetscBool flg;
240: PetscMPIInt mflg;
242: PetscFunctionBegin;
246: flg = PETSC_FALSE;
248: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)s1), PetscObjectComm((PetscObject)s2), &mflg));
249: if (mflg != MPI_CONGRUENT && mflg != MPI_IDENT) {
250: *congruent = PETSC_FALSE;
251: PetscFunctionReturn(PETSC_SUCCESS);
252: }
254: PetscCall(PetscSectionGetChart(s1, &pStart, &pEnd));
255: PetscCall(PetscSectionGetChart(s2, &n1, &n2));
256: if (pStart != n1 || pEnd != n2) goto not_congruent;
258: PetscCall(PetscSectionGetPermutation(s1, &perm1));
259: PetscCall(PetscSectionGetPermutation(s2, &perm2));
260: if (perm1 && perm2) {
261: PetscCall(ISEqual(perm1, perm2, congruent));
262: if (!(*congruent)) goto not_congruent;
263: } else if (perm1 != perm2) goto not_congruent;
265: for (p = pStart; p < pEnd; ++p) {
266: PetscCall(PetscSectionGetOffset(s1, p, &n1));
267: PetscCall(PetscSectionGetOffset(s2, p, &n2));
268: if (n1 != n2) goto not_congruent;
270: PetscCall(PetscSectionGetDof(s1, p, &n1));
271: PetscCall(PetscSectionGetDof(s2, p, &n2));
272: if (n1 != n2) goto not_congruent;
274: PetscCall(PetscSectionGetConstraintDof(s1, p, &ncdof));
275: PetscCall(PetscSectionGetConstraintDof(s2, p, &n2));
276: if (ncdof != n2) goto not_congruent;
278: PetscCall(PetscSectionGetConstraintIndices(s1, p, &idx1));
279: PetscCall(PetscSectionGetConstraintIndices(s2, p, &idx2));
280: PetscCall(PetscArraycmp(idx1, idx2, ncdof, congruent));
281: if (!(*congruent)) goto not_congruent;
282: }
284: PetscCall(PetscSectionGetNumFields(s1, &nfields));
285: PetscCall(PetscSectionGetNumFields(s2, &n2));
286: if (nfields != n2) goto not_congruent;
288: for (f = 0; f < nfields; ++f) {
289: PetscCall(PetscSectionGetFieldComponents(s1, f, &n1));
290: PetscCall(PetscSectionGetFieldComponents(s2, f, &n2));
291: if (n1 != n2) goto not_congruent;
293: for (p = pStart; p < pEnd; ++p) {
294: PetscCall(PetscSectionGetFieldOffset(s1, p, f, &n1));
295: PetscCall(PetscSectionGetFieldOffset(s2, p, f, &n2));
296: if (n1 != n2) goto not_congruent;
298: PetscCall(PetscSectionGetFieldDof(s1, p, f, &n1));
299: PetscCall(PetscSectionGetFieldDof(s2, p, f, &n2));
300: if (n1 != n2) goto not_congruent;
302: PetscCall(PetscSectionGetFieldConstraintDof(s1, p, f, &nfcdof));
303: PetscCall(PetscSectionGetFieldConstraintDof(s2, p, f, &n2));
304: if (nfcdof != n2) goto not_congruent;
306: PetscCall(PetscSectionGetFieldConstraintIndices(s1, p, f, &idx1));
307: PetscCall(PetscSectionGetFieldConstraintIndices(s2, p, f, &idx2));
308: PetscCall(PetscArraycmp(idx1, idx2, nfcdof, congruent));
309: if (!(*congruent)) goto not_congruent;
310: }
311: }
313: flg = PETSC_TRUE;
314: not_congruent:
315: PetscCall(MPIU_Allreduce(&flg, congruent, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)s1)));
316: PetscFunctionReturn(PETSC_SUCCESS);
317: }
319: /*@
320: PetscSectionGetNumFields - Returns the number of fields in a `PetscSection`, or 0 if no fields were defined.
322: Not Collective
324: Input Parameter:
325: . s - the `PetscSection`
327: Output Parameter:
328: . numFields - the number of fields defined, or 0 if none were defined
330: Level: intermediate
332: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetNumFields()`
333: @*/
334: PetscErrorCode PetscSectionGetNumFields(PetscSection s, PetscInt *numFields)
335: {
336: PetscFunctionBegin;
339: *numFields = s->numFields;
340: PetscFunctionReturn(PETSC_SUCCESS);
341: }
343: /*@
344: PetscSectionSetNumFields - Sets the number of fields in a `PetscSection`
346: Not Collective
348: Input Parameters:
349: + s - the `PetscSection`
350: - numFields - the number of fields
352: Level: intermediate
354: .seealso: [PetscSection](sec_petscsection), `PetscSection()`, `PetscSectionGetNumFields()`
355: @*/
356: PetscErrorCode PetscSectionSetNumFields(PetscSection s, PetscInt numFields)
357: {
358: PetscInt f;
360: PetscFunctionBegin;
362: PetscCheck(numFields > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "The number of fields %" PetscInt_FMT " must be positive", numFields);
363: PetscCall(PetscSectionReset(s));
365: s->numFields = numFields;
366: PetscCall(PetscMalloc1(s->numFields, &s->numFieldComponents));
367: PetscCall(PetscMalloc1(s->numFields, &s->fieldNames));
368: PetscCall(PetscMalloc1(s->numFields, &s->compNames));
369: PetscCall(PetscMalloc1(s->numFields, &s->field));
370: for (f = 0; f < s->numFields; ++f) {
371: char name[64];
373: s->numFieldComponents[f] = 1;
375: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &s->field[f]));
376: PetscCall(PetscSNPrintf(name, 64, "Field_%" PetscInt_FMT, f));
377: PetscCall(PetscStrallocpy(name, (char **)&s->fieldNames[f]));
378: PetscCall(PetscSNPrintf(name, 64, "Component_0"));
379: PetscCall(PetscMalloc1(s->numFieldComponents[f], &s->compNames[f]));
380: PetscCall(PetscStrallocpy(name, (char **)&s->compNames[f][0]));
381: }
382: PetscFunctionReturn(PETSC_SUCCESS);
383: }
385: /*@C
386: PetscSectionGetFieldName - Returns the name of a field in the `PetscSection`
388: Not Collective
390: Input Parameters:
391: + s - the `PetscSection`
392: - field - the field number
394: Output Parameter:
395: . fieldName - the field name
397: Level: intermediate
399: Note:
400: Will error if the field number is out of range
402: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`
403: @*/
404: PetscErrorCode PetscSectionGetFieldName(PetscSection s, PetscInt field, const char *fieldName[])
405: {
406: PetscFunctionBegin;
409: PetscSectionCheckValidField(field, s->numFields);
410: *fieldName = s->fieldNames[field];
411: PetscFunctionReturn(PETSC_SUCCESS);
412: }
414: /*@C
415: PetscSectionSetFieldName - Sets the name of a field in the `PetscSection`
417: Not Collective
419: Input Parameters:
420: + s - the `PetscSection`
421: . field - the field number
422: - fieldName - the field name
424: Level: intermediate
426: Note:
427: Will error if the field number is out of range
429: .seealso: [PetscSection](sec_petscsection), `PetscSectionGetFieldName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`
430: @*/
431: PetscErrorCode PetscSectionSetFieldName(PetscSection s, PetscInt field, const char fieldName[])
432: {
433: PetscFunctionBegin;
436: PetscSectionCheckValidField(field, s->numFields);
437: PetscCall(PetscFree(s->fieldNames[field]));
438: PetscCall(PetscStrallocpy(fieldName, (char **)&s->fieldNames[field]));
439: PetscFunctionReturn(PETSC_SUCCESS);
440: }
442: /*@C
443: PetscSectionGetComponentName - Gets the name of a field component in the `PetscSection`
445: Not Collective
447: Input Parameters:
448: + s - the `PetscSection`
449: . field - the field number
450: - comp - the component number
452: Output Parameter:
453: . compName - the component name
455: Level: intermediate
457: Note:
458: Will error if the field or component number do not exist
460: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`,
461: `PetscSectionSetComponentName()`, `PetscSectionSetFieldName()`, `PetscSectionGetFieldComponents()`, `PetscSectionSetFieldComponents()`
462: @*/
463: PetscErrorCode PetscSectionGetComponentName(PetscSection s, PetscInt field, PetscInt comp, const char *compName[])
464: {
465: PetscFunctionBegin;
468: PetscSectionCheckValidField(field, s->numFields);
469: PetscSectionCheckValidFieldComponent(comp, s->numFieldComponents[field]);
470: *compName = s->compNames[field][comp];
471: PetscFunctionReturn(PETSC_SUCCESS);
472: }
474: /*@C
475: PetscSectionSetComponentName - Sets the name of a field component in the `PetscSection`
477: Not Collective
479: Input Parameters:
480: + s - the `PetscSection`
481: . field - the field number
482: . comp - the component number
483: - compName - the component name
485: Level: intermediate
487: Note:
488: Will error if the field or component number do not exist
490: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetComponentName()`, `PetscSectionSetNumFields()`, `PetscSectionGetNumFields()`,
491: `PetscSectionSetComponentName()`, `PetscSectionSetFieldName()`, `PetscSectionGetFieldComponents()`, `PetscSectionSetFieldComponents()`
492: @*/
493: PetscErrorCode PetscSectionSetComponentName(PetscSection s, PetscInt field, PetscInt comp, const char compName[])
494: {
495: PetscFunctionBegin;
498: PetscSectionCheckValidField(field, s->numFields);
499: PetscSectionCheckValidFieldComponent(comp, s->numFieldComponents[field]);
500: PetscCall(PetscFree(s->compNames[field][comp]));
501: PetscCall(PetscStrallocpy(compName, (char **)&s->compNames[field][comp]));
502: PetscFunctionReturn(PETSC_SUCCESS);
503: }
505: /*@
506: PetscSectionGetFieldComponents - Returns the number of field components for the given field.
508: Not Collective
510: Input Parameters:
511: + s - the `PetscSection`
512: - field - the field number
514: Output Parameter:
515: . numComp - the number of field components
517: Level: intermediate
519: Developer Note:
520: This function is misnamed. There is a Num in `PetscSectionGetNumFields()` but not in this name
522: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldComponents()`, `PetscSectionGetNumFields()`
523: @*/
524: PetscErrorCode PetscSectionGetFieldComponents(PetscSection s, PetscInt field, PetscInt *numComp)
525: {
526: PetscFunctionBegin;
529: PetscSectionCheckValidField(field, s->numFields);
530: *numComp = s->numFieldComponents[field];
531: PetscFunctionReturn(PETSC_SUCCESS);
532: }
534: /*@
535: PetscSectionSetFieldComponents - Sets the number of field components for the given field.
537: Not Collective
539: Input Parameters:
540: + s - the `PetscSection`
541: . field - the field number
542: - numComp - the number of field components
544: Level: intermediate
546: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldComponents()`, `PetscSectionGetNumFields()`
547: @*/
548: PetscErrorCode PetscSectionSetFieldComponents(PetscSection s, PetscInt field, PetscInt numComp)
549: {
550: PetscInt c;
552: PetscFunctionBegin;
554: PetscSectionCheckValidField(field, s->numFields);
555: if (s->compNames) {
556: for (c = 0; c < s->numFieldComponents[field]; ++c) PetscCall(PetscFree(s->compNames[field][c]));
557: PetscCall(PetscFree(s->compNames[field]));
558: }
560: s->numFieldComponents[field] = numComp;
561: if (numComp) {
562: PetscCall(PetscMalloc1(numComp, (char ***)&s->compNames[field]));
563: for (c = 0; c < numComp; ++c) {
564: char name[64];
566: PetscCall(PetscSNPrintf(name, 64, "%" PetscInt_FMT, c));
567: PetscCall(PetscStrallocpy(name, (char **)&s->compNames[field][c]));
568: }
569: }
570: PetscFunctionReturn(PETSC_SUCCESS);
571: }
573: /*@
574: PetscSectionGetChart - Returns the range [`pStart`, `pEnd`) in which points (indices) lie for this `PetscSection`
576: Not Collective
578: Input Parameter:
579: . s - the `PetscSection`
581: Output Parameters:
582: + pStart - the first point
583: - pEnd - one past the last point
585: Level: intermediate
587: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetChart()`, `PetscSectionCreate()`
588: @*/
589: PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd)
590: {
591: PetscFunctionBegin;
593: if (pStart) *pStart = s->pStart;
594: if (pEnd) *pEnd = s->pEnd;
595: PetscFunctionReturn(PETSC_SUCCESS);
596: }
598: /*@
599: PetscSectionSetChart - Sets the range [`pStart`, `pEnd`) in which points (indices) lie for this `PetscSection`
601: Not Collective
603: Input Parameters:
604: + s - the `PetscSection`
605: . pStart - the first point
606: - pEnd - one past the last point
608: Level: intermediate
610: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetChart()`, `PetscSectionCreate()`
611: @*/
612: PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd)
613: {
614: PetscInt f;
616: PetscFunctionBegin;
618: if (pStart == s->pStart && pEnd == s->pEnd) PetscFunctionReturn(PETSC_SUCCESS);
619: /* Cannot Reset() because it destroys field information */
620: s->setup = PETSC_FALSE;
621: PetscCall(PetscSectionDestroy(&s->bc));
622: PetscCall(PetscFree(s->bcIndices));
623: PetscCall(PetscFree2(s->atlasDof, s->atlasOff));
625: s->pStart = pStart;
626: s->pEnd = pEnd;
627: PetscCall(PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff));
628: PetscCall(PetscArrayzero(s->atlasDof, pEnd - pStart));
629: for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetChart(s->field[f], pStart, pEnd));
630: PetscFunctionReturn(PETSC_SUCCESS);
631: }
633: /*@
634: PetscSectionGetPermutation - Returns the permutation of [0, `pEnd` - `pStart`) or `NULL` that was set with `PetscSectionSetPermutation()`
636: Not Collective
638: Input Parameter:
639: . s - the `PetscSection`
641: Output Parameters:
642: . perm - The permutation as an `IS`
644: Level: intermediate
646: .seealso: [](sec_scatter), `IS`, `PetscSection`, `PetscSectionSetPermutation()`, `PetscSectionCreate()`
647: @*/
648: PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm)
649: {
650: PetscFunctionBegin;
652: if (perm) {
654: *perm = s->perm;
655: }
656: PetscFunctionReturn(PETSC_SUCCESS);
657: }
659: /*@
660: PetscSectionSetPermutation - Sets the permutation for [0, `pEnd` - `pStart`)
662: Not Collective
664: Input Parameters:
665: + s - the `PetscSection`
666: - perm - the permutation of points
668: Level: intermediate
670: Developer Note:
671: What purpose does this permutation serve?
673: .seealso: [](sec_scatter), `IS`, `PetscSection`, `PetscSectionGetPermutation()`, `PetscSectionCreate()`
674: @*/
675: PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm)
676: {
677: PetscFunctionBegin;
680: PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup");
681: if (s->perm != perm) {
682: PetscCall(ISDestroy(&s->perm));
683: if (perm) {
684: s->perm = perm;
685: PetscCall(PetscObjectReference((PetscObject)s->perm));
686: }
687: }
688: PetscFunctionReturn(PETSC_SUCCESS);
689: }
691: /*@
692: PetscSectionGetPointMajor - Returns the flag for dof ordering, `PETSC_TRUE` if it is point major, `PETSC_FALSE` if it is field major
694: Not Collective
696: Input Parameter:
697: . s - the `PetscSection`
699: Output Parameter:
700: . pm - the flag for point major ordering
702: Level: intermediate
704: .seealso: [PetscSection](sec_petscsection), `PetscSection`, PetscSectionSetPointMajor()`
705: @*/
706: PetscErrorCode PetscSectionGetPointMajor(PetscSection s, PetscBool *pm)
707: {
708: PetscFunctionBegin;
711: *pm = s->pointMajor;
712: PetscFunctionReturn(PETSC_SUCCESS);
713: }
715: /*@
716: PetscSectionSetPointMajor - Sets the flag for dof ordering, `PETSC_TRUE` for point major, otherwise it will be field major
718: Not Collective
720: Input Parameters:
721: + s - the `PetscSection`
722: - pm - the flag for point major ordering
724: Level: intermediate
726: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetPointMajor()`
727: @*/
728: PetscErrorCode PetscSectionSetPointMajor(PetscSection s, PetscBool pm)
729: {
730: PetscFunctionBegin;
732: PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set the dof ordering after the section is setup");
733: s->pointMajor = pm;
734: PetscFunctionReturn(PETSC_SUCCESS);
735: }
737: /*@
738: PetscSectionGetIncludesConstraints - Returns the flag indicating if constrained dofs were included when computing offsets in the `PetscSection`.
739: The value is set with `PetscSectionSetIncludesConstraints()`
741: Not Collective
743: Input Parameter:
744: . s - the `PetscSection`
746: Output Parameter:
747: . includesConstraints - the flag indicating if constrained dofs were included when computing offsets
749: Level: intermediate
751: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetIncludesConstraints()`
752: @*/
753: PetscErrorCode PetscSectionGetIncludesConstraints(PetscSection s, PetscBool *includesConstraints)
754: {
755: PetscFunctionBegin;
758: *includesConstraints = s->includesConstraints;
759: PetscFunctionReturn(PETSC_SUCCESS);
760: }
762: /*@
763: PetscSectionSetIncludesConstraints - Sets the flag indicating if constrained dofs are to be included when computing offsets
765: Not Collective
767: Input Parameters:
768: + s - the `PetscSection`
769: - includesConstraints - the flag indicating if constrained dofs are to be included when computing offsets
771: Level: intermediate
773: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetIncludesConstraints()`
774: @*/
775: PetscErrorCode PetscSectionSetIncludesConstraints(PetscSection s, PetscBool includesConstraints)
776: {
777: PetscFunctionBegin;
779: PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set includesConstraints after the section is set up");
780: s->includesConstraints = includesConstraints;
781: PetscFunctionReturn(PETSC_SUCCESS);
782: }
784: /*@
785: PetscSectionGetDof - Return the number of degrees of freedom associated with a given point.
787: Not Collective
789: Input Parameters:
790: + s - the `PetscSection`
791: - point - the point
793: Output Parameter:
794: . numDof - the number of dof
796: Note:
797: In a global section, this size will be negative for points not owned by this process.
799: Level: intermediate
801: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetDof()`, `PetscSectionCreate()`
802: @*/
803: PetscErrorCode PetscSectionGetDof(PetscSection s, PetscInt point, PetscInt *numDof)
804: {
805: PetscFunctionBeginHot;
808: 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);
809: *numDof = s->atlasDof[point - s->pStart];
810: PetscFunctionReturn(PETSC_SUCCESS);
811: }
813: /*@
814: PetscSectionSetDof - Sets the number of degrees of freedom associated with a given point.
816: Not Collective
818: Input Parameters:
819: + s - the `PetscSection`
820: . point - the point
821: - numDof - the number of dof
823: Level: intermediate
825: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionAddDof()`, `PetscSectionCreate()`
826: @*/
827: PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof)
828: {
829: PetscFunctionBegin;
831: 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);
832: s->atlasDof[point - s->pStart] = numDof;
833: PetscCall(PetscSectionInvalidateMaxDof_Internal(s));
834: PetscFunctionReturn(PETSC_SUCCESS);
835: }
837: /*@
838: PetscSectionAddDof - Adds to the number of degrees of freedom associated with a given point.
840: Not Collective
842: Input Parameters:
843: + s - the `PetscSection`
844: . point - the point
845: - numDof - the number of additional dof
847: Level: intermediate
849: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetDof()`, `PetscSectionCreate()`
850: @*/
851: PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof)
852: {
853: PetscFunctionBeginHot;
855: 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);
856: s->atlasDof[point - s->pStart] += numDof;
857: PetscCall(PetscSectionInvalidateMaxDof_Internal(s));
858: PetscFunctionReturn(PETSC_SUCCESS);
859: }
861: /*@
862: PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point.
864: Not Collective
866: Input Parameters:
867: + s - the `PetscSection`
868: . point - the point
869: - field - the field
871: Output Parameter:
872: . numDof - the number of dof
874: Level: intermediate
876: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldDof()`, `PetscSectionCreate()`
877: @*/
878: PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
879: {
880: PetscFunctionBegin;
883: PetscSectionCheckValidField(field, s->numFields);
884: PetscCall(PetscSectionGetDof(s->field[field], point, numDof));
885: PetscFunctionReturn(PETSC_SUCCESS);
886: }
888: /*@
889: PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point.
891: Not Collective
893: Input Parameters:
894: + s - the `PetscSection`
895: . point - the point
896: . field - the field
897: - numDof - the number of dof
899: Level: intermediate
901: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldDof()`, `PetscSectionCreate()`
902: @*/
903: PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
904: {
905: PetscFunctionBegin;
907: PetscSectionCheckValidField(field, s->numFields);
908: PetscCall(PetscSectionSetDof(s->field[field], point, numDof));
909: PetscFunctionReturn(PETSC_SUCCESS);
910: }
912: /*@
913: PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point.
915: Not Collective
917: Input Parameters:
918: + s - the `PetscSection`
919: . point - the point
920: . field - the field
921: - numDof - the number of dof
923: Level: intermediate
925: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetFieldDof()`, `PetscSectionGetFieldDof()`, `PetscSectionCreate()`
926: @*/
927: PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
928: {
929: PetscFunctionBegin;
931: PetscSectionCheckValidField(field, s->numFields);
932: PetscCall(PetscSectionAddDof(s->field[field], point, numDof));
933: PetscFunctionReturn(PETSC_SUCCESS);
934: }
936: /*@
937: PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point.
939: Not Collective
941: Input Parameters:
942: + s - the `PetscSection`
943: - point - the point
945: Output Parameter:
946: . numDof - the number of dof which are fixed by constraints
948: Level: intermediate
950: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetConstraintDof()`, `PetscSectionCreate()`
951: @*/
952: PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof)
953: {
954: PetscFunctionBegin;
957: if (s->bc) {
958: PetscCall(PetscSectionGetDof(s->bc, point, numDof));
959: } else *numDof = 0;
960: PetscFunctionReturn(PETSC_SUCCESS);
961: }
963: /*@
964: PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point.
966: Not Collective
968: Input Parameters:
969: + s - the `PetscSection`
970: . point - the point
971: - numDof - the number of dof which are fixed by constraints
973: Level: intermediate
975: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetDof()`, `PetscSectionGetConstraintDof()`, `PetscSectionCreate()`
976: @*/
977: PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
978: {
979: PetscFunctionBegin;
981: if (numDof) {
982: PetscCall(PetscSectionCheckConstraints_Private(s));
983: PetscCall(PetscSectionSetDof(s->bc, point, numDof));
984: }
985: PetscFunctionReturn(PETSC_SUCCESS);
986: }
988: /*@
989: PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point.
991: Not Collective
993: Input Parameters:
994: + s - the `PetscSection`
995: . point - the point
996: - numDof - the number of additional dof which are fixed by constraints
998: Level: intermediate
1000: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionAddDof()`, `PetscSectionGetConstraintDof()`, `PetscSectionCreate()`
1001: @*/
1002: PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
1003: {
1004: PetscFunctionBegin;
1006: if (numDof) {
1007: PetscCall(PetscSectionCheckConstraints_Private(s));
1008: PetscCall(PetscSectionAddDof(s->bc, point, numDof));
1009: }
1010: PetscFunctionReturn(PETSC_SUCCESS);
1011: }
1013: /*@
1014: PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point.
1016: Not Collective
1018: Input Parameters:
1019: + s - the `PetscSection`
1020: . point - the point
1021: - field - the field
1023: Output Parameter:
1024: . numDof - the number of dof which are fixed by constraints
1026: Level: intermediate
1028: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetFieldConstraintDof()`, `PetscSectionCreate()`
1029: @*/
1030: PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
1031: {
1032: PetscFunctionBegin;
1035: PetscSectionCheckValidField(field, s->numFields);
1036: PetscCall(PetscSectionGetConstraintDof(s->field[field], point, numDof));
1037: PetscFunctionReturn(PETSC_SUCCESS);
1038: }
1040: /*@
1041: PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point.
1043: Not Collective
1045: Input Parameters:
1046: + s - the `PetscSection`
1047: . point - the point
1048: . field - the field
1049: - numDof - the number of dof which are fixed by constraints
1051: Level: intermediate
1053: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetDof()`, `PetscSectionGetFieldConstraintDof()`, `PetscSectionCreate()`
1054: @*/
1055: PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
1056: {
1057: PetscFunctionBegin;
1059: PetscSectionCheckValidField(field, s->numFields);
1060: PetscCall(PetscSectionSetConstraintDof(s->field[field], point, numDof));
1061: PetscFunctionReturn(PETSC_SUCCESS);
1062: }
1064: /*@
1065: PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point.
1067: Not Collective
1069: Input Parameters:
1070: + s - the `PetscSection`
1071: . point - the point
1072: . field - the field
1073: - numDof - the number of additional dof which are fixed by constraints
1075: Level: intermediate
1077: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionAddDof()`, `PetscSectionGetFieldConstraintDof()`, `PetscSectionCreate()`
1078: @*/
1079: PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
1080: {
1081: PetscFunctionBegin;
1083: PetscSectionCheckValidField(field, s->numFields);
1084: PetscCall(PetscSectionAddConstraintDof(s->field[field], point, numDof));
1085: PetscFunctionReturn(PETSC_SUCCESS);
1086: }
1088: /*@
1089: PetscSectionSetUpBC - Setup the subsections describing boundary conditions.
1091: Not Collective
1093: Input Parameter:
1094: . s - the `PetscSection`
1096: Level: advanced
1098: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSetUp()`, `PetscSectionCreate()`
1099: @*/
1100: PetscErrorCode PetscSectionSetUpBC(PetscSection s)
1101: {
1102: PetscFunctionBegin;
1104: if (s->bc) {
1105: const PetscInt last = (s->bc->pEnd - s->bc->pStart) - 1;
1107: PetscCall(PetscSectionSetUp(s->bc));
1108: PetscCall(PetscMalloc1((last >= 0 ? s->bc->atlasOff[last] + s->bc->atlasDof[last] : 0), &s->bcIndices));
1109: }
1110: PetscFunctionReturn(PETSC_SUCCESS);
1111: }
1113: /*@
1114: PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point.
1116: Not Collective
1118: Input Parameter:
1119: . s - the `PetscSection`
1121: Level: intermediate
1123: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`
1124: @*/
1125: PetscErrorCode PetscSectionSetUp(PetscSection s)
1126: {
1127: const PetscInt *pind = NULL;
1128: PetscInt offset = 0, foff, p, f;
1130: PetscFunctionBegin;
1132: if (s->setup) PetscFunctionReturn(PETSC_SUCCESS);
1133: s->setup = PETSC_TRUE;
1134: /* Set offsets and field offsets for all points */
1135: /* Assume that all fields have the same chart */
1136: PetscCheck(s->includesConstraints, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscSectionSetUp is currently unsupported for includesConstraints = PETSC_TRUE");
1137: if (s->perm) PetscCall(ISGetIndices(s->perm, &pind));
1138: if (s->pointMajor) {
1139: for (p = 0; p < s->pEnd - s->pStart; ++p) {
1140: const PetscInt q = pind ? pind[p] : p;
1142: /* Set point offset */
1143: s->atlasOff[q] = offset;
1144: offset += s->atlasDof[q];
1145: /* Set field offset */
1146: for (f = 0, foff = s->atlasOff[q]; f < s->numFields; ++f) {
1147: PetscSection sf = s->field[f];
1149: sf->atlasOff[q] = foff;
1150: foff += sf->atlasDof[q];
1151: }
1152: }
1153: } else {
1154: /* Set field offsets for all points */
1155: for (f = 0; f < s->numFields; ++f) {
1156: PetscSection sf = s->field[f];
1158: for (p = 0; p < s->pEnd - s->pStart; ++p) {
1159: const PetscInt q = pind ? pind[p] : p;
1161: sf->atlasOff[q] = offset;
1162: offset += sf->atlasDof[q];
1163: }
1164: }
1165: /* Disable point offsets since these are unused */
1166: for (p = 0; p < s->pEnd - s->pStart; ++p) s->atlasOff[p] = -1;
1167: }
1168: if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind));
1169: /* Setup BC sections */
1170: PetscCall(PetscSectionSetUpBC(s));
1171: for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetUpBC(s->field[f]));
1172: PetscFunctionReturn(PETSC_SUCCESS);
1173: }
1175: /*@
1176: PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the `PetscSection`
1178: Not Collective
1180: Input Parameters:
1181: . s - the `PetscSection`
1183: Output Parameter:
1184: . maxDof - the maximum dof
1186: Level: intermediate
1188: Note:
1189: The returned number is up-to-date without need for `PetscSectionSetUp()`.
1191: Developer Note:
1192: The returned number is calculated lazily and stashed.
1194: A call to `PetscSectionInvalidateMaxDof_Internal()` invalidates the stashed value.
1196: `PetscSectionInvalidateMaxDof_Internal()` is called in `PetscSectionSetDof()`, `PetscSectionAddDof()` and `PetscSectionReset()`
1198: It should also be called every time `atlasDof` is modified directly.
1200: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetDof()`, `PetscSectionSetDof()`, `PetscSectionAddDof()`, `PetscSectionCreate()`
1201: @*/
1202: PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof)
1203: {
1204: PetscInt p;
1206: PetscFunctionBegin;
1209: if (s->maxDof == PETSC_MIN_INT) {
1210: s->maxDof = 0;
1211: for (p = 0; p < s->pEnd - s->pStart; ++p) s->maxDof = PetscMax(s->maxDof, s->atlasDof[p]);
1212: }
1213: *maxDof = s->maxDof;
1214: PetscFunctionReturn(PETSC_SUCCESS);
1215: }
1217: /*@
1218: PetscSectionGetStorageSize - Return the size of an array or local `Vec` capable of holding all the degrees of freedom defined in a `PetscSection`
1220: Not Collective
1222: Input Parameter:
1223: . s - the `PetscSection`
1225: Output Parameter:
1226: . size - the size of an array which can hold all the dofs
1228: Level: intermediate
1230: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionGetConstrainedStorageSize()`, `PetscSectionCreate()`
1231: @*/
1232: PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size)
1233: {
1234: PetscInt p, n = 0;
1236: PetscFunctionBegin;
1239: for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
1240: *size = n;
1241: PetscFunctionReturn(PETSC_SUCCESS);
1242: }
1244: /*@
1245: PetscSectionGetConstrainedStorageSize - Return the size of an array or local `Vec` capable of holding all unconstrained degrees of freedom in a `PetscSection`
1247: Not Collective
1249: Input Parameter:
1250: . s - the `PetscSection`
1252: Output Parameter:
1253: . size - the size of an array which can hold all unconstrained dofs
1255: Level: intermediate
1257: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetStorageSize()`, `PetscSectionGetOffset()`, `PetscSectionCreate()`
1258: @*/
1259: PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size)
1260: {
1261: PetscInt p, n = 0;
1263: PetscFunctionBegin;
1266: for (p = 0; p < s->pEnd - s->pStart; ++p) {
1267: const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0;
1268: n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0;
1269: }
1270: *size = n;
1271: PetscFunctionReturn(PETSC_SUCCESS);
1272: }
1274: /*@
1275: PetscSectionCreateGlobalSection - Create a section describing the global field layout using
1276: the local section and a `PetscSF` describing the section point overlap.
1278: Input Parameters:
1279: + s - The `PetscSection` for the local field layout
1280: . sf - The `PetscSF` describing parallel layout of the section points (leaves are unowned local points)
1281: . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
1282: - localOffsets - If `PETSC_TRUE`, use local rather than global offsets for the points
1284: Output Parameter:
1285: . gsection - The `PetscSection` for the global field layout
1287: Level: intermediate
1289: Notes:
1290: If we have a set of local sections defining the layout of a set of local vectors, and also a `PetscSF` to determine which section points are shared and the ownership,
1291: we can calculate a global section defining the parallel data layout, and the associated global vector.
1293: This gives negative sizes and offsets to points not owned by this process
1295: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionCreateGlobalSectionCensored()`
1296: @*/
1297: PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscBool localOffsets, PetscSection *gsection)
1298: {
1299: PetscSection gs;
1300: const PetscInt *pind = NULL;
1301: PetscInt *recv = NULL, *neg = NULL;
1302: PetscInt pStart, pEnd, p, dof, cdof, off, foff, globalOff = 0, nroots, nlocal, maxleaf;
1303: PetscInt numFields, f, numComponents;
1305: PetscFunctionBegin;
1311: PetscCheck(s->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering");
1312: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &gs));
1313: PetscCall(PetscSectionGetNumFields(s, &numFields));
1314: if (numFields > 0) PetscCall(PetscSectionSetNumFields(gs, numFields));
1315: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1316: PetscCall(PetscSectionSetChart(gs, pStart, pEnd));
1317: gs->includesConstraints = includeConstraints;
1318: PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
1319: nlocal = nroots; /* The local/leaf space matches global/root space */
1320: /* Must allocate for all points visible to SF, which may be more than this section */
1321: if (nroots >= 0) { /* nroots < 0 means that the graph has not been set, only happens in serial */
1322: PetscCall(PetscSFGetLeafRange(sf, NULL, &maxleaf));
1323: PetscCheck(nroots >= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %" PetscInt_FMT " < pEnd %" PetscInt_FMT, nroots, pEnd);
1324: PetscCheck(maxleaf < nroots, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Max local leaf %" PetscInt_FMT " >= nroots %" PetscInt_FMT, maxleaf, nroots);
1325: PetscCall(PetscMalloc2(nroots, &neg, nlocal, &recv));
1326: PetscCall(PetscArrayzero(neg, nroots));
1327: }
1328: /* Mark all local points with negative dof */
1329: for (p = pStart; p < pEnd; ++p) {
1330: PetscCall(PetscSectionGetDof(s, p, &dof));
1331: PetscCall(PetscSectionSetDof(gs, p, dof));
1332: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
1333: if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(gs, p, cdof));
1334: if (neg) neg[p] = -(dof + 1);
1335: }
1336: PetscCall(PetscSectionSetUpBC(gs));
1337: 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]));
1338: if (nroots >= 0) {
1339: PetscCall(PetscArrayzero(recv, nlocal));
1340: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv, MPI_REPLACE));
1341: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv, MPI_REPLACE));
1342: for (p = pStart; p < pEnd; ++p) {
1343: if (recv[p] < 0) {
1344: gs->atlasDof[p - pStart] = recv[p];
1345: PetscCall(PetscSectionGetDof(s, p, &dof));
1346: 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);
1347: }
1348: }
1349: }
1350: /* Calculate new sizes, get process offset, and calculate point offsets */
1351: if (s->perm) PetscCall(ISGetIndices(s->perm, &pind));
1352: for (p = 0, off = 0; p < pEnd - pStart; ++p) {
1353: const PetscInt q = pind ? pind[p] : p;
1355: cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1356: gs->atlasOff[q] = off;
1357: off += gs->atlasDof[q] > 0 ? gs->atlasDof[q] - cdof : 0;
1358: }
1359: if (!localOffsets) {
1360: PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
1361: globalOff -= off;
1362: }
1363: for (p = pStart, off = 0; p < pEnd; ++p) {
1364: gs->atlasOff[p - pStart] += globalOff;
1365: if (neg) neg[p] = -(gs->atlasOff[p - pStart] + 1);
1366: }
1367: if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind));
1368: /* Put in negative offsets for ghost points */
1369: if (nroots >= 0) {
1370: PetscCall(PetscArrayzero(recv, nlocal));
1371: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv, MPI_REPLACE));
1372: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv, MPI_REPLACE));
1373: for (p = pStart; p < pEnd; ++p) {
1374: if (recv[p] < 0) gs->atlasOff[p - pStart] = recv[p];
1375: }
1376: }
1377: PetscCall(PetscFree2(neg, recv));
1378: /* Set field dofs/offsets/constraints */
1379: for (f = 0; f < numFields; ++f) {
1380: gs->field[f]->includesConstraints = includeConstraints;
1381: PetscCall(PetscSectionGetFieldComponents(s, f, &numComponents));
1382: PetscCall(PetscSectionSetFieldComponents(gs, f, numComponents));
1383: }
1384: for (p = pStart; p < pEnd; ++p) {
1385: PetscCall(PetscSectionGetOffset(gs, p, &off));
1386: for (f = 0, foff = off; f < numFields; ++f) {
1387: PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof));
1388: if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetFieldConstraintDof(gs, p, f, cdof));
1389: PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
1390: PetscCall(PetscSectionSetFieldDof(gs, p, f, off < 0 ? -(dof + 1) : dof));
1391: PetscCall(PetscSectionSetFieldOffset(gs, p, f, foff));
1392: PetscCall(PetscSectionGetFieldConstraintDof(gs, p, f, &cdof));
1393: foff = off < 0 ? foff - (dof - cdof) : foff + (dof - cdof);
1394: }
1395: }
1396: for (f = 0; f < numFields; ++f) {
1397: PetscSection gfs = gs->field[f];
1399: PetscCall(PetscSectionSetUpBC(gfs));
1400: 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]));
1401: }
1402: gs->setup = PETSC_TRUE;
1403: PetscCall(PetscSectionViewFromOptions(gs, NULL, "-global_section_view"));
1404: *gsection = gs;
1405: PetscFunctionReturn(PETSC_SUCCESS);
1406: }
1408: /*@
1409: PetscSectionCreateGlobalSectionCensored - Create a `PetscSection` describing the global field layout using
1410: the local section and an `PetscSF` describing the section point overlap.
1412: Input Parameters:
1413: + s - The `PetscSection` for the local field layout
1414: . sf - The `PetscSF` describing parallel layout of the section points
1415: . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
1416: . numExcludes - The number of exclusion ranges
1417: - excludes - An array [start_0, end_0, start_1, end_1, ...] where there are numExcludes pairs
1419: Output Parameter:
1420: . gsection - The `PetscSection` for the global field layout
1422: Level: advanced
1424: Note:
1425: This routine augments `PetscSectionCreateGlobalSection()` by allowing one to exclude certain ranges in the chart of the `PetscSection`
1427: This gives negative sizes and offsets to points not owned by this process
1429: Developer Note:
1430: This is a terrible function name
1432: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionCreateGlobalSectionCensored()`
1433: @*/
1434: PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection)
1435: {
1436: const PetscInt *pind = NULL;
1437: PetscInt *neg = NULL, *tmpOff = NULL;
1438: PetscInt pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
1440: PetscFunctionBegin;
1444: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
1445: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1446: PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
1447: PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
1448: if (nroots >= 0) {
1449: PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
1450: PetscCall(PetscCalloc1(nroots, &neg));
1451: if (nroots > pEnd - pStart) {
1452: PetscCall(PetscCalloc1(nroots, &tmpOff));
1453: } else {
1454: tmpOff = &(*gsection)->atlasDof[-pStart];
1455: }
1456: }
1457: /* Mark ghost points with negative dof */
1458: for (p = pStart; p < pEnd; ++p) {
1459: for (e = 0; e < numExcludes; ++e) {
1460: if ((p >= excludes[e * 2 + 0]) && (p < excludes[e * 2 + 1])) {
1461: PetscCall(PetscSectionSetDof(*gsection, p, 0));
1462: break;
1463: }
1464: }
1465: if (e < numExcludes) continue;
1466: PetscCall(PetscSectionGetDof(s, p, &dof));
1467: PetscCall(PetscSectionSetDof(*gsection, p, dof));
1468: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
1469: if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
1470: if (neg) neg[p] = -(dof + 1);
1471: }
1472: PetscCall(PetscSectionSetUpBC(*gsection));
1473: if (nroots >= 0) {
1474: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
1475: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
1476: if (nroots > pEnd - pStart) {
1477: for (p = pStart; p < pEnd; ++p) {
1478: if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
1479: }
1480: }
1481: }
1482: /* Calculate new sizes, get process offset, and calculate point offsets */
1483: if (s->perm) PetscCall(ISGetIndices(s->perm, &pind));
1484: for (p = 0, off = 0; p < pEnd - pStart; ++p) {
1485: const PetscInt q = pind ? pind[p] : p;
1487: cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1488: (*gsection)->atlasOff[q] = off;
1489: off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q] - cdof : 0;
1490: }
1491: PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
1492: globalOff -= off;
1493: for (p = 0, off = 0; p < pEnd - pStart; ++p) {
1494: (*gsection)->atlasOff[p] += globalOff;
1495: if (neg) neg[p + pStart] = -((*gsection)->atlasOff[p] + 1);
1496: }
1497: if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind));
1498: /* Put in negative offsets for ghost points */
1499: if (nroots >= 0) {
1500: if (nroots == pEnd - pStart) tmpOff = &(*gsection)->atlasOff[-pStart];
1501: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
1502: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
1503: if (nroots > pEnd - pStart) {
1504: for (p = pStart; p < pEnd; ++p) {
1505: if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
1506: }
1507: }
1508: }
1509: if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
1510: PetscCall(PetscFree(neg));
1511: PetscFunctionReturn(PETSC_SUCCESS);
1512: }
1514: /*@
1515: PetscSectionGetPointLayout - Get the `PetscLayout` associated with a `PetscSection`
1517: Collective
1519: Input Parameters:
1520: + comm - The `MPI_Comm`
1521: - s - The `PetscSection`
1523: Output Parameter:
1524: . layout - The point layout for the data that defines the section
1526: Level: advanced
1528: Notes:
1529: `PetscSectionGetValueLayout()` provides the `layout` for an array of data associated with the `PetscSection`. `PetscSectionGetPointLayout()`
1530: provides the `layout` for the data that
1531: defines the `PetscSection`
1533: This is usually called for the default global section.
1535: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetValueLayout()`, `PetscSectionCreate()`
1536: @*/
1537: PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1538: {
1539: PetscInt pStart, pEnd, p, localSize = 0;
1541: PetscFunctionBegin;
1542: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1543: for (p = pStart; p < pEnd; ++p) {
1544: PetscInt dof;
1546: PetscCall(PetscSectionGetDof(s, p, &dof));
1547: if (dof >= 0) ++localSize;
1548: }
1549: PetscCall(PetscLayoutCreate(comm, layout));
1550: PetscCall(PetscLayoutSetLocalSize(*layout, localSize));
1551: PetscCall(PetscLayoutSetBlockSize(*layout, 1));
1552: PetscCall(PetscLayoutSetUp(*layout));
1553: PetscFunctionReturn(PETSC_SUCCESS);
1554: }
1556: /*@
1557: PetscSectionGetValueLayout - Get the `PetscLayout` associated with the section dofs of a `PetscSection`
1559: Collective
1561: Input Parameters:
1562: + comm - The `MPI_Comm`
1563: - s - The `PetscSection`
1565: Output Parameter:
1566: . layout - The dof layout for the section
1568: Level: advanced
1570: Notes:
1571: `PetscSectionGetValueLayout()` provides the `layout` for an array of data associated with the `PetscSection`. `PetscSectionGetPointLayout()`
1572: provides the `layout` for the data that
1573: defines the `PetscSection`
1575: This is usually called for the default global section.
1577: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetPointLayout()`, `PetscSectionCreate()`
1578: @*/
1579: PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1580: {
1581: PetscInt pStart, pEnd, p, localSize = 0;
1583: PetscFunctionBegin;
1586: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1587: for (p = pStart; p < pEnd; ++p) {
1588: PetscInt dof, cdof;
1590: PetscCall(PetscSectionGetDof(s, p, &dof));
1591: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
1592: if (dof - cdof > 0) localSize += dof - cdof;
1593: }
1594: PetscCall(PetscLayoutCreate(comm, layout));
1595: PetscCall(PetscLayoutSetLocalSize(*layout, localSize));
1596: PetscCall(PetscLayoutSetBlockSize(*layout, 1));
1597: PetscCall(PetscLayoutSetUp(*layout));
1598: PetscFunctionReturn(PETSC_SUCCESS);
1599: }
1601: /*@
1602: PetscSectionGetOffset - Return the offset into an array or `Vec` for the dof associated with the given point.
1604: Not Collective
1606: Input Parameters:
1607: + s - the `PetscSection`
1608: - point - the point
1610: Output Parameter:
1611: . offset - the offset
1613: Note:
1614: In a global section, this offset will be negative for points not owned by this process.
1616: Level: intermediate
1618: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldOffset()`, `PetscSectionCreate()`
1619: @*/
1620: PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset)
1621: {
1622: PetscFunctionBegin;
1625: if (PetscDefined(USE_DEBUG)) 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);
1626: *offset = s->atlasOff[point - s->pStart];
1627: PetscFunctionReturn(PETSC_SUCCESS);
1628: }
1630: /*@
1631: PetscSectionSetOffset - Set the offset into an array or `Vec` for the dof associated with the given point.
1633: Not Collective
1635: Input Parameters:
1636: + s - the `PetscSection`
1637: . point - the point
1638: - offset - the offset
1640: Level: intermediate
1642: Note:
1643: The user usually does not call this function, but uses `PetscSectionSetUp()`
1645: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldOffset()`, `PetscSectionCreate()`, `PetscSectionSetUp()`
1646: @*/
1647: PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset)
1648: {
1649: PetscFunctionBegin;
1651: 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);
1652: s->atlasOff[point - s->pStart] = offset;
1653: PetscFunctionReturn(PETSC_SUCCESS);
1654: }
1656: /*@
1657: PetscSectionGetFieldOffset - Return the offset into an array or `Vec` for the field dof associated with the given point.
1659: Not Collective
1661: Input Parameters:
1662: + s - the `PetscSection`
1663: . point - the point
1664: - field - the field
1666: Output Parameter:
1667: . offset - the offset
1669: Note:
1670: In a global section, this offset will be negative for points not owned by this process.
1672: Level: intermediate
1674: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionCreate()`
1675: @*/
1676: PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1677: {
1678: PetscFunctionBegin;
1681: PetscSectionCheckValidField(field, s->numFields);
1682: PetscCall(PetscSectionGetOffset(s->field[field], point, offset));
1683: PetscFunctionReturn(PETSC_SUCCESS);
1684: }
1686: /*@
1687: PetscSectionSetFieldOffset - Set the offset into an array or `Vec` for the dof associated with the given field at a point.
1689: Not Collective
1691: Input Parameters:
1692: + s - the `PetscSection`
1693: . point - the point
1694: . field - the field
1695: - offset - the offset
1697: Level: developer
1699: Note:
1700: The user usually does not call this function, but uses `PetscSectionSetUp()`
1702: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetFieldOffset()`, `PetscSectionSetOffset()`, `PetscSectionCreate()`, `PetscSectionSetUp()`
1703: @*/
1704: PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset)
1705: {
1706: PetscFunctionBegin;
1708: PetscSectionCheckValidField(field, s->numFields);
1709: PetscCall(PetscSectionSetOffset(s->field[field], point, offset));
1710: PetscFunctionReturn(PETSC_SUCCESS);
1711: }
1713: /*@
1714: PetscSectionGetFieldPointOffset - Return the offset on the given point for the dof associated with the given point.
1716: Not Collective
1718: Input Parameters:
1719: + s - the `PetscSection`
1720: . point - the point
1721: - field - the field
1723: Output Parameter:
1724: . offset - the offset
1726: Level: advanced
1728: Note:
1729: This gives the offset on a point of the field, ignoring constraints, meaning starting at the first dof for
1730: this point, what number is the first dof with this field.
1732: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionCreate()`
1733: @*/
1734: PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1735: {
1736: PetscInt off, foff;
1738: PetscFunctionBegin;
1741: PetscSectionCheckValidField(field, s->numFields);
1742: PetscCall(PetscSectionGetOffset(s, point, &off));
1743: PetscCall(PetscSectionGetOffset(s->field[field], point, &foff));
1744: *offset = foff - off;
1745: PetscFunctionReturn(PETSC_SUCCESS);
1746: }
1748: /*@
1749: PetscSectionGetOffsetRange - Return the full range of offsets [`start`, `end`) for a `PetscSection`
1751: Not Collective
1753: Input Parameter:
1754: . s - the `PetscSection`
1756: Output Parameters:
1757: + start - the minimum offset
1758: - end - one more than the maximum offset
1760: Level: intermediate
1762: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetOffset()`, `PetscSectionCreate()`
1763: @*/
1764: PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end)
1765: {
1766: PetscInt os = 0, oe = 0, pStart, pEnd, p;
1768: PetscFunctionBegin;
1770: if (s->atlasOff) {
1771: os = s->atlasOff[0];
1772: oe = s->atlasOff[0];
1773: }
1774: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1775: for (p = 0; p < pEnd - pStart; ++p) {
1776: PetscInt dof = s->atlasDof[p], off = s->atlasOff[p];
1778: if (off >= 0) {
1779: os = PetscMin(os, off);
1780: oe = PetscMax(oe, off + dof);
1781: }
1782: }
1783: if (start) *start = os;
1784: if (end) *end = oe;
1785: PetscFunctionReturn(PETSC_SUCCESS);
1786: }
1788: /*@
1789: PetscSectionCreateSubsection - Create a new, smaller `PetscSection` composed of only the selected fields
1791: Collective
1793: Input Parameters:
1794: + s - the `PetscSection`
1795: . len - the number of subfields
1796: - fields - the subfield numbers
1798: Output Parameter:
1799: . subs - the subsection
1801: Level: advanced
1803: Notes:
1804: The section offsets now refer to a new, smaller vector.
1806: This will error if a fieldnumber is out of range
1808: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSupersection()`, `PetscSectionCreate()`
1809: @*/
1810: PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt len, const PetscInt fields[], PetscSection *subs)
1811: {
1812: PetscInt nF, f, c, pStart, pEnd, p, maxCdof = 0;
1814: PetscFunctionBegin;
1815: if (!len) PetscFunctionReturn(PETSC_SUCCESS);
1819: PetscCall(PetscSectionGetNumFields(s, &nF));
1820: 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);
1821: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), subs));
1822: PetscCall(PetscSectionSetNumFields(*subs, len));
1823: for (f = 0; f < len; ++f) {
1824: const char *name = NULL;
1825: PetscInt numComp = 0;
1827: PetscCall(PetscSectionGetFieldName(s, fields[f], &name));
1828: PetscCall(PetscSectionSetFieldName(*subs, f, name));
1829: PetscCall(PetscSectionGetFieldComponents(s, fields[f], &numComp));
1830: PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp));
1831: for (c = 0; c < s->numFieldComponents[fields[f]]; ++c) {
1832: PetscCall(PetscSectionGetComponentName(s, fields[f], c, &name));
1833: PetscCall(PetscSectionSetComponentName(*subs, f, c, name));
1834: }
1835: }
1836: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
1837: PetscCall(PetscSectionSetChart(*subs, pStart, pEnd));
1838: for (p = pStart; p < pEnd; ++p) {
1839: PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0;
1841: for (f = 0; f < len; ++f) {
1842: PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof));
1843: PetscCall(PetscSectionSetFieldDof(*subs, p, f, fdof));
1844: PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof));
1845: if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof));
1846: dof += fdof;
1847: cdof += cfdof;
1848: }
1849: PetscCall(PetscSectionSetDof(*subs, p, dof));
1850: if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, p, cdof));
1851: maxCdof = PetscMax(cdof, maxCdof);
1852: }
1853: PetscCall(PetscSectionSetUp(*subs));
1854: if (maxCdof) {
1855: PetscInt *indices;
1857: PetscCall(PetscMalloc1(maxCdof, &indices));
1858: for (p = pStart; p < pEnd; ++p) {
1859: PetscInt cdof;
1861: PetscCall(PetscSectionGetConstraintDof(*subs, p, &cdof));
1862: if (cdof) {
1863: const PetscInt *oldIndices = NULL;
1864: PetscInt fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0;
1866: for (f = 0; f < len; ++f) {
1867: PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof));
1868: PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof));
1869: PetscCall(PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices));
1870: PetscCall(PetscSectionSetFieldConstraintIndices(*subs, p, f, oldIndices));
1871: for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] = oldIndices[fc] + fOff;
1872: numConst += cfdof;
1873: fOff += fdof;
1874: }
1875: PetscCall(PetscSectionSetConstraintIndices(*subs, p, indices));
1876: }
1877: }
1878: PetscCall(PetscFree(indices));
1879: }
1880: PetscFunctionReturn(PETSC_SUCCESS);
1881: }
1883: /*@
1884: PetscSectionCreateSupersection - Create a new, larger section composed of multiple input `PetscSection`s
1886: Collective
1888: Input Parameters:
1889: + s - the input sections
1890: - len - the number of input sections
1892: Output Parameter:
1893: . supers - the supersection
1895: Level: advanced
1897: Note:
1898: The section offsets now refer to a new, larger vector.
1900: Developer Note:
1901: Needs to explain how the sections are composed
1903: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSubsection()`, `PetscSectionCreate()`
1904: @*/
1905: PetscErrorCode PetscSectionCreateSupersection(PetscSection s[], PetscInt len, PetscSection *supers)
1906: {
1907: PetscInt Nf = 0, f, pStart = PETSC_MAX_INT, pEnd = 0, p, maxCdof = 0, i;
1909: PetscFunctionBegin;
1910: if (!len) PetscFunctionReturn(PETSC_SUCCESS);
1911: for (i = 0; i < len; ++i) {
1912: PetscInt nf, pStarti, pEndi;
1914: PetscCall(PetscSectionGetNumFields(s[i], &nf));
1915: PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi));
1916: pStart = PetscMin(pStart, pStarti);
1917: pEnd = PetscMax(pEnd, pEndi);
1918: Nf += nf;
1919: }
1920: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s[0]), supers));
1921: PetscCall(PetscSectionSetNumFields(*supers, Nf));
1922: for (i = 0, f = 0; i < len; ++i) {
1923: PetscInt nf, fi, ci;
1925: PetscCall(PetscSectionGetNumFields(s[i], &nf));
1926: for (fi = 0; fi < nf; ++fi, ++f) {
1927: const char *name = NULL;
1928: PetscInt numComp = 0;
1930: PetscCall(PetscSectionGetFieldName(s[i], fi, &name));
1931: PetscCall(PetscSectionSetFieldName(*supers, f, name));
1932: PetscCall(PetscSectionGetFieldComponents(s[i], fi, &numComp));
1933: PetscCall(PetscSectionSetFieldComponents(*supers, f, numComp));
1934: for (ci = 0; ci < s[i]->numFieldComponents[fi]; ++ci) {
1935: PetscCall(PetscSectionGetComponentName(s[i], fi, ci, &name));
1936: PetscCall(PetscSectionSetComponentName(*supers, f, ci, name));
1937: }
1938: }
1939: }
1940: PetscCall(PetscSectionSetChart(*supers, pStart, pEnd));
1941: for (p = pStart; p < pEnd; ++p) {
1942: PetscInt dof = 0, cdof = 0;
1944: for (i = 0, f = 0; i < len; ++i) {
1945: PetscInt nf, fi, pStarti, pEndi;
1946: PetscInt fdof = 0, cfdof = 0;
1948: PetscCall(PetscSectionGetNumFields(s[i], &nf));
1949: PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi));
1950: if ((p < pStarti) || (p >= pEndi)) continue;
1951: for (fi = 0; fi < nf; ++fi, ++f) {
1952: PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof));
1953: PetscCall(PetscSectionAddFieldDof(*supers, p, f, fdof));
1954: PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof));
1955: if (cfdof) PetscCall(PetscSectionAddFieldConstraintDof(*supers, p, f, cfdof));
1956: dof += fdof;
1957: cdof += cfdof;
1958: }
1959: }
1960: PetscCall(PetscSectionSetDof(*supers, p, dof));
1961: if (cdof) PetscCall(PetscSectionSetConstraintDof(*supers, p, cdof));
1962: maxCdof = PetscMax(cdof, maxCdof);
1963: }
1964: PetscCall(PetscSectionSetUp(*supers));
1965: if (maxCdof) {
1966: PetscInt *indices;
1968: PetscCall(PetscMalloc1(maxCdof, &indices));
1969: for (p = pStart; p < pEnd; ++p) {
1970: PetscInt cdof;
1972: PetscCall(PetscSectionGetConstraintDof(*supers, p, &cdof));
1973: if (cdof) {
1974: PetscInt dof, numConst = 0, fOff = 0;
1976: for (i = 0, f = 0; i < len; ++i) {
1977: const PetscInt *oldIndices = NULL;
1978: PetscInt nf, fi, pStarti, pEndi, fdof, cfdof, fc;
1980: PetscCall(PetscSectionGetNumFields(s[i], &nf));
1981: PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi));
1982: if ((p < pStarti) || (p >= pEndi)) continue;
1983: for (fi = 0; fi < nf; ++fi, ++f) {
1984: PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof));
1985: PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof));
1986: PetscCall(PetscSectionGetFieldConstraintIndices(s[i], p, fi, &oldIndices));
1987: for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] = oldIndices[fc];
1988: PetscCall(PetscSectionSetFieldConstraintIndices(*supers, p, f, &indices[numConst]));
1989: for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] += fOff;
1990: numConst += cfdof;
1991: }
1992: PetscCall(PetscSectionGetDof(s[i], p, &dof));
1993: fOff += dof;
1994: }
1995: PetscCall(PetscSectionSetConstraintIndices(*supers, p, indices));
1996: }
1997: }
1998: PetscCall(PetscFree(indices));
1999: }
2000: PetscFunctionReturn(PETSC_SUCCESS);
2001: }
2003: PetscErrorCode PetscSectionCreateSubplexSection_Internal(PetscSection s, IS subpointMap, PetscBool renumberPoints, PetscSection *subs)
2004: {
2005: const PetscInt *points = NULL, *indices = NULL;
2006: PetscInt numFields, f, c, numSubpoints = 0, pStart, pEnd, p, spStart, spEnd, subp;
2008: PetscFunctionBegin;
2012: PetscCall(PetscSectionGetNumFields(s, &numFields));
2013: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), subs));
2014: if (numFields) PetscCall(PetscSectionSetNumFields(*subs, numFields));
2015: for (f = 0; f < numFields; ++f) {
2016: const char *name = NULL;
2017: PetscInt numComp = 0;
2019: PetscCall(PetscSectionGetFieldName(s, f, &name));
2020: PetscCall(PetscSectionSetFieldName(*subs, f, name));
2021: PetscCall(PetscSectionGetFieldComponents(s, f, &numComp));
2022: PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp));
2023: for (c = 0; c < s->numFieldComponents[f]; ++c) {
2024: PetscCall(PetscSectionGetComponentName(s, f, c, &name));
2025: PetscCall(PetscSectionSetComponentName(*subs, f, c, name));
2026: }
2027: }
2028: /* For right now, we do not try to squeeze the subchart */
2029: if (subpointMap) {
2030: PetscCall(ISGetSize(subpointMap, &numSubpoints));
2031: PetscCall(ISGetIndices(subpointMap, &points));
2032: }
2033: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
2034: if (renumberPoints) {
2035: spStart = 0;
2036: spEnd = numSubpoints;
2037: } else {
2038: PetscCall(ISGetMinMax(subpointMap, &spStart, &spEnd));
2039: ++spEnd;
2040: }
2041: PetscCall(PetscSectionSetChart(*subs, spStart, spEnd));
2042: for (p = pStart; p < pEnd; ++p) {
2043: PetscInt dof, cdof, fdof = 0, cfdof = 0;
2045: PetscCall(PetscFindInt(p, numSubpoints, points, &subp));
2046: if (subp < 0) continue;
2047: if (!renumberPoints) subp = p;
2048: for (f = 0; f < numFields; ++f) {
2049: PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof));
2050: PetscCall(PetscSectionSetFieldDof(*subs, subp, f, fdof));
2051: PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cfdof));
2052: if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof));
2053: }
2054: PetscCall(PetscSectionGetDof(s, p, &dof));
2055: PetscCall(PetscSectionSetDof(*subs, subp, dof));
2056: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
2057: if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, subp, cdof));
2058: }
2059: PetscCall(PetscSectionSetUp(*subs));
2060: /* Change offsets to original offsets */
2061: for (p = pStart; p < pEnd; ++p) {
2062: PetscInt off, foff = 0;
2064: PetscCall(PetscFindInt(p, numSubpoints, points, &subp));
2065: if (subp < 0) continue;
2066: if (!renumberPoints) subp = p;
2067: for (f = 0; f < numFields; ++f) {
2068: PetscCall(PetscSectionGetFieldOffset(s, p, f, &foff));
2069: PetscCall(PetscSectionSetFieldOffset(*subs, subp, f, foff));
2070: }
2071: PetscCall(PetscSectionGetOffset(s, p, &off));
2072: PetscCall(PetscSectionSetOffset(*subs, subp, off));
2073: }
2074: /* Copy constraint indices */
2075: for (subp = spStart; subp < spEnd; ++subp) {
2076: PetscInt cdof;
2078: PetscCall(PetscSectionGetConstraintDof(*subs, subp, &cdof));
2079: if (cdof) {
2080: for (f = 0; f < numFields; ++f) {
2081: PetscCall(PetscSectionGetFieldConstraintIndices(s, points[subp - spStart], f, &indices));
2082: PetscCall(PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices));
2083: }
2084: PetscCall(PetscSectionGetConstraintIndices(s, points[subp - spStart], &indices));
2085: PetscCall(PetscSectionSetConstraintIndices(*subs, subp, indices));
2086: }
2087: }
2088: if (subpointMap) PetscCall(ISRestoreIndices(subpointMap, &points));
2089: PetscFunctionReturn(PETSC_SUCCESS);
2090: }
2092: /*@
2093: PetscSectionCreateSubmeshSection - Create a new, smaller section with support on the submesh
2095: Collective
2097: Input Parameters:
2098: + s - the `PetscSection`
2099: - subpointMap - a sorted list of points in the original mesh which are in the submesh
2101: Output Parameter:
2102: . subs - the subsection
2104: Level: advanced
2106: Note:
2107: The points are renumbered from 0, and the section offsets now refer to a new, smaller vector.
2108: Compare this with `PetscSectionCreateSubdomainSection()` that does not map the points numbers to start at zero but leaves them as before
2110: Developer Note:
2111: 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`
2113: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSubdomainSection()`, `PetscSectionCreateSubsection()`, `DMPlexGetSubpointMap()`, `PetscSectionCreate()`
2114: @*/
2115: PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs)
2116: {
2117: PetscFunctionBegin;
2118: PetscCall(PetscSectionCreateSubplexSection_Internal(s, subpointMap, PETSC_TRUE, subs));
2119: PetscFunctionReturn(PETSC_SUCCESS);
2120: }
2122: /*@
2123: PetscSectionCreateSubdomainSection - Create a new, smaller section with support on a subdomain of the mesh
2125: Collective
2127: Input Parameters:
2128: + s - the `PetscSection`
2129: - subpointMap - a sorted list of points in the original mesh which are in the subdomain
2131: Output Parameter:
2132: . subs - the subsection
2134: Level: advanced
2136: Note:
2137: The point numbers remain the same as in the larger `PetscSection`, but the section offsets now refer to a new, smaller vector.
2138: Compare this with `PetscSectionCreateSubmeshSection()` that maps the point numbers to start at zero
2140: Developer Notes:
2141: 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`
2143: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreateSubmeshSection()`, `PetscSectionCreateSubsection()`, `DMPlexGetSubpointMap()`, `PetscSectionCreate()`
2144: @*/
2145: PetscErrorCode PetscSectionCreateSubdomainSection(PetscSection s, IS subpointMap, PetscSection *subs)
2146: {
2147: PetscFunctionBegin;
2148: PetscCall(PetscSectionCreateSubplexSection_Internal(s, subpointMap, PETSC_FALSE, subs));
2149: PetscFunctionReturn(PETSC_SUCCESS);
2150: }
2152: static PetscErrorCode PetscSectionView_ASCII(PetscSection s, PetscViewer viewer)
2153: {
2154: PetscInt p;
2155: PetscMPIInt rank;
2157: PetscFunctionBegin;
2158: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
2159: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
2160: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
2161: for (p = 0; p < s->pEnd - s->pStart; ++p) {
2162: if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
2163: PetscInt b;
2165: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT " constrained", p + s->pStart, s->atlasDof[p], s->atlasOff[p]));
2166: if (s->bcIndices) {
2167: for (b = 0; b < s->bc->atlasDof[p]; ++b) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, s->bcIndices[s->bc->atlasOff[p] + b]));
2168: }
2169: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
2170: } else {
2171: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT "\n", p + s->pStart, s->atlasDof[p], s->atlasOff[p]));
2172: }
2173: }
2174: PetscCall(PetscViewerFlush(viewer));
2175: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
2176: if (s->sym) {
2177: PetscCall(PetscViewerASCIIPushTab(viewer));
2178: PetscCall(PetscSectionSymView(s->sym, viewer));
2179: PetscCall(PetscViewerASCIIPopTab(viewer));
2180: }
2181: PetscFunctionReturn(PETSC_SUCCESS);
2182: }
2184: /*@C
2185: PetscSectionViewFromOptions - View the `PetscSection` based on values in the options database
2187: Collective
2189: Input Parameters:
2190: + A - the `PetscSection` object to view
2191: . obj - Optional object that provides the options prefix used for the options
2192: - name - command line option
2194: Level: intermediate
2196: Note:
2197: See `PetscObjectViewFromOptions()` for available values of `PetscViewer` and `PetscViewerFormat`
2199: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionView`, `PetscObjectViewFromOptions()`, `PetscSectionCreate()`, `PetscSectionView()`
2200: @*/
2201: PetscErrorCode PetscSectionViewFromOptions(PetscSection A, PetscObject obj, const char name[])
2202: {
2203: PetscFunctionBegin;
2205: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
2206: PetscFunctionReturn(PETSC_SUCCESS);
2207: }
2209: /*@C
2210: PetscSectionView - Views a `PetscSection`
2212: Collective
2214: Input Parameters:
2215: + s - the `PetscSection` object to view
2216: - v - the viewer
2218: Level: beginner
2220: Note:
2221: `PetscSectionView()`, when viewer is of type `PETSCVIEWERHDF5`, only saves
2222: distribution independent data, such as dofs, offsets, constraint dofs,
2223: and constraint indices. Points that have negative dofs, for instance,
2224: are not saved as they represent points owned by other processes.
2225: Point numbering and rank assignment is currently not stored.
2226: The saved section can be loaded with `PetscSectionLoad()`.
2228: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionLoad()`, `PetscViewer`
2229: @*/
2230: PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer)
2231: {
2232: PetscBool isascii, ishdf5;
2233: PetscInt f;
2235: PetscFunctionBegin;
2237: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)s), &viewer));
2239: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2240: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2241: if (isascii) {
2242: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)s, viewer));
2243: if (s->numFields) {
2244: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " fields\n", s->numFields));
2245: for (f = 0; f < s->numFields; ++f) {
2246: PetscCall(PetscViewerASCIIPrintf(viewer, " field %" PetscInt_FMT " with %" PetscInt_FMT " components\n", f, s->numFieldComponents[f]));
2247: PetscCall(PetscSectionView_ASCII(s->field[f], viewer));
2248: }
2249: } else {
2250: PetscCall(PetscSectionView_ASCII(s, viewer));
2251: }
2252: } else if (ishdf5) {
2253: #if PetscDefined(HAVE_HDF5)
2254: PetscCall(PetscSectionView_HDF5_Internal(s, viewer));
2255: #else
2256: SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2257: #endif
2258: }
2259: PetscFunctionReturn(PETSC_SUCCESS);
2260: }
2262: /*@C
2263: PetscSectionLoad - Loads a `PetscSection`
2265: Collective
2267: Input Parameters:
2268: + s - the `PetscSection` object to load
2269: - v - the viewer
2271: Level: beginner
2273: Note:
2274: `PetscSectionLoad()`, when viewer is of type `PETSCVIEWERHDF5`, loads
2275: a section saved with `PetscSectionView()`. The number of processes
2276: used here (N) does not need to be the same as that used when saving.
2277: After calling this function, the chart of s on rank i will be set
2278: to [0, E_i), where \sum_{i=0}^{N-1}E_i equals to the total number of
2279: saved section points.
2281: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionView()`
2282: @*/
2283: PetscErrorCode PetscSectionLoad(PetscSection s, PetscViewer viewer)
2284: {
2285: PetscBool ishdf5;
2287: PetscFunctionBegin;
2290: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2291: if (ishdf5) {
2292: #if PetscDefined(HAVE_HDF5)
2293: PetscCall(PetscSectionLoad_HDF5_Internal(s, viewer));
2294: PetscFunctionReturn(PETSC_SUCCESS);
2295: #else
2296: SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2297: #endif
2298: } else SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "Viewer type %s not yet supported for PetscSection loading", ((PetscObject)viewer)->type_name);
2299: }
2301: static PetscErrorCode PetscSectionResetClosurePermutation(PetscSection section)
2302: {
2303: PetscSectionClosurePermVal clVal;
2305: PetscFunctionBegin;
2306: if (!section->clHash) PetscFunctionReturn(PETSC_SUCCESS);
2307: kh_foreach_value(section->clHash, clVal, {
2308: PetscCall(PetscFree(clVal.perm));
2309: PetscCall(PetscFree(clVal.invPerm));
2310: });
2311: kh_destroy(ClPerm, section->clHash);
2312: section->clHash = NULL;
2313: PetscFunctionReturn(PETSC_SUCCESS);
2314: }
2316: /*@
2317: PetscSectionReset - Frees all section data.
2319: Not Collective
2321: Input Parameters:
2322: . s - the `PetscSection`
2324: Level: beginner
2326: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`
2327: @*/
2328: PetscErrorCode PetscSectionReset(PetscSection s)
2329: {
2330: PetscInt f, c;
2332: PetscFunctionBegin;
2334: for (f = 0; f < s->numFields; ++f) {
2335: PetscCall(PetscSectionDestroy(&s->field[f]));
2336: PetscCall(PetscFree(s->fieldNames[f]));
2337: for (c = 0; c < s->numFieldComponents[f]; ++c) PetscCall(PetscFree(s->compNames[f][c]));
2338: PetscCall(PetscFree(s->compNames[f]));
2339: }
2340: PetscCall(PetscFree(s->numFieldComponents));
2341: PetscCall(PetscFree(s->fieldNames));
2342: PetscCall(PetscFree(s->compNames));
2343: PetscCall(PetscFree(s->field));
2344: PetscCall(PetscSectionDestroy(&s->bc));
2345: PetscCall(PetscFree(s->bcIndices));
2346: PetscCall(PetscFree2(s->atlasDof, s->atlasOff));
2347: PetscCall(PetscSectionDestroy(&s->clSection));
2348: PetscCall(ISDestroy(&s->clPoints));
2349: PetscCall(ISDestroy(&s->perm));
2350: PetscCall(PetscSectionResetClosurePermutation(s));
2351: PetscCall(PetscSectionSymDestroy(&s->sym));
2352: PetscCall(PetscSectionDestroy(&s->clSection));
2353: PetscCall(ISDestroy(&s->clPoints));
2354: PetscCall(PetscSectionInvalidateMaxDof_Internal(s));
2355: s->pStart = -1;
2356: s->pEnd = -1;
2357: s->maxDof = 0;
2358: s->setup = PETSC_FALSE;
2359: s->numFields = 0;
2360: s->clObj = NULL;
2361: PetscFunctionReturn(PETSC_SUCCESS);
2362: }
2364: /*@
2365: PetscSectionDestroy - Frees a section object and frees its range if that exists.
2367: Not Collective
2369: Input Parameters:
2370: . s - the `PetscSection`
2372: Level: beginner
2374: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionCreate()`, `PetscSectionReset()`
2375: @*/
2376: PetscErrorCode PetscSectionDestroy(PetscSection *s)
2377: {
2378: PetscFunctionBegin;
2379: if (!*s) PetscFunctionReturn(PETSC_SUCCESS);
2381: if (--((PetscObject)(*s))->refct > 0) {
2382: *s = NULL;
2383: PetscFunctionReturn(PETSC_SUCCESS);
2384: }
2385: PetscCall(PetscSectionReset(*s));
2386: PetscCall(PetscHeaderDestroy(s));
2387: PetscFunctionReturn(PETSC_SUCCESS);
2388: }
2390: PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values)
2391: {
2392: const PetscInt p = point - s->pStart;
2394: PetscFunctionBegin;
2396: *values = &baseArray[s->atlasOff[p]];
2397: PetscFunctionReturn(PETSC_SUCCESS);
2398: }
2400: PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode)
2401: {
2402: PetscInt *array;
2403: const PetscInt p = point - s->pStart;
2404: const PetscInt orientation = 0; /* Needs to be included for use in closure operations */
2405: PetscInt cDim = 0;
2407: PetscFunctionBegin;
2409: PetscCall(PetscSectionGetConstraintDof(s, p, &cDim));
2410: array = &baseArray[s->atlasOff[p]];
2411: if (!cDim) {
2412: if (orientation >= 0) {
2413: const PetscInt dim = s->atlasDof[p];
2414: PetscInt i;
2416: if (mode == INSERT_VALUES) {
2417: for (i = 0; i < dim; ++i) array[i] = values[i];
2418: } else {
2419: for (i = 0; i < dim; ++i) array[i] += values[i];
2420: }
2421: } else {
2422: PetscInt offset = 0;
2423: PetscInt j = -1, field, i;
2425: for (field = 0; field < s->numFields; ++field) {
2426: const PetscInt dim = s->field[field]->atlasDof[p];
2428: for (i = dim - 1; i >= 0; --i) array[++j] = values[i + offset];
2429: offset += dim;
2430: }
2431: }
2432: } else {
2433: if (orientation >= 0) {
2434: const PetscInt dim = s->atlasDof[p];
2435: PetscInt cInd = 0, i;
2436: const PetscInt *cDof;
2438: PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof));
2439: if (mode == INSERT_VALUES) {
2440: for (i = 0; i < dim; ++i) {
2441: if ((cInd < cDim) && (i == cDof[cInd])) {
2442: ++cInd;
2443: continue;
2444: }
2445: array[i] = values[i];
2446: }
2447: } else {
2448: for (i = 0; i < dim; ++i) {
2449: if ((cInd < cDim) && (i == cDof[cInd])) {
2450: ++cInd;
2451: continue;
2452: }
2453: array[i] += values[i];
2454: }
2455: }
2456: } else {
2457: const PetscInt *cDof;
2458: PetscInt offset = 0;
2459: PetscInt cOffset = 0;
2460: PetscInt j = 0, field;
2462: PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof));
2463: for (field = 0; field < s->numFields; ++field) {
2464: const PetscInt dim = s->field[field]->atlasDof[p]; /* PetscSectionGetFieldDof() */
2465: const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */
2466: const PetscInt sDim = dim - tDim;
2467: PetscInt cInd = 0, i, k;
2469: for (i = 0, k = dim + offset - 1; i < dim; ++i, ++j, --k) {
2470: if ((cInd < sDim) && (j == cDof[cInd + cOffset])) {
2471: ++cInd;
2472: continue;
2473: }
2474: array[j] = values[k];
2475: }
2476: offset += dim;
2477: cOffset += dim - tDim;
2478: }
2479: }
2480: }
2481: PetscFunctionReturn(PETSC_SUCCESS);
2482: }
2484: /*@C
2485: PetscSectionHasConstraints - Determine whether a `PetscSection` has constrained dofs
2487: Not Collective
2489: Input Parameter:
2490: . s - The `PetscSection`
2492: Output Parameter:
2493: . hasConstraints - flag indicating that the section has constrained dofs
2495: Level: intermediate
2497: .seealso: [PetscSection](sec_petscsection), `PetscSectionSetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2498: @*/
2499: PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints)
2500: {
2501: PetscFunctionBegin;
2504: *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE;
2505: PetscFunctionReturn(PETSC_SUCCESS);
2506: }
2508: /*@C
2509: PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained for a given point
2511: Not Collective
2513: Input Parameters:
2514: + s - The `PetscSection`
2515: - point - The point
2517: Output Parameter:
2518: . indices - The constrained dofs
2520: Level: intermediate
2522: Fortran Note:
2523: Use `PetscSectionGetConstraintIndicesF90()` and `PetscSectionRestoreConstraintIndicesF90()`
2525: .seealso: [PetscSection](sec_petscsection), `PetscSectionSetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2526: @*/
2527: PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices)
2528: {
2529: PetscFunctionBegin;
2531: if (s->bc) {
2532: PetscCall(VecIntGetValuesSection(s->bcIndices, s->bc, point, indices));
2533: } else *indices = NULL;
2534: PetscFunctionReturn(PETSC_SUCCESS);
2535: }
2537: /*@C
2538: PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained
2540: Not Collective
2542: Input Parameters:
2543: + s - The `PetscSection`
2544: . point - The point
2545: - indices - The constrained dofs
2547: Level: intermediate
2549: Fortran Note:
2550: Use `PetscSectionSetConstraintIndicesF90()`
2552: .seealso: [PetscSection](sec_petscsection), `PetscSectionGetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2553: @*/
2554: PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[])
2555: {
2556: PetscFunctionBegin;
2558: if (s->bc) {
2559: const PetscInt dof = s->atlasDof[point];
2560: const PetscInt cdof = s->bc->atlasDof[point];
2561: PetscInt d;
2563: 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]);
2564: PetscCall(VecIntSetValuesSection(s->bcIndices, s->bc, point, indices, INSERT_VALUES));
2565: }
2566: PetscFunctionReturn(PETSC_SUCCESS);
2567: }
2569: /*@C
2570: PetscSectionGetFieldConstraintIndices - Get the field dof numbers, in [0, fdof), which are constrained
2572: Not Collective
2574: Input Parameters:
2575: + s - The `PetscSection`
2576: . field - The field number
2577: - point - The point
2579: Output Parameter:
2580: . indices - The constrained dofs sorted in ascending order
2582: Level: intermediate
2584: Note:
2585: 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()`.
2587: Fortran Note:
2588: Use `PetscSectionGetFieldConstraintIndicesF90()` and `PetscSectionRestoreFieldConstraintIndicesF90()`
2590: .seealso: [PetscSection](sec_petscsection), `PetscSectionSetFieldConstraintIndices()`, `PetscSectionGetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2591: @*/
2592: PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices)
2593: {
2594: PetscFunctionBegin;
2597: PetscSectionCheckValidField(field, s->numFields);
2598: PetscCall(PetscSectionGetConstraintIndices(s->field[field], point, indices));
2599: PetscFunctionReturn(PETSC_SUCCESS);
2600: }
2602: /*@C
2603: PetscSectionSetFieldConstraintIndices - Set the field dof numbers, in [0, fdof), which are constrained
2605: Not Collective
2607: Input Parameters:
2608: + s - The `PetscSection`
2609: . point - The point
2610: . field - The field number
2611: - indices - The constrained dofs
2613: Level: intermediate
2615: Fortran Note:
2616: Use `PetscSectionSetFieldConstraintIndicesF90()`
2618: .seealso: [PetscSection](sec_petscsection), `PetscSectionSetConstraintIndices()`, `PetscSectionGetFieldConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection`
2619: @*/
2620: PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[])
2621: {
2622: PetscFunctionBegin;
2624: if (PetscDefined(USE_DEBUG)) {
2625: PetscInt nfdof;
2627: PetscCall(PetscSectionGetFieldConstraintDof(s, point, field, &nfdof));
2629: }
2630: PetscSectionCheckValidField(field, s->numFields);
2631: PetscCall(PetscSectionSetConstraintIndices(s->field[field], point, indices));
2632: PetscFunctionReturn(PETSC_SUCCESS);
2633: }
2635: /*@
2636: PetscSectionPermute - Reorder the section according to the input point permutation
2638: Collective
2640: Input Parameters:
2641: + section - The `PetscSection` object
2642: - perm - The point permutation, old point p becomes new point perm[p]
2644: Output Parameter:
2645: . sectionNew - The permuted `PetscSection`
2647: Level: intermediate
2649: .seealso: [PetscSection](sec_petscsection), `IS`, `PetscSection`, `MatPermute()`
2650: @*/
2651: PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew)
2652: {
2653: PetscSection s = section, sNew;
2654: const PetscInt *perm;
2655: PetscInt numFields, f, c, numPoints, pStart, pEnd, p;
2657: PetscFunctionBegin;
2661: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &sNew));
2662: PetscCall(PetscSectionGetNumFields(s, &numFields));
2663: if (numFields) PetscCall(PetscSectionSetNumFields(sNew, numFields));
2664: for (f = 0; f < numFields; ++f) {
2665: const char *name;
2666: PetscInt numComp;
2668: PetscCall(PetscSectionGetFieldName(s, f, &name));
2669: PetscCall(PetscSectionSetFieldName(sNew, f, name));
2670: PetscCall(PetscSectionGetFieldComponents(s, f, &numComp));
2671: PetscCall(PetscSectionSetFieldComponents(sNew, f, numComp));
2672: for (c = 0; c < s->numFieldComponents[f]; ++c) {
2673: PetscCall(PetscSectionGetComponentName(s, f, c, &name));
2674: PetscCall(PetscSectionSetComponentName(sNew, f, c, name));
2675: }
2676: }
2677: PetscCall(ISGetLocalSize(permutation, &numPoints));
2678: PetscCall(ISGetIndices(permutation, &perm));
2679: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
2680: PetscCall(PetscSectionSetChart(sNew, pStart, pEnd));
2681: PetscCheck(numPoints >= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %" PetscInt_FMT " is less than largest Section point %" PetscInt_FMT, numPoints, pEnd);
2682: for (p = pStart; p < pEnd; ++p) {
2683: PetscInt dof, cdof;
2685: PetscCall(PetscSectionGetDof(s, p, &dof));
2686: PetscCall(PetscSectionSetDof(sNew, perm[p], dof));
2687: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
2688: if (cdof) PetscCall(PetscSectionSetConstraintDof(sNew, perm[p], cdof));
2689: for (f = 0; f < numFields; ++f) {
2690: PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
2691: PetscCall(PetscSectionSetFieldDof(sNew, perm[p], f, dof));
2692: PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof));
2693: if (cdof) PetscCall(PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof));
2694: }
2695: }
2696: PetscCall(PetscSectionSetUp(sNew));
2697: for (p = pStart; p < pEnd; ++p) {
2698: const PetscInt *cind;
2699: PetscInt cdof;
2701: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
2702: if (cdof) {
2703: PetscCall(PetscSectionGetConstraintIndices(s, p, &cind));
2704: PetscCall(PetscSectionSetConstraintIndices(sNew, perm[p], cind));
2705: }
2706: for (f = 0; f < numFields; ++f) {
2707: PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof));
2708: if (cdof) {
2709: PetscCall(PetscSectionGetFieldConstraintIndices(s, p, f, &cind));
2710: PetscCall(PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind));
2711: }
2712: }
2713: }
2714: PetscCall(ISRestoreIndices(permutation, &perm));
2715: *sectionNew = sNew;
2716: PetscFunctionReturn(PETSC_SUCCESS);
2717: }
2719: /*@
2720: PetscSectionSetClosureIndex - Create an internal data structure to speed up closure queries.
2722: Collective
2724: Input Parameters:
2725: + section - The `PetscSection`
2726: . obj - A `PetscObject` which serves as the key for this index
2727: . clSection - `PetscSection` giving the size of the closure of each point
2728: - clPoints - `IS` giving the points in each closure
2730: Level: advanced
2732: Note:
2733: This function creates an internal map from each point to its closure. We compress out closure points with no dofs in this section.
2735: Developer Note:
2736: The information provided here is completely opaque
2738: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionGetClosureIndex()`, `DMPlexCreateClosureIndex()`
2739: @*/
2740: PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints)
2741: {
2742: PetscFunctionBegin;
2746: if (section->clObj != obj) PetscCall(PetscSectionResetClosurePermutation(section));
2747: section->clObj = obj;
2748: PetscCall(PetscObjectReference((PetscObject)clSection));
2749: PetscCall(PetscObjectReference((PetscObject)clPoints));
2750: PetscCall(PetscSectionDestroy(§ion->clSection));
2751: PetscCall(ISDestroy(§ion->clPoints));
2752: section->clSection = clSection;
2753: section->clPoints = clPoints;
2754: PetscFunctionReturn(PETSC_SUCCESS);
2755: }
2757: /*@
2758: PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section set with `PetscSectionSetClosureIndex()`
2760: Collective
2762: Input Parameters:
2763: + section - The `PetscSection`
2764: - obj - A `PetscObject` which serves as the key for this index
2766: Output Parameters:
2767: + clSection - `PetscSection` giving the size of the closure of each point
2768: - clPoints - `IS` giving the points in each closure
2770: Level: advanced
2772: .seealso: [PetscSection](sec_petscsection), `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()`
2773: @*/
2774: PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints)
2775: {
2776: PetscFunctionBegin;
2777: if (section->clObj == obj) {
2778: if (clSection) *clSection = section->clSection;
2779: if (clPoints) *clPoints = section->clPoints;
2780: } else {
2781: if (clSection) *clSection = NULL;
2782: if (clPoints) *clPoints = NULL;
2783: }
2784: PetscFunctionReturn(PETSC_SUCCESS);
2785: }
2787: PetscErrorCode PetscSectionSetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, PetscCopyMode mode, PetscInt *clPerm)
2788: {
2789: PetscInt i;
2790: khiter_t iter;
2791: int new_entry;
2792: PetscSectionClosurePermKey key = {depth, clSize};
2793: PetscSectionClosurePermVal *val;
2795: PetscFunctionBegin;
2796: if (section->clObj != obj) {
2797: PetscCall(PetscSectionDestroy(§ion->clSection));
2798: PetscCall(ISDestroy(§ion->clPoints));
2799: }
2800: section->clObj = obj;
2801: if (!section->clHash) PetscCall(PetscClPermCreate(§ion->clHash));
2802: iter = kh_put(ClPerm, section->clHash, key, &new_entry);
2803: val = &kh_val(section->clHash, iter);
2804: if (!new_entry) {
2805: PetscCall(PetscFree(val->perm));
2806: PetscCall(PetscFree(val->invPerm));
2807: }
2808: if (mode == PETSC_COPY_VALUES) {
2809: PetscCall(PetscMalloc1(clSize, &val->perm));
2810: PetscCall(PetscArraycpy(val->perm, clPerm, clSize));
2811: } else if (mode == PETSC_OWN_POINTER) {
2812: val->perm = clPerm;
2813: } else SETERRQ(PetscObjectComm(obj), PETSC_ERR_SUP, "Do not support borrowed arrays");
2814: PetscCall(PetscMalloc1(clSize, &val->invPerm));
2815: for (i = 0; i < clSize; ++i) val->invPerm[clPerm[i]] = i;
2816: PetscFunctionReturn(PETSC_SUCCESS);
2817: }
2819: /*@
2820: PetscSectionSetClosurePermutation - Set the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex.
2822: Not Collective
2824: Input Parameters:
2825: + section - The `PetscSection`
2826: . obj - A `PetscObject` which serves as the key for this index (usually a `DM`)
2827: . depth - Depth of points on which to apply the given permutation
2828: - perm - Permutation of the cell dof closure
2830: Level: intermediate
2832: Notes:
2833: The specified permutation will only be applied to points at depth whose closure size matches the length of perm. In a
2834: mixed-topology or variable-degree finite element space, this function can be called multiple times at each depth for
2835: each topology and degree.
2837: This approach assumes that (depth, len(perm)) uniquely identifies the desired permutation; this might not be true for
2838: exotic/enriched spaces on mixed topology meshes.
2840: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionGetClosurePermutation()`, `PetscSectionGetClosureIndex()`, `DMPlexCreateClosureIndex()`, `PetscCopyMode`
2841: @*/
2842: PetscErrorCode PetscSectionSetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, IS perm)
2843: {
2844: const PetscInt *clPerm = NULL;
2845: PetscInt clSize = 0;
2847: PetscFunctionBegin;
2848: if (perm) {
2849: PetscCall(ISGetLocalSize(perm, &clSize));
2850: PetscCall(ISGetIndices(perm, &clPerm));
2851: }
2852: PetscCall(PetscSectionSetClosurePermutation_Internal(section, obj, depth, clSize, PETSC_COPY_VALUES, (PetscInt *)clPerm));
2853: if (perm) PetscCall(ISRestoreIndices(perm, &clPerm));
2854: PetscFunctionReturn(PETSC_SUCCESS);
2855: }
2857: PetscErrorCode PetscSectionGetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[])
2858: {
2859: PetscFunctionBegin;
2860: if (section->clObj == obj) {
2861: PetscSectionClosurePermKey k = {depth, size};
2862: PetscSectionClosurePermVal v;
2863: PetscCall(PetscClPermGet(section->clHash, k, &v));
2864: if (perm) *perm = v.perm;
2865: } else {
2866: if (perm) *perm = NULL;
2867: }
2868: PetscFunctionReturn(PETSC_SUCCESS);
2869: }
2871: /*@
2872: PetscSectionGetClosurePermutation - Get the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex.
2874: Not Collective
2876: Input Parameters:
2877: + section - The `PetscSection`
2878: . obj - A `PetscObject` which serves as the key for this index (usually a DM)
2879: . depth - Depth stratum on which to obtain closure permutation
2880: - clSize - Closure size to be permuted (e.g., may vary with element topology and degree)
2882: Output Parameter:
2883: . perm - The dof closure permutation
2885: Level: intermediate
2887: Note:
2888: The user must destroy the `IS` that is returned.
2890: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionSetClosurePermutation()`, `PetscSectionGetClosureInversePermutation()`, `PetscSectionGetClosureIndex()`, `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()`
2891: @*/
2892: PetscErrorCode PetscSectionGetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm)
2893: {
2894: const PetscInt *clPerm;
2896: PetscFunctionBegin;
2897: PetscCall(PetscSectionGetClosurePermutation_Internal(section, obj, depth, clSize, &clPerm));
2898: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm));
2899: PetscFunctionReturn(PETSC_SUCCESS);
2900: }
2902: PetscErrorCode PetscSectionGetClosureInversePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[])
2903: {
2904: PetscFunctionBegin;
2905: if (section->clObj == obj && section->clHash) {
2906: PetscSectionClosurePermKey k = {depth, size};
2907: PetscSectionClosurePermVal v;
2908: PetscCall(PetscClPermGet(section->clHash, k, &v));
2909: if (perm) *perm = v.invPerm;
2910: } else {
2911: if (perm) *perm = NULL;
2912: }
2913: PetscFunctionReturn(PETSC_SUCCESS);
2914: }
2916: /*@
2917: PetscSectionGetClosureInversePermutation - Get the inverse dof permutation for the closure of each cell in the section, meaning clPerm[oldIndex] = newIndex.
2919: Not Collective
2921: Input Parameters:
2922: + section - The `PetscSection`
2923: . obj - A `PetscObject` which serves as the key for this index (usually a `DM`)
2924: . depth - Depth stratum on which to obtain closure permutation
2925: - clSize - Closure size to be permuted (e.g., may vary with element topology and degree)
2927: Output Parameters:
2928: . perm - The dof closure permutation
2930: Level: intermediate
2932: Note:
2933: The user must destroy the `IS` that is returned.
2935: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionSetClosurePermutation()`, `PetscSectionGetClosureIndex()`, `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()`
2936: @*/
2937: PetscErrorCode PetscSectionGetClosureInversePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm)
2938: {
2939: const PetscInt *clPerm;
2941: PetscFunctionBegin;
2942: PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, obj, depth, clSize, &clPerm));
2943: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm));
2944: PetscFunctionReturn(PETSC_SUCCESS);
2945: }
2947: /*@
2948: PetscSectionGetField - Get the subsection associated with a single field
2950: Input Parameters:
2951: + s - The `PetscSection`
2952: - field - The field number
2954: Output Parameter:
2955: . subs - The subsection for the given field
2957: Level: intermediate
2959: Note:
2960: Does not increase the reference count of the selected sub-section. There is no matching `PetscSectionRestoreField()`
2962: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `IS`, `PetscSectionSetNumFields()`
2963: @*/
2964: PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs)
2965: {
2966: PetscFunctionBegin;
2969: PetscSectionCheckValidField(field, s->numFields);
2970: *subs = s->field[field];
2971: PetscFunctionReturn(PETSC_SUCCESS);
2972: }
2974: PetscClassId PETSC_SECTION_SYM_CLASSID;
2975: PetscFunctionList PetscSectionSymList = NULL;
2977: /*@
2978: PetscSectionSymCreate - Creates an empty `PetscSectionSym` object.
2980: Collective
2982: Input Parameter:
2983: . comm - the MPI communicator
2985: Output Parameter:
2986: . sym - pointer to the new set of symmetries
2988: Level: developer
2990: .seealso: [PetscSection](sec_petscsection), `PetscSection`, `PetscSectionSym`, `PetscSectionSymDestroy()`
2991: @*/
2992: PetscErrorCode PetscSectionSymCreate(MPI_Comm comm, PetscSectionSym *sym)
2993: {
2994: PetscFunctionBegin;
2996: PetscCall(ISInitializePackage());
2997: PetscCall(PetscHeaderCreate(*sym, PETSC_SECTION_SYM_CLASSID, "PetscSectionSym", "Section Symmetry", "IS", comm, PetscSectionSymDestroy, PetscSectionSymView));
2998: PetscFunctionReturn(PETSC_SUCCESS);
2999: }
3001: /*@C
3002: PetscSectionSymSetType - Builds a `PetscSectionSym`, for a particular implementation.
3004: Collective
3006: Input Parameters:
3007: + sym - The section symmetry object
3008: - method - The name of the section symmetry type
3010: Level: developer
3012: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymType`, `PetscSectionSymGetType()`, `PetscSectionSymCreate()`
3013: @*/
3014: PetscErrorCode PetscSectionSymSetType(PetscSectionSym sym, PetscSectionSymType method)
3015: {
3016: PetscErrorCode (*r)(PetscSectionSym);
3017: PetscBool match;
3019: PetscFunctionBegin;
3021: PetscCall(PetscObjectTypeCompare((PetscObject)sym, method, &match));
3022: if (match) PetscFunctionReturn(PETSC_SUCCESS);
3024: PetscCall(PetscFunctionListFind(PetscSectionSymList, method, &r));
3025: PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscSectionSym type: %s", method);
3026: PetscTryTypeMethod(sym, destroy);
3027: sym->ops->destroy = NULL;
3029: PetscCall((*r)(sym));
3030: PetscCall(PetscObjectChangeTypeName((PetscObject)sym, method));
3031: PetscFunctionReturn(PETSC_SUCCESS);
3032: }
3034: /*@C
3035: PetscSectionSymGetType - Gets the section symmetry type name (as a string) from the `PetscSectionSym`.
3037: Not Collective
3039: Input Parameter:
3040: . sym - The section symmetry
3042: Output Parameter:
3043: . type - The index set type name
3045: Level: developer
3047: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymType`, `PetscSectionSymSetType()`, `PetscSectionSymCreate()`
3048: @*/
3049: PetscErrorCode PetscSectionSymGetType(PetscSectionSym sym, PetscSectionSymType *type)
3050: {
3051: PetscFunctionBegin;
3054: *type = ((PetscObject)sym)->type_name;
3055: PetscFunctionReturn(PETSC_SUCCESS);
3056: }
3058: /*@C
3059: PetscSectionSymRegister - Registers a new section symmetry implementation
3061: Not Collective
3063: Input Parameters:
3064: + name - The name of a new user-defined creation routine
3065: - create_func - The creation routine itself
3067: Level: developer
3069: Notes:
3070: `PetscSectionSymRegister()` may be called multiple times to add several user-defined vectors
3072: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymType`, `PetscSectionSymCreate()`, `PetscSectionSymSetType()`
3073: @*/
3074: PetscErrorCode PetscSectionSymRegister(const char sname[], PetscErrorCode (*function)(PetscSectionSym))
3075: {
3076: PetscFunctionBegin;
3077: PetscCall(ISInitializePackage());
3078: PetscCall(PetscFunctionListAdd(&PetscSectionSymList, sname, function));
3079: PetscFunctionReturn(PETSC_SUCCESS);
3080: }
3082: /*@
3083: PetscSectionSymDestroy - Destroys a section symmetry.
3085: Collective
3087: Input Parameters:
3088: . sym - the section symmetry
3090: Level: developer
3092: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymCreate()`, `PetscSectionSymDestroy()`
3093: @*/
3094: PetscErrorCode PetscSectionSymDestroy(PetscSectionSym *sym)
3095: {
3096: SymWorkLink link, next;
3098: PetscFunctionBegin;
3099: if (!*sym) PetscFunctionReturn(PETSC_SUCCESS);
3101: if (--((PetscObject)(*sym))->refct > 0) {
3102: *sym = NULL;
3103: PetscFunctionReturn(PETSC_SUCCESS);
3104: }
3105: if ((*sym)->ops->destroy) PetscCall((*(*sym)->ops->destroy)(*sym));
3106: PetscCheck(!(*sym)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out");
3107: for (link = (*sym)->workin; link; link = next) {
3108: PetscInt **perms = (PetscInt **)link->perms;
3109: PetscScalar **rots = (PetscScalar **)link->rots;
3110: PetscCall(PetscFree2(perms, rots));
3111: next = link->next;
3112: PetscCall(PetscFree(link));
3113: }
3114: (*sym)->workin = NULL;
3115: PetscCall(PetscHeaderDestroy(sym));
3116: PetscFunctionReturn(PETSC_SUCCESS);
3117: }
3119: /*@C
3120: PetscSectionSymView - Displays a section symmetry
3122: Collective
3124: Input Parameters:
3125: + sym - the index set
3126: - viewer - viewer used to display the set, for example `PETSC_VIEWER_STDOUT_SELF`.
3128: Level: developer
3130: .seealso: `PetscSectionSym`, `PetscViewer`, `PetscViewerASCIIOpen()`
3131: @*/
3132: PetscErrorCode PetscSectionSymView(PetscSectionSym sym, PetscViewer viewer)
3133: {
3134: PetscFunctionBegin;
3136: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sym), &viewer));
3138: PetscCheckSameComm(sym, 1, viewer, 2);
3139: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sym, viewer));
3140: PetscTryTypeMethod(sym, view, viewer);
3141: PetscFunctionReturn(PETSC_SUCCESS);
3142: }
3144: /*@
3145: PetscSectionSetSym - Set the symmetries for the data referred to by the section
3147: Collective
3149: Input Parameters:
3150: + section - the section describing data layout
3151: - sym - the symmetry describing the affect of orientation on the access of the data
3153: Level: developer
3155: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetSym()`, `PetscSectionSymCreate()`
3156: @*/
3157: PetscErrorCode PetscSectionSetSym(PetscSection section, PetscSectionSym sym)
3158: {
3159: PetscFunctionBegin;
3161: PetscCall(PetscSectionSymDestroy(&(section->sym)));
3162: if (sym) {
3164: PetscCheckSameComm(section, 1, sym, 2);
3165: PetscCall(PetscObjectReference((PetscObject)sym));
3166: }
3167: section->sym = sym;
3168: PetscFunctionReturn(PETSC_SUCCESS);
3169: }
3171: /*@
3172: PetscSectionGetSym - Get the symmetries for the data referred to by the section
3174: Not Collective
3176: Input Parameters:
3177: . section - the section describing data layout
3179: Output Parameters:
3180: . sym - the symmetry describing the affect of orientation on the access of the data, provided previously by `PetscSectionSetSym()`
3182: Level: developer
3184: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSetSym()`, `PetscSectionSymCreate()`
3185: @*/
3186: PetscErrorCode PetscSectionGetSym(PetscSection section, PetscSectionSym *sym)
3187: {
3188: PetscFunctionBegin;
3190: *sym = section->sym;
3191: PetscFunctionReturn(PETSC_SUCCESS);
3192: }
3194: /*@
3195: PetscSectionSetFieldSym - Set the symmetries for the data referred to by a field of the section
3197: Collective
3199: Input Parameters:
3200: + section - the section describing data layout
3201: . field - the field number
3202: - sym - the symmetry describing the affect of orientation on the access of the data
3204: Level: developer
3206: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetFieldSym()`, `PetscSectionSymCreate()`
3207: @*/
3208: PetscErrorCode PetscSectionSetFieldSym(PetscSection section, PetscInt field, PetscSectionSym sym)
3209: {
3210: PetscFunctionBegin;
3212: PetscSectionCheckValidField(field, section->numFields);
3213: PetscCall(PetscSectionSetSym(section->field[field], sym));
3214: PetscFunctionReturn(PETSC_SUCCESS);
3215: }
3217: /*@
3218: PetscSectionGetFieldSym - Get the symmetries for the data referred to by a field of the section
3220: Collective
3222: Input Parameters:
3223: + section - the section describing data layout
3224: - field - the field number
3226: Output Parameters:
3227: . sym - the symmetry describing the affect of orientation on the access of the data
3229: Level: developer
3231: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSetFieldSym()`, `PetscSectionSymCreate()`
3232: @*/
3233: PetscErrorCode PetscSectionGetFieldSym(PetscSection section, PetscInt field, PetscSectionSym *sym)
3234: {
3235: PetscFunctionBegin;
3237: PetscSectionCheckValidField(field, section->numFields);
3238: *sym = section->field[field]->sym;
3239: PetscFunctionReturn(PETSC_SUCCESS);
3240: }
3242: /*@C
3243: PetscSectionGetPointSyms - Get the symmetries for a set of points in a `PetscSection` under specific orientations.
3245: Not Collective
3247: Input Parameters:
3248: + section - the section
3249: . numPoints - the number of points
3250: - points - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3251: arbitrary integer: its interpretation is up to sym. Orientations are used by `DM`: for their interpretation in that
3252: context, see `DMPlexGetConeOrientation()`).
3254: Output Parameters:
3255: + perms - The permutations for the given orientations (or `NULL` if there is no symmetry or the permutation is the identity).
3256: - rots - The field rotations symmetries for the given orientations (or `NULL` if there is no symmetry or the rotations are all
3257: identity).
3259: Example of usage, gathering dofs into a local array (lArray) from a section array (sArray):
3260: .vb
3261: const PetscInt **perms;
3262: const PetscScalar **rots;
3263: PetscInt lOffset;
3265: PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots);
3266: for (i = 0, lOffset = 0; i < numPoints; i++) {
3267: PetscInt point = points[2*i], dof, sOffset;
3268: const PetscInt *perm = perms ? perms[i] : NULL;
3269: const PetscScalar *rot = rots ? rots[i] : NULL;
3271: PetscSectionGetDof(section,point,&dof);
3272: PetscSectionGetOffset(section,point,&sOffset);
3274: if (perm) {for (j = 0; j < dof; j++) {lArray[lOffset + perm[j]] = sArray[sOffset + j];}}
3275: else {for (j = 0; j < dof; j++) {lArray[lOffset + j ] = sArray[sOffset + j];}}
3276: if (rot) {for (j = 0; j < dof; j++) {lArray[lOffset + j ] *= rot[j]; }}
3277: lOffset += dof;
3278: }
3279: PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots);
3280: .ve
3282: Example of usage, adding dofs into a section array (sArray) from a local array (lArray):
3283: .vb
3284: const PetscInt **perms;
3285: const PetscScalar **rots;
3286: PetscInt lOffset;
3288: PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots);
3289: for (i = 0, lOffset = 0; i < numPoints; i++) {
3290: PetscInt point = points[2*i], dof, sOffset;
3291: const PetscInt *perm = perms ? perms[i] : NULL;
3292: const PetscScalar *rot = rots ? rots[i] : NULL;
3294: PetscSectionGetDof(section,point,&dof);
3295: PetscSectionGetOffset(section,point,&sOff);
3297: if (perm) {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + perm[j]] * (rot ? PetscConj(rot[perm[j]]) : 1.);}}
3298: else {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + j ] * (rot ? PetscConj(rot[ j ]) : 1.);}}
3299: offset += dof;
3300: }
3301: PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots);
3302: .ve
3304: Level: developer
3306: Note:
3307: `PetscSectionSetSym()` must have been previously called to provide the symmetries to the `PetscSection`
3309: Use `PetscSectionRestorePointSyms()` when finished with the data
3311: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionRestorePointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`
3312: @*/
3313: PetscErrorCode PetscSectionGetPointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3314: {
3315: PetscSectionSym sym;
3317: PetscFunctionBegin;
3320: if (perms) *perms = NULL;
3321: if (rots) *rots = NULL;
3322: sym = section->sym;
3323: if (sym && (perms || rots)) {
3324: SymWorkLink link;
3326: if (sym->workin) {
3327: link = sym->workin;
3328: sym->workin = sym->workin->next;
3329: } else {
3330: PetscCall(PetscNew(&link));
3331: }
3332: if (numPoints > link->numPoints) {
3333: PetscInt **perms = (PetscInt **)link->perms;
3334: PetscScalar **rots = (PetscScalar **)link->rots;
3335: PetscCall(PetscFree2(perms, rots));
3336: PetscCall(PetscMalloc2(numPoints, (PetscInt ***)&link->perms, numPoints, (PetscScalar ***)&link->rots));
3337: link->numPoints = numPoints;
3338: }
3339: link->next = sym->workout;
3340: sym->workout = link;
3341: PetscCall(PetscArrayzero((PetscInt **)link->perms, numPoints));
3342: PetscCall(PetscArrayzero((PetscInt **)link->rots, numPoints));
3343: PetscCall((*sym->ops->getpoints)(sym, section, numPoints, points, link->perms, link->rots));
3344: if (perms) *perms = link->perms;
3345: if (rots) *rots = link->rots;
3346: }
3347: PetscFunctionReturn(PETSC_SUCCESS);
3348: }
3350: /*@C
3351: PetscSectionRestorePointSyms - Restore the symmetries returned by `PetscSectionGetPointSyms()`
3353: Not Collective
3355: Input Parameters:
3356: + section - the section
3357: . numPoints - the number of points
3358: - points - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3359: arbitrary integer: its interpretation is up to sym. Orientations are used by `DM`: for their interpretation in that
3360: context, see `DMPlexGetConeOrientation()`).
3361: . perms - The permutations for the given orientations: set to `NULL` at conclusion
3362: - rots - The field rotations symmetries for the given orientations: set to `NULL` at conclusion
3364: Level: developer
3366: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`
3367: @*/
3368: PetscErrorCode PetscSectionRestorePointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3369: {
3370: PetscSectionSym sym;
3372: PetscFunctionBegin;
3374: sym = section->sym;
3375: if (sym && (perms || rots)) {
3376: SymWorkLink *p, link;
3378: for (p = &sym->workout; (link = *p); p = &link->next) {
3379: if ((perms && link->perms == *perms) || (rots && link->rots == *rots)) {
3380: *p = link->next;
3381: link->next = sym->workin;
3382: sym->workin = link;
3383: if (perms) *perms = NULL;
3384: if (rots) *rots = NULL;
3385: PetscFunctionReturn(PETSC_SUCCESS);
3386: }
3387: }
3388: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
3389: }
3390: PetscFunctionReturn(PETSC_SUCCESS);
3391: }
3393: /*@C
3394: PetscSectionGetFieldPointSyms - Get the symmetries for a set of points in a field of a `PetscSection` under specific orientations.
3396: Not Collective
3398: Input Parameters:
3399: + section - the section
3400: . field - the field of the section
3401: . numPoints - the number of points
3402: - points - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3403: arbitrary integer: its interpretation is up to sym. Orientations are used by `DM`: for their interpretation in that
3404: context, see `DMPlexGetConeOrientation()`).
3406: Output Parameters:
3407: + perms - The permutations for the given orientations (or `NULL` if there is no symmetry or the permutation is the identity).
3408: - rots - The field rotations symmetries for the given orientations (or `NULL` if there is no symmetry or the rotations are all
3409: identity).
3411: Level: developer
3413: Notes:
3414: `PetscSectionSetFieldSym()` must have been previously called to provide the symmetries to the `PetscSection`
3416: Use `PetscSectionRestoreFieldPointSyms()` when finished with the data
3418: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetPointSyms()`, `PetscSectionRestoreFieldPointSyms()`
3419: @*/
3420: PetscErrorCode PetscSectionGetFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3421: {
3422: PetscFunctionBegin;
3424: 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);
3425: PetscCall(PetscSectionGetPointSyms(section->field[field], numPoints, points, perms, rots));
3426: PetscFunctionReturn(PETSC_SUCCESS);
3427: }
3429: /*@C
3430: PetscSectionRestoreFieldPointSyms - Restore the symmetries returned by `PetscSectionGetFieldPointSyms()`
3432: Not Collective
3434: Input Parameters:
3435: + section - the section
3436: . field - the field number
3437: . numPoints - the number of points
3438: - points - an array of size 2 * `numPoints`, containing a list of (point, orientation) pairs. (An orientation is an
3439: arbitrary integer: its interpretation is up to sym. Orientations are used by `DM`: for their interpretation in that
3440: context, see `DMPlexGetConeOrientation()`).
3441: . perms - The permutations for the given orientations: set to NULL at conclusion
3442: - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion
3444: Level: developer
3446: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionRestorePointSyms()`, `petscSectionGetFieldPointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`
3447: @*/
3448: PetscErrorCode PetscSectionRestoreFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3449: {
3450: PetscFunctionBegin;
3452: 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);
3453: PetscCall(PetscSectionRestorePointSyms(section->field[field], numPoints, points, perms, rots));
3454: PetscFunctionReturn(PETSC_SUCCESS);
3455: }
3457: /*@
3458: PetscSectionSymCopy - Copy the symmetries, assuming that the point structure is compatible
3460: Not Collective
3462: Input Parameter:
3463: . sym - the `PetscSectionSym`
3465: Output Parameter:
3466: . nsym - the equivalent symmetries
3468: Level: developer
3470: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
3471: @*/
3472: PetscErrorCode PetscSectionSymCopy(PetscSectionSym sym, PetscSectionSym nsym)
3473: {
3474: PetscFunctionBegin;
3477: PetscTryTypeMethod(sym, copy, nsym);
3478: PetscFunctionReturn(PETSC_SUCCESS);
3479: }
3481: /*@
3482: PetscSectionSymDistribute - Distribute the symmetries in accordance with the input `PetscSF`
3484: Collective
3486: Input Parameters:
3487: + sym - the `PetscSectionSym`
3488: - migrationSF - the distribution map from roots to leaves
3490: Output Parameters:
3491: . dsym - the redistributed symmetries
3493: Level: developer
3495: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
3496: @*/
3497: PetscErrorCode PetscSectionSymDistribute(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
3498: {
3499: PetscFunctionBegin;
3503: PetscTryTypeMethod(sym, distribute, migrationSF, dsym);
3504: PetscFunctionReturn(PETSC_SUCCESS);
3505: }
3507: /*@
3508: PetscSectionGetUseFieldOffsets - Get the flag indicating if field offsets are used directly in a global section, rather than just the point offset
3510: Not Collective
3512: Input Parameter:
3513: . s - the global `PetscSection`
3515: Output Parameters:
3516: . flg - the flag
3518: Level: developer
3520: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionSetChart()`, `PetscSectionCreate()`
3521: @*/
3522: PetscErrorCode PetscSectionGetUseFieldOffsets(PetscSection s, PetscBool *flg)
3523: {
3524: PetscFunctionBegin;
3526: *flg = s->useFieldOff;
3527: PetscFunctionReturn(PETSC_SUCCESS);
3528: }
3530: /*@
3531: PetscSectionSetUseFieldOffsets - Set the flag to use field offsets directly in a global section, rather than just the point offset
3533: Not Collective
3535: Input Parameters:
3536: + s - the global `PetscSection`
3537: - flg - the flag
3539: Level: developer
3541: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetUseFieldOffsets()`, `PetscSectionSetChart()`, `PetscSectionCreate()`
3542: @*/
3543: PetscErrorCode PetscSectionSetUseFieldOffsets(PetscSection s, PetscBool flg)
3544: {
3545: PetscFunctionBegin;
3547: s->useFieldOff = flg;
3548: PetscFunctionReturn(PETSC_SUCCESS);
3549: }
3551: #define PetscSectionExpandPoints_Loop(TYPE) \
3552: { \
3553: PetscInt i, n, o0, o1, size; \
3554: TYPE *a0 = (TYPE *)origArray, *a1; \
3555: PetscCall(PetscSectionGetStorageSize(s, &size)); \
3556: PetscCall(PetscMalloc1(size, &a1)); \
3557: for (i = 0; i < npoints; i++) { \
3558: PetscCall(PetscSectionGetOffset(origSection, points_[i], &o0)); \
3559: PetscCall(PetscSectionGetOffset(s, i, &o1)); \
3560: PetscCall(PetscSectionGetDof(s, i, &n)); \
3561: PetscCall(PetscMemcpy(&a1[o1], &a0[o0], n *unitsize)); \
3562: } \
3563: *newArray = (void *)a1; \
3564: }
3566: /*@
3567: PetscSectionExtractDofsFromArray - Extracts elements of an array corresponding to DOFs of specified points.
3569: Not Collective
3571: Input Parameters:
3572: + origSection - the `PetscSection` describing the layout of the array
3573: . dataType - `MPI_Datatype` describing the data type of the array (currently only `MPIU_INT`, `MPIU_SCALAR`, `MPIU_REAL`)
3574: . origArray - the array; its size must be equal to the storage size of `origSection`
3575: - points - `IS` with points to extract; its indices must lie in the chart of `origSection`
3577: Output Parameters:
3578: + newSection - the new `PetscSection` describing the layout of the new array (with points renumbered 0,1,... but preserving numbers of DOFs)
3579: - newArray - the array of the extracted DOFs; its size is the storage size of `newSection`
3581: Level: developer
3583: .seealso: [PetscSection](sec_petscsection), `PetscSectionSym`, `PetscSectionGetChart()`, `PetscSectionGetDof()`, `PetscSectionGetStorageSize()`, `PetscSectionCreate()`
3584: @*/
3585: PetscErrorCode PetscSectionExtractDofsFromArray(PetscSection origSection, MPI_Datatype dataType, const void *origArray, IS points, PetscSection *newSection, void *newArray[])
3586: {
3587: PetscSection s;
3588: const PetscInt *points_;
3589: PetscInt i, n, npoints, pStart, pEnd;
3590: PetscMPIInt unitsize;
3592: PetscFunctionBegin;
3598: PetscCallMPI(MPI_Type_size(dataType, &unitsize));
3599: PetscCall(ISGetLocalSize(points, &npoints));
3600: PetscCall(ISGetIndices(points, &points_));
3601: PetscCall(PetscSectionGetChart(origSection, &pStart, &pEnd));
3602: PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
3603: PetscCall(PetscSectionSetChart(s, 0, npoints));
3604: for (i = 0; i < npoints; i++) {
3605: 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);
3606: PetscCall(PetscSectionGetDof(origSection, points_[i], &n));
3607: PetscCall(PetscSectionSetDof(s, i, n));
3608: }
3609: PetscCall(PetscSectionSetUp(s));
3610: if (newArray) {
3611: if (dataType == MPIU_INT) {
3612: PetscSectionExpandPoints_Loop(PetscInt);
3613: } else if (dataType == MPIU_SCALAR) {
3614: PetscSectionExpandPoints_Loop(PetscScalar);
3615: } else if (dataType == MPIU_REAL) {
3616: PetscSectionExpandPoints_Loop(PetscReal);
3617: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "not implemented for this MPI_Datatype");
3618: }
3619: if (newSection) {
3620: *newSection = s;
3621: } else {
3622: PetscCall(PetscSectionDestroy(&s));
3623: }
3624: PetscCall(ISRestoreIndices(points, &points_));
3625: PetscFunctionReturn(PETSC_SUCCESS);
3626: }