Actual source code: dmlabel.c
1: #include <petscdm.h>
2: #include <petsc/private/dmlabelimpl.h>
3: #include <petsc/private/sectionimpl.h>
4: #include <petscsf.h>
5: #include <petscsection.h>
7: PetscFunctionList DMLabelList = NULL;
8: PetscBool DMLabelRegisterAllCalled = PETSC_FALSE;
10: /*@C
11: DMLabelCreate - Create a DMLabel object, which is a multimap
13: Collective
15: Input parameters:
16: + comm - The communicator, usually PETSC_COMM_SELF
17: - name - The label name
19: Output parameter:
20: . label - The DMLabel
22: Level: beginner
24: Notes:
25: The label name is actually usual PetscObject name.
26: One can get/set it with PetscObjectGetName()/PetscObjectSetName().
28: .seealso: `DMLabelDestroy()`
29: @*/
30: PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
31: {
32: PetscFunctionBegin;
34: PetscCall(DMInitializePackage());
36: PetscCall(PetscHeaderCreate(*label, DMLABEL_CLASSID, "DMLabel", "DMLabel", "DM", comm, DMLabelDestroy, DMLabelView));
38: (*label)->numStrata = 0;
39: (*label)->defaultValue = -1;
40: (*label)->stratumValues = NULL;
41: (*label)->validIS = NULL;
42: (*label)->stratumSizes = NULL;
43: (*label)->points = NULL;
44: (*label)->ht = NULL;
45: (*label)->pStart = -1;
46: (*label)->pEnd = -1;
47: (*label)->bt = NULL;
48: PetscCall(PetscHMapICreate(&(*label)->hmap));
49: PetscCall(PetscObjectSetName((PetscObject)*label, name));
50: PetscCall(DMLabelSetType(*label, DMLABELCONCRETE));
51: PetscFunctionReturn(PETSC_SUCCESS);
52: }
54: /*@C
55: DMLabelSetUp - SetUp a `DMLabel` object
57: Collective
59: Input parameters:
60: . label - The `DMLabel`
62: Level: intermediate
64: .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
65: @*/
66: PetscErrorCode DMLabelSetUp(DMLabel label)
67: {
68: PetscFunctionBegin;
70: PetscTryTypeMethod(label, setup);
71: PetscFunctionReturn(PETSC_SUCCESS);
72: }
74: /*
75: DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
77: Not collective
79: Input parameter:
80: + label - The DMLabel
81: - v - The stratum value
83: Output parameter:
84: . label - The DMLabel with stratum in sorted list format
86: Level: developer
88: .seealso: `DMLabelCreate()`
89: */
90: static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
91: {
92: IS is;
93: PetscInt off = 0, *pointArray, p;
95: if ((PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) || label->readonly) return PETSC_SUCCESS;
96: PetscFunctionBegin;
97: PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeValid_Private", v);
98: PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
99: PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
100: PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
101: PetscCall(PetscHSetIClear(label->ht[v]));
102: PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
103: if (label->bt) {
104: for (p = 0; p < label->stratumSizes[v]; ++p) {
105: const PetscInt point = pointArray[p];
106: PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
107: PetscCall(PetscBTSet(label->bt, point - label->pStart));
108: }
109: }
110: if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
111: PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
112: PetscCall(PetscFree(pointArray));
113: } else {
114: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
115: }
116: PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
117: label->points[v] = is;
118: label->validIS[v] = PETSC_TRUE;
119: PetscCall(PetscObjectStateIncrease((PetscObject)label));
120: PetscFunctionReturn(PETSC_SUCCESS);
121: }
123: /*
124: DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
126: Not collective
128: Input parameter:
129: . label - The DMLabel
131: Output parameter:
132: . label - The DMLabel with all strata in sorted list format
134: Level: developer
136: .seealso: `DMLabelCreate()`
137: */
138: static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
139: {
140: PetscInt v;
142: PetscFunctionBegin;
143: for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeValid_Private(label, v));
144: PetscFunctionReturn(PETSC_SUCCESS);
145: }
147: /*
148: DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
150: Not collective
152: Input parameter:
153: + label - The DMLabel
154: - v - The stratum value
156: Output parameter:
157: . label - The DMLabel with stratum in hash format
159: Level: developer
161: .seealso: `DMLabelCreate()`
162: */
163: static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
164: {
165: PetscInt p;
166: const PetscInt *points;
168: if ((PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) || label->readonly) return PETSC_SUCCESS;
169: PetscFunctionBegin;
170: PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeInvalid_Private", v);
171: if (label->points[v]) {
172: PetscCall(ISGetIndices(label->points[v], &points));
173: for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
174: PetscCall(ISRestoreIndices(label->points[v], &points));
175: PetscCall(ISDestroy(&(label->points[v])));
176: }
177: label->validIS[v] = PETSC_FALSE;
178: PetscFunctionReturn(PETSC_SUCCESS);
179: }
181: PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label)
182: {
183: PetscInt v;
185: PetscFunctionBegin;
186: for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeInvalid_Private(label, v));
187: PetscFunctionReturn(PETSC_SUCCESS);
188: }
190: #if !defined(DMLABEL_LOOKUP_THRESHOLD)
191: #define DMLABEL_LOOKUP_THRESHOLD 16
192: #endif
194: PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
195: {
196: PetscInt v;
198: PetscFunctionBegin;
199: *index = -1;
200: if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD || label->readonly) {
201: for (v = 0; v < label->numStrata; ++v)
202: if (label->stratumValues[v] == value) {
203: *index = v;
204: break;
205: }
206: } else {
207: PetscCall(PetscHMapIGet(label->hmap, value, index));
208: }
209: if (PetscDefined(USE_DEBUG) && !label->readonly) { /* Check strata hash map consistency */
210: PetscInt len, loc = -1;
211: PetscCall(PetscHMapIGetSize(label->hmap, &len));
212: PetscCheck(len == label->numStrata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
213: if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
214: PetscCall(PetscHMapIGet(label->hmap, value, &loc));
215: } else {
216: for (v = 0; v < label->numStrata; ++v)
217: if (label->stratumValues[v] == value) {
218: loc = v;
219: break;
220: }
221: }
222: PetscCheck(loc == *index, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
223: }
224: PetscFunctionReturn(PETSC_SUCCESS);
225: }
227: static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
228: {
229: PetscInt v;
230: PetscInt *tmpV;
231: PetscInt *tmpS;
232: PetscHSetI *tmpH, ht;
233: IS *tmpP, is;
234: PetscBool *tmpB;
235: PetscHMapI hmap = label->hmap;
237: PetscFunctionBegin;
238: v = label->numStrata;
239: tmpV = label->stratumValues;
240: tmpS = label->stratumSizes;
241: tmpH = label->ht;
242: tmpP = label->points;
243: tmpB = label->validIS;
244: { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free */
245: PetscInt *oldV = tmpV;
246: PetscInt *oldS = tmpS;
247: PetscHSetI *oldH = tmpH;
248: IS *oldP = tmpP;
249: PetscBool *oldB = tmpB;
250: PetscCall(PetscMalloc((v + 1) * sizeof(*tmpV), &tmpV));
251: PetscCall(PetscMalloc((v + 1) * sizeof(*tmpS), &tmpS));
252: PetscCall(PetscCalloc((v + 1) * sizeof(*tmpH), &tmpH));
253: PetscCall(PetscCalloc((v + 1) * sizeof(*tmpP), &tmpP));
254: PetscCall(PetscMalloc((v + 1) * sizeof(*tmpB), &tmpB));
255: PetscCall(PetscArraycpy(tmpV, oldV, v));
256: PetscCall(PetscArraycpy(tmpS, oldS, v));
257: PetscCall(PetscArraycpy(tmpH, oldH, v));
258: PetscCall(PetscArraycpy(tmpP, oldP, v));
259: PetscCall(PetscArraycpy(tmpB, oldB, v));
260: PetscCall(PetscFree(oldV));
261: PetscCall(PetscFree(oldS));
262: PetscCall(PetscFree(oldH));
263: PetscCall(PetscFree(oldP));
264: PetscCall(PetscFree(oldB));
265: }
266: label->numStrata = v + 1;
267: label->stratumValues = tmpV;
268: label->stratumSizes = tmpS;
269: label->ht = tmpH;
270: label->points = tmpP;
271: label->validIS = tmpB;
272: PetscCall(PetscHSetICreate(&ht));
273: PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
274: PetscCall(PetscHMapISet(hmap, value, v));
275: tmpV[v] = value;
276: tmpS[v] = 0;
277: tmpH[v] = ht;
278: tmpP[v] = is;
279: tmpB[v] = PETSC_TRUE;
280: PetscCall(PetscObjectStateIncrease((PetscObject)label));
281: *index = v;
282: PetscFunctionReturn(PETSC_SUCCESS);
283: }
285: static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
286: {
287: PetscFunctionBegin;
288: PetscCall(DMLabelLookupStratum(label, value, index));
289: if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
290: PetscFunctionReturn(PETSC_SUCCESS);
291: }
293: PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
294: {
295: PetscFunctionBegin;
296: *size = 0;
297: if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
298: if (label->readonly || label->validIS[v]) {
299: *size = label->stratumSizes[v];
300: } else {
301: PetscCall(PetscHSetIGetSize(label->ht[v], size));
302: }
303: PetscFunctionReturn(PETSC_SUCCESS);
304: }
306: /*@
307: DMLabelAddStratum - Adds a new stratum value in a DMLabel
309: Input Parameters:
310: + label - The DMLabel
311: - value - The stratum value
313: Level: beginner
315: .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
316: @*/
317: PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
318: {
319: PetscInt v;
321: PetscFunctionBegin;
323: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
324: PetscCall(DMLabelLookupAddStratum(label, value, &v));
325: PetscFunctionReturn(PETSC_SUCCESS);
326: }
328: /*@
329: DMLabelAddStrata - Adds new stratum values in a DMLabel
331: Not collective
333: Input Parameters:
334: + label - The DMLabel
335: . numStrata - The number of stratum values
336: - stratumValues - The stratum values
338: Level: beginner
340: .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
341: @*/
342: PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
343: {
344: PetscInt *values, v;
346: PetscFunctionBegin;
349: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
350: PetscCall(PetscMalloc1(numStrata, &values));
351: PetscCall(PetscArraycpy(values, stratumValues, numStrata));
352: PetscCall(PetscSortRemoveDupsInt(&numStrata, values));
353: if (!label->numStrata) { /* Fast preallocation */
354: PetscInt *tmpV;
355: PetscInt *tmpS;
356: PetscHSetI *tmpH, ht;
357: IS *tmpP, is;
358: PetscBool *tmpB;
359: PetscHMapI hmap = label->hmap;
361: PetscCall(PetscMalloc1(numStrata, &tmpV));
362: PetscCall(PetscMalloc1(numStrata, &tmpS));
363: PetscCall(PetscCalloc1(numStrata, &tmpH));
364: PetscCall(PetscCalloc1(numStrata, &tmpP));
365: PetscCall(PetscMalloc1(numStrata, &tmpB));
366: label->numStrata = numStrata;
367: label->stratumValues = tmpV;
368: label->stratumSizes = tmpS;
369: label->ht = tmpH;
370: label->points = tmpP;
371: label->validIS = tmpB;
372: for (v = 0; v < numStrata; ++v) {
373: PetscCall(PetscHSetICreate(&ht));
374: PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
375: PetscCall(PetscHMapISet(hmap, values[v], v));
376: tmpV[v] = values[v];
377: tmpS[v] = 0;
378: tmpH[v] = ht;
379: tmpP[v] = is;
380: tmpB[v] = PETSC_TRUE;
381: }
382: PetscCall(PetscObjectStateIncrease((PetscObject)label));
383: } else {
384: for (v = 0; v < numStrata; ++v) PetscCall(DMLabelAddStratum(label, values[v]));
385: }
386: PetscCall(PetscFree(values));
387: PetscFunctionReturn(PETSC_SUCCESS);
388: }
390: /*@
391: DMLabelAddStrataIS - Adds new stratum values in a DMLabel
393: Not collective
395: Input Parameters:
396: + label - The DMLabel
397: - valueIS - Index set with stratum values
399: Level: beginner
401: .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
402: @*/
403: PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
404: {
405: PetscInt numStrata;
406: const PetscInt *stratumValues;
408: PetscFunctionBegin;
411: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
412: PetscCall(ISGetLocalSize(valueIS, &numStrata));
413: PetscCall(ISGetIndices(valueIS, &stratumValues));
414: PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
415: PetscFunctionReturn(PETSC_SUCCESS);
416: }
418: static PetscErrorCode DMLabelView_Concrete_Ascii(DMLabel label, PetscViewer viewer)
419: {
420: PetscInt v;
421: PetscMPIInt rank;
423: PetscFunctionBegin;
424: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
425: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
426: if (label) {
427: const char *name;
429: PetscCall(PetscObjectGetName((PetscObject)label, &name));
430: PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
431: if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, " Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
432: for (v = 0; v < label->numStrata; ++v) {
433: const PetscInt value = label->stratumValues[v];
434: const PetscInt *points;
435: PetscInt p;
437: PetscCall(ISGetIndices(label->points[v], &points));
438: for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
439: PetscCall(ISRestoreIndices(label->points[v], &points));
440: }
441: }
442: PetscCall(PetscViewerFlush(viewer));
443: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
444: PetscFunctionReturn(PETSC_SUCCESS);
445: }
447: PetscErrorCode DMLabelView_Concrete(DMLabel label, PetscViewer viewer)
448: {
449: PetscBool iascii;
451: PetscFunctionBegin;
452: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
453: if (iascii) PetscCall(DMLabelView_Concrete_Ascii(label, viewer));
454: PetscFunctionReturn(PETSC_SUCCESS);
455: }
457: /*@C
458: DMLabelView - View the label
460: Collective on viewer
462: Input Parameters:
463: + label - The DMLabel
464: - viewer - The PetscViewer
466: Level: intermediate
468: .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
469: @*/
470: PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
471: {
472: PetscFunctionBegin;
474: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
476: PetscCall(DMLabelMakeAllValid_Private(label));
477: PetscUseTypeMethod(label, view, viewer);
478: PetscFunctionReturn(PETSC_SUCCESS);
479: }
481: /*@
482: DMLabelReset - Destroys internal data structures in a DMLabel
484: Not collective
486: Input Parameter:
487: . label - The DMLabel
489: Level: beginner
491: .seealso: `DMLabelDestroy()`, `DMLabelCreate()`
492: @*/
493: PetscErrorCode DMLabelReset(DMLabel label)
494: {
495: PetscInt v;
497: PetscFunctionBegin;
499: for (v = 0; v < label->numStrata; ++v) {
500: if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
501: PetscCall(ISDestroy(&label->points[v]));
502: }
503: label->numStrata = 0;
504: PetscCall(PetscFree(label->stratumValues));
505: PetscCall(PetscFree(label->stratumSizes));
506: PetscCall(PetscFree(label->ht));
507: PetscCall(PetscFree(label->points));
508: PetscCall(PetscFree(label->validIS));
509: label->stratumValues = NULL;
510: label->stratumSizes = NULL;
511: label->ht = NULL;
512: label->points = NULL;
513: label->validIS = NULL;
514: PetscCall(PetscHMapIReset(label->hmap));
515: label->pStart = -1;
516: label->pEnd = -1;
517: PetscCall(PetscBTDestroy(&label->bt));
518: PetscFunctionReturn(PETSC_SUCCESS);
519: }
521: /*@
522: DMLabelDestroy - Destroys a DMLabel
524: Collective on label
526: Input Parameter:
527: . label - The DMLabel
529: Level: beginner
531: .seealso: `DMLabelReset()`, `DMLabelCreate()`
532: @*/
533: PetscErrorCode DMLabelDestroy(DMLabel *label)
534: {
535: PetscFunctionBegin;
536: if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
538: if (--((PetscObject)(*label))->refct > 0) {
539: *label = NULL;
540: PetscFunctionReturn(PETSC_SUCCESS);
541: }
542: PetscCall(DMLabelReset(*label));
543: PetscCall(PetscHMapIDestroy(&(*label)->hmap));
544: PetscCall(PetscHeaderDestroy(label));
545: PetscFunctionReturn(PETSC_SUCCESS);
546: }
548: PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
549: {
550: PetscFunctionBegin;
551: for (PetscInt v = 0; v < label->numStrata; ++v) {
552: PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
553: PetscCall(PetscObjectReference((PetscObject)(label->points[v])));
554: (*labelnew)->points[v] = label->points[v];
555: }
556: PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
557: PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
558: PetscFunctionReturn(PETSC_SUCCESS);
559: }
561: /*@
562: DMLabelDuplicate - Duplicates a DMLabel
564: Collective on label
566: Input Parameter:
567: . label - The DMLabel
569: Output Parameter:
570: . labelnew - location to put new vector
572: Level: intermediate
574: .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
575: @*/
576: PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
577: {
578: const char *name;
580: PetscFunctionBegin;
582: PetscCall(DMLabelMakeAllValid_Private(label));
583: PetscCall(PetscObjectGetName((PetscObject)label, &name));
584: PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
586: (*labelnew)->numStrata = label->numStrata;
587: (*labelnew)->defaultValue = label->defaultValue;
588: PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
589: PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
590: PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
591: PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
592: PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
593: for (PetscInt v = 0; v < label->numStrata; ++v) {
594: (*labelnew)->stratumValues[v] = label->stratumValues[v];
595: (*labelnew)->stratumSizes[v] = label->stratumSizes[v];
596: (*labelnew)->validIS[v] = PETSC_TRUE;
597: }
598: (*labelnew)->pStart = -1;
599: (*labelnew)->pEnd = -1;
600: (*labelnew)->bt = NULL;
601: PetscUseTypeMethod(label, duplicate, labelnew);
602: PetscFunctionReturn(PETSC_SUCCESS);
603: }
605: /*@C
606: DMLabelCompare - Compare two DMLabel objects
608: Collective on comm
610: Input Parameters:
611: + comm - Comm over which to compare labels
612: . l0 - First DMLabel
613: - l1 - Second DMLabel
615: Output Parameters
616: + equal - (Optional) Flag whether the two labels are equal
617: - message - (Optional) Message describing the difference
619: Level: intermediate
621: Notes:
622: The output flag equal is the same on all processes.
623: If it is passed as NULL and difference is found, an error is thrown on all processes.
624: Make sure to pass NULL on all processes.
626: The output message is set independently on each rank.
627: It is set to NULL if no difference was found on the current rank. It must be freed by user.
628: If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
629: Make sure to pass NULL on all processes.
631: For the comparison, we ignore the order of stratum values, and strata with no points.
633: The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
635: Fortran Notes:
636: This function is currently not available from Fortran.
638: .seealso: `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
639: @*/
640: PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
641: {
642: const char *name0, *name1;
643: char msg[PETSC_MAX_PATH_LEN] = "";
644: PetscBool eq;
645: PetscMPIInt rank;
647: PetscFunctionBegin;
652: PetscCallMPI(MPI_Comm_rank(comm, &rank));
653: PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
654: PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
655: {
656: PetscInt v0, v1;
658: PetscCall(DMLabelGetDefaultValue(l0, &v0));
659: PetscCall(DMLabelGetDefaultValue(l1, &v1));
660: eq = (PetscBool)(v0 == v1);
661: if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %" PetscInt_FMT " != %" PetscInt_FMT " = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
662: PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
663: if (!eq) goto finish;
664: }
665: {
666: IS is0, is1;
668: PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
669: PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
670: PetscCall(ISEqual(is0, is1, &eq));
671: PetscCall(ISDestroy(&is0));
672: PetscCall(ISDestroy(&is1));
673: if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
674: PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
675: if (!eq) goto finish;
676: }
677: {
678: PetscInt i, nValues;
680: PetscCall(DMLabelGetNumValues(l0, &nValues));
681: for (i = 0; i < nValues; i++) {
682: const PetscInt v = l0->stratumValues[i];
683: PetscInt n;
684: IS is0, is1;
686: PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
687: if (!n) continue;
688: PetscCall(DMLabelGetStratumIS(l0, v, &is0));
689: PetscCall(DMLabelGetStratumIS(l1, v, &is1));
690: PetscCall(ISEqualUnsorted(is0, is1, &eq));
691: PetscCall(ISDestroy(&is0));
692: PetscCall(ISDestroy(&is1));
693: if (!eq) {
694: PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum #%" PetscInt_FMT " with value %" PetscInt_FMT " contains different points in DMLabel l0 \"%s\" and DMLabel l1 \"%s\"", i, v, name0, name1));
695: break;
696: }
697: }
698: PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
699: }
700: finish:
701: /* If message output arg not set, print to stderr */
702: if (message) {
703: *message = NULL;
704: if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
705: } else {
706: if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
707: PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
708: }
709: /* If same output arg not ser and labels are not equal, throw error */
710: if (equal) *equal = eq;
711: else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
712: PetscFunctionReturn(PETSC_SUCCESS);
713: }
715: /*@
716: DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
718: Not collective
720: Input Parameter:
721: . label - The DMLabel
723: Level: intermediate
725: .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
726: @*/
727: PetscErrorCode DMLabelComputeIndex(DMLabel label)
728: {
729: PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v;
731: PetscFunctionBegin;
733: PetscCall(DMLabelMakeAllValid_Private(label));
734: for (v = 0; v < label->numStrata; ++v) {
735: const PetscInt *points;
736: PetscInt i;
738: PetscCall(ISGetIndices(label->points[v], &points));
739: for (i = 0; i < label->stratumSizes[v]; ++i) {
740: const PetscInt point = points[i];
742: pStart = PetscMin(point, pStart);
743: pEnd = PetscMax(point + 1, pEnd);
744: }
745: PetscCall(ISRestoreIndices(label->points[v], &points));
746: }
747: label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
748: label->pEnd = pEnd;
749: PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
750: PetscFunctionReturn(PETSC_SUCCESS);
751: }
753: /*@
754: DMLabelCreateIndex - Create an index structure for membership determination
756: Not collective
758: Input Parameters:
759: + label - The DMLabel
760: . pStart - The smallest point
761: - pEnd - The largest point + 1
763: Level: intermediate
765: .seealso: `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
766: @*/
767: PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
768: {
769: PetscInt v;
771: PetscFunctionBegin;
773: PetscCall(DMLabelDestroyIndex(label));
774: PetscCall(DMLabelMakeAllValid_Private(label));
775: label->pStart = pStart;
776: label->pEnd = pEnd;
777: /* This can be hooked into SetValue(), ClearValue(), etc. for updating */
778: PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
779: for (v = 0; v < label->numStrata; ++v) {
780: IS pointIS;
781: const PetscInt *points;
782: PetscInt i;
784: PetscUseTypeMethod(label, getstratumis, v, &pointIS);
785: PetscCall(ISGetIndices(pointIS, &points));
786: for (i = 0; i < label->stratumSizes[v]; ++i) {
787: const PetscInt point = points[i];
789: PetscCheck(!(point < pStart) && !(point >= pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " in stratum %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->stratumValues[v], pStart, pEnd);
790: PetscCall(PetscBTSet(label->bt, point - pStart));
791: }
792: PetscCall(ISRestoreIndices(label->points[v], &points));
793: PetscCall(ISDestroy(&pointIS));
794: }
795: PetscFunctionReturn(PETSC_SUCCESS);
796: }
798: /*@
799: DMLabelDestroyIndex - Destroy the index structure
801: Not collective
803: Input Parameter:
804: . label - the DMLabel
806: Level: intermediate
808: .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
809: @*/
810: PetscErrorCode DMLabelDestroyIndex(DMLabel label)
811: {
812: PetscFunctionBegin;
814: label->pStart = -1;
815: label->pEnd = -1;
816: PetscCall(PetscBTDestroy(&label->bt));
817: PetscFunctionReturn(PETSC_SUCCESS);
818: }
820: /*@
821: DMLabelGetBounds - Return the smallest and largest point in the label
823: Not collective
825: Input Parameter:
826: . label - the DMLabel
828: Output Parameters:
829: + pStart - The smallest point
830: - pEnd - The largest point + 1
832: Note: This will compute an index for the label if one does not exist.
834: Level: intermediate
836: .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
837: @*/
838: PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
839: {
840: PetscFunctionBegin;
842: if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
843: if (pStart) {
845: *pStart = label->pStart;
846: }
847: if (pEnd) {
849: *pEnd = label->pEnd;
850: }
851: PetscFunctionReturn(PETSC_SUCCESS);
852: }
854: /*@
855: DMLabelHasValue - Determine whether a label assigns the value to any point
857: Not collective
859: Input Parameters:
860: + label - the DMLabel
861: - value - the value
863: Output Parameter:
864: . contains - Flag indicating whether the label maps this value to any point
866: Level: developer
868: .seealso: `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
869: @*/
870: PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
871: {
872: PetscInt v;
874: PetscFunctionBegin;
877: PetscCall(DMLabelLookupStratum(label, value, &v));
878: *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
879: PetscFunctionReturn(PETSC_SUCCESS);
880: }
882: /*@
883: DMLabelHasPoint - Determine whether a label assigns a value to a point
885: Not collective
887: Input Parameters:
888: + label - the DMLabel
889: - point - the point
891: Output Parameter:
892: . contains - Flag indicating whether the label maps this point to a value
894: Note: The user must call DMLabelCreateIndex() before this function.
896: Level: developer
898: .seealso: `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
899: @*/
900: PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
901: {
902: PetscFunctionBeginHot;
905: PetscCall(DMLabelMakeAllValid_Private(label));
906: if (PetscDefined(USE_DEBUG)) {
907: PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
908: PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
909: }
910: *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
911: PetscFunctionReturn(PETSC_SUCCESS);
912: }
914: /*@
915: DMLabelStratumHasPoint - Return true if the stratum contains a point
917: Not collective
919: Input Parameters:
920: + label - the DMLabel
921: . value - the stratum value
922: - point - the point
924: Output Parameter:
925: . contains - true if the stratum contains the point
927: Level: intermediate
929: .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
930: @*/
931: PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
932: {
933: PetscFunctionBeginHot;
936: if (value == label->defaultValue) {
937: PetscInt pointVal;
939: PetscCall(DMLabelGetValue(label, point, &pointVal));
940: *contains = (PetscBool)(pointVal == value);
941: } else {
942: PetscInt v;
944: PetscCall(DMLabelLookupStratum(label, value, &v));
945: if (v >= 0) {
946: if (label->validIS[v] || label->readonly) {
947: IS is;
948: PetscInt i;
950: PetscUseTypeMethod(label, getstratumis, v, &is);
951: PetscCall(ISLocate(is, point, &i));
952: PetscCall(ISDestroy(&is));
953: *contains = (PetscBool)(i >= 0);
954: } else {
955: PetscCall(PetscHSetIHas(label->ht[v], point, contains));
956: }
957: } else { // value is not present
958: *contains = PETSC_FALSE;
959: }
960: }
961: PetscFunctionReturn(PETSC_SUCCESS);
962: }
964: /*@
965: DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
966: When a label is created, it is initialized to -1.
968: Not collective
970: Input parameter:
971: . label - a DMLabel object
973: Output parameter:
974: . defaultValue - the default value
976: Level: beginner
978: .seealso: `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
979: @*/
980: PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
981: {
982: PetscFunctionBegin;
984: *defaultValue = label->defaultValue;
985: PetscFunctionReturn(PETSC_SUCCESS);
986: }
988: /*@
989: DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
990: When a label is created, it is initialized to -1.
992: Not collective
994: Input parameter:
995: . label - a DMLabel object
997: Output parameter:
998: . defaultValue - the default value
1000: Level: beginner
1002: .seealso: `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1003: @*/
1004: PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1005: {
1006: PetscFunctionBegin;
1008: label->defaultValue = defaultValue;
1009: PetscFunctionReturn(PETSC_SUCCESS);
1010: }
1012: /*@
1013: DMLabelGetValue - Return the value a label assigns to a point, or the label's default value (which is initially -1, and can be changed with DMLabelSetDefaultValue())
1015: Not collective
1017: Input Parameters:
1018: + label - the DMLabel
1019: - point - the point
1021: Output Parameter:
1022: . value - The point value, or the default value (-1 by default)
1024: Note: a label may assign multiple values to a point. No guarantees are made about which value is returned in that case. Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
1026: Level: intermediate
1028: .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1029: @*/
1030: PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1031: {
1032: PetscInt v;
1034: PetscFunctionBeginHot;
1037: *value = label->defaultValue;
1038: for (v = 0; v < label->numStrata; ++v) {
1039: if (label->validIS[v] || label->readonly) {
1040: IS is;
1041: PetscInt i;
1043: PetscUseTypeMethod(label, getstratumis, v, &is);
1044: PetscCall(ISLocate(label->points[v], point, &i));
1045: PetscCall(ISDestroy(&is));
1046: if (i >= 0) {
1047: *value = label->stratumValues[v];
1048: break;
1049: }
1050: } else {
1051: PetscBool has;
1053: PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1054: if (has) {
1055: *value = label->stratumValues[v];
1056: break;
1057: }
1058: }
1059: }
1060: PetscFunctionReturn(PETSC_SUCCESS);
1061: }
1063: /*@
1064: DMLabelSetValue - Set the value a label assigns to a point. If the value is the same as the label's default value (which is initially -1, and can be changed with DMLabelSetDefaultValue() to something different), then this function will do nothing.
1066: Not collective
1068: Input Parameters:
1069: + label - the DMLabel
1070: . point - the point
1071: - value - The point value
1073: Level: intermediate
1075: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1076: @*/
1077: PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1078: {
1079: PetscInt v;
1081: PetscFunctionBegin;
1083: /* Find label value, add new entry if needed */
1084: if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
1085: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1086: PetscCall(DMLabelLookupAddStratum(label, value, &v));
1087: /* Set key */
1088: PetscCall(DMLabelMakeInvalid_Private(label, v));
1089: PetscCall(PetscHSetIAdd(label->ht[v], point));
1090: PetscFunctionReturn(PETSC_SUCCESS);
1091: }
1093: /*@
1094: DMLabelClearValue - Clear the value a label assigns to a point
1096: Not collective
1098: Input Parameters:
1099: + label - the DMLabel
1100: . point - the point
1101: - value - The point value
1103: Level: intermediate
1105: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1106: @*/
1107: PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1108: {
1109: PetscInt v;
1111: PetscFunctionBegin;
1113: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1114: /* Find label value */
1115: PetscCall(DMLabelLookupStratum(label, value, &v));
1116: if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
1118: if (label->bt) {
1119: PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
1120: PetscCall(PetscBTClear(label->bt, point - label->pStart));
1121: }
1123: /* Delete key */
1124: PetscCall(DMLabelMakeInvalid_Private(label, v));
1125: PetscCall(PetscHSetIDel(label->ht[v], point));
1126: PetscFunctionReturn(PETSC_SUCCESS);
1127: }
1129: /*@
1130: DMLabelInsertIS - Set all points in the IS to a value
1132: Not collective
1134: Input Parameters:
1135: + label - the DMLabel
1136: . is - the point IS
1137: - value - The point value
1139: Level: intermediate
1141: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1142: @*/
1143: PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1144: {
1145: PetscInt v, n, p;
1146: const PetscInt *points;
1148: PetscFunctionBegin;
1151: /* Find label value, add new entry if needed */
1152: if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
1153: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1154: PetscCall(DMLabelLookupAddStratum(label, value, &v));
1155: /* Set keys */
1156: PetscCall(DMLabelMakeInvalid_Private(label, v));
1157: PetscCall(ISGetLocalSize(is, &n));
1158: PetscCall(ISGetIndices(is, &points));
1159: for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
1160: PetscCall(ISRestoreIndices(is, &points));
1161: PetscFunctionReturn(PETSC_SUCCESS);
1162: }
1164: /*@
1165: DMLabelGetNumValues - Get the number of values that the DMLabel takes
1167: Not collective
1169: Input Parameter:
1170: . label - the DMLabel
1172: Output Parameter:
1173: . numValues - the number of values
1175: Level: intermediate
1177: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1178: @*/
1179: PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1180: {
1181: PetscFunctionBegin;
1184: *numValues = label->numStrata;
1185: PetscFunctionReturn(PETSC_SUCCESS);
1186: }
1188: /*@
1189: DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
1191: Not collective
1193: Input Parameter:
1194: . label - the DMLabel
1196: Output Parameter:
1197: . is - the value IS
1199: Level: intermediate
1201: Notes:
1202: The output IS should be destroyed when no longer needed.
1203: Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
1204: If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
1206: .seealso: `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1207: @*/
1208: PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1209: {
1210: PetscFunctionBegin;
1213: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1214: PetscFunctionReturn(PETSC_SUCCESS);
1215: }
1217: /*@
1218: DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
1220: Not collective
1222: Input Parameter:
1223: . label - the DMLabel
1225: Output Parameter:
1226: . is - the value IS
1228: Level: intermediate
1230: Notes:
1231: The output IS should be destroyed when no longer needed.
1232: This is similar to DMLabelGetValueIS() but counts only nonempty strata.
1234: .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1235: @*/
1236: PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1237: {
1238: PetscInt i, j;
1239: PetscInt *valuesArr;
1241: PetscFunctionBegin;
1244: PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
1245: for (i = 0, j = 0; i < label->numStrata; i++) {
1246: PetscInt n;
1248: PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
1249: if (n) valuesArr[j++] = label->stratumValues[i];
1250: }
1251: if (j == label->numStrata) {
1252: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1253: } else {
1254: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
1255: }
1256: PetscCall(PetscFree(valuesArr));
1257: PetscFunctionReturn(PETSC_SUCCESS);
1258: }
1260: /*@
1261: DMLabelGetValueIndex - Get the index of a given value in the list of values for the DMlabel, or -1 if it is not present
1263: Not collective
1265: Input Parameters:
1266: + label - the DMLabel
1267: - value - the value
1269: Output Parameter:
1270: . index - the index of value in the list of values
1272: Level: intermediate
1274: .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1275: @*/
1276: PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1277: {
1278: PetscInt v;
1280: PetscFunctionBegin;
1283: /* Do not assume they are sorted */
1284: for (v = 0; v < label->numStrata; ++v)
1285: if (label->stratumValues[v] == value) break;
1286: if (v >= label->numStrata) *index = -1;
1287: else *index = v;
1288: PetscFunctionReturn(PETSC_SUCCESS);
1289: }
1291: /*@
1292: DMLabelHasStratum - Determine whether points exist with the given value
1294: Not collective
1296: Input Parameters:
1297: + label - the DMLabel
1298: - value - the stratum value
1300: Output Parameter:
1301: . exists - Flag saying whether points exist
1303: Level: intermediate
1305: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1306: @*/
1307: PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1308: {
1309: PetscInt v;
1311: PetscFunctionBegin;
1314: PetscCall(DMLabelLookupStratum(label, value, &v));
1315: *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1316: PetscFunctionReturn(PETSC_SUCCESS);
1317: }
1319: /*@
1320: DMLabelGetStratumSize - Get the size of a stratum
1322: Not collective
1324: Input Parameters:
1325: + label - the DMLabel
1326: - value - the stratum value
1328: Output Parameter:
1329: . size - The number of points in the stratum
1331: Level: intermediate
1333: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1334: @*/
1335: PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1336: {
1337: PetscInt v;
1339: PetscFunctionBegin;
1342: PetscCall(DMLabelLookupStratum(label, value, &v));
1343: PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1344: PetscFunctionReturn(PETSC_SUCCESS);
1345: }
1347: /*@
1348: DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
1350: Not collective
1352: Input Parameters:
1353: + label - the DMLabel
1354: - value - the stratum value
1356: Output Parameters:
1357: + start - the smallest point in the stratum
1358: - end - the largest point in the stratum
1360: Level: intermediate
1362: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1363: @*/
1364: PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1365: {
1366: IS is;
1367: PetscInt v, min, max;
1369: PetscFunctionBegin;
1371: if (start) {
1373: *start = -1;
1374: }
1375: if (end) {
1377: *end = -1;
1378: }
1379: PetscCall(DMLabelLookupStratum(label, value, &v));
1380: if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
1381: PetscCall(DMLabelMakeValid_Private(label, v));
1382: if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
1383: PetscUseTypeMethod(label, getstratumis, v, &is);
1384: PetscCall(ISGetMinMax(is, &min, &max));
1385: PetscCall(ISDestroy(&is));
1386: if (start) *start = min;
1387: if (end) *end = max + 1;
1388: PetscFunctionReturn(PETSC_SUCCESS);
1389: }
1391: PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
1392: {
1393: PetscFunctionBegin;
1394: PetscCall(PetscObjectReference((PetscObject)label->points[v]));
1395: *pointIS = label->points[v];
1396: PetscFunctionReturn(PETSC_SUCCESS);
1397: }
1399: /*@
1400: DMLabelGetStratumIS - Get an IS with the stratum points
1402: Not collective
1404: Input Parameters:
1405: + label - the DMLabel
1406: - value - the stratum value
1408: Output Parameter:
1409: . points - The stratum points
1411: Level: intermediate
1413: Notes:
1414: The output IS should be destroyed when no longer needed.
1415: Returns NULL if the stratum is empty.
1417: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1418: @*/
1419: PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1420: {
1421: PetscInt v;
1423: PetscFunctionBegin;
1426: *points = NULL;
1427: PetscCall(DMLabelLookupStratum(label, value, &v));
1428: if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
1429: PetscCall(DMLabelMakeValid_Private(label, v));
1430: PetscUseTypeMethod(label, getstratumis, v, points);
1431: PetscFunctionReturn(PETSC_SUCCESS);
1432: }
1434: /*@
1435: DMLabelSetStratumIS - Set the stratum points using an IS
1437: Not collective
1439: Input Parameters:
1440: + label - the DMLabel
1441: . value - the stratum value
1442: - points - The stratum points
1444: Level: intermediate
1446: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1447: @*/
1448: PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1449: {
1450: PetscInt v;
1452: PetscFunctionBegin;
1455: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1456: PetscCall(DMLabelLookupAddStratum(label, value, &v));
1457: if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
1458: PetscCall(DMLabelClearStratum(label, value));
1459: PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
1460: PetscCall(PetscObjectReference((PetscObject)is));
1461: PetscCall(ISDestroy(&(label->points[v])));
1462: label->points[v] = is;
1463: label->validIS[v] = PETSC_TRUE;
1464: PetscCall(PetscObjectStateIncrease((PetscObject)label));
1465: if (label->bt) {
1466: const PetscInt *points;
1467: PetscInt p;
1469: PetscCall(ISGetIndices(is, &points));
1470: for (p = 0; p < label->stratumSizes[v]; ++p) {
1471: const PetscInt point = points[p];
1473: PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
1474: PetscCall(PetscBTSet(label->bt, point - label->pStart));
1475: }
1476: }
1477: PetscFunctionReturn(PETSC_SUCCESS);
1478: }
1480: /*@
1481: DMLabelClearStratum - Remove a stratum
1483: Not collective
1485: Input Parameters:
1486: + label - the DMLabel
1487: - value - the stratum value
1489: Level: intermediate
1491: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1492: @*/
1493: PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1494: {
1495: PetscInt v;
1497: PetscFunctionBegin;
1499: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1500: PetscCall(DMLabelLookupStratum(label, value, &v));
1501: if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
1502: if (label->validIS[v]) {
1503: if (label->bt) {
1504: PetscInt i;
1505: const PetscInt *points;
1507: PetscCall(ISGetIndices(label->points[v], &points));
1508: for (i = 0; i < label->stratumSizes[v]; ++i) {
1509: const PetscInt point = points[i];
1511: PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
1512: PetscCall(PetscBTClear(label->bt, point - label->pStart));
1513: }
1514: PetscCall(ISRestoreIndices(label->points[v], &points));
1515: }
1516: label->stratumSizes[v] = 0;
1517: PetscCall(ISDestroy(&label->points[v]));
1518: PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
1519: PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
1520: PetscCall(PetscObjectStateIncrease((PetscObject)label));
1521: } else {
1522: PetscCall(PetscHSetIClear(label->ht[v]));
1523: }
1524: PetscFunctionReturn(PETSC_SUCCESS);
1525: }
1527: /*@
1528: DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1530: Not collective
1532: Input Parameters:
1533: + label - The DMLabel
1534: . value - The label value for all points
1535: . pStart - The first point
1536: - pEnd - A point beyond all marked points
1538: Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1540: Level: intermediate
1542: .seealso: `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1543: @*/
1544: PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1545: {
1546: IS pIS;
1548: PetscFunctionBegin;
1549: PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
1550: PetscCall(DMLabelSetStratumIS(label, value, pIS));
1551: PetscCall(ISDestroy(&pIS));
1552: PetscFunctionReturn(PETSC_SUCCESS);
1553: }
1555: /*@
1556: DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1558: Not collective
1560: Input Parameters:
1561: + label - The DMLabel
1562: . value - The label value
1563: - p - A point with this value
1565: Output Parameter:
1566: . index - The index of this point in the stratum, or -1 if the point is not in the stratum or the stratum does not exist
1568: Level: intermediate
1570: .seealso: `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1571: @*/
1572: PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1573: {
1574: IS pointIS;
1575: const PetscInt *indices;
1576: PetscInt v;
1578: PetscFunctionBegin;
1581: *index = -1;
1582: PetscCall(DMLabelLookupStratum(label, value, &v));
1583: if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
1584: PetscCall(DMLabelMakeValid_Private(label, v));
1585: PetscUseTypeMethod(label, getstratumis, v, &pointIS);
1586: PetscCall(ISGetIndices(pointIS, &indices));
1587: PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
1588: PetscCall(ISRestoreIndices(pointIS, &indices));
1589: PetscCall(ISDestroy(&pointIS));
1590: PetscFunctionReturn(PETSC_SUCCESS);
1591: }
1593: /*@
1594: DMLabelFilter - Remove all points outside of [start, end)
1596: Not collective
1598: Input Parameters:
1599: + label - the DMLabel
1600: . start - the first point kept
1601: - end - one more than the last point kept
1603: Level: intermediate
1605: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1606: @*/
1607: PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1608: {
1609: PetscInt v;
1611: PetscFunctionBegin;
1613: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1614: PetscCall(DMLabelDestroyIndex(label));
1615: PetscCall(DMLabelMakeAllValid_Private(label));
1616: for (v = 0; v < label->numStrata; ++v) {
1617: PetscCall(ISGeneralFilter(label->points[v], start, end));
1618: PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
1619: }
1620: PetscCall(DMLabelCreateIndex(label, start, end));
1621: PetscFunctionReturn(PETSC_SUCCESS);
1622: }
1624: /*@
1625: DMLabelPermute - Create a new label with permuted points
1627: Not collective
1629: Input Parameters:
1630: + label - the DMLabel
1631: - permutation - the point permutation
1633: Output Parameter:
1634: . labelnew - the new label containing the permuted points
1636: Level: intermediate
1638: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1639: @*/
1640: PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1641: {
1642: const PetscInt *perm;
1643: PetscInt numValues, numPoints, v, q;
1645: PetscFunctionBegin;
1648: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1649: PetscCall(DMLabelMakeAllValid_Private(label));
1650: PetscCall(DMLabelDuplicate(label, labelNew));
1651: PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
1652: PetscCall(ISGetLocalSize(permutation, &numPoints));
1653: PetscCall(ISGetIndices(permutation, &perm));
1654: for (v = 0; v < numValues; ++v) {
1655: const PetscInt size = (*labelNew)->stratumSizes[v];
1656: const PetscInt *points;
1657: PetscInt *pointsNew;
1659: PetscCall(ISGetIndices((*labelNew)->points[v], &points));
1660: PetscCall(PetscCalloc1(size, &pointsNew));
1661: for (q = 0; q < size; ++q) {
1662: const PetscInt point = points[q];
1664: PetscCheck(!(point < 0) && !(point >= numPoints), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ") for the remapping", point, numPoints);
1665: pointsNew[q] = perm[point];
1666: }
1667: PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
1668: PetscCall(PetscSortInt(size, pointsNew));
1669: PetscCall(ISDestroy(&((*labelNew)->points[v])));
1670: if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
1671: PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
1672: PetscCall(PetscFree(pointsNew));
1673: } else {
1674: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1675: }
1676: PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1677: }
1678: PetscCall(ISRestoreIndices(permutation, &perm));
1679: if (label->bt) {
1680: PetscCall(PetscBTDestroy(&label->bt));
1681: PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1682: }
1683: PetscFunctionReturn(PETSC_SUCCESS);
1684: }
1686: PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1687: {
1688: MPI_Comm comm;
1689: PetscInt s, l, nroots, nleaves, offset, size;
1690: PetscInt *remoteOffsets, *rootStrata, *rootIdx;
1691: PetscSection rootSection;
1692: PetscSF labelSF;
1694: PetscFunctionBegin;
1695: if (label) PetscCall(DMLabelMakeAllValid_Private(label));
1696: PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
1697: /* Build a section of stratum values per point, generate the according SF
1698: and distribute point-wise stratum values to leaves. */
1699: PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
1700: PetscCall(PetscSectionCreate(comm, &rootSection));
1701: PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
1702: if (label) {
1703: for (s = 0; s < label->numStrata; ++s) {
1704: const PetscInt *points;
1706: PetscCall(ISGetIndices(label->points[s], &points));
1707: for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
1708: PetscCall(ISRestoreIndices(label->points[s], &points));
1709: }
1710: }
1711: PetscCall(PetscSectionSetUp(rootSection));
1712: /* Create a point-wise array of stratum values */
1713: PetscCall(PetscSectionGetStorageSize(rootSection, &size));
1714: PetscCall(PetscMalloc1(size, &rootStrata));
1715: PetscCall(PetscCalloc1(nroots, &rootIdx));
1716: if (label) {
1717: for (s = 0; s < label->numStrata; ++s) {
1718: const PetscInt *points;
1720: PetscCall(ISGetIndices(label->points[s], &points));
1721: for (l = 0; l < label->stratumSizes[s]; l++) {
1722: const PetscInt p = points[l];
1723: PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
1724: rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
1725: }
1726: PetscCall(ISRestoreIndices(label->points[s], &points));
1727: }
1728: }
1729: /* Build SF that maps label points to remote processes */
1730: PetscCall(PetscSectionCreate(comm, leafSection));
1731: PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
1732: PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
1733: PetscCall(PetscFree(remoteOffsets));
1734: /* Send the strata for each point over the derived SF */
1735: PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
1736: PetscCall(PetscMalloc1(size, leafStrata));
1737: PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
1738: PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
1739: /* Clean up */
1740: PetscCall(PetscFree(rootStrata));
1741: PetscCall(PetscFree(rootIdx));
1742: PetscCall(PetscSectionDestroy(&rootSection));
1743: PetscCall(PetscSFDestroy(&labelSF));
1744: PetscFunctionReturn(PETSC_SUCCESS);
1745: }
1747: /*@
1748: DMLabelDistribute - Create a new label pushed forward over the PetscSF
1750: Collective on sf
1752: Input Parameters:
1753: + label - the DMLabel
1754: - sf - the map from old to new distribution
1756: Output Parameter:
1757: . labelnew - the new redistributed label
1759: Level: intermediate
1761: .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1762: @*/
1763: PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1764: {
1765: MPI_Comm comm;
1766: PetscSection leafSection;
1767: PetscInt p, pStart, pEnd, s, size, dof, offset, stratum;
1768: PetscInt *leafStrata, *strataIdx;
1769: PetscInt **points;
1770: const char *lname = NULL;
1771: char *name;
1772: PetscInt nameSize;
1773: PetscHSetI stratumHash;
1774: size_t len = 0;
1775: PetscMPIInt rank;
1777: PetscFunctionBegin;
1779: if (label) {
1781: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1782: PetscCall(DMLabelMakeAllValid_Private(label));
1783: }
1784: PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
1785: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1786: /* Bcast name */
1787: if (rank == 0) {
1788: PetscCall(PetscObjectGetName((PetscObject)label, &lname));
1789: PetscCall(PetscStrlen(lname, &len));
1790: }
1791: nameSize = len;
1792: PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
1793: PetscCall(PetscMalloc1(nameSize + 1, &name));
1794: if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
1795: PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
1796: PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
1797: PetscCall(PetscFree(name));
1798: /* Bcast defaultValue */
1799: if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
1800: PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
1801: /* Distribute stratum values over the SF and get the point mapping on the receiver */
1802: PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
1803: /* Determine received stratum values and initialise new label*/
1804: PetscCall(PetscHSetICreate(&stratumHash));
1805: PetscCall(PetscSectionGetStorageSize(leafSection, &size));
1806: for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
1807: PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
1808: PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1809: for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
1810: PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
1811: /* Turn leafStrata into indices rather than stratum values */
1812: offset = 0;
1813: PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
1814: PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
1815: for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
1816: for (p = 0; p < size; ++p) {
1817: for (s = 0; s < (*labelNew)->numStrata; ++s) {
1818: if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
1819: leafStrata[p] = s;
1820: break;
1821: }
1822: }
1823: }
1824: /* Rebuild the point strata on the receiver */
1825: PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
1826: PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1827: for (p = pStart; p < pEnd; p++) {
1828: PetscCall(PetscSectionGetDof(leafSection, p, &dof));
1829: PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1830: for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1831: }
1832: PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
1833: PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
1834: PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1835: for (s = 0; s < (*labelNew)->numStrata; ++s) {
1836: PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
1837: PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1838: }
1839: /* Insert points into new strata */
1840: PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
1841: PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1842: for (p = pStart; p < pEnd; p++) {
1843: PetscCall(PetscSectionGetDof(leafSection, p, &dof));
1844: PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1845: for (s = 0; s < dof; s++) {
1846: stratum = leafStrata[offset + s];
1847: points[stratum][strataIdx[stratum]++] = p;
1848: }
1849: }
1850: for (s = 0; s < (*labelNew)->numStrata; s++) {
1851: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &(points[s][0]), PETSC_OWN_POINTER, &((*labelNew)->points[s])));
1852: PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1853: }
1854: PetscCall(PetscFree(points));
1855: PetscCall(PetscHSetIDestroy(&stratumHash));
1856: PetscCall(PetscFree(leafStrata));
1857: PetscCall(PetscFree(strataIdx));
1858: PetscCall(PetscSectionDestroy(&leafSection));
1859: PetscFunctionReturn(PETSC_SUCCESS);
1860: }
1862: /*@
1863: DMLabelGather - Gather all label values from leafs into roots
1865: Collective on sf
1867: Input Parameters:
1868: + label - the DMLabel
1869: - sf - the Star Forest point communication map
1871: Output Parameters:
1872: . labelNew - the new DMLabel with localised leaf values
1874: Level: developer
1876: Note: This is the inverse operation to DMLabelDistribute.
1878: .seealso: `DMLabelDistribute()`
1879: @*/
1880: PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1881: {
1882: MPI_Comm comm;
1883: PetscSection rootSection;
1884: PetscSF sfLabel;
1885: PetscSFNode *rootPoints, *leafPoints;
1886: PetscInt p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
1887: const PetscInt *rootDegree, *ilocal;
1888: PetscInt *rootStrata;
1889: const char *lname;
1890: char *name;
1891: PetscInt nameSize;
1892: size_t len = 0;
1893: PetscMPIInt rank, size;
1895: PetscFunctionBegin;
1898: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1899: PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
1900: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1901: PetscCallMPI(MPI_Comm_size(comm, &size));
1902: /* Bcast name */
1903: if (rank == 0) {
1904: PetscCall(PetscObjectGetName((PetscObject)label, &lname));
1905: PetscCall(PetscStrlen(lname, &len));
1906: }
1907: nameSize = len;
1908: PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
1909: PetscCall(PetscMalloc1(nameSize + 1, &name));
1910: if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
1911: PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
1912: PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
1913: PetscCall(PetscFree(name));
1914: /* Gather rank/index pairs of leaves into local roots to build
1915: an inverse, multi-rooted SF. Note that this ignores local leaf
1916: indexing due to the use of the multiSF in PetscSFGather. */
1917: PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
1918: PetscCall(PetscMalloc1(nroots, &leafPoints));
1919: for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
1920: for (p = 0; p < nleaves; p++) {
1921: PetscInt ilp = ilocal ? ilocal[p] : p;
1923: leafPoints[ilp].index = ilp;
1924: leafPoints[ilp].rank = rank;
1925: }
1926: PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
1927: PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
1928: for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
1929: PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
1930: PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
1931: PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
1932: PetscCall(PetscSFCreate(comm, &sfLabel));
1933: PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
1934: /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
1935: PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
1936: /* Rebuild the point strata on the receiver */
1937: for (p = 0, idx = 0; p < nroots; p++) {
1938: for (d = 0; d < rootDegree[p]; d++) {
1939: PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
1940: PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
1941: for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
1942: }
1943: idx += rootDegree[p];
1944: }
1945: PetscCall(PetscFree(leafPoints));
1946: PetscCall(PetscFree(rootStrata));
1947: PetscCall(PetscSectionDestroy(&rootSection));
1948: PetscCall(PetscSFDestroy(&sfLabel));
1949: PetscFunctionReturn(PETSC_SUCCESS);
1950: }
1952: static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1953: {
1954: const PetscInt *degree;
1955: const PetscInt *points;
1956: PetscInt Nr, r, Nl, l, val, defVal;
1958: PetscFunctionBegin;
1959: PetscCall(DMLabelGetDefaultValue(label, &defVal));
1960: /* Add in leaves */
1961: PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1962: for (l = 0; l < Nl; ++l) {
1963: PetscCall(DMLabelGetValue(label, points[l], &val));
1964: if (val != defVal) valArray[points[l]] = val;
1965: }
1966: /* Add in shared roots */
1967: PetscCall(PetscSFComputeDegreeBegin(pointSF, °ree));
1968: PetscCall(PetscSFComputeDegreeEnd(pointSF, °ree));
1969: for (r = 0; r < Nr; ++r) {
1970: if (degree[r]) {
1971: PetscCall(DMLabelGetValue(label, r, &val));
1972: if (val != defVal) valArray[r] = val;
1973: }
1974: }
1975: PetscFunctionReturn(PETSC_SUCCESS);
1976: }
1978: static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1979: {
1980: const PetscInt *degree;
1981: const PetscInt *points;
1982: PetscInt Nr, r, Nl, l, val, defVal;
1984: PetscFunctionBegin;
1985: PetscCall(DMLabelGetDefaultValue(label, &defVal));
1986: /* Read out leaves */
1987: PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1988: for (l = 0; l < Nl; ++l) {
1989: const PetscInt p = points[l];
1990: const PetscInt cval = valArray[p];
1992: if (cval != defVal) {
1993: PetscCall(DMLabelGetValue(label, p, &val));
1994: if (val == defVal) {
1995: PetscCall(DMLabelSetValue(label, p, cval));
1996: if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
1997: }
1998: }
1999: }
2000: /* Read out shared roots */
2001: PetscCall(PetscSFComputeDegreeBegin(pointSF, °ree));
2002: PetscCall(PetscSFComputeDegreeEnd(pointSF, °ree));
2003: for (r = 0; r < Nr; ++r) {
2004: if (degree[r]) {
2005: const PetscInt cval = valArray[r];
2007: if (cval != defVal) {
2008: PetscCall(DMLabelGetValue(label, r, &val));
2009: if (val == defVal) {
2010: PetscCall(DMLabelSetValue(label, r, cval));
2011: if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2012: }
2013: }
2014: }
2015: }
2016: PetscFunctionReturn(PETSC_SUCCESS);
2017: }
2019: /*@
2020: DMLabelPropagateBegin - Setup a cycle of label propagation
2022: Collective on sf
2024: Input Parameters:
2025: + label - The DMLabel to propagate across processes
2026: - sf - The SF describing parallel layout of the label points
2028: Level: intermediate
2030: .seealso: `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2031: @*/
2032: PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2033: {
2034: PetscInt Nr, r, defVal;
2035: PetscMPIInt size;
2037: PetscFunctionBegin;
2038: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2039: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2040: if (size > 1) {
2041: PetscCall(DMLabelGetDefaultValue(label, &defVal));
2042: PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2043: if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2044: for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2045: }
2046: PetscFunctionReturn(PETSC_SUCCESS);
2047: }
2049: /*@
2050: DMLabelPropagateEnd - Tear down a cycle of label propagation
2052: Collective on sf
2054: Input Parameters:
2055: + label - The DMLabel to propagate across processes
2056: - sf - The SF describing parallel layout of the label points
2058: Level: intermediate
2060: .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2061: @*/
2062: PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2063: {
2064: PetscFunctionBegin;
2065: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2066: PetscCall(PetscFree(label->propArray));
2067: label->propArray = NULL;
2068: PetscFunctionReturn(PETSC_SUCCESS);
2069: }
2071: /*@C
2072: DMLabelPropagatePush - Tear down a cycle of label propagation
2074: Collective on sf
2076: Input Parameters:
2077: + label - The DMLabel to propagate across processes
2078: . sf - The SF describing parallel layout of the label points
2079: . markPoint - An optional callback that is called when a point is marked, or NULL
2080: - ctx - An optional user context for the callback, or NULL
2082: Calling sequence of markPoint:
2083: $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
2085: + label - The DMLabel
2086: . p - The point being marked
2087: . val - The label value for p
2088: - ctx - An optional user context
2090: Level: intermediate
2092: .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2093: @*/
2094: PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2095: {
2096: PetscInt *valArray = label->propArray, Nr;
2097: PetscMPIInt size;
2099: PetscFunctionBegin;
2100: PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2101: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2102: PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2103: if (size > 1 && Nr >= 0) {
2104: /* Communicate marked edges
2105: The current implementation allocates an array the size of the number of root. We put the label values into the
2106: array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2108: TODO: We could use in-place communication with a different SF
2109: We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2110: already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2112: In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2113: values will have 1+0=1 and old values will have 1+1=2. Loop over these, resetting the values to 1, and adding any new
2114: edge to the queue.
2115: */
2116: PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2117: PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2118: PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2119: PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2120: PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2121: PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2122: }
2123: PetscFunctionReturn(PETSC_SUCCESS);
2124: }
2126: /*@
2127: DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
2129: Not collective
2131: Input Parameter:
2132: . label - the DMLabel
2134: Output Parameters:
2135: + section - the section giving offsets for each stratum
2136: - is - An IS containing all the label points
2138: Level: developer
2140: .seealso: `DMLabelDistribute()`
2141: @*/
2142: PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2143: {
2144: IS vIS;
2145: const PetscInt *values;
2146: PetscInt *points;
2147: PetscInt nV, vS = 0, vE = 0, v, N;
2149: PetscFunctionBegin;
2151: PetscCall(DMLabelGetNumValues(label, &nV));
2152: PetscCall(DMLabelGetValueIS(label, &vIS));
2153: PetscCall(ISGetIndices(vIS, &values));
2154: if (nV) {
2155: vS = values[0];
2156: vE = values[0] + 1;
2157: }
2158: for (v = 1; v < nV; ++v) {
2159: vS = PetscMin(vS, values[v]);
2160: vE = PetscMax(vE, values[v] + 1);
2161: }
2162: PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
2163: PetscCall(PetscSectionSetChart(*section, vS, vE));
2164: for (v = 0; v < nV; ++v) {
2165: PetscInt n;
2167: PetscCall(DMLabelGetStratumSize(label, values[v], &n));
2168: PetscCall(PetscSectionSetDof(*section, values[v], n));
2169: }
2170: PetscCall(PetscSectionSetUp(*section));
2171: PetscCall(PetscSectionGetStorageSize(*section, &N));
2172: PetscCall(PetscMalloc1(N, &points));
2173: for (v = 0; v < nV; ++v) {
2174: IS is;
2175: const PetscInt *spoints;
2176: PetscInt dof, off, p;
2178: PetscCall(PetscSectionGetDof(*section, values[v], &dof));
2179: PetscCall(PetscSectionGetOffset(*section, values[v], &off));
2180: PetscCall(DMLabelGetStratumIS(label, values[v], &is));
2181: PetscCall(ISGetIndices(is, &spoints));
2182: for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
2183: PetscCall(ISRestoreIndices(is, &spoints));
2184: PetscCall(ISDestroy(&is));
2185: }
2186: PetscCall(ISRestoreIndices(vIS, &values));
2187: PetscCall(ISDestroy(&vIS));
2188: PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2189: PetscFunctionReturn(PETSC_SUCCESS);
2190: }
2192: /*@C
2193: DMLabelRegister - Adds a new label component implementation
2195: Not Collective
2197: Input Parameters:
2198: + name - The name of a new user-defined creation routine
2199: - create_func - The creation routine itself
2201: Notes:
2202: `DMLabelRegister()` may be called multiple times to add several user-defined labels
2204: Sample usage:
2205: .vb
2206: DMLabelRegister("my_label", MyLabelCreate);
2207: .ve
2209: Then, your label type can be chosen with the procedural interface via
2210: .vb
2211: DMLabelCreate(MPI_Comm, DMLabel *);
2212: DMLabelSetType(DMLabel, "my_label");
2213: .ve
2214: or at runtime via the option
2215: .vb
2216: -dm_label_type my_label
2217: .ve
2219: Level: advanced
2221: .seealso: `DMLabel`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
2222: @*/
2223: PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
2224: {
2225: PetscFunctionBegin;
2226: PetscCall(DMInitializePackage());
2227: PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
2228: PetscFunctionReturn(PETSC_SUCCESS);
2229: }
2231: PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
2232: PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
2234: /*@C
2235: DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
2237: Not Collective
2239: Level: advanced
2241: .seealso: `DMRegisterAll()`, `DMLabelRegisterDestroy()`
2242: @*/
2243: PetscErrorCode DMLabelRegisterAll(void)
2244: {
2245: PetscFunctionBegin;
2246: if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
2247: DMLabelRegisterAllCalled = PETSC_TRUE;
2249: PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
2250: PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
2251: PetscFunctionReturn(PETSC_SUCCESS);
2252: }
2254: /*@C
2255: DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
2257: Level: developer
2259: .seealso: `PetscInitialize()`
2260: @*/
2261: PetscErrorCode DMLabelRegisterDestroy(void)
2262: {
2263: PetscFunctionBegin;
2264: PetscCall(PetscFunctionListDestroy(&DMLabelList));
2265: DMLabelRegisterAllCalled = PETSC_FALSE;
2266: PetscFunctionReturn(PETSC_SUCCESS);
2267: }
2269: /*@C
2270: DMLabelSetType - Sets the particular implementation for a label.
2272: Collective on tr
2274: Input Parameters:
2275: + label - The label
2276: - method - The name of the label type
2278: Options Database Key:
2279: . -dm_label_type <type> - Sets the label type; use -help for a list of available types
2281: Notes:
2282: See "petsc/include/petscdmlabel.h" for available label types
2284: Level: intermediate
2286: .seealso: `DMLabelGetType()`, `DMLabelCreate()`
2287: @*/
2288: PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
2289: {
2290: PetscErrorCode (*r)(DMLabel);
2291: PetscBool match;
2293: PetscFunctionBegin;
2295: PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
2296: if (match) PetscFunctionReturn(PETSC_SUCCESS);
2298: PetscCall(DMLabelRegisterAll());
2299: PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
2300: PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
2302: PetscTryTypeMethod(label, destroy);
2303: PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
2304: PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
2305: PetscCall((*r)(label));
2306: PetscFunctionReturn(PETSC_SUCCESS);
2307: }
2309: /*@C
2310: DMLabelGetType - Gets the type name (as a string) from the label.
2312: Not Collective
2314: Input Parameter:
2315: . label - The DMLabel
2317: Output Parameter:
2318: . type - The DMLabel type name
2320: Level: intermediate
2322: .seealso: `DMLabelSetType()`, `DMLabelCreate()`
2323: @*/
2324: PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
2325: {
2326: PetscFunctionBegin;
2329: PetscCall(DMLabelRegisterAll());
2330: *type = ((PetscObject)label)->type_name;
2331: PetscFunctionReturn(PETSC_SUCCESS);
2332: }
2334: static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
2335: {
2336: PetscFunctionBegin;
2337: label->ops->view = DMLabelView_Concrete;
2338: label->ops->setup = NULL;
2339: label->ops->duplicate = DMLabelDuplicate_Concrete;
2340: label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
2341: PetscFunctionReturn(PETSC_SUCCESS);
2342: }
2344: PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
2345: {
2346: PetscFunctionBegin;
2348: PetscCall(DMLabelInitialize_Concrete(label));
2349: PetscFunctionReturn(PETSC_SUCCESS);
2350: }
2352: /*@
2353: PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2354: the local section and an SF describing the section point overlap.
2356: Collective on sf
2358: Input Parameters:
2359: + s - The PetscSection for the local field layout
2360: . sf - The SF describing parallel layout of the section points
2361: . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2362: . label - The label specifying the points
2363: - labelValue - The label stratum specifying the points
2365: Output Parameter:
2366: . gsection - The PetscSection for the global field layout
2368: Note: This gives negative sizes and offsets to points not owned by this process
2370: Level: developer
2372: .seealso: `PetscSectionCreate()`
2373: @*/
2374: PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2375: {
2376: PetscInt *neg = NULL, *tmpOff = NULL;
2377: PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2379: PetscFunctionBegin;
2383: PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
2384: PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
2385: PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
2386: PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2387: if (nroots >= 0) {
2388: PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
2389: PetscCall(PetscCalloc1(nroots, &neg));
2390: if (nroots > pEnd - pStart) {
2391: PetscCall(PetscCalloc1(nroots, &tmpOff));
2392: } else {
2393: tmpOff = &(*gsection)->atlasDof[-pStart];
2394: }
2395: }
2396: /* Mark ghost points with negative dof */
2397: for (p = pStart; p < pEnd; ++p) {
2398: PetscInt value;
2400: PetscCall(DMLabelGetValue(label, p, &value));
2401: if (value != labelValue) continue;
2402: PetscCall(PetscSectionGetDof(s, p, &dof));
2403: PetscCall(PetscSectionSetDof(*gsection, p, dof));
2404: PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
2405: if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2406: if (neg) neg[p] = -(dof + 1);
2407: }
2408: PetscCall(PetscSectionSetUpBC(*gsection));
2409: if (nroots >= 0) {
2410: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2411: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2412: if (nroots > pEnd - pStart) {
2413: for (p = pStart; p < pEnd; ++p) {
2414: if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
2415: }
2416: }
2417: }
2418: /* Calculate new sizes, get process offset, and calculate point offsets */
2419: for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2420: cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2421: (*gsection)->atlasOff[p] = off;
2422: off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2423: }
2424: PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2425: globalOff -= off;
2426: for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2427: (*gsection)->atlasOff[p] += globalOff;
2428: if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2429: }
2430: /* Put in negative offsets for ghost points */
2431: if (nroots >= 0) {
2432: PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2433: PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2434: if (nroots > pEnd - pStart) {
2435: for (p = pStart; p < pEnd; ++p) {
2436: if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
2437: }
2438: }
2439: }
2440: if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
2441: PetscCall(PetscFree(neg));
2442: PetscFunctionReturn(PETSC_SUCCESS);
2443: }
2445: typedef struct _n_PetscSectionSym_Label {
2446: DMLabel label;
2447: PetscCopyMode *modes;
2448: PetscInt *sizes;
2449: const PetscInt ***perms;
2450: const PetscScalar ***rots;
2451: PetscInt (*minMaxOrients)[2];
2452: PetscInt numStrata; /* numStrata is only increasing, functions as a state */
2453: } PetscSectionSym_Label;
2455: static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2456: {
2457: PetscInt i, j;
2458: PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2460: PetscFunctionBegin;
2461: for (i = 0; i <= sl->numStrata; i++) {
2462: if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
2463: for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
2464: if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
2465: if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
2466: }
2467: if (sl->perms[i]) {
2468: const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
2470: PetscCall(PetscFree(perms));
2471: }
2472: if (sl->rots[i]) {
2473: const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
2475: PetscCall(PetscFree(rots));
2476: }
2477: }
2478: }
2479: PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
2480: PetscCall(DMLabelDestroy(&sl->label));
2481: sl->numStrata = 0;
2482: PetscFunctionReturn(PETSC_SUCCESS);
2483: }
2485: static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2486: {
2487: PetscFunctionBegin;
2488: PetscCall(PetscSectionSymLabelReset(sym));
2489: PetscCall(PetscFree(sym->data));
2490: PetscFunctionReturn(PETSC_SUCCESS);
2491: }
2493: static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2494: {
2495: PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2496: PetscBool isAscii;
2497: DMLabel label = sl->label;
2498: const char *name;
2500: PetscFunctionBegin;
2501: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
2502: if (isAscii) {
2503: PetscInt i, j, k;
2504: PetscViewerFormat format;
2506: PetscCall(PetscViewerGetFormat(viewer, &format));
2507: if (label) {
2508: PetscCall(PetscViewerGetFormat(viewer, &format));
2509: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2510: PetscCall(PetscViewerASCIIPushTab(viewer));
2511: PetscCall(DMLabelView(label, viewer));
2512: PetscCall(PetscViewerASCIIPopTab(viewer));
2513: } else {
2514: PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2515: PetscCall(PetscViewerASCIIPrintf(viewer, " Label '%s'\n", name));
2516: }
2517: } else {
2518: PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
2519: }
2520: PetscCall(PetscViewerASCIIPushTab(viewer));
2521: for (i = 0; i <= sl->numStrata; i++) {
2522: PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
2524: if (!(sl->perms[i] || sl->rots[i])) {
2525: PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
2526: } else {
2527: PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
2528: PetscCall(PetscViewerASCIIPushTab(viewer));
2529: PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
2530: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2531: PetscCall(PetscViewerASCIIPushTab(viewer));
2532: for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
2533: if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
2534: PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
2535: } else {
2536: PetscInt tab;
2538: PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
2539: PetscCall(PetscViewerASCIIPushTab(viewer));
2540: PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
2541: if (sl->perms[i] && sl->perms[i][j]) {
2542: PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
2543: PetscCall(PetscViewerASCIISetTab(viewer, 0));
2544: for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
2545: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
2546: PetscCall(PetscViewerASCIISetTab(viewer, tab));
2547: }
2548: if (sl->rots[i] && sl->rots[i][j]) {
2549: PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations: "));
2550: PetscCall(PetscViewerASCIISetTab(viewer, 0));
2551: #if defined(PETSC_USE_COMPLEX)
2552: for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g+i*%+g", (double)PetscRealPart(sl->rots[i][j][k]), (double)PetscImaginaryPart(sl->rots[i][j][k])));
2553: #else
2554: for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
2555: #endif
2556: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
2557: PetscCall(PetscViewerASCIISetTab(viewer, tab));
2558: }
2559: PetscCall(PetscViewerASCIIPopTab(viewer));
2560: }
2561: }
2562: PetscCall(PetscViewerASCIIPopTab(viewer));
2563: }
2564: PetscCall(PetscViewerASCIIPopTab(viewer));
2565: }
2566: }
2567: PetscCall(PetscViewerASCIIPopTab(viewer));
2568: }
2569: PetscFunctionReturn(PETSC_SUCCESS);
2570: }
2572: /*@
2573: PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
2575: Logically collective on sym
2577: Input parameters:
2578: + sym - the section symmetries
2579: - label - the DMLabel describing the types of points
2581: Level: developer:
2583: .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
2584: @*/
2585: PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2586: {
2587: PetscSectionSym_Label *sl;
2589: PetscFunctionBegin;
2591: sl = (PetscSectionSym_Label *)sym->data;
2592: if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
2593: if (label) {
2594: sl->label = label;
2595: PetscCall(PetscObjectReference((PetscObject)label));
2596: PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
2597: PetscCall(PetscMalloc5(sl->numStrata + 1, &sl->modes, sl->numStrata + 1, &sl->sizes, sl->numStrata + 1, &sl->perms, sl->numStrata + 1, &sl->rots, sl->numStrata + 1, &sl->minMaxOrients));
2598: PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
2599: PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
2600: PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
2601: PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
2602: PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
2603: }
2604: PetscFunctionReturn(PETSC_SUCCESS);
2605: }
2607: /*@C
2608: PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2610: Logically collective on sym
2612: Input Parameters:
2613: + sym - the section symmetries
2614: - stratum - the stratum value in the label that we are assigning symmetries for
2616: Output Parameters:
2617: + size - the number of dofs for points in the stratum of the label
2618: . minOrient - the smallest orientation for a point in this stratum
2619: . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2620: . perms - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation. A NULL permutation is the identity
2621: - rots - NULL if there are no rotations, or (maxOrient - minOrient) sets of rotations, one for each orientation. A NULL set of orientations is the identity
2623: Level: developer
2625: .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2626: @*/
2627: PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2628: {
2629: PetscSectionSym_Label *sl;
2630: const char *name;
2631: PetscInt i;
2633: PetscFunctionBegin;
2635: sl = (PetscSectionSym_Label *)sym->data;
2636: PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2637: for (i = 0; i <= sl->numStrata; i++) {
2638: PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2640: if (stratum == value) break;
2641: }
2642: PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2643: PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
2644: if (size) {
2646: *size = sl->sizes[i];
2647: }
2648: if (minOrient) {
2650: *minOrient = sl->minMaxOrients[i][0];
2651: }
2652: if (maxOrient) {
2654: *maxOrient = sl->minMaxOrients[i][1];
2655: }
2656: if (perms) {
2658: *perms = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;
2659: }
2660: if (rots) {
2662: *rots = sl->rots[i] ? &sl->rots[i][sl->minMaxOrients[i][0]] : NULL;
2663: }
2664: PetscFunctionReturn(PETSC_SUCCESS);
2665: }
2667: /*@C
2668: PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
2670: Logically collective on sym
2672: InputParameters:
2673: + sym - the section symmetries
2674: . stratum - the stratum value in the label that we are assigning symmetries for
2675: . size - the number of dofs for points in the stratum of the label
2676: . minOrient - the smallest orientation for a point in this stratum
2677: . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2678: . mode - how sym should copy the perms and rots arrays
2679: . perms - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation. A NULL permutation is the identity
2680: - rots - NULL if there are no rotations, or (maxOrient - minOrient) sets of rotations, one for each orientation. A NULL set of orientations is the identity
2682: Level: developer
2684: .seealso: `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2685: @*/
2686: PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2687: {
2688: PetscSectionSym_Label *sl;
2689: const char *name;
2690: PetscInt i, j, k;
2692: PetscFunctionBegin;
2694: sl = (PetscSectionSym_Label *)sym->data;
2695: PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2696: for (i = 0; i <= sl->numStrata; i++) {
2697: PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2699: if (stratum == value) break;
2700: }
2701: PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2702: PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
2703: sl->sizes[i] = size;
2704: sl->modes[i] = mode;
2705: sl->minMaxOrients[i][0] = minOrient;
2706: sl->minMaxOrients[i][1] = maxOrient;
2707: if (mode == PETSC_COPY_VALUES) {
2708: if (perms) {
2709: PetscInt **ownPerms;
2711: PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
2712: for (j = 0; j < maxOrient - minOrient; j++) {
2713: if (perms[j]) {
2714: PetscCall(PetscMalloc1(size, &ownPerms[j]));
2715: for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
2716: }
2717: }
2718: sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
2719: }
2720: if (rots) {
2721: PetscScalar **ownRots;
2723: PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
2724: for (j = 0; j < maxOrient - minOrient; j++) {
2725: if (rots[j]) {
2726: PetscCall(PetscMalloc1(size, &ownRots[j]));
2727: for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
2728: }
2729: }
2730: sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
2731: }
2732: } else {
2733: sl->perms[i] = perms ? &perms[-minOrient] : NULL;
2734: sl->rots[i] = rots ? &rots[-minOrient] : NULL;
2735: }
2736: PetscFunctionReturn(PETSC_SUCCESS);
2737: }
2739: static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2740: {
2741: PetscInt i, j, numStrata;
2742: PetscSectionSym_Label *sl;
2743: DMLabel label;
2745: PetscFunctionBegin;
2746: sl = (PetscSectionSym_Label *)sym->data;
2747: numStrata = sl->numStrata;
2748: label = sl->label;
2749: for (i = 0; i < numPoints; i++) {
2750: PetscInt point = points[2 * i];
2751: PetscInt ornt = points[2 * i + 1];
2753: for (j = 0; j < numStrata; j++) {
2754: if (label->validIS[j]) {
2755: PetscInt k;
2757: PetscCall(ISLocate(label->points[j], point, &k));
2758: if (k >= 0) break;
2759: } else {
2760: PetscBool has;
2762: PetscCall(PetscHSetIHas(label->ht[j], point, &has));
2763: if (has) break;
2764: }
2765: }
2766: PetscCheck(!(sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) || !(ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "point %" PetscInt_FMT " orientation %" PetscInt_FMT " not in range [%" PetscInt_FMT ", %" PetscInt_FMT ") for stratum %" PetscInt_FMT, point, ornt, sl->minMaxOrients[j][0], sl->minMaxOrients[j][1],
2767: j < numStrata ? label->stratumValues[j] : label->defaultValue);
2768: if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2769: if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
2770: }
2771: PetscFunctionReturn(PETSC_SUCCESS);
2772: }
2774: static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2775: {
2776: PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2777: IS valIS;
2778: const PetscInt *values;
2779: PetscInt Nv, v;
2781: PetscFunctionBegin;
2782: PetscCall(DMLabelGetNumValues(sl->label, &Nv));
2783: PetscCall(DMLabelGetValueIS(sl->label, &valIS));
2784: PetscCall(ISGetIndices(valIS, &values));
2785: for (v = 0; v < Nv; ++v) {
2786: const PetscInt val = values[v];
2787: PetscInt size, minOrient, maxOrient;
2788: const PetscInt **perms;
2789: const PetscScalar **rots;
2791: PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
2792: PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2793: }
2794: PetscCall(ISDestroy(&valIS));
2795: PetscFunctionReturn(PETSC_SUCCESS);
2796: }
2798: static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2799: {
2800: PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2801: DMLabel dlabel;
2803: PetscFunctionBegin;
2804: PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
2805: PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
2806: PetscCall(DMLabelDestroy(&dlabel));
2807: PetscCall(PetscSectionSymCopy(sym, *dsym));
2808: PetscFunctionReturn(PETSC_SUCCESS);
2809: }
2811: PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2812: {
2813: PetscSectionSym_Label *sl;
2815: PetscFunctionBegin;
2816: PetscCall(PetscNew(&sl));
2817: sym->ops->getpoints = PetscSectionSymGetPoints_Label;
2818: sym->ops->distribute = PetscSectionSymDistribute_Label;
2819: sym->ops->copy = PetscSectionSymCopy_Label;
2820: sym->ops->view = PetscSectionSymView_Label;
2821: sym->ops->destroy = PetscSectionSymDestroy_Label;
2822: sym->data = (void *)sl;
2823: PetscFunctionReturn(PETSC_SUCCESS);
2824: }
2826: /*@
2827: PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
2829: Collective
2831: Input Parameters:
2832: + comm - the MPI communicator for the new symmetry
2833: - label - the label defining the strata
2835: Output Parameters:
2836: . sym - the section symmetries
2838: Level: developer
2840: .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
2841: @*/
2842: PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2843: {
2844: PetscFunctionBegin;
2845: PetscCall(DMInitializePackage());
2846: PetscCall(PetscSectionSymCreate(comm, sym));
2847: PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
2848: PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
2849: PetscFunctionReturn(PETSC_SUCCESS);
2850: }