Actual source code: vsectionis.c
petsc-3.7.3 2016-08-01
1: /*
2: This file contains routines for basic section object implementation.
3: */
5: #include <petsc/private/isimpl.h> /*I "petscvec.h" I*/
6: #include <petscsf.h>
7: #include <petscviewer.h>
9: PetscClassId PETSC_SECTION_CLASSID;
13: /*@
14: PetscSectionCreate - Allocates PetscSection space and sets the map contents to the default.
16: Collective on MPI_Comm
18: Input Parameters:
19: + comm - the MPI communicator
20: - s - pointer to the section
22: Level: developer
24: Notes: Typical calling sequence
25: $ PetscSectionCreate(MPI_Comm,PetscSection *);
26: $ PetscSectionSetNumFields(PetscSection, numFields);
27: $ PetscSectionSetChart(PetscSection,low,high);
28: $ PetscSectionSetDof(PetscSection,point,numdof);
29: $ PetscSectionSetUp(PetscSection);
30: $ PetscSectionGetOffset(PetscSection,point,PetscInt *);
31: $ PetscSectionDestroy(PetscSection);
33: The PetscSection object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
34: recommended they not be used in user codes unless you really gain something in their use.
36: .seealso: PetscSection, PetscSectionDestroy()
37: @*/
38: PetscErrorCode PetscSectionCreate(MPI_Comm comm, PetscSection *s)
39: {
44: ISInitializePackage();
46: PetscHeaderCreate(*s,PETSC_SECTION_CLASSID,"PetscSection","Section","IS",comm,PetscSectionDestroy,PetscSectionView);
48: (*s)->pStart = -1;
49: (*s)->pEnd = -1;
50: (*s)->perm = NULL;
51: (*s)->maxDof = 0;
52: (*s)->atlasDof = NULL;
53: (*s)->atlasOff = NULL;
54: (*s)->bc = NULL;
55: (*s)->bcIndices = NULL;
56: (*s)->setup = PETSC_FALSE;
57: (*s)->numFields = 0;
58: (*s)->fieldNames = NULL;
59: (*s)->field = NULL;
60: (*s)->clObj = NULL;
61: (*s)->clSection = NULL;
62: (*s)->clPoints = NULL;
63: return(0);
64: }
68: /*@
69: PetscSectionCopy - Creates a shallow (if possible) copy of the PetscSection
71: Collective on MPI_Comm
73: Input Parameter:
74: . section - the PetscSection
76: Output Parameter:
77: . newSection - the copy
79: Level: developer
81: .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
82: @*/
83: PetscErrorCode PetscSectionCopy(PetscSection section, PetscSection newSection)
84: {
85: IS perm;
86: PetscInt numFields, f, pStart, pEnd, p;
90: PetscSectionGetNumFields(section, &numFields);
91: if (numFields) {PetscSectionSetNumFields(newSection, numFields);}
92: for (f = 0; f < numFields; ++f) {
93: const char *name = NULL;
94: PetscInt numComp = 0;
96: PetscSectionGetFieldName(section, f, &name);
97: PetscSectionSetFieldName(newSection, f, name);
98: PetscSectionGetFieldComponents(section, f, &numComp);
99: PetscSectionSetFieldComponents(newSection, f, numComp);
100: }
101: PetscSectionGetChart(section, &pStart, &pEnd);
102: PetscSectionSetChart(newSection, pStart, pEnd);
103: PetscSectionGetPermutation(section, &perm);
104: PetscSectionSetPermutation(newSection, perm);
105: for (p = pStart; p < pEnd; ++p) {
106: PetscInt dof, cdof, fcdof = 0;
108: PetscSectionGetDof(section, p, &dof);
109: PetscSectionSetDof(newSection, p, dof);
110: PetscSectionGetConstraintDof(section, p, &cdof);
111: if (cdof) {PetscSectionSetConstraintDof(newSection, p, cdof);}
112: for (f = 0; f < numFields; ++f) {
113: PetscSectionGetFieldDof(section, p, f, &dof);
114: PetscSectionSetFieldDof(newSection, p, f, dof);
115: if (cdof) {
116: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
117: if (fcdof) {PetscSectionSetFieldConstraintDof(newSection, p, f, fcdof);}
118: }
119: }
120: }
121: PetscSectionSetUp(newSection);
122: for (p = pStart; p < pEnd; ++p) {
123: PetscInt off, cdof, fcdof = 0;
124: const PetscInt *cInd;
126: /* Must set offsets in case they do not agree with the prefix sums */
127: PetscSectionGetOffset(section, p, &off);
128: PetscSectionSetOffset(newSection, p, off);
129: PetscSectionGetConstraintDof(section, p, &cdof);
130: if (cdof) {
131: PetscSectionGetConstraintIndices(section, p, &cInd);
132: PetscSectionSetConstraintIndices(newSection, p, cInd);
133: for (f = 0; f < numFields; ++f) {
134: PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);
135: if (fcdof) {
136: PetscSectionGetFieldConstraintIndices(section, p, f, &cInd);
137: PetscSectionSetFieldConstraintIndices(newSection, p, f, cInd);
138: }
139: }
140: }
141: }
142: return(0);
143: }
147: /*@
148: PetscSectionClone - Creates a shallow (if possible) copy of the PetscSection
150: Collective on MPI_Comm
152: Input Parameter:
153: . section - the PetscSection
155: Output Parameter:
156: . newSection - the copy
158: Level: developer
160: .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
161: @*/
162: PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection)
163: {
167: PetscSectionCreate(PetscObjectComm((PetscObject) section), newSection);
168: PetscSectionCopy(section, *newSection);
169: return(0);
170: }
174: /*@
175: PetscSectionGetNumFields - Returns the number of fields, or 0 if no fields were defined.
177: Not collective
179: Input Parameter:
180: . s - the PetscSection
182: Output Parameter:
183: . numFields - the number of fields defined, or 0 if none were defined
185: Level: intermediate
187: .seealso: PetscSectionSetNumFields()
188: @*/
189: PetscErrorCode PetscSectionGetNumFields(PetscSection s, PetscInt *numFields)
190: {
193: *numFields = s->numFields;
194: return(0);
195: }
199: /*@
200: PetscSectionSetNumFields - Sets the number of fields.
202: Not collective
204: Input Parameters:
205: + s - the PetscSection
206: - numFields - the number of fields
208: Level: intermediate
210: .seealso: PetscSectionGetNumFields()
211: @*/
212: PetscErrorCode PetscSectionSetNumFields(PetscSection s, PetscInt numFields)
213: {
214: PetscInt f;
218: if (numFields <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "The number of fields %d must be positive", numFields);
219: PetscSectionReset(s);
221: s->numFields = numFields;
222: PetscMalloc1(s->numFields, &s->numFieldComponents);
223: PetscMalloc1(s->numFields, &s->fieldNames);
224: PetscMalloc1(s->numFields, &s->field);
225: for (f = 0; f < s->numFields; ++f) {
226: char name[64];
228: s->numFieldComponents[f] = 1;
230: PetscSectionCreate(PetscObjectComm((PetscObject) s), &s->field[f]);
231: PetscSNPrintf(name, 64, "Field_%D", f);
232: PetscStrallocpy(name, (char **) &s->fieldNames[f]);
233: }
234: return(0);
235: }
239: /*@C
240: PetscSectionGetFieldName - Returns the name of a field in the PetscSection
242: Not Collective
244: Input Parameters:
245: + s - the PetscSection
246: - field - the field number
248: Output Parameter:
249: . fieldName - the field name
251: Level: developer
253: .seealso: PetscSectionSetFieldName()
254: @*/
255: PetscErrorCode PetscSectionGetFieldName(PetscSection s, PetscInt field, const char *fieldName[])
256: {
259: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
260: *fieldName = s->fieldNames[field];
261: return(0);
262: }
266: /*@C
267: PetscSectionSetFieldName - Sets the name of a field in the PetscSection
269: Not Collective
271: Input Parameters:
272: + s - the PetscSection
273: . field - the field number
274: - fieldName - the field name
276: Level: developer
278: .seealso: PetscSectionGetFieldName()
279: @*/
280: PetscErrorCode PetscSectionSetFieldName(PetscSection s, PetscInt field, const char fieldName[])
281: {
286: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
287: PetscFree(s->fieldNames[field]);
288: PetscStrallocpy(fieldName, (char**) &s->fieldNames[field]);
289: return(0);
290: }
294: /*@
295: PetscSectionGetFieldComponents - Returns the number of field components for the given field.
297: Not collective
299: Input Parameters:
300: + s - the PetscSection
301: - field - the field number
303: Output Parameter:
304: . numComp - the number of field components
306: Level: intermediate
308: .seealso: PetscSectionSetNumFieldComponents(), PetscSectionGetNumFields()
309: @*/
310: PetscErrorCode PetscSectionGetFieldComponents(PetscSection s, PetscInt field, PetscInt *numComp)
311: {
314: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
315: *numComp = s->numFieldComponents[field];
316: return(0);
317: }
321: /*@
322: PetscSectionSetFieldComponents - Sets the number of field components for the given field.
324: Not collective
326: Input Parameters:
327: + s - the PetscSection
328: . field - the field number
329: - numComp - the number of field components
331: Level: intermediate
333: .seealso: PetscSectionGetNumFieldComponents(), PetscSectionGetNumFields()
334: @*/
335: PetscErrorCode PetscSectionSetFieldComponents(PetscSection s, PetscInt field, PetscInt numComp)
336: {
338: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
339: s->numFieldComponents[field] = numComp;
340: return(0);
341: }
345: static PetscErrorCode PetscSectionCheckConstraints_Static(PetscSection s)
346: {
350: if (!s->bc) {
351: PetscSectionCreate(PETSC_COMM_SELF, &s->bc);
352: PetscSectionSetChart(s->bc, s->pStart, s->pEnd);
353: }
354: return(0);
355: }
359: /*@
360: PetscSectionGetChart - Returns the range [pStart, pEnd) in which points in the lie.
362: Not collective
364: Input Parameter:
365: . s - the PetscSection
367: Output Parameters:
368: + pStart - the first point
369: - pEnd - one past the last point
371: Level: intermediate
373: .seealso: PetscSectionSetChart(), PetscSectionCreate()
374: @*/
375: PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd)
376: {
379: if (pStart) *pStart = s->pStart;
380: if (pEnd) *pEnd = s->pEnd;
381: return(0);
382: }
386: /*@
387: PetscSectionSetChart - Sets the range [pStart, pEnd) in which points in the lie.
389: Not collective
391: Input Parameters:
392: + s - the PetscSection
393: . pStart - the first point
394: - pEnd - one past the last point
396: Level: intermediate
398: .seealso: PetscSectionGetChart(), PetscSectionCreate()
399: @*/
400: PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd)
401: {
402: PetscInt f;
407: /* Cannot Reset() because it destroys field information */
408: s->setup = PETSC_FALSE;
409: PetscSectionDestroy(&s->bc);
410: PetscFree(s->bcIndices);
411: PetscFree2(s->atlasDof, s->atlasOff);
413: s->pStart = pStart;
414: s->pEnd = pEnd;
415: PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff);
416: PetscMemzero(s->atlasDof, (pEnd - pStart)*sizeof(PetscInt));
417: for (f = 0; f < s->numFields; ++f) {
418: PetscSectionSetChart(s->field[f], pStart, pEnd);
419: }
420: return(0);
421: }
425: /*@
426: PetscSectionGetPermutation - Returns the permutation of [0, pEnd-pStart) or NULL
428: Not collective
430: Input Parameter:
431: . s - the PetscSection
433: Output Parameters:
434: . perm - The permutation as an IS
436: Level: intermediate
438: .seealso: PetscSectionSetPermutation(), PetscSectionCreate()
439: @*/
440: PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm)
441: {
445: return(0);
446: }
450: /*@
451: PetscSectionSetPermutation - Sets the permutation for [0, pEnd-pStart)
453: Not collective
455: Input Parameters:
456: + s - the PetscSection
457: - perm - the permutation of points
459: Level: intermediate
461: .seealso: PetscSectionGetPermutation(), PetscSectionCreate()
462: @*/
463: PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm)
464: {
468: if (s->setup) SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup");
469: if (s->perm != perm) {
470: ISDestroy(&s->perm);
471: s->perm = perm;
472: PetscObjectReference((PetscObject) s->perm);
473: }
474: return(0);
475: }
479: /*@
480: PetscSectionGetDof - Return the number of degrees of freedom associated with a given point.
482: Not collective
484: Input Parameters:
485: + s - the PetscSection
486: - point - the point
488: Output Parameter:
489: . numDof - the number of dof
491: Level: intermediate
493: .seealso: PetscSectionSetDof(), PetscSectionCreate()
494: @*/
495: PetscErrorCode PetscSectionGetDof(PetscSection s, PetscInt point, PetscInt *numDof)
496: {
498: #if defined(PETSC_USE_DEBUG)
499: if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
500: #endif
501: *numDof = s->atlasDof[point - s->pStart];
502: return(0);
503: }
507: /*@
508: PetscSectionSetDof - Sets the number of degrees of freedom associated with a given point.
510: Not collective
512: Input Parameters:
513: + s - the PetscSection
514: . point - the point
515: - numDof - the number of dof
517: Level: intermediate
519: .seealso: PetscSectionGetDof(), PetscSectionAddDof(), PetscSectionCreate()
520: @*/
521: PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof)
522: {
524: if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
525: s->atlasDof[point - s->pStart] = numDof;
526: return(0);
527: }
531: /*@
532: PetscSectionAddDof - Adds to the number of degrees of freedom associated with a given point.
534: Not collective
536: Input Parameters:
537: + s - the PetscSection
538: . point - the point
539: - numDof - the number of additional dof
541: Level: intermediate
543: .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate()
544: @*/
545: PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof)
546: {
548: if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
549: s->atlasDof[point - s->pStart] += numDof;
550: return(0);
551: }
555: /*@
556: PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point.
558: Not collective
560: Input Parameters:
561: + s - the PetscSection
562: . point - the point
563: - field - the field
565: Output Parameter:
566: . numDof - the number of dof
568: Level: intermediate
570: .seealso: PetscSectionSetFieldDof(), PetscSectionCreate()
571: @*/
572: PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
573: {
577: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
578: PetscSectionGetDof(s->field[field], point, numDof);
579: return(0);
580: }
584: /*@
585: PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point.
587: Not collective
589: Input Parameters:
590: + s - the PetscSection
591: . point - the point
592: . field - the field
593: - numDof - the number of dof
595: Level: intermediate
597: .seealso: PetscSectionGetFieldDof(), PetscSectionCreate()
598: @*/
599: PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
600: {
604: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
605: PetscSectionSetDof(s->field[field], point, numDof);
606: return(0);
607: }
611: /*@
612: PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point.
614: Not collective
616: Input Parameters:
617: + s - the PetscSection
618: . point - the point
619: . field - the field
620: - numDof - the number of dof
622: Level: intermediate
624: .seealso: PetscSectionSetFieldDof(), PetscSectionGetFieldDof(), PetscSectionCreate()
625: @*/
626: PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
627: {
631: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
632: PetscSectionAddDof(s->field[field], point, numDof);
633: return(0);
634: }
638: /*@
639: PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point.
641: Not collective
643: Input Parameters:
644: + s - the PetscSection
645: - point - the point
647: Output Parameter:
648: . numDof - the number of dof which are fixed by constraints
650: Level: intermediate
652: .seealso: PetscSectionGetDof(), PetscSectionSetConstraintDof(), PetscSectionCreate()
653: @*/
654: PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof)
655: {
659: if (s->bc) {
660: PetscSectionGetDof(s->bc, point, numDof);
661: } else *numDof = 0;
662: return(0);
663: }
667: /*@
668: PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point.
670: Not collective
672: Input Parameters:
673: + s - the PetscSection
674: . point - the point
675: - numDof - the number of dof which are fixed by constraints
677: Level: intermediate
679: .seealso: PetscSectionSetDof(), PetscSectionGetConstraintDof(), PetscSectionCreate()
680: @*/
681: PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
682: {
686: if (numDof) {
687: PetscSectionCheckConstraints_Static(s);
688: PetscSectionSetDof(s->bc, point, numDof);
689: }
690: return(0);
691: }
695: /*@
696: PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point.
698: Not collective
700: Input Parameters:
701: + s - the PetscSection
702: . point - the point
703: - numDof - the number of additional dof which are fixed by constraints
705: Level: intermediate
707: .seealso: PetscSectionAddDof(), PetscSectionGetConstraintDof(), PetscSectionCreate()
708: @*/
709: PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
710: {
714: if (numDof) {
715: PetscSectionCheckConstraints_Static(s);
716: PetscSectionAddDof(s->bc, point, numDof);
717: }
718: return(0);
719: }
723: /*@
724: PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point.
726: Not collective
728: Input Parameters:
729: + s - the PetscSection
730: . point - the point
731: - field - the field
733: Output Parameter:
734: . numDof - the number of dof which are fixed by constraints
736: Level: intermediate
738: .seealso: PetscSectionGetDof(), PetscSectionSetFieldConstraintDof(), PetscSectionCreate()
739: @*/
740: PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
741: {
745: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
746: PetscSectionGetConstraintDof(s->field[field], point, numDof);
747: return(0);
748: }
752: /*@
753: PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point.
755: Not collective
757: Input Parameters:
758: + s - the PetscSection
759: . point - the point
760: . field - the field
761: - numDof - the number of dof which are fixed by constraints
763: Level: intermediate
765: .seealso: PetscSectionSetDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate()
766: @*/
767: PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
768: {
772: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
773: PetscSectionSetConstraintDof(s->field[field], point, numDof);
774: return(0);
775: }
779: /*@
780: PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point.
782: Not collective
784: Input Parameters:
785: + s - the PetscSection
786: . point - the point
787: . field - the field
788: - numDof - the number of additional dof which are fixed by constraints
790: Level: intermediate
792: .seealso: PetscSectionAddDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate()
793: @*/
794: PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
795: {
799: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
800: PetscSectionAddConstraintDof(s->field[field], point, numDof);
801: return(0);
802: }
806: PetscErrorCode PetscSectionSetUpBC(PetscSection s)
807: {
811: if (s->bc) {
812: const PetscInt last = (s->bc->pEnd-s->bc->pStart) - 1;
814: PetscSectionSetUp(s->bc);
815: PetscMalloc1(s->bc->atlasOff[last] + s->bc->atlasDof[last], &s->bcIndices);
816: }
817: return(0);
818: }
822: /*@
823: PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point.
825: Not collective
827: Input Parameter:
828: . s - the PetscSection
830: Level: intermediate
832: .seealso: PetscSectionCreate()
833: @*/
834: PetscErrorCode PetscSectionSetUp(PetscSection s)
835: {
836: const PetscInt *pind = NULL;
837: PetscInt offset = 0, p, f;
838: PetscErrorCode ierr;
841: if (s->setup) return(0);
842: s->setup = PETSC_TRUE;
843: if (s->perm) {ISGetIndices(s->perm, &pind);}
844: for (p = 0; p < s->pEnd - s->pStart; ++p) {
845: const PetscInt q = pind ? pind[p] : p;
847: s->atlasOff[q] = offset;
848: offset += s->atlasDof[q];
849: s->maxDof = PetscMax(s->maxDof, s->atlasDof[q]);
850: }
851: PetscSectionSetUpBC(s);
852: /* Assume that all fields have the same chart */
853: for (p = 0; p < s->pEnd - s->pStart; ++p) {
854: const PetscInt q = pind ? pind[p] : p;
855: PetscInt off = s->atlasOff[q];
857: for (f = 0; f < s->numFields; ++f) {
858: PetscSection sf = s->field[f];
860: sf->atlasOff[q] = off;
861: off += sf->atlasDof[q];
862: }
863: }
864: if (s->perm) {ISRestoreIndices(s->perm, &pind);}
865: for (f = 0; f < s->numFields; ++f) {
866: PetscSectionSetUpBC(s->field[f]);
867: }
868: return(0);
869: }
873: /*@
874: PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the chart
876: Not collective
878: Input Parameters:
879: . s - the PetscSection
881: Output Parameter:
882: . maxDof - the maximum dof
884: Level: intermediate
886: .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate()
887: @*/
888: PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof)
889: {
891: *maxDof = s->maxDof;
892: return(0);
893: }
897: /*@
898: PetscSectionGetStorageSize - Return the size of an array or local Vec capable of holding all the degrees of freedom.
900: Not collective
902: Input Parameters:
903: + s - the PetscSection
904: - size - the allocated size
906: Output Parameter:
907: . size - the size of an array which can hold all the dofs
909: Level: intermediate
911: .seealso: PetscSectionGetOffset(), PetscSectionGetConstrainedStorageSize(), PetscSectionCreate()
912: @*/
913: PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size)
914: {
915: PetscInt p, n = 0;
918: for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
919: *size = n;
920: return(0);
921: }
925: /*@
926: PetscSectionGetConstrainedStorageSize - Return the size of an array or local Vec capable of holding all unconstrained degrees of freedom.
928: Not collective
930: Input Parameters:
931: + s - the PetscSection
932: - point - the point
934: Output Parameter:
935: . size - the size of an array which can hold all unconstrained dofs
937: Level: intermediate
939: .seealso: PetscSectionGetStorageSize(), PetscSectionGetOffset(), PetscSectionCreate()
940: @*/
941: PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size)
942: {
943: PetscInt p, n = 0;
946: for (p = 0; p < s->pEnd - s->pStart; ++p) {
947: const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0;
948: n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0;
949: }
950: *size = n;
951: return(0);
952: }
956: /*@
957: PetscSectionCreateGlobalSection - Create a section describing the global field layout using
958: the local section and an SF describing the section point overlap.
960: Input Parameters:
961: + s - The PetscSection for the local field layout
962: . sf - The SF describing parallel layout of the section points (leaves are unowned local points)
963: . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
964: - localOffsets - If PETSC_TRUE, use local rather than global offsets for the points
966: Output Parameter:
967: . gsection - The PetscSection for the global field layout
969: Note: This gives negative sizes and offsets to points not owned by this process
971: Level: developer
973: .seealso: PetscSectionCreate()
974: @*/
975: PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscBool localOffsets, PetscSection *gsection)
976: {
977: const PetscInt *pind = NULL;
978: PetscInt *recv = NULL, *neg = NULL;
979: PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots, nlocal;
980: PetscErrorCode ierr;
983: PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);
984: PetscSectionGetChart(s, &pStart, &pEnd);
985: PetscSectionSetChart(*gsection, pStart, pEnd);
986: PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);
987: nlocal = nroots; /* The local/leaf space matches global/root space */
988: /* Must allocate for all points visible to SF, which may be more than this section */
989: if (nroots >= 0) { /* nroots < 0 means that the graph has not been set, only happens in serial */
990: if (nroots < pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %d < pEnd %d", nroots, pEnd);
991: PetscMalloc2(nroots,&neg,nlocal,&recv);
992: PetscMemzero(neg,nroots*sizeof(PetscInt));
993: }
994: /* Mark all local points with negative dof */
995: for (p = pStart; p < pEnd; ++p) {
996: PetscSectionGetDof(s, p, &dof);
997: PetscSectionSetDof(*gsection, p, dof);
998: PetscSectionGetConstraintDof(s, p, &cdof);
999: if (!includeConstraints && cdof > 0) {PetscSectionSetConstraintDof(*gsection, p, cdof);}
1000: if (neg) neg[p] = -(dof+1);
1001: }
1002: PetscSectionSetUpBC(*gsection);
1003: if (nroots >= 0) {
1004: PetscMemzero(recv,nlocal*sizeof(PetscInt));
1005: PetscSFBcastBegin(sf, MPIU_INT, neg, recv);
1006: PetscSFBcastEnd(sf, MPIU_INT, neg, recv);
1007: for (p = pStart; p < pEnd; ++p) {
1008: if (recv[p] < 0) {
1009: (*gsection)->atlasDof[p-pStart] = recv[p];
1010: PetscSectionGetDof(s, p, &dof);
1011: if (-(recv[p]+1) != dof) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is not the unconstrained %d", -(recv[p]+1), p, dof);
1012: }
1013: }
1014: }
1015: /* Calculate new sizes, get proccess offset, and calculate point offsets */
1016: if (s->perm) {ISGetIndices(s->perm, &pind);}
1017: for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1018: const PetscInt q = pind ? pind[p] : p;
1020: cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1021: (*gsection)->atlasOff[q] = off;
1022: off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
1023: }
1024: if (!localOffsets) {
1025: MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));
1026: globalOff -= off;
1027: }
1028: for (p = pStart, off = 0; p < pEnd; ++p) {
1029: (*gsection)->atlasOff[p-pStart] += globalOff;
1030: if (neg) neg[p] = -((*gsection)->atlasOff[p-pStart]+1);
1031: }
1032: if (s->perm) {ISRestoreIndices(s->perm, &pind);}
1033: /* Put in negative offsets for ghost points */
1034: if (nroots >= 0) {
1035: PetscMemzero(recv,nlocal*sizeof(PetscInt));
1036: PetscSFBcastBegin(sf, MPIU_INT, neg, recv);
1037: PetscSFBcastEnd(sf, MPIU_INT, neg, recv);
1038: for (p = pStart; p < pEnd; ++p) {
1039: if (recv[p] < 0) (*gsection)->atlasOff[p-pStart] = recv[p];
1040: }
1041: }
1042: PetscFree2(neg,recv);
1043: PetscSectionViewFromOptions(*gsection,NULL,"-global_section_view");
1044: return(0);
1045: }
1049: /*@
1050: PetscSectionCreateGlobalSectionCensored - Create a section describing the global field layout using
1051: the local section and an SF describing the section point overlap.
1053: Input Parameters:
1054: + s - The PetscSection for the local field layout
1055: . sf - The SF describing parallel layout of the section points
1056: . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1057: . numExcludes - The number of exclusion ranges
1058: - excludes - An array [start_0, end_0, start_1, end_1, ...] where there are numExcludes pairs
1060: Output Parameter:
1061: . gsection - The PetscSection for the global field layout
1063: Note: This gives negative sizes and offsets to points not owned by this process
1065: Level: developer
1067: .seealso: PetscSectionCreate()
1068: @*/
1069: PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection)
1070: {
1071: const PetscInt *pind = NULL;
1072: PetscInt *neg = NULL, *tmpOff = NULL;
1073: PetscInt pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
1074: PetscErrorCode ierr;
1077: PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);
1078: PetscSectionGetChart(s, &pStart, &pEnd);
1079: PetscSectionSetChart(*gsection, pStart, pEnd);
1080: PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);
1081: if (nroots >= 0) {
1082: if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
1083: PetscCalloc1(nroots, &neg);
1084: if (nroots > pEnd-pStart) {
1085: PetscCalloc1(nroots, &tmpOff);
1086: } else {
1087: tmpOff = &(*gsection)->atlasDof[-pStart];
1088: }
1089: }
1090: /* Mark ghost points with negative dof */
1091: for (p = pStart; p < pEnd; ++p) {
1092: for (e = 0; e < numExcludes; ++e) {
1093: if ((p >= excludes[e*2+0]) && (p < excludes[e*2+1])) {
1094: PetscSectionSetDof(*gsection, p, 0);
1095: break;
1096: }
1097: }
1098: if (e < numExcludes) continue;
1099: PetscSectionGetDof(s, p, &dof);
1100: PetscSectionSetDof(*gsection, p, dof);
1101: PetscSectionGetConstraintDof(s, p, &cdof);
1102: if (!includeConstraints && cdof > 0) {PetscSectionSetConstraintDof(*gsection, p, cdof);}
1103: if (neg) neg[p] = -(dof+1);
1104: }
1105: PetscSectionSetUpBC(*gsection);
1106: if (nroots >= 0) {
1107: PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);
1108: PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);
1109: if (nroots > pEnd - pStart) {
1110: for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1111: }
1112: }
1113: /* Calculate new sizes, get proccess offset, and calculate point offsets */
1114: if (s->perm) {ISGetIndices(s->perm, &pind);}
1115: for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1116: const PetscInt q = pind ? pind[p] : p;
1118: cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1119: (*gsection)->atlasOff[q] = off;
1120: off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
1121: }
1122: MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));
1123: globalOff -= off;
1124: for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1125: (*gsection)->atlasOff[p] += globalOff;
1126: if (neg) neg[p+pStart] = -((*gsection)->atlasOff[p]+1);
1127: }
1128: if (s->perm) {ISRestoreIndices(s->perm, &pind);}
1129: /* Put in negative offsets for ghost points */
1130: if (nroots >= 0) {
1131: if (nroots == pEnd-pStart) tmpOff = &(*gsection)->atlasOff[-pStart];
1132: PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);
1133: PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);
1134: if (nroots > pEnd - pStart) {
1135: for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
1136: }
1137: }
1138: if (nroots >= 0 && nroots > pEnd-pStart) {PetscFree(tmpOff);}
1139: PetscFree(neg);
1140: return(0);
1141: }
1145: PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1146: {
1147: PetscInt pStart, pEnd, p, localSize = 0;
1151: PetscSectionGetChart(s, &pStart, &pEnd);
1152: for (p = pStart; p < pEnd; ++p) {
1153: PetscInt dof;
1155: PetscSectionGetDof(s, p, &dof);
1156: if (dof > 0) ++localSize;
1157: }
1158: PetscLayoutCreate(comm, layout);
1159: PetscLayoutSetLocalSize(*layout, localSize);
1160: PetscLayoutSetBlockSize(*layout, 1);
1161: PetscLayoutSetUp(*layout);
1162: return(0);
1163: }
1167: /*@
1168: PetscSectionGetValueLayout - Get the PetscLayout associated with a section, usually the default global section.
1170: Input Parameters:
1171: + comm - The MPI_Comm
1172: - s - The PetscSection
1174: Output Parameter:
1175: . layout - The layout for the section
1177: Level: developer
1179: .seealso: PetscSectionCreate()
1180: @*/
1181: PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1182: {
1183: PetscInt pStart, pEnd, p, localSize = 0;
1187: PetscSectionGetChart(s, &pStart, &pEnd);
1188: for (p = pStart; p < pEnd; ++p) {
1189: PetscInt dof,cdof;
1191: PetscSectionGetDof(s, p, &dof);
1192: PetscSectionGetConstraintDof(s, p, &cdof);
1193: if (dof-cdof > 0) localSize += dof-cdof;
1194: }
1195: PetscLayoutCreate(comm, layout);
1196: PetscLayoutSetLocalSize(*layout, localSize);
1197: PetscLayoutSetBlockSize(*layout, 1);
1198: PetscLayoutSetUp(*layout);
1199: return(0);
1200: }
1204: /*@
1205: PetscSectionGetOffset - Return the offset into an array or local Vec for the dof associated with the given point.
1207: Not collective
1209: Input Parameters:
1210: + s - the PetscSection
1211: - point - the point
1213: Output Parameter:
1214: . offset - the offset
1216: Level: intermediate
1218: .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate()
1219: @*/
1220: PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset)
1221: {
1223: #if defined(PETSC_USE_DEBUG)
1224: if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
1225: #endif
1226: *offset = s->atlasOff[point - s->pStart];
1227: return(0);
1228: }
1232: /*@
1233: PetscSectionSetOffset - Set the offset into an array or local Vec for the dof associated with the given point.
1235: Not collective
1237: Input Parameters:
1238: + s - the PetscSection
1239: . point - the point
1240: - offset - the offset
1242: Note: The user usually does not call this function, but uses PetscSectionSetUp()
1244: Level: intermediate
1246: .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate(), PetscSectionSetUp()
1247: @*/
1248: PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset)
1249: {
1251: if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->pStart, s->pEnd);
1252: s->atlasOff[point - s->pStart] = offset;
1253: return(0);
1254: }
1258: /*@
1259: PetscSectionGetFieldOffset - Return the offset into an array or local Vec for the dof associated with the given point.
1261: Not collective
1263: Input Parameters:
1264: + s - the PetscSection
1265: . point - the point
1266: - field - the field
1268: Output Parameter:
1269: . offset - the offset
1271: Level: intermediate
1273: .seealso: PetscSectionGetOffset(), PetscSectionCreate()
1274: @*/
1275: PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1276: {
1280: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
1281: PetscSectionGetOffset(s->field[field], point, offset);
1282: return(0);
1283: }
1287: /*@
1288: PetscSectionSetFieldOffset - Set the offset into an array or local Vec for the dof associated with the given point.
1290: Not collective
1292: Input Parameters:
1293: + s - the PetscSection
1294: . point - the point
1295: . field - the field
1296: - offset - the offset
1298: Note: The user usually does not call this function, but uses PetscSectionSetUp()
1300: Level: intermediate
1302: .seealso: PetscSectionGetOffset(), PetscSectionCreate(), PetscSectionSetUp()
1303: @*/
1304: PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset)
1305: {
1309: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
1310: PetscSectionSetOffset(s->field[field], point, offset);
1311: return(0);
1312: }
1316: /* This gives the offset on a point of the field, ignoring constraints */
1317: PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1318: {
1319: PetscInt off, foff;
1323: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
1324: PetscSectionGetOffset(s, point, &off);
1325: PetscSectionGetOffset(s->field[field], point, &foff);
1326: *offset = foff - off;
1327: return(0);
1328: }
1332: /*@
1333: PetscSectionGetOffsetRange - Return the full range of offsets [start, end)
1335: Not collective
1337: Input Parameter:
1338: . s - the PetscSection
1340: Output Parameters:
1341: + start - the minimum offset
1342: - end - one more than the maximum offset
1344: Level: intermediate
1346: .seealso: PetscSectionGetOffset(), PetscSectionCreate()
1347: @*/
1348: PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end)
1349: {
1350: PetscInt os = 0, oe = 0, pStart, pEnd, p;
1354: if (s->atlasOff) {os = s->atlasOff[0]; oe = s->atlasOff[0];}
1355: PetscSectionGetChart(s, &pStart, &pEnd);
1356: for (p = 0; p < pEnd-pStart; ++p) {
1357: PetscInt dof = s->atlasDof[p], off = s->atlasOff[p];
1359: if (off >= 0) {
1360: os = PetscMin(os, off);
1361: oe = PetscMax(oe, off+dof);
1362: }
1363: }
1364: if (start) *start = os;
1365: if (end) *end = oe;
1366: return(0);
1367: }
1371: PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt numFields, PetscInt fields[], PetscSection *subs)
1372: {
1373: PetscInt nF, f, pStart, pEnd, p, maxCdof = 0;
1377: if (!numFields) return(0);
1378: PetscSectionGetNumFields(s, &nF);
1379: if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of fields %d", numFields, nF);
1380: PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);
1381: PetscSectionSetNumFields(*subs, numFields);
1382: for (f = 0; f < numFields; ++f) {
1383: const char *name = NULL;
1384: PetscInt numComp = 0;
1386: PetscSectionGetFieldName(s, fields[f], &name);
1387: PetscSectionSetFieldName(*subs, f, name);
1388: PetscSectionGetFieldComponents(s, fields[f], &numComp);
1389: PetscSectionSetFieldComponents(*subs, f, numComp);
1390: }
1391: PetscSectionGetChart(s, &pStart, &pEnd);
1392: PetscSectionSetChart(*subs, pStart, pEnd);
1393: for (p = pStart; p < pEnd; ++p) {
1394: PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0;
1396: for (f = 0; f < numFields; ++f) {
1397: PetscSectionGetFieldDof(s, p, fields[f], &fdof);
1398: PetscSectionSetFieldDof(*subs, p, f, fdof);
1399: PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof);
1400: if (cfdof) {PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof);}
1401: dof += fdof;
1402: cdof += cfdof;
1403: }
1404: PetscSectionSetDof(*subs, p, dof);
1405: if (cdof) {PetscSectionSetConstraintDof(*subs, p, cdof);}
1406: maxCdof = PetscMax(cdof, maxCdof);
1407: }
1408: PetscSectionSetUp(*subs);
1409: if (maxCdof) {
1410: PetscInt *indices;
1412: PetscMalloc1(maxCdof, &indices);
1413: for (p = pStart; p < pEnd; ++p) {
1414: PetscInt cdof;
1416: PetscSectionGetConstraintDof(*subs, p, &cdof);
1417: if (cdof) {
1418: const PetscInt *oldIndices = NULL;
1419: PetscInt fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0;
1421: for (f = 0; f < numFields; ++f) {
1422: PetscInt oldFoff = 0, oldf;
1424: PetscSectionGetFieldDof(s, p, fields[f], &fdof);
1425: PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof);
1426: PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices);
1427: /* This can be sped up if we assume sorted fields */
1428: for (oldf = 0; oldf < fields[f]; ++oldf) {
1429: PetscInt oldfdof = 0;
1430: PetscSectionGetFieldDof(s, p, oldf, &oldfdof);
1431: oldFoff += oldfdof;
1432: }
1433: for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] = oldIndices[fc] + (fOff - oldFoff);
1434: PetscSectionSetFieldConstraintIndices(*subs, p, f, &indices[numConst]);
1435: numConst += cfdof;
1436: fOff += fdof;
1437: }
1438: PetscSectionSetConstraintIndices(*subs, p, indices);
1439: }
1440: }
1441: PetscFree(indices);
1442: }
1443: return(0);
1444: }
1448: PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs)
1449: {
1450: const PetscInt *points = NULL, *indices = NULL;
1451: PetscInt numFields, f, numSubpoints = 0, pStart, pEnd, p, subp;
1455: PetscSectionGetNumFields(s, &numFields);
1456: PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);
1457: if (numFields) {PetscSectionSetNumFields(*subs, numFields);}
1458: for (f = 0; f < numFields; ++f) {
1459: const char *name = NULL;
1460: PetscInt numComp = 0;
1462: PetscSectionGetFieldName(s, f, &name);
1463: PetscSectionSetFieldName(*subs, f, name);
1464: PetscSectionGetFieldComponents(s, f, &numComp);
1465: PetscSectionSetFieldComponents(*subs, f, numComp);
1466: }
1467: /* For right now, we do not try to squeeze the subchart */
1468: if (subpointMap) {
1469: ISGetSize(subpointMap, &numSubpoints);
1470: ISGetIndices(subpointMap, &points);
1471: }
1472: PetscSectionGetChart(s, &pStart, &pEnd);
1473: PetscSectionSetChart(*subs, 0, numSubpoints);
1474: for (p = pStart; p < pEnd; ++p) {
1475: PetscInt dof, cdof, fdof = 0, cfdof = 0;
1477: PetscFindInt(p, numSubpoints, points, &subp);
1478: if (subp < 0) continue;
1479: for (f = 0; f < numFields; ++f) {
1480: PetscSectionGetFieldDof(s, p, f, &fdof);
1481: PetscSectionSetFieldDof(*subs, subp, f, fdof);
1482: PetscSectionGetFieldConstraintDof(s, p, f, &cfdof);
1483: if (cfdof) {PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof);}
1484: }
1485: PetscSectionGetDof(s, p, &dof);
1486: PetscSectionSetDof(*subs, subp, dof);
1487: PetscSectionGetConstraintDof(s, p, &cdof);
1488: if (cdof) {PetscSectionSetConstraintDof(*subs, subp, cdof);}
1489: }
1490: PetscSectionSetUp(*subs);
1491: /* Change offsets to original offsets */
1492: for (p = pStart; p < pEnd; ++p) {
1493: PetscInt off, foff = 0;
1495: PetscFindInt(p, numSubpoints, points, &subp);
1496: if (subp < 0) continue;
1497: for (f = 0; f < numFields; ++f) {
1498: PetscSectionGetFieldOffset(s, p, f, &foff);
1499: PetscSectionSetFieldOffset(*subs, subp, f, foff);
1500: }
1501: PetscSectionGetOffset(s, p, &off);
1502: PetscSectionSetOffset(*subs, subp, off);
1503: }
1504: /* Copy constraint indices */
1505: for (subp = 0; subp < numSubpoints; ++subp) {
1506: PetscInt cdof;
1508: PetscSectionGetConstraintDof(*subs, subp, &cdof);
1509: if (cdof) {
1510: for (f = 0; f < numFields; ++f) {
1511: PetscSectionGetFieldConstraintIndices(s, points[subp], f, &indices);
1512: PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices);
1513: }
1514: PetscSectionGetConstraintIndices(s, points[subp], &indices);
1515: PetscSectionSetConstraintIndices(*subs, subp, indices);
1516: }
1517: }
1518: if (subpointMap) {ISRestoreIndices(subpointMap, &points);}
1519: return(0);
1520: }
1524: PetscErrorCode PetscSectionView_ASCII(PetscSection s, PetscViewer viewer)
1525: {
1526: PetscInt p;
1527: PetscMPIInt rank;
1531: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1532: PetscViewerASCIIPushSynchronized(viewer);
1533: PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);
1534: for (p = 0; p < s->pEnd - s->pStart; ++p) {
1535: if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
1536: PetscInt b;
1538: PetscViewerASCIISynchronizedPrintf(viewer, " (%4d) dim %2d offset %3d constrained", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);
1539: for (b = 0; b < s->bc->atlasDof[p]; ++b) {
1540: PetscViewerASCIISynchronizedPrintf(viewer, " %d", s->bcIndices[s->bc->atlasOff[p]+b]);
1541: }
1542: PetscViewerASCIISynchronizedPrintf(viewer, "\n");
1543: } else {
1544: PetscViewerASCIISynchronizedPrintf(viewer, " (%4d) dim %2d offset %3d\n", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);
1545: }
1546: }
1547: PetscViewerFlush(viewer);
1548: PetscViewerASCIIPopSynchronized(viewer);
1549: return(0);
1550: }
1554: /*@C
1555: PetscSectionView - Views a PetscSection
1557: Collective on PetscSection
1559: Input Parameters:
1560: + s - the PetscSection object to view
1561: - v - the viewer
1563: Level: developer
1565: .seealso PetscSectionCreate(), PetscSectionDestroy()
1566: @*/
1567: PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer)
1568: {
1569: PetscBool isascii;
1570: PetscInt f;
1574: if (!viewer) {PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer);}
1576: PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);
1577: if (isascii) {
1578: PetscObjectPrintClassNamePrefixType((PetscObject)s,viewer);
1579: if (s->numFields) {
1580: PetscViewerASCIIPrintf(viewer, "%D fields\n", s->numFields);
1581: for (f = 0; f < s->numFields; ++f) {
1582: PetscViewerASCIIPrintf(viewer, " field %D with %D components\n", f, s->numFieldComponents[f]);
1583: PetscSectionView_ASCII(s->field[f], viewer);
1584: }
1585: } else {
1586: PetscSectionView_ASCII(s, viewer);
1587: }
1588: }
1589: return(0);
1590: }
1594: /*@
1595: PetscSectionReset - Frees all section data.
1597: Not collective
1599: Input Parameters:
1600: . s - the PetscSection
1602: Level: developer
1604: .seealso: PetscSection, PetscSectionCreate()
1605: @*/
1606: PetscErrorCode PetscSectionReset(PetscSection s)
1607: {
1608: PetscInt f;
1612: PetscFree(s->numFieldComponents);
1613: for (f = 0; f < s->numFields; ++f) {
1614: PetscSectionDestroy(&s->field[f]);
1615: PetscFree(s->fieldNames[f]);
1616: }
1617: PetscFree(s->fieldNames);
1618: PetscFree(s->field);
1619: PetscSectionDestroy(&s->bc);
1620: PetscFree(s->bcIndices);
1621: PetscFree2(s->atlasDof, s->atlasOff);
1622: PetscSectionDestroy(&s->clSection);
1623: ISDestroy(&s->clPoints);
1624: ISDestroy(&s->perm);
1626: s->pStart = -1;
1627: s->pEnd = -1;
1628: s->maxDof = 0;
1629: s->setup = PETSC_FALSE;
1630: s->numFields = 0;
1631: s->clObj = NULL;
1632: return(0);
1633: }
1637: /*@
1638: PetscSectionDestroy - Frees a section object and frees its range if that exists.
1640: Not collective
1642: Input Parameters:
1643: . s - the PetscSection
1645: Level: developer
1647: The PetscSection object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
1648: recommended they not be used in user codes unless you really gain something in their use.
1650: .seealso: PetscSection, PetscSectionCreate()
1651: @*/
1652: PetscErrorCode PetscSectionDestroy(PetscSection *s)
1653: {
1657: if (!*s) return(0);
1659: if (--((PetscObject)(*s))->refct > 0) {
1660: *s = NULL;
1661: return(0);
1662: }
1663: PetscSectionReset(*s);
1664: PetscHeaderDestroy(s);
1665: return(0);
1666: }
1670: PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values)
1671: {
1672: const PetscInt p = point - s->pStart;
1675: *values = &baseArray[s->atlasOff[p]];
1676: return(0);
1677: }
1681: PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode)
1682: {
1683: PetscInt *array;
1684: const PetscInt p = point - s->pStart;
1685: const PetscInt orientation = 0; /* Needs to be included for use in closure operations */
1686: PetscInt cDim = 0;
1690: PetscSectionGetConstraintDof(s, p, &cDim);
1691: array = &baseArray[s->atlasOff[p]];
1692: if (!cDim) {
1693: if (orientation >= 0) {
1694: const PetscInt dim = s->atlasDof[p];
1695: PetscInt i;
1697: if (mode == INSERT_VALUES) {
1698: for (i = 0; i < dim; ++i) array[i] = values[i];
1699: } else {
1700: for (i = 0; i < dim; ++i) array[i] += values[i];
1701: }
1702: } else {
1703: PetscInt offset = 0;
1704: PetscInt j = -1, field, i;
1706: for (field = 0; field < s->numFields; ++field) {
1707: const PetscInt dim = s->field[field]->atlasDof[p];
1709: for (i = dim-1; i >= 0; --i) array[++j] = values[i+offset];
1710: offset += dim;
1711: }
1712: }
1713: } else {
1714: if (orientation >= 0) {
1715: const PetscInt dim = s->atlasDof[p];
1716: PetscInt cInd = 0, i;
1717: const PetscInt *cDof;
1719: PetscSectionGetConstraintIndices(s, point, &cDof);
1720: if (mode == INSERT_VALUES) {
1721: for (i = 0; i < dim; ++i) {
1722: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1723: array[i] = values[i];
1724: }
1725: } else {
1726: for (i = 0; i < dim; ++i) {
1727: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1728: array[i] += values[i];
1729: }
1730: }
1731: } else {
1732: const PetscInt *cDof;
1733: PetscInt offset = 0;
1734: PetscInt cOffset = 0;
1735: PetscInt j = 0, field;
1737: PetscSectionGetConstraintIndices(s, point, &cDof);
1738: for (field = 0; field < s->numFields; ++field) {
1739: const PetscInt dim = s->field[field]->atlasDof[p]; /* PetscSectionGetFieldDof() */
1740: const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */
1741: const PetscInt sDim = dim - tDim;
1742: PetscInt cInd = 0, i,k;
1744: for (i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
1745: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1746: array[j] = values[k];
1747: }
1748: offset += dim;
1749: cOffset += dim - tDim;
1750: }
1751: }
1752: }
1753: return(0);
1754: }
1758: PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints)
1759: {
1763: *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE;
1764: return(0);
1765: }
1769: /*@C
1770: PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained
1772: Input Parameters:
1773: + s - The PetscSection
1774: - point - The point
1776: Output Parameter:
1777: . indices - The constrained dofs
1779: Note: In Fortran, you call PetscSectionGetConstraintIndicesF90() and PetscSectionRestoreConstraintIndicesF90()
1781: Level: advanced
1783: .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
1784: @*/
1785: PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices)
1786: {
1790: if (s->bc) {
1791: VecIntGetValuesSection(s->bcIndices, s->bc, point, indices);
1792: } else *indices = NULL;
1793: return(0);
1794: }
1798: /*@C
1799: PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained
1801: Input Parameters:
1802: + s - The PetscSection
1803: . point - The point
1804: - indices - The constrained dofs
1806: Note: The Fortran is PetscSectionSetConstraintIndicesF90()
1808: Level: advanced
1810: .seealso: PetscSectionGetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
1811: @*/
1812: PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[])
1813: {
1817: if (s->bc) {
1818: VecIntSetValuesSection(s->bcIndices, s->bc, point, indices, INSERT_VALUES);
1819: }
1820: return(0);
1821: }
1825: PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices)
1826: {
1830: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
1831: PetscSectionGetConstraintIndices(s->field[field], point, indices);
1832: return(0);
1833: }
1837: PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[])
1838: {
1842: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
1843: PetscSectionSetConstraintIndices(s->field[field], point, indices);
1844: return(0);
1845: }
1849: /*@
1850: PetscSectionPermute - Reorder the section according to the input point permutation
1852: Collective on PetscSection
1854: Input Parameter:
1855: + section - The PetscSection object
1856: - perm - The point permutation, old point p becomes new point perm[p]
1858: Output Parameter:
1859: . sectionNew - The permuted PetscSection
1861: Level: intermediate
1863: .keywords: mesh
1864: .seealso: MatPermute()
1865: @*/
1866: PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew)
1867: {
1868: PetscSection s = section, sNew;
1869: const PetscInt *perm;
1870: PetscInt numFields, f, numPoints, pStart, pEnd, p;
1871: PetscErrorCode ierr;
1877: PetscSectionCreate(PetscObjectComm((PetscObject) s), &sNew);
1878: PetscSectionGetNumFields(s, &numFields);
1879: if (numFields) {PetscSectionSetNumFields(sNew, numFields);}
1880: for (f = 0; f < numFields; ++f) {
1881: const char *name;
1882: PetscInt numComp;
1884: PetscSectionGetFieldName(s, f, &name);
1885: PetscSectionSetFieldName(sNew, f, name);
1886: PetscSectionGetFieldComponents(s, f, &numComp);
1887: PetscSectionSetFieldComponents(sNew, f, numComp);
1888: }
1889: ISGetLocalSize(permutation, &numPoints);
1890: ISGetIndices(permutation, &perm);
1891: PetscSectionGetChart(s, &pStart, &pEnd);
1892: PetscSectionSetChart(sNew, pStart, pEnd);
1893: if (numPoints < pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %d is less than largest Section point %d", numPoints, pEnd);
1894: for (p = pStart; p < pEnd; ++p) {
1895: PetscInt dof, cdof;
1897: PetscSectionGetDof(s, p, &dof);
1898: PetscSectionSetDof(sNew, perm[p], dof);
1899: PetscSectionGetConstraintDof(s, p, &cdof);
1900: if (cdof) {PetscSectionSetConstraintDof(sNew, perm[p], cdof);}
1901: for (f = 0; f < numFields; ++f) {
1902: PetscSectionGetFieldDof(s, p, f, &dof);
1903: PetscSectionSetFieldDof(sNew, perm[p], f, dof);
1904: PetscSectionGetFieldConstraintDof(s, p, f, &cdof);
1905: if (cdof) {PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof);}
1906: }
1907: }
1908: PetscSectionSetUp(sNew);
1909: for (p = pStart; p < pEnd; ++p) {
1910: const PetscInt *cind;
1911: PetscInt cdof;
1913: PetscSectionGetConstraintDof(s, p, &cdof);
1914: if (cdof) {
1915: PetscSectionGetConstraintIndices(s, p, &cind);
1916: PetscSectionSetConstraintIndices(sNew, perm[p], cind);
1917: }
1918: for (f = 0; f < numFields; ++f) {
1919: PetscSectionGetFieldConstraintDof(s, p, f, &cdof);
1920: if (cdof) {
1921: PetscSectionGetFieldConstraintIndices(s, p, f, &cind);
1922: PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind);
1923: }
1924: }
1925: }
1926: ISRestoreIndices(permutation, &perm);
1927: *sectionNew = sNew;
1928: return(0);
1929: }
1933: /*@C
1934: PetscSFDistributeSection - Create a new PetscSection reorganized, moving from the root to the leaves of the SF
1936: Collective
1938: Input Parameters:
1939: + sf - The SF
1940: - rootSection - Section defined on root space
1942: Output Parameters:
1943: + remoteOffsets - root offsets in leaf storage, or NULL
1944: - leafSection - Section defined on the leaf space
1946: Level: intermediate
1948: .seealso: PetscSFCreate()
1949: @*/
1950: PetscErrorCode PetscSFDistributeSection(PetscSF sf, PetscSection rootSection, PetscInt **remoteOffsets, PetscSection leafSection)
1951: {
1952: PetscSF embedSF;
1953: const PetscInt *ilocal, *indices;
1954: IS selected;
1955: PetscInt numFields, nroots, nleaves, rpStart, rpEnd, lpStart = PETSC_MAX_INT, lpEnd = -1, i, f;
1959: PetscSectionGetNumFields(rootSection, &numFields);
1960: if (numFields) {PetscSectionSetNumFields(leafSection, numFields);}
1961: for (f = 0; f < numFields; ++f) {
1962: PetscInt numComp = 0;
1963: PetscSectionGetFieldComponents(rootSection, f, &numComp);
1964: PetscSectionSetFieldComponents(leafSection, f, numComp);
1965: }
1966: PetscSectionGetChart(rootSection, &rpStart, &rpEnd);
1967: PetscSFGetGraph(sf,&nroots,NULL,NULL,NULL);
1968: rpEnd = PetscMin(rpEnd,nroots);
1969: rpEnd = PetscMax(rpStart,rpEnd);
1970: ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected);
1971: ISGetIndices(selected, &indices);
1972: PetscSFCreateEmbeddedSF(sf, rpEnd - rpStart, indices, &embedSF);
1973: ISRestoreIndices(selected, &indices);
1974: ISDestroy(&selected);
1975: PetscSFGetGraph(embedSF, NULL, &nleaves, &ilocal, NULL);
1976: if (nleaves && ilocal) {
1977: for (i = 0; i < nleaves; ++i) {
1978: lpStart = PetscMin(lpStart, ilocal[i]);
1979: lpEnd = PetscMax(lpEnd, ilocal[i]);
1980: }
1981: ++lpEnd;
1982: } else {
1983: lpStart = 0;
1984: lpEnd = nleaves;
1985: }
1986: PetscSectionSetChart(leafSection, lpStart, lpEnd);
1987: /* Could fuse these at the cost of a copy and extra allocation */
1988: PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart]);
1989: PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart]);
1990: for (f = 0; f < numFields; ++f) {
1991: PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart]);
1992: PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart]);
1993: }
1994: if (remoteOffsets) {
1995: PetscMalloc1(lpEnd - lpStart, remoteOffsets);
1996: PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
1997: PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
1998: }
1999: PetscSFDestroy(&embedSF);
2000: PetscSectionSetUp(leafSection);
2001: return(0);
2002: }
2006: PetscErrorCode PetscSFCreateRemoteOffsets(PetscSF sf, PetscSection rootSection, PetscSection leafSection, PetscInt **remoteOffsets)
2007: {
2008: PetscSF embedSF;
2009: const PetscInt *indices;
2010: IS selected;
2011: PetscInt numRoots, rpStart = 0, rpEnd = 0, lpStart = 0, lpEnd = 0;
2012: PetscErrorCode ierr;
2015: *remoteOffsets = NULL;
2016: PetscSFGetGraph(sf, &numRoots, NULL, NULL, NULL);
2017: if (numRoots < 0) return(0);
2018: PetscSectionGetChart(rootSection, &rpStart, &rpEnd);
2019: PetscSectionGetChart(leafSection, &lpStart, &lpEnd);
2020: ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected);
2021: ISGetIndices(selected, &indices);
2022: PetscSFCreateEmbeddedSF(sf, rpEnd - rpStart, indices, &embedSF);
2023: ISRestoreIndices(selected, &indices);
2024: ISDestroy(&selected);
2025: PetscCalloc1(lpEnd - lpStart, remoteOffsets);
2026: PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
2027: PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);
2028: PetscSFDestroy(&embedSF);
2029: return(0);
2030: }
2034: /*@C
2035: PetscSFCreateSectionSF - Create an expanded SF of dofs, assuming the input SF relates points
2037: Input Parameters:
2038: + sf - The SF
2039: . rootSection - Data layout of remote points for outgoing data (this is usually the serial section)
2040: . remoteOffsets - Offsets for point data on remote processes (these are offsets from the root section), or NULL
2041: - leafSection - Data layout of local points for incoming data (this is the distributed section)
2043: Output Parameters:
2044: - sectionSF - The new SF
2046: Note: Either rootSection or remoteOffsets can be specified
2048: Level: intermediate
2050: .seealso: PetscSFCreate()
2051: @*/
2052: PetscErrorCode PetscSFCreateSectionSF(PetscSF sf, PetscSection rootSection, PetscInt remoteOffsets[], PetscSection leafSection, PetscSF *sectionSF)
2053: {
2054: MPI_Comm comm;
2055: const PetscInt *localPoints;
2056: const PetscSFNode *remotePoints;
2057: PetscInt lpStart, lpEnd;
2058: PetscInt numRoots, numSectionRoots, numPoints, numIndices = 0;
2059: PetscInt *localIndices;
2060: PetscSFNode *remoteIndices;
2061: PetscInt i, ind;
2062: PetscErrorCode ierr;
2070: PetscObjectGetComm((PetscObject)sf,&comm);
2071: PetscSFCreate(comm, sectionSF);
2072: PetscSectionGetChart(leafSection, &lpStart, &lpEnd);
2073: PetscSectionGetStorageSize(rootSection, &numSectionRoots);
2074: PetscSFGetGraph(sf, &numRoots, &numPoints, &localPoints, &remotePoints);
2075: if (numRoots < 0) return(0);
2076: for (i = 0; i < numPoints; ++i) {
2077: PetscInt localPoint = localPoints ? localPoints[i] : i;
2078: PetscInt dof;
2080: if ((localPoint >= lpStart) && (localPoint < lpEnd)) {
2081: PetscSectionGetDof(leafSection, localPoint, &dof);
2082: numIndices += dof;
2083: }
2084: }
2085: PetscMalloc1(numIndices, &localIndices);
2086: PetscMalloc1(numIndices, &remoteIndices);
2087: /* Create new index graph */
2088: for (i = 0, ind = 0; i < numPoints; ++i) {
2089: PetscInt localPoint = localPoints ? localPoints[i] : i;
2090: PetscInt rank = remotePoints[i].rank;
2092: if ((localPoint >= lpStart) && (localPoint < lpEnd)) {
2093: PetscInt remoteOffset = remoteOffsets[localPoint-lpStart];
2094: PetscInt loff, dof, d;
2096: PetscSectionGetOffset(leafSection, localPoint, &loff);
2097: PetscSectionGetDof(leafSection, localPoint, &dof);
2098: for (d = 0; d < dof; ++d, ++ind) {
2099: localIndices[ind] = loff+d;
2100: remoteIndices[ind].rank = rank;
2101: remoteIndices[ind].index = remoteOffset+d;
2102: }
2103: }
2104: }
2105: if (numIndices != ind) SETERRQ2(comm, PETSC_ERR_PLIB, "Inconsistency in indices, %d should be %d", ind, numIndices);
2106: PetscSFSetGraph(*sectionSF, numSectionRoots, numIndices, localIndices, PETSC_OWN_POINTER, remoteIndices, PETSC_OWN_POINTER);
2107: return(0);
2108: }
2112: /*@
2113: PetscSectionSetClosureIndex - Set a cache of points in the closure of each point in the section
2115: Input Parameters:
2116: + section - The PetscSection
2117: . obj - A PetscObject which serves as the key for this index
2118: . clSection - Section giving the size of the closure of each point
2119: - clPoints - IS giving the points in each closure
2121: Note: We compress out closure points with no dofs in this section
2123: Level: intermediate
2125: .seealso: PetscSectionGetClosureIndex(), DMPlexCreateClosureIndex()
2126: @*/
2127: PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints)
2128: {
2132: section->clObj = obj;
2133: PetscSectionDestroy(§ion->clSection);
2134: ISDestroy(§ion->clPoints);
2135: section->clSection = clSection;
2136: section->clPoints = clPoints;
2137: return(0);
2138: }
2142: /*@
2143: PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section
2145: Input Parameters:
2146: + section - The PetscSection
2147: - obj - A PetscObject which serves as the key for this index
2149: Output Parameters:
2150: + clSection - Section giving the size of the closure of each point
2151: - clPoints - IS giving the points in each closure
2153: Note: We compress out closure points with no dofs in this section
2155: Level: intermediate
2157: .seealso: PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex()
2158: @*/
2159: PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints)
2160: {
2162: if (section->clObj == obj) {
2163: if (clSection) *clSection = section->clSection;
2164: if (clPoints) *clPoints = section->clPoints;
2165: } else {
2166: if (clSection) *clSection = NULL;
2167: if (clPoints) *clPoints = NULL;
2168: }
2169: return(0);
2170: }
2174: /*@
2175: PetscSectionGetField - Get the subsection associated with a single field
2177: Input Parameters:
2178: + s - The PetscSection
2179: - field - The field number
2181: Output Parameter:
2182: . subs - The subsection for the given field
2184: Level: intermediate
2186: .seealso: PetscSectionSetNumFields()
2187: @*/
2188: PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs)
2189: {
2195: if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, s->numFields);
2196: PetscObjectReference((PetscObject) s->field[field]);
2197: *subs = s->field[field];
2198: return(0);
2199: }