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