xref: /petsc/src/dm/label/tutorials/ex1.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1 static char help[] = "Tests DMLabel operations.\n\n";
2 
3 #include <petscdm.h>
4 #include <petscdmplex.h>
5 
6 PetscErrorCode ViewLabels(DM dm, PetscViewer viewer)
7 {
8   DMLabel     label;
9   const char *labelName;
10   PetscInt    numLabels, l;
11 
12   PetscFunctionBegin;
13   /* query the number and name of labels*/
14   PetscCall(DMGetNumLabels(dm, &numLabels));
15   PetscCall(PetscViewerASCIIPrintf(viewer, "Number of labels: %" PetscInt_FMT "\n", numLabels));
16   for (l = 0; l < numLabels; ++l) {
17     IS labelIS, tmpIS;
18 
19     PetscCall(DMGetLabelName(dm, l, &labelName));
20     PetscCall(PetscViewerASCIIPrintf(viewer, "Label %" PetscInt_FMT ": name: %s\n", l, labelName));
21     PetscCall(PetscViewerASCIIPrintf(viewer, "IS of values\n"));
22     PetscCall(DMGetLabel(dm, labelName, &label));
23     PetscCall(DMLabelGetValueIS(label, &labelIS));
24     PetscCall(ISOnComm(labelIS, PetscObjectComm((PetscObject)viewer), PETSC_USE_POINTER, &tmpIS));
25     PetscCall(PetscViewerASCIIPushTab(viewer));
26     PetscCall(ISView(tmpIS, viewer));
27     PetscCall(PetscViewerASCIIPopTab(viewer));
28     PetscCall(ISDestroy(&tmpIS));
29     PetscCall(ISDestroy(&labelIS));
30     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
31   }
32   /* Making sure that string literals work */
33   PetscCall(PetscViewerASCIIPrintf(viewer, "\n\nCell Set label IS\n"));
34   PetscCall(DMGetLabel(dm, "Cell Sets", &label));
35   if (label) {
36     IS labelIS, tmpIS;
37 
38     PetscCall(DMLabelGetValueIS(label, &labelIS));
39     PetscCall(ISOnComm(labelIS, PetscObjectComm((PetscObject)viewer), PETSC_USE_POINTER, &tmpIS));
40     PetscCall(ISView(tmpIS, viewer));
41     PetscCall(ISDestroy(&tmpIS));
42     PetscCall(ISDestroy(&labelIS));
43   }
44   PetscFunctionReturn(0);
45 }
46 
47 PetscErrorCode CheckLabelsSame(DMLabel label0, DMLabel label1)
48 {
49   const char *name0, *name1;
50   PetscBool   same;
51   char       *msg;
52 
53   PetscFunctionBegin;
54   PetscCall(PetscObjectGetName((PetscObject)label0, &name0));
55   PetscCall(PetscObjectGetName((PetscObject)label1, &name1));
56   PetscCall(DMLabelCompare(PETSC_COMM_WORLD, label0, label1, &same, &msg));
57   PetscCheck(same == (PetscBool)!msg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "DMLabelCompare returns inconsistent same=%d msg=\"%s\"", same, msg);
58   PetscCheck(same, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Labels \"%s\" and \"%s\" should not differ! Message:\n%s", name0, name1, msg);
59   /* Test passing NULL, must not fail */
60   PetscCall(DMLabelCompare(PETSC_COMM_WORLD, label0, label1, NULL, NULL));
61   PetscCall(PetscFree(msg));
62   PetscFunctionReturn(0);
63 }
64 
65 PetscErrorCode CheckLabelsNotSame(DMLabel label0, DMLabel label1)
66 {
67   const char *name0, *name1;
68   PetscBool   same;
69   char       *msg;
70 
71   PetscFunctionBegin;
72   PetscCall(PetscObjectGetName((PetscObject)label0, &name0));
73   PetscCall(PetscObjectGetName((PetscObject)label1, &name1));
74   PetscCall(DMLabelCompare(PETSC_COMM_WORLD, label0, label1, &same, &msg));
75   PetscCheck(same == (PetscBool)!msg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "DMLabelCompare returns inconsistent same=%d msg=\"%s\"", same, msg);
76   PetscCheck(!same, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Labels \"%s\" and \"%s\" should differ!", name0, name1);
77   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Compare label \"%s\" with \"%s\": %s\n", name0, name1, msg));
78   PetscCall(PetscFree(msg));
79   PetscFunctionReturn(0);
80 }
81 
82 PetscErrorCode CheckDMLabelsSame(DM dm0, DM dm1)
83 {
84   const char *name0, *name1;
85   PetscBool   same;
86   char       *msg;
87 
88   PetscFunctionBegin;
89   PetscCall(PetscObjectGetName((PetscObject)dm0, &name0));
90   PetscCall(PetscObjectGetName((PetscObject)dm1, &name1));
91   PetscCall(DMCompareLabels(dm0, dm1, &same, &msg));
92   PetscCheck(same == (PetscBool)!msg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "DMCompareLabels returns inconsistent same=%d msg=\"%s\"", same, msg);
93   PetscCheck(same, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Labels of DMs \"%s\" and \"%s\" should not differ! Message:\n%s", name0, name1, msg);
94   /* Test passing NULL, must not fail */
95   PetscCall(DMCompareLabels(dm0, dm1, NULL, NULL));
96   PetscCall(PetscFree(msg));
97   PetscFunctionReturn(0);
98 }
99 
100 PetscErrorCode CheckDMLabelsNotSame(DM dm0, DM dm1)
101 {
102   const char *name0, *name1;
103   PetscBool   same;
104   char       *msg;
105 
106   PetscFunctionBegin;
107   PetscCall(PetscObjectGetName((PetscObject)dm0, &name0));
108   PetscCall(PetscObjectGetName((PetscObject)dm1, &name1));
109   PetscCall(DMCompareLabels(dm0, dm1, &same, &msg));
110   PetscCheck(same == (PetscBool)!msg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "DMCompareLabels returns inconsistent same=%d msg=\"%s\"", same, msg);
111   PetscCheck(!same, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Labels of DMs \"%s\" and \"%s\" should differ!", name0, name1);
112   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Labels of DMs \"%s\" and \"%s\" differ: %s\n", name0, name1, msg));
113   PetscCall(PetscFree(msg));
114   PetscFunctionReturn(0);
115 }
116 
117 PetscErrorCode CreateMesh(const char name[], DM *newdm)
118 {
119   DM        dm, dmDist;
120   char      filename[PETSC_MAX_PATH_LEN] = "";
121   PetscBool interpolate                  = PETSC_FALSE;
122 
123   PetscFunctionBegin;
124   /* initialize and get options */
125   PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "DMLabel ex1 Options", "DMLabel");
126   PetscCall(PetscOptionsString("-i", "filename to read", "ex1.c", filename, filename, sizeof(filename), NULL));
127   PetscCall(PetscOptionsBool("-interpolate", "Generate intermediate mesh elements", "ex1.c", interpolate, &interpolate, NULL));
128   PetscOptionsEnd();
129 
130   /* create and distribute DM */
131   PetscCall(DMPlexCreateFromFile(PETSC_COMM_WORLD, filename, "ex1_plex", interpolate, &dm));
132   PetscCall(DMPlexDistribute(dm, 0, NULL, &dmDist));
133   if (dmDist) {
134     PetscCall(DMDestroy(&dm));
135     dm = dmDist;
136   }
137   PetscCall(DMSetFromOptions(dm));
138   PetscCall(PetscObjectSetName((PetscObject)dm, name));
139   *newdm = dm;
140   PetscFunctionReturn(0);
141 }
142 
143 int main(int argc, char **argv)
144 {
145   DM dm;
146 
147   PetscFunctionBeginUser;
148   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
149   PetscCall(CreateMesh("plex0", &dm));
150   /* add custom labels to test adding/removal */
151   {
152     DMLabel  label0, label1, label2, label3;
153     PetscInt p, pStart, pEnd;
154     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
155     /* create label in DM and get from DM */
156     PetscCall(DMCreateLabel(dm, "label0"));
157     PetscCall(DMGetLabel(dm, "label0", &label0));
158     /* alternative: create standalone label and add to DM; needs to be destroyed */
159     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "label1", &label1));
160     PetscCall(DMAddLabel(dm, label1));
161 
162     pEnd = PetscMin(pEnd, pStart + 5);
163     for (p = pStart; p < pEnd; p++) {
164       PetscCall(DMLabelSetValue(label0, p, 1));
165       PetscCall(DMLabelSetValue(label1, p, 2));
166     }
167     /* duplicate label */
168     PetscCall(DMLabelDuplicate(label0, &label2));
169     PetscCall(DMLabelDuplicate(label1, &label3));
170     PetscCall(PetscObjectSetName((PetscObject)label2, "label2"));
171     PetscCall(PetscObjectSetName((PetscObject)label3, "label3"));
172     PetscCall(DMAddLabel(dm, label2));
173     PetscCall(DMAddLabel(dm, label3));
174     /* remove the labels in this scope */
175     PetscCall(DMLabelDestroy(&label1));
176     PetscCall(DMLabelDestroy(&label2));
177     PetscCall(DMLabelDestroy(&label3));
178   }
179 
180   PetscCall(ViewLabels(dm, PETSC_VIEWER_STDOUT_WORLD));
181 
182   /* do label perturbations and comparisons */
183   {
184     DMLabel  label0, label1, label2, label3;
185     PetscInt val;
186     PetscInt p, pStart, pEnd;
187 
188     PetscCall(DMGetLabel(dm, "label0", &label0));
189     PetscCall(DMGetLabel(dm, "label1", &label1));
190     PetscCall(DMGetLabel(dm, "label2", &label2));
191     PetscCall(DMGetLabel(dm, "label3", &label3));
192 
193     PetscCall(CheckLabelsNotSame(label0, label1));
194     PetscCall(CheckLabelsSame(label0, label2));
195     PetscCall(CheckLabelsSame(label1, label3));
196 
197     PetscCall(DMLabelGetDefaultValue(label1, &val));
198     PetscCall(DMLabelSetDefaultValue(label1, 333));
199     PetscCall(CheckLabelsNotSame(label1, label3));
200     PetscCall(DMLabelSetDefaultValue(label1, val));
201     PetscCall(CheckLabelsSame(label1, label3));
202 
203     PetscCall(DMLabelGetBounds(label1, &pStart, &pEnd));
204 
205     for (p = pStart; p < pEnd; p++) {
206       PetscCall(DMLabelGetValue(label1, p, &val));
207       // This is weird. Perhaps we should not need to call DMLabelClearValue()
208       PetscCall(DMLabelClearValue(label1, p, val));
209       val++;
210       PetscCall(DMLabelSetValue(label1, p, val));
211     }
212     PetscCall(CheckLabelsNotSame(label1, label3));
213     for (p = pStart; p < pEnd; p++) {
214       PetscCall(DMLabelGetValue(label1, p, &val));
215       // This is weird. Perhaps we should not need to call DMLabelClearValue()
216       PetscCall(DMLabelClearValue(label1, p, val));
217       val--;
218       PetscCall(DMLabelSetValue(label1, p, val));
219     }
220     PetscCall(CheckLabelsSame(label1, label3));
221 
222     PetscCall(DMLabelGetValue(label3, pEnd - 1, &val));
223     PetscCall(DMLabelSetValue(label3, pEnd, val));
224     PetscCall(CheckLabelsNotSame(label1, label3));
225     // This is weird. Perhaps we should not need to call DMLabelClearValue()
226     PetscCall(DMLabelClearValue(label3, pEnd, val));
227     PetscCall(CheckLabelsSame(label1, label3));
228   }
229 
230   {
231     DM       dm1;
232     DMLabel  label02, label12;
233     PetscInt p = 0, val;
234 
235     PetscCall(CreateMesh("plex1", &dm1));
236     PetscCall(CheckDMLabelsNotSame(dm, dm1));
237 
238     PetscCall(DMCopyLabels(dm, dm1, PETSC_OWN_POINTER, PETSC_FALSE, DM_COPY_LABELS_REPLACE));
239     PetscCall(CheckDMLabelsSame(dm, dm1));
240 
241     PetscCall(DMCopyLabels(dm, dm1, PETSC_COPY_VALUES, PETSC_FALSE, DM_COPY_LABELS_REPLACE));
242     PetscCall(DMGetLabel(dm, "label2", &label02));
243     PetscCall(DMGetLabel(dm1, "label2", &label12));
244     PetscCall(CheckLabelsSame(label02, label12));
245 
246     PetscCall(DMLabelGetValue(label12, p, &val));
247     // This is weird. Perhaps we should not need to call DMLabelClearValue()
248     PetscCall(DMLabelClearValue(label12, p, val));
249     PetscCall(DMLabelSetValue(label12, p, val + 1));
250     PetscCall(CheckLabelsNotSame(label02, label12));
251     PetscCall(CheckDMLabelsNotSame(dm, dm1));
252 
253     // This is weird. Perhaps we should not need to call DMLabelClearValue()
254     PetscCall(DMLabelClearValue(label12, p, val + 1));
255     PetscCall(DMLabelSetValue(label12, p, val));
256     PetscCall(CheckLabelsSame(label02, label12));
257     PetscCall(CheckDMLabelsSame(dm, dm1));
258 
259     PetscCall(PetscObjectSetName((PetscObject)label12, "label12"));
260     PetscCall(CheckDMLabelsNotSame(dm, dm1));
261     PetscCall(PetscObjectSetName((PetscObject)label12, "label2"));
262     PetscCall(CheckDMLabelsSame(dm, dm1));
263 
264     PetscCall(DMDestroy(&dm1));
265   }
266 
267   /* remove label0 and label1 just to test manual removal; let label3 be removed automatically by DMDestroy() */
268   {
269     DMLabel label0, label1, label2;
270     PetscCall(DMGetLabel(dm, "label0", &label0));
271     PetscCall(DMGetLabel(dm, "label1", &label1));
272     PetscCheck(label0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label0 must not be NULL now");
273     PetscCheck(label1, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label1 must not be NULL now");
274     PetscCall(DMRemoveLabel(dm, "label1", NULL));
275     PetscCall(DMRemoveLabel(dm, "label2", &label2));
276     PetscCall(DMRemoveLabelBySelf(dm, &label0, PETSC_TRUE));
277     PetscCall(DMGetLabel(dm, "label0", &label0));
278     PetscCall(DMGetLabel(dm, "label1", &label1));
279     PetscCheck(!label0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label0 must be NULL now");
280     PetscCheck(!label1, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label1 must be NULL now");
281     PetscCheck(label2, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label2 must not be NULL now");
282     PetscCall(DMRemoveLabelBySelf(dm, &label2, PETSC_FALSE)); /* this should do nothing */
283     PetscCheck(label2, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label2 must not be NULL now");
284     PetscCall(DMLabelDestroy(&label2));
285     PetscCall(DMGetLabel(dm, "label2", &label2));
286     PetscCheck(!label2, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "label2 must be NULL now");
287   }
288 
289   PetscCall(DMDestroy(&dm));
290   PetscCall(PetscFinalize());
291   return 0;
292 }
293 
294 /*TEST
295 
296   test:
297     suffix: 0
298     nsize: {{1 2}separate output}
299     args: -i ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.exo -interpolate
300     requires: exodusii
301 
302 TEST*/
303