1 #include <petscdm.h> 2 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3 #include <petsc/private/sectionimpl.h> /*I "petscsection.h" I*/ 4 #include <petscsf.h> 5 #include <petscsection.h> 6 7 /*@C 8 DMLabelCreate - Create a DMLabel object, which is a multimap 9 10 Collective 11 12 Input parameters: 13 + comm - The communicator, usually PETSC_COMM_SELF 14 - name - The label name 15 16 Output parameter: 17 . label - The DMLabel 18 19 Level: beginner 20 21 Notes: 22 The label name is actually usual PetscObject name. 23 One can get/set it with PetscObjectGetName()/PetscObjectSetName(). 24 25 .seealso: DMLabelDestroy() 26 @*/ 27 PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label) 28 { 29 PetscErrorCode ierr; 30 31 PetscFunctionBegin; 32 PetscValidPointer(label,3); 33 ierr = DMInitializePackage();CHKERRQ(ierr); 34 35 ierr = PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView);CHKERRQ(ierr); 36 37 (*label)->numStrata = 0; 38 (*label)->defaultValue = -1; 39 (*label)->stratumValues = NULL; 40 (*label)->validIS = NULL; 41 (*label)->stratumSizes = NULL; 42 (*label)->points = NULL; 43 (*label)->ht = NULL; 44 (*label)->pStart = -1; 45 (*label)->pEnd = -1; 46 (*label)->bt = NULL; 47 ierr = PetscHMapICreate(&(*label)->hmap);CHKERRQ(ierr); 48 ierr = PetscObjectSetName((PetscObject) *label, name);CHKERRQ(ierr); 49 PetscFunctionReturn(0); 50 } 51 52 /* 53 DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format 54 55 Not collective 56 57 Input parameter: 58 + label - The DMLabel 59 - v - The stratum value 60 61 Output parameter: 62 . label - The DMLabel with stratum in sorted list format 63 64 Level: developer 65 66 .seealso: DMLabelCreate() 67 */ 68 static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v) 69 { 70 IS is; 71 PetscInt off = 0, *pointArray, p; 72 PetscErrorCode ierr; 73 74 if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0; 75 PetscFunctionBegin; 76 if (v < 0 || v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeValid_Private\n", v); 77 ierr = PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]);CHKERRQ(ierr); 78 ierr = PetscMalloc1(label->stratumSizes[v], &pointArray);CHKERRQ(ierr); 79 ierr = PetscHSetIGetElems(label->ht[v], &off, pointArray);CHKERRQ(ierr); 80 ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr); 81 ierr = PetscSortInt(label->stratumSizes[v], pointArray);CHKERRQ(ierr); 82 if (label->bt) { 83 for (p = 0; p < label->stratumSizes[v]; ++p) { 84 const PetscInt point = pointArray[p]; 85 if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd); 86 ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr); 87 } 88 } 89 if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v]-1] == pointArray[0] + label->stratumSizes[v]-1) { 90 ierr = ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is);CHKERRQ(ierr); 91 ierr = PetscFree(pointArray);CHKERRQ(ierr); 92 } else { 93 ierr = ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is);CHKERRQ(ierr); 94 } 95 ierr = PetscObjectSetName((PetscObject) is, "indices");CHKERRQ(ierr); 96 label->points[v] = is; 97 label->validIS[v] = PETSC_TRUE; 98 ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr); 99 PetscFunctionReturn(0); 100 } 101 102 /* 103 DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format 104 105 Not collective 106 107 Input parameter: 108 . label - The DMLabel 109 110 Output parameter: 111 . label - The DMLabel with all strata in sorted list format 112 113 Level: developer 114 115 .seealso: DMLabelCreate() 116 */ 117 static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label) 118 { 119 PetscInt v; 120 PetscErrorCode ierr; 121 122 PetscFunctionBegin; 123 for (v = 0; v < label->numStrata; v++) { 124 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 125 } 126 PetscFunctionReturn(0); 127 } 128 129 /* 130 DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format 131 132 Not collective 133 134 Input parameter: 135 + label - The DMLabel 136 - v - The stratum value 137 138 Output parameter: 139 . label - The DMLabel with stratum in hash format 140 141 Level: developer 142 143 .seealso: DMLabelCreate() 144 */ 145 static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v) 146 { 147 PetscInt p; 148 const PetscInt *points; 149 PetscErrorCode ierr; 150 151 if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0; 152 PetscFunctionBegin; 153 if (v < 0 || v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeInvalid_Private\n", v); 154 if (label->points[v]) { 155 ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr); 156 for (p = 0; p < label->stratumSizes[v]; ++p) { 157 ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr); 158 } 159 ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr); 160 ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr); 161 } 162 label->validIS[v] = PETSC_FALSE; 163 PetscFunctionReturn(0); 164 } 165 166 #if !defined(DMLABEL_LOOKUP_THRESHOLD) 167 #define DMLABEL_LOOKUP_THRESHOLD 16 168 #endif 169 170 PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index) 171 { 172 PetscInt v; 173 PetscErrorCode ierr; 174 175 PetscFunctionBegin; 176 *index = -1; 177 if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) { 178 for (v = 0; v < label->numStrata; ++v) 179 if (label->stratumValues[v] == value) {*index = v; break;} 180 } else { 181 ierr = PetscHMapIGet(label->hmap, value, index);CHKERRQ(ierr); 182 } 183 if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */ 184 PetscInt len, loc = -1; 185 ierr = PetscHMapIGetSize(label->hmap, &len);CHKERRQ(ierr); 186 if (len != label->numStrata) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size"); 187 if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) { 188 ierr = PetscHMapIGet(label->hmap, value, &loc);CHKERRQ(ierr); 189 } else { 190 for (v = 0; v < label->numStrata; ++v) 191 if (label->stratumValues[v] == value) {loc = v; break;} 192 } 193 if (loc != *index) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup"); 194 } 195 PetscFunctionReturn(0); 196 } 197 198 PETSC_STATIC_INLINE PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index) 199 { 200 PetscInt v; 201 PetscInt *tmpV; 202 PetscInt *tmpS; 203 PetscHSetI *tmpH, ht; 204 IS *tmpP, is; 205 PetscBool *tmpB; 206 PetscHMapI hmap = label->hmap; 207 PetscErrorCode ierr; 208 209 PetscFunctionBegin; 210 v = label->numStrata; 211 tmpV = label->stratumValues; 212 tmpS = label->stratumSizes; 213 tmpH = label->ht; 214 tmpP = label->points; 215 tmpB = label->validIS; 216 { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free */ 217 PetscInt *oldV = tmpV; 218 PetscInt *oldS = tmpS; 219 PetscHSetI *oldH = tmpH; 220 IS *oldP = tmpP; 221 PetscBool *oldB = tmpB; 222 ierr = PetscMalloc((v+1)*sizeof(*tmpV), &tmpV);CHKERRQ(ierr); 223 ierr = PetscMalloc((v+1)*sizeof(*tmpS), &tmpS);CHKERRQ(ierr); 224 ierr = PetscMalloc((v+1)*sizeof(*tmpH), &tmpH);CHKERRQ(ierr); 225 ierr = PetscMalloc((v+1)*sizeof(*tmpP), &tmpP);CHKERRQ(ierr); 226 ierr = PetscMalloc((v+1)*sizeof(*tmpB), &tmpB);CHKERRQ(ierr); 227 ierr = PetscArraycpy(tmpV, oldV, v);CHKERRQ(ierr); 228 ierr = PetscArraycpy(tmpS, oldS, v);CHKERRQ(ierr); 229 ierr = PetscArraycpy(tmpH, oldH, v);CHKERRQ(ierr); 230 ierr = PetscArraycpy(tmpP, oldP, v);CHKERRQ(ierr); 231 ierr = PetscArraycpy(tmpB, oldB, v);CHKERRQ(ierr); 232 ierr = PetscFree(oldV);CHKERRQ(ierr); 233 ierr = PetscFree(oldS);CHKERRQ(ierr); 234 ierr = PetscFree(oldH);CHKERRQ(ierr); 235 ierr = PetscFree(oldP);CHKERRQ(ierr); 236 ierr = PetscFree(oldB);CHKERRQ(ierr); 237 } 238 label->numStrata = v+1; 239 label->stratumValues = tmpV; 240 label->stratumSizes = tmpS; 241 label->ht = tmpH; 242 label->points = tmpP; 243 label->validIS = tmpB; 244 ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 245 ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr); 246 ierr = PetscHMapISet(hmap, value, v);CHKERRQ(ierr); 247 tmpV[v] = value; 248 tmpS[v] = 0; 249 tmpH[v] = ht; 250 tmpP[v] = is; 251 tmpB[v] = PETSC_TRUE; 252 ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr); 253 *index = v; 254 PetscFunctionReturn(0); 255 } 256 257 PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index) 258 { 259 PetscErrorCode ierr; 260 PetscFunctionBegin; 261 ierr = DMLabelLookupStratum(label, value, index);CHKERRQ(ierr); 262 if (*index < 0) {ierr = DMLabelNewStratum(label, value, index);CHKERRQ(ierr);} 263 PetscFunctionReturn(0); 264 } 265 266 /*@ 267 DMLabelAddStratum - Adds a new stratum value in a DMLabel 268 269 Input Parameters: 270 + label - The DMLabel 271 - value - The stratum value 272 273 Level: beginner 274 275 .seealso: DMLabelCreate(), DMLabelDestroy() 276 @*/ 277 PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value) 278 { 279 PetscInt v; 280 PetscErrorCode ierr; 281 282 PetscFunctionBegin; 283 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 284 ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr); 285 PetscFunctionReturn(0); 286 } 287 288 /*@ 289 DMLabelAddStrata - Adds new stratum values in a DMLabel 290 291 Not collective 292 293 Input Parameters: 294 + label - The DMLabel 295 . numStrata - The number of stratum values 296 - stratumValues - The stratum values 297 298 Level: beginner 299 300 .seealso: DMLabelCreate(), DMLabelDestroy() 301 @*/ 302 PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[]) 303 { 304 PetscInt *values, v; 305 PetscErrorCode ierr; 306 307 PetscFunctionBegin; 308 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 309 if (numStrata) PetscValidIntPointer(stratumValues, 3); 310 ierr = PetscMalloc1(numStrata, &values);CHKERRQ(ierr); 311 ierr = PetscArraycpy(values, stratumValues, numStrata);CHKERRQ(ierr); 312 ierr = PetscSortRemoveDupsInt(&numStrata, values);CHKERRQ(ierr); 313 if (!label->numStrata) { /* Fast preallocation */ 314 PetscInt *tmpV; 315 PetscInt *tmpS; 316 PetscHSetI *tmpH, ht; 317 IS *tmpP, is; 318 PetscBool *tmpB; 319 PetscHMapI hmap = label->hmap; 320 321 ierr = PetscMalloc1(numStrata, &tmpV);CHKERRQ(ierr); 322 ierr = PetscMalloc1(numStrata, &tmpS);CHKERRQ(ierr); 323 ierr = PetscMalloc1(numStrata, &tmpH);CHKERRQ(ierr); 324 ierr = PetscMalloc1(numStrata, &tmpP);CHKERRQ(ierr); 325 ierr = PetscMalloc1(numStrata, &tmpB);CHKERRQ(ierr); 326 label->numStrata = numStrata; 327 label->stratumValues = tmpV; 328 label->stratumSizes = tmpS; 329 label->ht = tmpH; 330 label->points = tmpP; 331 label->validIS = tmpB; 332 for (v = 0; v < numStrata; ++v) { 333 ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 334 ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr); 335 ierr = PetscHMapISet(hmap, values[v], v);CHKERRQ(ierr); 336 tmpV[v] = values[v]; 337 tmpS[v] = 0; 338 tmpH[v] = ht; 339 tmpP[v] = is; 340 tmpB[v] = PETSC_TRUE; 341 } 342 ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr); 343 } else { 344 for (v = 0; v < numStrata; ++v) { 345 ierr = DMLabelAddStratum(label, values[v]);CHKERRQ(ierr); 346 } 347 } 348 ierr = PetscFree(values);CHKERRQ(ierr); 349 PetscFunctionReturn(0); 350 } 351 352 /*@ 353 DMLabelAddStrataIS - Adds new stratum values in a DMLabel 354 355 Not collective 356 357 Input Parameters: 358 + label - The DMLabel 359 - valueIS - Index set with stratum values 360 361 Level: beginner 362 363 .seealso: DMLabelCreate(), DMLabelDestroy() 364 @*/ 365 PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS) 366 { 367 PetscInt numStrata; 368 const PetscInt *stratumValues; 369 PetscErrorCode ierr; 370 371 PetscFunctionBegin; 372 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 373 PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2); 374 ierr = ISGetLocalSize(valueIS, &numStrata);CHKERRQ(ierr); 375 ierr = ISGetIndices(valueIS, &stratumValues);CHKERRQ(ierr); 376 ierr = DMLabelAddStrata(label, numStrata, stratumValues);CHKERRQ(ierr); 377 PetscFunctionReturn(0); 378 } 379 380 static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer) 381 { 382 PetscInt v; 383 PetscMPIInt rank; 384 PetscErrorCode ierr; 385 386 PetscFunctionBegin; 387 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr); 388 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 389 if (label) { 390 const char *name; 391 392 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 393 ierr = PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name);CHKERRQ(ierr); 394 if (label->bt) {ierr = PetscViewerASCIIPrintf(viewer, " Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd);CHKERRQ(ierr);} 395 for (v = 0; v < label->numStrata; ++v) { 396 const PetscInt value = label->stratumValues[v]; 397 const PetscInt *points; 398 PetscInt p; 399 400 ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr); 401 for (p = 0; p < label->stratumSizes[v]; ++p) { 402 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, points[p], value);CHKERRQ(ierr); 403 } 404 ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr); 405 } 406 } 407 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 408 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 409 PetscFunctionReturn(0); 410 } 411 412 /*@C 413 DMLabelView - View the label 414 415 Collective on viewer 416 417 Input Parameters: 418 + label - The DMLabel 419 - viewer - The PetscViewer 420 421 Level: intermediate 422 423 .seealso: DMLabelCreate(), DMLabelDestroy() 424 @*/ 425 PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer) 426 { 427 PetscBool iascii; 428 PetscErrorCode ierr; 429 430 PetscFunctionBegin; 431 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 432 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer);CHKERRQ(ierr);} 433 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 434 if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);} 435 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 436 if (iascii) { 437 ierr = DMLabelView_Ascii(label, viewer);CHKERRQ(ierr); 438 } 439 PetscFunctionReturn(0); 440 } 441 442 /*@ 443 DMLabelReset - Destroys internal data structures in a DMLabel 444 445 Not collective 446 447 Input Parameter: 448 . label - The DMLabel 449 450 Level: beginner 451 452 .seealso: DMLabelDestroy(), DMLabelCreate() 453 @*/ 454 PetscErrorCode DMLabelReset(DMLabel label) 455 { 456 PetscInt v; 457 PetscErrorCode ierr; 458 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 461 for (v = 0; v < label->numStrata; ++v) { 462 ierr = PetscHSetIDestroy(&label->ht[v]);CHKERRQ(ierr); 463 ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr); 464 } 465 label->numStrata = 0; 466 ierr = PetscFree(label->stratumValues);CHKERRQ(ierr); 467 ierr = PetscFree(label->stratumSizes);CHKERRQ(ierr); 468 ierr = PetscFree(label->ht);CHKERRQ(ierr); 469 ierr = PetscFree(label->points);CHKERRQ(ierr); 470 ierr = PetscFree(label->validIS);CHKERRQ(ierr); 471 label->stratumValues = NULL; 472 label->stratumSizes = NULL; 473 label->ht = NULL; 474 label->points = NULL; 475 label->validIS = NULL; 476 ierr = PetscHMapIReset(label->hmap);CHKERRQ(ierr); 477 label->pStart = -1; 478 label->pEnd = -1; 479 ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr); 480 PetscFunctionReturn(0); 481 } 482 483 /*@ 484 DMLabelDestroy - Destroys a DMLabel 485 486 Collective on label 487 488 Input Parameter: 489 . label - The DMLabel 490 491 Level: beginner 492 493 .seealso: DMLabelReset(), DMLabelCreate() 494 @*/ 495 PetscErrorCode DMLabelDestroy(DMLabel *label) 496 { 497 PetscErrorCode ierr; 498 499 PetscFunctionBegin; 500 if (!*label) PetscFunctionReturn(0); 501 PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1); 502 if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);} 503 ierr = DMLabelReset(*label);CHKERRQ(ierr); 504 ierr = PetscHMapIDestroy(&(*label)->hmap);CHKERRQ(ierr); 505 ierr = PetscHeaderDestroy(label);CHKERRQ(ierr); 506 PetscFunctionReturn(0); 507 } 508 509 /*@ 510 DMLabelDuplicate - Duplicates a DMLabel 511 512 Collective on label 513 514 Input Parameter: 515 . label - The DMLabel 516 517 Output Parameter: 518 . labelnew - location to put new vector 519 520 Level: intermediate 521 522 .seealso: DMLabelCreate(), DMLabelDestroy() 523 @*/ 524 PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew) 525 { 526 const char *name; 527 PetscInt v; 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 532 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 533 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 534 ierr = DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew);CHKERRQ(ierr); 535 536 (*labelnew)->numStrata = label->numStrata; 537 (*labelnew)->defaultValue = label->defaultValue; 538 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues);CHKERRQ(ierr); 539 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes);CHKERRQ(ierr); 540 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->ht);CHKERRQ(ierr); 541 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->points);CHKERRQ(ierr); 542 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->validIS);CHKERRQ(ierr); 543 for (v = 0; v < label->numStrata; ++v) { 544 ierr = PetscHSetICreate(&(*labelnew)->ht[v]);CHKERRQ(ierr); 545 (*labelnew)->stratumValues[v] = label->stratumValues[v]; 546 (*labelnew)->stratumSizes[v] = label->stratumSizes[v]; 547 ierr = PetscObjectReference((PetscObject) (label->points[v]));CHKERRQ(ierr); 548 (*labelnew)->points[v] = label->points[v]; 549 (*labelnew)->validIS[v] = PETSC_TRUE; 550 } 551 ierr = PetscHMapIDestroy(&(*labelnew)->hmap);CHKERRQ(ierr); 552 ierr = PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap);CHKERRQ(ierr); 553 (*labelnew)->pStart = -1; 554 (*labelnew)->pEnd = -1; 555 (*labelnew)->bt = NULL; 556 PetscFunctionReturn(0); 557 } 558 559 /*@ 560 DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds 561 562 Not collective 563 564 Input Parameter: 565 . label - The DMLabel 566 567 Level: intermediate 568 569 .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue() 570 @*/ 571 PetscErrorCode DMLabelComputeIndex(DMLabel label) 572 { 573 PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v; 574 PetscErrorCode ierr; 575 576 PetscFunctionBegin; 577 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 578 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 579 for (v = 0; v < label->numStrata; ++v) { 580 const PetscInt *points; 581 PetscInt i; 582 583 ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr); 584 for (i = 0; i < label->stratumSizes[v]; ++i) { 585 const PetscInt point = points[i]; 586 587 pStart = PetscMin(point, pStart); 588 pEnd = PetscMax(point+1, pEnd); 589 } 590 ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr); 591 } 592 label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart; 593 label->pEnd = pEnd; 594 ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr); 595 PetscFunctionReturn(0); 596 } 597 598 /*@ 599 DMLabelCreateIndex - Create an index structure for membership determination 600 601 Not collective 602 603 Input Parameters: 604 + label - The DMLabel 605 . pStart - The smallest point 606 - pEnd - The largest point + 1 607 608 Level: intermediate 609 610 .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue() 611 @*/ 612 PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd) 613 { 614 PetscInt v; 615 PetscErrorCode ierr; 616 617 PetscFunctionBegin; 618 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 619 ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr); 620 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 621 label->pStart = pStart; 622 label->pEnd = pEnd; 623 /* This can be hooked into SetValue(), ClearValue(), etc. for updating */ 624 ierr = PetscBTCreate(pEnd - pStart, &label->bt);CHKERRQ(ierr); 625 for (v = 0; v < label->numStrata; ++v) { 626 const PetscInt *points; 627 PetscInt i; 628 629 ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr); 630 for (i = 0; i < label->stratumSizes[v]; ++i) { 631 const PetscInt point = points[i]; 632 633 if ((point < pStart) || (point >= pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, pStart, pEnd); 634 ierr = PetscBTSet(label->bt, point - pStart);CHKERRQ(ierr); 635 } 636 ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr); 637 } 638 PetscFunctionReturn(0); 639 } 640 641 /*@ 642 DMLabelDestroyIndex - Destroy the index structure 643 644 Not collective 645 646 Input Parameter: 647 . label - the DMLabel 648 649 Level: intermediate 650 651 .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue() 652 @*/ 653 PetscErrorCode DMLabelDestroyIndex(DMLabel label) 654 { 655 PetscErrorCode ierr; 656 657 PetscFunctionBegin; 658 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 659 label->pStart = -1; 660 label->pEnd = -1; 661 ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr); 662 PetscFunctionReturn(0); 663 } 664 665 /*@ 666 DMLabelGetBounds - Return the smallest and largest point in the label 667 668 Not collective 669 670 Input Parameter: 671 . label - the DMLabel 672 673 Output Parameters: 674 + pStart - The smallest point 675 - pEnd - The largest point + 1 676 677 Note: This will compute an index for the label if one does not exist. 678 679 Level: intermediate 680 681 .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue() 682 @*/ 683 PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd) 684 { 685 PetscErrorCode ierr; 686 687 PetscFunctionBegin; 688 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 689 if ((label->pStart == -1) && (label->pEnd == -1)) {ierr = DMLabelComputeIndex(label);CHKERRQ(ierr);} 690 if (pStart) { 691 PetscValidIntPointer(pStart, 2); 692 *pStart = label->pStart; 693 } 694 if (pEnd) { 695 PetscValidIntPointer(pEnd, 3); 696 *pEnd = label->pEnd; 697 } 698 PetscFunctionReturn(0); 699 } 700 701 /*@ 702 DMLabelHasValue - Determine whether a label assigns the value to any point 703 704 Not collective 705 706 Input Parameters: 707 + label - the DMLabel 708 - value - the value 709 710 Output Parameter: 711 . contains - Flag indicating whether the label maps this value to any point 712 713 Level: developer 714 715 .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue() 716 @*/ 717 PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains) 718 { 719 PetscInt v; 720 PetscErrorCode ierr; 721 722 PetscFunctionBegin; 723 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 724 PetscValidBoolPointer(contains, 3); 725 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 726 *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE; 727 PetscFunctionReturn(0); 728 } 729 730 /*@ 731 DMLabelHasPoint - Determine whether a label assigns a value to a point 732 733 Not collective 734 735 Input Parameters: 736 + label - the DMLabel 737 - point - the point 738 739 Output Parameter: 740 . contains - Flag indicating whether the label maps this point to a value 741 742 Note: The user must call DMLabelCreateIndex() before this function. 743 744 Level: developer 745 746 .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue() 747 @*/ 748 PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains) 749 { 750 PetscErrorCode ierr; 751 752 PetscFunctionBeginHot; 753 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 754 PetscValidBoolPointer(contains, 3); 755 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 756 if (PetscDefined(USE_DEBUG)) { 757 if (!label->bt) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()"); 758 if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd); 759 } 760 *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE; 761 PetscFunctionReturn(0); 762 } 763 764 /*@ 765 DMLabelStratumHasPoint - Return true if the stratum contains a point 766 767 Not collective 768 769 Input Parameters: 770 + label - the DMLabel 771 . value - the stratum value 772 - point - the point 773 774 Output Parameter: 775 . contains - true if the stratum contains the point 776 777 Level: intermediate 778 779 .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue() 780 @*/ 781 PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains) 782 { 783 PetscInt v; 784 PetscErrorCode ierr; 785 786 PetscFunctionBeginHot; 787 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 788 PetscValidBoolPointer(contains, 4); 789 *contains = PETSC_FALSE; 790 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 791 if (v < 0) PetscFunctionReturn(0); 792 793 if (label->validIS[v]) { 794 PetscInt i; 795 796 ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr); 797 if (i >= 0) *contains = PETSC_TRUE; 798 } else { 799 PetscBool has; 800 801 ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr); 802 if (has) *contains = PETSC_TRUE; 803 } 804 PetscFunctionReturn(0); 805 } 806 807 /*@ 808 DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value. 809 When a label is created, it is initialized to -1. 810 811 Not collective 812 813 Input parameter: 814 . label - a DMLabel object 815 816 Output parameter: 817 . defaultValue - the default value 818 819 Level: beginner 820 821 .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue() 822 @*/ 823 PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue) 824 { 825 PetscFunctionBegin; 826 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 827 *defaultValue = label->defaultValue; 828 PetscFunctionReturn(0); 829 } 830 831 /*@ 832 DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value. 833 When a label is created, it is initialized to -1. 834 835 Not collective 836 837 Input parameter: 838 . label - a DMLabel object 839 840 Output parameter: 841 . defaultValue - the default value 842 843 Level: beginner 844 845 .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue() 846 @*/ 847 PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue) 848 { 849 PetscFunctionBegin; 850 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 851 label->defaultValue = defaultValue; 852 PetscFunctionReturn(0); 853 } 854 855 /*@ 856 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()) 857 858 Not collective 859 860 Input Parameters: 861 + label - the DMLabel 862 - point - the point 863 864 Output Parameter: 865 . value - The point value, or the default value (-1 by default) 866 867 Level: intermediate 868 869 .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue() 870 @*/ 871 PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value) 872 { 873 PetscInt v; 874 PetscErrorCode ierr; 875 876 PetscFunctionBeginHot; 877 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 878 PetscValidPointer(value, 3); 879 *value = label->defaultValue; 880 for (v = 0; v < label->numStrata; ++v) { 881 if (label->validIS[v]) { 882 PetscInt i; 883 884 ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr); 885 if (i >= 0) { 886 *value = label->stratumValues[v]; 887 break; 888 } 889 } else { 890 PetscBool has; 891 892 ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr); 893 if (has) { 894 *value = label->stratumValues[v]; 895 break; 896 } 897 } 898 } 899 PetscFunctionReturn(0); 900 } 901 902 /*@ 903 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. 904 905 Not collective 906 907 Input Parameters: 908 + label - the DMLabel 909 . point - the point 910 - value - The point value 911 912 Level: intermediate 913 914 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue() 915 @*/ 916 PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value) 917 { 918 PetscInt v; 919 PetscErrorCode ierr; 920 921 PetscFunctionBegin; 922 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 923 /* Find label value, add new entry if needed */ 924 if (value == label->defaultValue) PetscFunctionReturn(0); 925 ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr); 926 /* Set key */ 927 ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr); 928 ierr = PetscHSetIAdd(label->ht[v], point);CHKERRQ(ierr); 929 PetscFunctionReturn(0); 930 } 931 932 /*@ 933 DMLabelClearValue - Clear the value a label assigns to a point 934 935 Not collective 936 937 Input Parameters: 938 + label - the DMLabel 939 . point - the point 940 - value - The point value 941 942 Level: intermediate 943 944 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue() 945 @*/ 946 PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value) 947 { 948 PetscInt v; 949 PetscErrorCode ierr; 950 951 PetscFunctionBegin; 952 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 953 /* Find label value */ 954 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 955 if (v < 0) PetscFunctionReturn(0); 956 957 if (label->bt) { 958 if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd); 959 ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr); 960 } 961 962 /* Delete key */ 963 ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr); 964 ierr = PetscHSetIDel(label->ht[v], point);CHKERRQ(ierr); 965 PetscFunctionReturn(0); 966 } 967 968 /*@ 969 DMLabelInsertIS - Set all points in the IS to a value 970 971 Not collective 972 973 Input Parameters: 974 + label - the DMLabel 975 . is - the point IS 976 - value - The point value 977 978 Level: intermediate 979 980 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 981 @*/ 982 PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value) 983 { 984 PetscInt v, n, p; 985 const PetscInt *points; 986 PetscErrorCode ierr; 987 988 PetscFunctionBegin; 989 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 990 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 991 /* Find label value, add new entry if needed */ 992 if (value == label->defaultValue) PetscFunctionReturn(0); 993 ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr); 994 /* Set keys */ 995 ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr); 996 ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr); 997 ierr = ISGetIndices(is, &points);CHKERRQ(ierr); 998 for (p = 0; p < n; ++p) {ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);} 999 ierr = ISRestoreIndices(is, &points);CHKERRQ(ierr); 1000 PetscFunctionReturn(0); 1001 } 1002 1003 /*@ 1004 DMLabelGetNumValues - Get the number of values that the DMLabel takes 1005 1006 Not collective 1007 1008 Input Parameter: 1009 . label - the DMLabel 1010 1011 Output Parameter: 1012 . numValues - the number of values 1013 1014 Level: intermediate 1015 1016 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1017 @*/ 1018 PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues) 1019 { 1020 PetscFunctionBegin; 1021 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1022 PetscValidPointer(numValues, 2); 1023 *numValues = label->numStrata; 1024 PetscFunctionReturn(0); 1025 } 1026 1027 /*@ 1028 DMLabelGetValueIS - Get an IS of all values that the DMlabel takes 1029 1030 Not collective 1031 1032 Input Parameter: 1033 . label - the DMLabel 1034 1035 Output Parameter: 1036 . is - the value IS 1037 1038 Level: intermediate 1039 1040 Notes: 1041 The output IS should be destroyed when no longer needed. 1042 1043 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1044 @*/ 1045 PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values) 1046 { 1047 PetscErrorCode ierr; 1048 1049 PetscFunctionBegin; 1050 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1051 PetscValidPointer(values, 2); 1052 ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr); 1053 PetscFunctionReturn(0); 1054 } 1055 1056 /*@ 1057 DMLabelGetValueIndex - Get the index of a given value in the list of values for the DMlabel, or -1 if it is not present 1058 1059 Not collective 1060 1061 Input Parameters: 1062 + label - the DMLabel 1063 - value - the value 1064 1065 Output Parameter: 1066 . index - the index of value in the list of values 1067 1068 Level: intermediate 1069 1070 .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1071 @*/ 1072 PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index) 1073 { 1074 PetscInt v; 1075 1076 PetscFunctionBegin; 1077 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1078 PetscValidPointer(index, 3); 1079 /* Do not assume they are sorted */ 1080 for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break; 1081 if (v >= label->numStrata) *index = -1; 1082 else *index = v; 1083 PetscFunctionReturn(0); 1084 } 1085 1086 /*@ 1087 DMLabelHasStratum - Determine whether points exist with the given value 1088 1089 Not collective 1090 1091 Input Parameters: 1092 + label - the DMLabel 1093 - value - the stratum value 1094 1095 Output Parameter: 1096 . exists - Flag saying whether points exist 1097 1098 Level: intermediate 1099 1100 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1101 @*/ 1102 PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists) 1103 { 1104 PetscInt v; 1105 PetscErrorCode ierr; 1106 1107 PetscFunctionBegin; 1108 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1109 PetscValidPointer(exists, 3); 1110 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 1111 *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE; 1112 PetscFunctionReturn(0); 1113 } 1114 1115 /*@ 1116 DMLabelGetStratumSize - Get the size of a stratum 1117 1118 Not collective 1119 1120 Input Parameters: 1121 + label - the DMLabel 1122 - value - the stratum value 1123 1124 Output Parameter: 1125 . size - The number of points in the stratum 1126 1127 Level: intermediate 1128 1129 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1130 @*/ 1131 PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size) 1132 { 1133 PetscInt v; 1134 PetscErrorCode ierr; 1135 1136 PetscFunctionBegin; 1137 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1138 PetscValidPointer(size, 3); 1139 *size = 0; 1140 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 1141 if (v < 0) PetscFunctionReturn(0); 1142 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 1143 *size = label->stratumSizes[v]; 1144 PetscFunctionReturn(0); 1145 } 1146 1147 /*@ 1148 DMLabelGetStratumBounds - Get the largest and smallest point of a stratum 1149 1150 Not collective 1151 1152 Input Parameters: 1153 + label - the DMLabel 1154 - value - the stratum value 1155 1156 Output Parameters: 1157 + start - the smallest point in the stratum 1158 - end - the largest point in the stratum 1159 1160 Level: intermediate 1161 1162 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1163 @*/ 1164 PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end) 1165 { 1166 PetscInt v, min, max; 1167 PetscErrorCode ierr; 1168 1169 PetscFunctionBegin; 1170 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1171 if (start) {PetscValidPointer(start, 3); *start = -1;} 1172 if (end) {PetscValidPointer(end, 4); *end = -1;} 1173 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 1174 if (v < 0) PetscFunctionReturn(0); 1175 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 1176 if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0); 1177 ierr = ISGetMinMax(label->points[v], &min, &max);CHKERRQ(ierr); 1178 if (start) *start = min; 1179 if (end) *end = max+1; 1180 PetscFunctionReturn(0); 1181 } 1182 1183 /*@ 1184 DMLabelGetStratumIS - Get an IS with the stratum points 1185 1186 Not collective 1187 1188 Input Parameters: 1189 + label - the DMLabel 1190 - value - the stratum value 1191 1192 Output Parameter: 1193 . points - The stratum points 1194 1195 Level: intermediate 1196 1197 Notes: 1198 The output IS should be destroyed when no longer needed. 1199 Returns NULL if the stratum is empty. 1200 1201 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1202 @*/ 1203 PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points) 1204 { 1205 PetscInt v; 1206 PetscErrorCode ierr; 1207 1208 PetscFunctionBegin; 1209 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1210 PetscValidPointer(points, 3); 1211 *points = NULL; 1212 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 1213 if (v < 0) PetscFunctionReturn(0); 1214 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 1215 ierr = PetscObjectReference((PetscObject) label->points[v]);CHKERRQ(ierr); 1216 *points = label->points[v]; 1217 PetscFunctionReturn(0); 1218 } 1219 1220 /*@ 1221 DMLabelSetStratumIS - Set the stratum points using an IS 1222 1223 Not collective 1224 1225 Input Parameters: 1226 + label - the DMLabel 1227 . value - the stratum value 1228 - points - The stratum points 1229 1230 Level: intermediate 1231 1232 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1233 @*/ 1234 PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is) 1235 { 1236 PetscInt v; 1237 PetscErrorCode ierr; 1238 1239 PetscFunctionBegin; 1240 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1241 PetscValidHeaderSpecific(is, IS_CLASSID, 3); 1242 ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr); 1243 if (is == label->points[v]) PetscFunctionReturn(0); 1244 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 1245 ierr = ISGetLocalSize(is, &(label->stratumSizes[v]));CHKERRQ(ierr); 1246 ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 1247 ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr); 1248 label->points[v] = is; 1249 label->validIS[v] = PETSC_TRUE; 1250 ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr); 1251 if (label->bt) { 1252 const PetscInt *points; 1253 PetscInt p; 1254 1255 ierr = ISGetIndices(is,&points);CHKERRQ(ierr); 1256 for (p = 0; p < label->stratumSizes[v]; ++p) { 1257 const PetscInt point = points[p]; 1258 1259 if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd); 1260 ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr); 1261 } 1262 } 1263 PetscFunctionReturn(0); 1264 } 1265 1266 /*@ 1267 DMLabelClearStratum - Remove a stratum 1268 1269 Not collective 1270 1271 Input Parameters: 1272 + label - the DMLabel 1273 - value - the stratum value 1274 1275 Level: intermediate 1276 1277 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1278 @*/ 1279 PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value) 1280 { 1281 PetscInt v; 1282 PetscErrorCode ierr; 1283 1284 PetscFunctionBegin; 1285 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1286 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 1287 if (v < 0) PetscFunctionReturn(0); 1288 if (label->validIS[v]) { 1289 if (label->bt) { 1290 PetscInt i; 1291 const PetscInt *points; 1292 1293 ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr); 1294 for (i = 0; i < label->stratumSizes[v]; ++i) { 1295 const PetscInt point = points[i]; 1296 1297 if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd); 1298 ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr); 1299 } 1300 ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr); 1301 } 1302 label->stratumSizes[v] = 0; 1303 ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr); 1304 ierr = ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]);CHKERRQ(ierr); 1305 ierr = PetscObjectSetName((PetscObject) label->points[v], "indices");CHKERRQ(ierr); 1306 ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr); 1307 } else { 1308 ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr); 1309 } 1310 PetscFunctionReturn(0); 1311 } 1312 1313 /*@ 1314 DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value 1315 1316 Not collective 1317 1318 Input Parameters: 1319 + label - The DMLabel 1320 . value - The label value for all points 1321 . pStart - The first point 1322 - pEnd - A point beyond all marked points 1323 1324 Note: The marks points are [pStart, pEnd), and only the bounds are stored. 1325 1326 Level: intermediate 1327 1328 .seealso: DMLabelCreate(), DMLabelSetStratumIS(), DMLabelGetStratumIS() 1329 @*/ 1330 PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd) 1331 { 1332 IS pIS; 1333 PetscErrorCode ierr; 1334 1335 PetscFunctionBegin; 1336 ierr = ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS);CHKERRQ(ierr); 1337 ierr = DMLabelSetStratumIS(label, value, pIS);CHKERRQ(ierr); 1338 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 1339 PetscFunctionReturn(0); 1340 } 1341 1342 /*@ 1343 DMLabelGetStratumPointIndex - Get the index of a point in a given stratum 1344 1345 Not collective 1346 1347 Input Parameters: 1348 + label - The DMLabel 1349 . value - The label value 1350 - p - A point with this value 1351 1352 Output Parameter: 1353 . 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 1354 1355 Level: intermediate 1356 1357 .seealso: DMLabelGetValueIndex(), DMLabelGetStratumIS(), DMLabelCreate() 1358 @*/ 1359 PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index) 1360 { 1361 const PetscInt *indices; 1362 PetscInt v; 1363 PetscErrorCode ierr; 1364 1365 PetscFunctionBegin; 1366 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1367 PetscValidPointer(index, 4); 1368 *index = -1; 1369 ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr); 1370 if (v < 0) PetscFunctionReturn(0); 1371 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 1372 ierr = ISGetIndices(label->points[v], &indices);CHKERRQ(ierr); 1373 ierr = PetscFindInt(p, label->stratumSizes[v], indices, index);CHKERRQ(ierr); 1374 ierr = ISRestoreIndices(label->points[v], &indices);CHKERRQ(ierr); 1375 PetscFunctionReturn(0); 1376 } 1377 1378 /*@ 1379 DMLabelFilter - Remove all points outside of [start, end) 1380 1381 Not collective 1382 1383 Input Parameters: 1384 + label - the DMLabel 1385 . start - the first point kept 1386 - end - one more than the last point kept 1387 1388 Level: intermediate 1389 1390 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1391 @*/ 1392 PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end) 1393 { 1394 PetscInt v; 1395 PetscErrorCode ierr; 1396 1397 PetscFunctionBegin; 1398 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1399 ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr); 1400 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 1401 for (v = 0; v < label->numStrata; ++v) { 1402 ierr = ISGeneralFilter(label->points[v], start, end);CHKERRQ(ierr); 1403 } 1404 ierr = DMLabelCreateIndex(label, start, end);CHKERRQ(ierr); 1405 PetscFunctionReturn(0); 1406 } 1407 1408 /*@ 1409 DMLabelPermute - Create a new label with permuted points 1410 1411 Not collective 1412 1413 Input Parameters: 1414 + label - the DMLabel 1415 - permutation - the point permutation 1416 1417 Output Parameter: 1418 . labelnew - the new label containing the permuted points 1419 1420 Level: intermediate 1421 1422 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1423 @*/ 1424 PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew) 1425 { 1426 const PetscInt *perm; 1427 PetscInt numValues, numPoints, v, q; 1428 PetscErrorCode ierr; 1429 1430 PetscFunctionBegin; 1431 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1432 PetscValidHeaderSpecific(permutation, IS_CLASSID, 2); 1433 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 1434 ierr = DMLabelDuplicate(label, labelNew);CHKERRQ(ierr); 1435 ierr = DMLabelGetNumValues(*labelNew, &numValues);CHKERRQ(ierr); 1436 ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr); 1437 ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr); 1438 for (v = 0; v < numValues; ++v) { 1439 const PetscInt size = (*labelNew)->stratumSizes[v]; 1440 const PetscInt *points; 1441 PetscInt *pointsNew; 1442 1443 ierr = ISGetIndices((*labelNew)->points[v],&points);CHKERRQ(ierr); 1444 ierr = PetscMalloc1(size,&pointsNew);CHKERRQ(ierr); 1445 for (q = 0; q < size; ++q) { 1446 const PetscInt point = points[q]; 1447 1448 if ((point < 0) || (point >= numPoints)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [0, %D) for the remapping", point, numPoints); 1449 pointsNew[q] = perm[point]; 1450 } 1451 ierr = ISRestoreIndices((*labelNew)->points[v],&points);CHKERRQ(ierr); 1452 ierr = PetscSortInt(size, pointsNew);CHKERRQ(ierr); 1453 ierr = ISDestroy(&((*labelNew)->points[v]));CHKERRQ(ierr); 1454 if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) { 1455 ierr = ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v]));CHKERRQ(ierr); 1456 ierr = PetscFree(pointsNew);CHKERRQ(ierr); 1457 } else { 1458 ierr = ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v]));CHKERRQ(ierr); 1459 } 1460 ierr = PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices");CHKERRQ(ierr); 1461 } 1462 ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr); 1463 if (label->bt) { 1464 ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr); 1465 ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr); 1466 } 1467 PetscFunctionReturn(0); 1468 } 1469 1470 PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata) 1471 { 1472 MPI_Comm comm; 1473 PetscInt s, l, nroots, nleaves, dof, offset, size; 1474 PetscInt *remoteOffsets, *rootStrata, *rootIdx; 1475 PetscSection rootSection; 1476 PetscSF labelSF; 1477 PetscErrorCode ierr; 1478 1479 PetscFunctionBegin; 1480 if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);} 1481 ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr); 1482 /* Build a section of stratum values per point, generate the according SF 1483 and distribute point-wise stratum values to leaves. */ 1484 ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL);CHKERRQ(ierr); 1485 ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 1486 ierr = PetscSectionSetChart(rootSection, 0, nroots);CHKERRQ(ierr); 1487 if (label) { 1488 for (s = 0; s < label->numStrata; ++s) { 1489 const PetscInt *points; 1490 1491 ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr); 1492 for (l = 0; l < label->stratumSizes[s]; l++) { 1493 ierr = PetscSectionGetDof(rootSection, points[l], &dof);CHKERRQ(ierr); 1494 ierr = PetscSectionSetDof(rootSection, points[l], dof+1);CHKERRQ(ierr); 1495 } 1496 ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr); 1497 } 1498 } 1499 ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 1500 /* Create a point-wise array of stratum values */ 1501 ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr); 1502 ierr = PetscMalloc1(size, &rootStrata);CHKERRQ(ierr); 1503 ierr = PetscCalloc1(nroots, &rootIdx);CHKERRQ(ierr); 1504 if (label) { 1505 for (s = 0; s < label->numStrata; ++s) { 1506 const PetscInt *points; 1507 1508 ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr); 1509 for (l = 0; l < label->stratumSizes[s]; l++) { 1510 const PetscInt p = points[l]; 1511 ierr = PetscSectionGetOffset(rootSection, p, &offset);CHKERRQ(ierr); 1512 rootStrata[offset+rootIdx[p]++] = label->stratumValues[s]; 1513 } 1514 ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr); 1515 } 1516 } 1517 /* Build SF that maps label points to remote processes */ 1518 ierr = PetscSectionCreate(comm, leafSection);CHKERRQ(ierr); 1519 ierr = PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection);CHKERRQ(ierr); 1520 ierr = PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF);CHKERRQ(ierr); 1521 ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 1522 /* Send the strata for each point over the derived SF */ 1523 ierr = PetscSectionGetStorageSize(*leafSection, &size);CHKERRQ(ierr); 1524 ierr = PetscMalloc1(size, leafStrata);CHKERRQ(ierr); 1525 ierr = PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE);CHKERRQ(ierr); 1526 ierr = PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE);CHKERRQ(ierr); 1527 /* Clean up */ 1528 ierr = PetscFree(rootStrata);CHKERRQ(ierr); 1529 ierr = PetscFree(rootIdx);CHKERRQ(ierr); 1530 ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 1531 ierr = PetscSFDestroy(&labelSF);CHKERRQ(ierr); 1532 PetscFunctionReturn(0); 1533 } 1534 1535 /*@ 1536 DMLabelDistribute - Create a new label pushed forward over the PetscSF 1537 1538 Collective on sf 1539 1540 Input Parameters: 1541 + label - the DMLabel 1542 - sf - the map from old to new distribution 1543 1544 Output Parameter: 1545 . labelnew - the new redistributed label 1546 1547 Level: intermediate 1548 1549 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 1550 @*/ 1551 PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew) 1552 { 1553 MPI_Comm comm; 1554 PetscSection leafSection; 1555 PetscInt p, pStart, pEnd, s, size, dof, offset, stratum; 1556 PetscInt *leafStrata, *strataIdx; 1557 PetscInt **points; 1558 const char *lname = NULL; 1559 char *name; 1560 PetscInt nameSize; 1561 PetscHSetI stratumHash; 1562 size_t len = 0; 1563 PetscMPIInt rank; 1564 PetscErrorCode ierr; 1565 1566 PetscFunctionBegin; 1567 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1568 if (label) { 1569 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1570 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 1571 } 1572 ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr); 1573 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1574 /* Bcast name */ 1575 if (rank == 0) { 1576 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 1577 ierr = PetscStrlen(lname, &len);CHKERRQ(ierr); 1578 } 1579 nameSize = len; 1580 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1581 ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr); 1582 if (rank == 0) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);} 1583 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr); 1584 ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr); 1585 ierr = PetscFree(name);CHKERRQ(ierr); 1586 /* Bcast defaultValue */ 1587 if (rank == 0) (*labelNew)->defaultValue = label->defaultValue; 1588 ierr = MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1589 /* Distribute stratum values over the SF and get the point mapping on the receiver */ 1590 ierr = DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata);CHKERRQ(ierr); 1591 /* Determine received stratum values and initialise new label*/ 1592 ierr = PetscHSetICreate(&stratumHash);CHKERRQ(ierr); 1593 ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr); 1594 for (p = 0; p < size; ++p) {ierr = PetscHSetIAdd(stratumHash, leafStrata[p]);CHKERRQ(ierr);} 1595 ierr = PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata);CHKERRQ(ierr); 1596 ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS);CHKERRQ(ierr); 1597 for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE; 1598 ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues);CHKERRQ(ierr); 1599 /* Turn leafStrata into indices rather than stratum values */ 1600 offset = 0; 1601 ierr = PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues);CHKERRQ(ierr); 1602 ierr = PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues);CHKERRQ(ierr); 1603 for (s = 0; s < (*labelNew)->numStrata; ++s) { 1604 ierr = PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s);CHKERRQ(ierr); 1605 } 1606 for (p = 0; p < size; ++p) { 1607 for (s = 0; s < (*labelNew)->numStrata; ++s) { 1608 if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;} 1609 } 1610 } 1611 /* Rebuild the point strata on the receiver */ 1612 ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes);CHKERRQ(ierr); 1613 ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr); 1614 for (p=pStart; p<pEnd; p++) { 1615 ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr); 1616 ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr); 1617 for (s=0; s<dof; s++) { 1618 (*labelNew)->stratumSizes[leafStrata[offset+s]]++; 1619 } 1620 } 1621 ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht);CHKERRQ(ierr); 1622 ierr = PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points);CHKERRQ(ierr); 1623 ierr = PetscMalloc1((*labelNew)->numStrata,&points);CHKERRQ(ierr); 1624 for (s = 0; s < (*labelNew)->numStrata; ++s) { 1625 ierr = PetscHSetICreate(&(*labelNew)->ht[s]);CHKERRQ(ierr); 1626 ierr = PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s]));CHKERRQ(ierr); 1627 } 1628 /* Insert points into new strata */ 1629 ierr = PetscCalloc1((*labelNew)->numStrata, &strataIdx);CHKERRQ(ierr); 1630 ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr); 1631 for (p=pStart; p<pEnd; p++) { 1632 ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr); 1633 ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr); 1634 for (s=0; s<dof; s++) { 1635 stratum = leafStrata[offset+s]; 1636 points[stratum][strataIdx[stratum]++] = p; 1637 } 1638 } 1639 for (s = 0; s < (*labelNew)->numStrata; s++) { 1640 ierr = ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s]));CHKERRQ(ierr); 1641 ierr = PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices");CHKERRQ(ierr); 1642 } 1643 ierr = PetscFree(points);CHKERRQ(ierr); 1644 ierr = PetscHSetIDestroy(&stratumHash);CHKERRQ(ierr); 1645 ierr = PetscFree(leafStrata);CHKERRQ(ierr); 1646 ierr = PetscFree(strataIdx);CHKERRQ(ierr); 1647 ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 1648 PetscFunctionReturn(0); 1649 } 1650 1651 /*@ 1652 DMLabelGather - Gather all label values from leafs into roots 1653 1654 Collective on sf 1655 1656 Input Parameters: 1657 + label - the DMLabel 1658 - sf - the Star Forest point communication map 1659 1660 Output Parameters: 1661 . labelNew - the new DMLabel with localised leaf values 1662 1663 Level: developer 1664 1665 Note: This is the inverse operation to DMLabelDistribute. 1666 1667 .seealso: DMLabelDistribute() 1668 @*/ 1669 PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew) 1670 { 1671 MPI_Comm comm; 1672 PetscSection rootSection; 1673 PetscSF sfLabel; 1674 PetscSFNode *rootPoints, *leafPoints; 1675 PetscInt p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset; 1676 const PetscInt *rootDegree, *ilocal; 1677 PetscInt *rootStrata; 1678 const char *lname; 1679 char *name; 1680 PetscInt nameSize; 1681 size_t len = 0; 1682 PetscMPIInt rank, size; 1683 PetscErrorCode ierr; 1684 1685 PetscFunctionBegin; 1686 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1687 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1688 ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr); 1689 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1690 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1691 /* Bcast name */ 1692 if (rank == 0) { 1693 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 1694 ierr = PetscStrlen(lname, &len);CHKERRQ(ierr); 1695 } 1696 nameSize = len; 1697 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr); 1698 ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr); 1699 if (rank == 0) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);} 1700 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr); 1701 ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr); 1702 ierr = PetscFree(name);CHKERRQ(ierr); 1703 /* Gather rank/index pairs of leaves into local roots to build 1704 an inverse, multi-rooted SF. Note that this ignores local leaf 1705 indexing due to the use of the multiSF in PetscSFGather. */ 1706 ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL);CHKERRQ(ierr); 1707 ierr = PetscMalloc1(nroots, &leafPoints);CHKERRQ(ierr); 1708 for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1; 1709 for (p = 0; p < nleaves; p++) { 1710 PetscInt ilp = ilocal ? ilocal[p] : p; 1711 1712 leafPoints[ilp].index = ilp; 1713 leafPoints[ilp].rank = rank; 1714 } 1715 ierr = PetscSFComputeDegreeBegin(sf, &rootDegree);CHKERRQ(ierr); 1716 ierr = PetscSFComputeDegreeEnd(sf, &rootDegree);CHKERRQ(ierr); 1717 for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p]; 1718 ierr = PetscMalloc1(nmultiroots, &rootPoints);CHKERRQ(ierr); 1719 ierr = PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr); 1720 ierr = PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr); 1721 ierr = PetscSFCreate(comm,& sfLabel);CHKERRQ(ierr); 1722 ierr = PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 1723 /* Migrate label over inverted SF to pull stratum values at leaves into roots. */ 1724 ierr = DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata);CHKERRQ(ierr); 1725 /* Rebuild the point strata on the receiver */ 1726 for (p = 0, idx = 0; p < nroots; p++) { 1727 for (d = 0; d < rootDegree[p]; d++) { 1728 ierr = PetscSectionGetDof(rootSection, idx+d, &dof);CHKERRQ(ierr); 1729 ierr = PetscSectionGetOffset(rootSection, idx+d, &offset);CHKERRQ(ierr); 1730 for (s = 0; s < dof; s++) {ierr = DMLabelSetValue(*labelNew, p, rootStrata[offset+s]);CHKERRQ(ierr);} 1731 } 1732 idx += rootDegree[p]; 1733 } 1734 ierr = PetscFree(leafPoints);CHKERRQ(ierr); 1735 ierr = PetscFree(rootStrata);CHKERRQ(ierr); 1736 ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 1737 ierr = PetscSFDestroy(&sfLabel);CHKERRQ(ierr); 1738 PetscFunctionReturn(0); 1739 } 1740 1741 /*@ 1742 DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label 1743 1744 Not collective 1745 1746 Input Parameter: 1747 . label - the DMLabel 1748 1749 Output Parameters: 1750 + section - the section giving offsets for each stratum 1751 - is - An IS containing all the label points 1752 1753 Level: developer 1754 1755 .seealso: DMLabelDistribute() 1756 @*/ 1757 PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is) 1758 { 1759 IS vIS; 1760 const PetscInt *values; 1761 PetscInt *points; 1762 PetscInt nV, vS = 0, vE = 0, v, N; 1763 PetscErrorCode ierr; 1764 1765 PetscFunctionBegin; 1766 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1); 1767 ierr = DMLabelGetNumValues(label, &nV);CHKERRQ(ierr); 1768 ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr); 1769 ierr = ISGetIndices(vIS, &values);CHKERRQ(ierr); 1770 if (nV) {vS = values[0]; vE = values[0]+1;} 1771 for (v = 1; v < nV; ++v) { 1772 vS = PetscMin(vS, values[v]); 1773 vE = PetscMax(vE, values[v]+1); 1774 } 1775 ierr = PetscSectionCreate(PETSC_COMM_SELF, section);CHKERRQ(ierr); 1776 ierr = PetscSectionSetChart(*section, vS, vE);CHKERRQ(ierr); 1777 for (v = 0; v < nV; ++v) { 1778 PetscInt n; 1779 1780 ierr = DMLabelGetStratumSize(label, values[v], &n);CHKERRQ(ierr); 1781 ierr = PetscSectionSetDof(*section, values[v], n);CHKERRQ(ierr); 1782 } 1783 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 1784 ierr = PetscSectionGetStorageSize(*section, &N);CHKERRQ(ierr); 1785 ierr = PetscMalloc1(N, &points);CHKERRQ(ierr); 1786 for (v = 0; v < nV; ++v) { 1787 IS is; 1788 const PetscInt *spoints; 1789 PetscInt dof, off, p; 1790 1791 ierr = PetscSectionGetDof(*section, values[v], &dof);CHKERRQ(ierr); 1792 ierr = PetscSectionGetOffset(*section, values[v], &off);CHKERRQ(ierr); 1793 ierr = DMLabelGetStratumIS(label, values[v], &is);CHKERRQ(ierr); 1794 ierr = ISGetIndices(is, &spoints);CHKERRQ(ierr); 1795 for (p = 0; p < dof; ++p) points[off+p] = spoints[p]; 1796 ierr = ISRestoreIndices(is, &spoints);CHKERRQ(ierr); 1797 ierr = ISDestroy(&is);CHKERRQ(ierr); 1798 } 1799 ierr = ISRestoreIndices(vIS, &values);CHKERRQ(ierr); 1800 ierr = ISDestroy(&vIS);CHKERRQ(ierr); 1801 ierr = ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 1802 PetscFunctionReturn(0); 1803 } 1804 1805 /*@ 1806 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 1807 the local section and an SF describing the section point overlap. 1808 1809 Collective on sf 1810 1811 Input Parameters: 1812 + s - The PetscSection for the local field layout 1813 . sf - The SF describing parallel layout of the section points 1814 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 1815 . label - The label specifying the points 1816 - labelValue - The label stratum specifying the points 1817 1818 Output Parameter: 1819 . gsection - The PetscSection for the global field layout 1820 1821 Note: This gives negative sizes and offsets to points not owned by this process 1822 1823 Level: developer 1824 1825 .seealso: PetscSectionCreate() 1826 @*/ 1827 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 1828 { 1829 PetscInt *neg = NULL, *tmpOff = NULL; 1830 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 1831 PetscErrorCode ierr; 1832 1833 PetscFunctionBegin; 1834 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1835 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1836 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 1837 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); 1838 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1839 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 1840 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 1841 if (nroots >= 0) { 1842 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 1843 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 1844 if (nroots > pEnd-pStart) { 1845 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 1846 } else { 1847 tmpOff = &(*gsection)->atlasDof[-pStart]; 1848 } 1849 } 1850 /* Mark ghost points with negative dof */ 1851 for (p = pStart; p < pEnd; ++p) { 1852 PetscInt value; 1853 1854 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 1855 if (value != labelValue) continue; 1856 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 1857 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 1858 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 1859 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 1860 if (neg) neg[p] = -(dof+1); 1861 } 1862 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 1863 if (nroots >= 0) { 1864 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr); 1865 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr); 1866 if (nroots > pEnd-pStart) { 1867 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 1868 } 1869 } 1870 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 1871 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1872 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 1873 (*gsection)->atlasOff[p] = off; 1874 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 1875 } 1876 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRMPI(ierr); 1877 globalOff -= off; 1878 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1879 (*gsection)->atlasOff[p] += globalOff; 1880 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 1881 } 1882 /* Put in negative offsets for ghost points */ 1883 if (nroots >= 0) { 1884 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr); 1885 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr); 1886 if (nroots > pEnd-pStart) { 1887 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 1888 } 1889 } 1890 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 1891 ierr = PetscFree(neg);CHKERRQ(ierr); 1892 PetscFunctionReturn(0); 1893 } 1894 1895 typedef struct _n_PetscSectionSym_Label 1896 { 1897 DMLabel label; 1898 PetscCopyMode *modes; 1899 PetscInt *sizes; 1900 const PetscInt ***perms; 1901 const PetscScalar ***rots; 1902 PetscInt (*minMaxOrients)[2]; 1903 PetscInt numStrata; /* numStrata is only increasing, functions as a state */ 1904 } PetscSectionSym_Label; 1905 1906 static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym) 1907 { 1908 PetscInt i, j; 1909 PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data; 1910 PetscErrorCode ierr; 1911 1912 PetscFunctionBegin; 1913 for (i = 0; i <= sl->numStrata; i++) { 1914 if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) { 1915 for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) { 1916 if (sl->perms[i]) {ierr = PetscFree(sl->perms[i][j]);CHKERRQ(ierr);} 1917 if (sl->rots[i]) {ierr = PetscFree(sl->rots[i][j]);CHKERRQ(ierr);} 1918 } 1919 if (sl->perms[i]) { 1920 const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]]; 1921 1922 ierr = PetscFree(perms);CHKERRQ(ierr); 1923 } 1924 if (sl->rots[i]) { 1925 const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]]; 1926 1927 ierr = PetscFree(rots);CHKERRQ(ierr); 1928 } 1929 } 1930 } 1931 ierr = PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients);CHKERRQ(ierr); 1932 ierr = DMLabelDestroy(&sl->label);CHKERRQ(ierr); 1933 sl->numStrata = 0; 1934 PetscFunctionReturn(0); 1935 } 1936 1937 static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym) 1938 { 1939 PetscErrorCode ierr; 1940 1941 PetscFunctionBegin; 1942 ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr); 1943 ierr = PetscFree(sym->data);CHKERRQ(ierr); 1944 PetscFunctionReturn(0); 1945 } 1946 1947 static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer) 1948 { 1949 PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data; 1950 PetscBool isAscii; 1951 DMLabel label = sl->label; 1952 const char *name; 1953 PetscErrorCode ierr; 1954 1955 PetscFunctionBegin; 1956 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr); 1957 if (isAscii) { 1958 PetscInt i, j, k; 1959 PetscViewerFormat format; 1960 1961 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1962 if (label) { 1963 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1964 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1965 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1966 ierr = DMLabelView(label, viewer);CHKERRQ(ierr); 1967 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1968 } else { 1969 ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr); 1970 ierr = PetscViewerASCIIPrintf(viewer," Label '%s'\n",name);CHKERRQ(ierr); 1971 } 1972 } else { 1973 ierr = PetscViewerASCIIPrintf(viewer, "No label given\n");CHKERRQ(ierr); 1974 } 1975 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1976 for (i = 0; i <= sl->numStrata; i++) { 1977 PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue; 1978 1979 if (!(sl->perms[i] || sl->rots[i])) { 1980 ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]);CHKERRQ(ierr); 1981 } else { 1982 ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]);CHKERRQ(ierr); 1983 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1984 ierr = PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]);CHKERRQ(ierr); 1985 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1986 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1987 for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) { 1988 if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) { 1989 ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j);CHKERRQ(ierr); 1990 } else { 1991 PetscInt tab; 1992 1993 ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j);CHKERRQ(ierr); 1994 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1995 ierr = PetscViewerASCIIGetTab(viewer,&tab);CHKERRQ(ierr); 1996 if (sl->perms[i] && sl->perms[i][j]) { 1997 ierr = PetscViewerASCIIPrintf(viewer,"Permutation:");CHKERRQ(ierr); 1998 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr); 1999 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]);CHKERRQ(ierr);} 2000 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 2001 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr); 2002 } 2003 if (sl->rots[i] && sl->rots[i][j]) { 2004 ierr = PetscViewerASCIIPrintf(viewer,"Rotations: ");CHKERRQ(ierr); 2005 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr); 2006 #if defined(PETSC_USE_COMPLEX) 2007 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f+i*%+f",PetscRealPart(sl->rots[i][j][k]),PetscImaginaryPart(sl->rots[i][j][k]));CHKERRQ(ierr);} 2008 #else 2009 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]);CHKERRQ(ierr);} 2010 #endif 2011 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 2012 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr); 2013 } 2014 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2015 } 2016 } 2017 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2018 } 2019 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2020 } 2021 } 2022 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2023 } 2024 PetscFunctionReturn(0); 2025 } 2026 2027 /*@ 2028 PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries 2029 2030 Logically collective on sym 2031 2032 Input parameters: 2033 + sym - the section symmetries 2034 - label - the DMLabel describing the types of points 2035 2036 Level: developer: 2037 2038 .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms() 2039 @*/ 2040 PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label) 2041 { 2042 PetscSectionSym_Label *sl; 2043 PetscErrorCode ierr; 2044 2045 PetscFunctionBegin; 2046 PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1); 2047 sl = (PetscSectionSym_Label *) sym->data; 2048 if (sl->label && sl->label != label) {ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);} 2049 if (label) { 2050 sl->label = label; 2051 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 2052 ierr = DMLabelGetNumValues(label,&sl->numStrata);CHKERRQ(ierr); 2053 ierr = 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);CHKERRQ(ierr); 2054 ierr = PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode));CHKERRQ(ierr); 2055 ierr = PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt));CHKERRQ(ierr); 2056 ierr = PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **));CHKERRQ(ierr); 2057 ierr = PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **));CHKERRQ(ierr); 2058 ierr = PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2]));CHKERRQ(ierr); 2059 } 2060 PetscFunctionReturn(0); 2061 } 2062 2063 /*@C 2064 PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum 2065 2066 Logically collective on sym 2067 2068 InputParameters: 2069 + sym - the section symmetries 2070 . stratum - the stratum value in the label that we are assigning symmetries for 2071 . size - the number of dofs for points in the stratum of the label 2072 . minOrient - the smallest orientation for a point in this stratum 2073 . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient)) 2074 . mode - how sym should copy the perms and rots arrays 2075 . perms - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation. A NULL permutation is the identity 2076 - 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 2077 2078 Level: developer 2079 2080 .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel() 2081 @*/ 2082 PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots) 2083 { 2084 PetscSectionSym_Label *sl; 2085 const char *name; 2086 PetscInt i, j, k; 2087 PetscErrorCode ierr; 2088 2089 PetscFunctionBegin; 2090 PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1); 2091 sl = (PetscSectionSym_Label *) sym->data; 2092 if (!sl->label) SETERRQ(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_WRONGSTATE,"No label set yet"); 2093 for (i = 0; i <= sl->numStrata; i++) { 2094 PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue; 2095 2096 if (stratum == value) break; 2097 } 2098 ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr); 2099 if (i > sl->numStrata) SETERRQ2(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_OUTOFRANGE,"Stratum %D not found in label %s\n",stratum,name); 2100 sl->sizes[i] = size; 2101 sl->modes[i] = mode; 2102 sl->minMaxOrients[i][0] = minOrient; 2103 sl->minMaxOrients[i][1] = maxOrient; 2104 if (mode == PETSC_COPY_VALUES) { 2105 if (perms) { 2106 PetscInt **ownPerms; 2107 2108 ierr = PetscCalloc1(maxOrient - minOrient,&ownPerms);CHKERRQ(ierr); 2109 for (j = 0; j < maxOrient-minOrient; j++) { 2110 if (perms[j]) { 2111 ierr = PetscMalloc1(size,&ownPerms[j]);CHKERRQ(ierr); 2112 for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];} 2113 } 2114 } 2115 sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient]; 2116 } 2117 if (rots) { 2118 PetscScalar **ownRots; 2119 2120 ierr = PetscCalloc1(maxOrient - minOrient,&ownRots);CHKERRQ(ierr); 2121 for (j = 0; j < maxOrient-minOrient; j++) { 2122 if (rots[j]) { 2123 ierr = PetscMalloc1(size,&ownRots[j]);CHKERRQ(ierr); 2124 for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];} 2125 } 2126 } 2127 sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient]; 2128 } 2129 } else { 2130 sl->perms[i] = perms ? &perms[-minOrient] : NULL; 2131 sl->rots[i] = rots ? &rots[-minOrient] : NULL; 2132 } 2133 PetscFunctionReturn(0); 2134 } 2135 2136 static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots) 2137 { 2138 PetscInt i, j, numStrata; 2139 PetscSectionSym_Label *sl; 2140 DMLabel label; 2141 PetscErrorCode ierr; 2142 2143 PetscFunctionBegin; 2144 sl = (PetscSectionSym_Label *) sym->data; 2145 numStrata = sl->numStrata; 2146 label = sl->label; 2147 for (i = 0; i < numPoints; i++) { 2148 PetscInt point = points[2*i]; 2149 PetscInt ornt = points[2*i+1]; 2150 2151 for (j = 0; j < numStrata; j++) { 2152 if (label->validIS[j]) { 2153 PetscInt k; 2154 2155 ierr = ISLocate(label->points[j],point,&k);CHKERRQ(ierr); 2156 if (k >= 0) break; 2157 } else { 2158 PetscBool has; 2159 2160 ierr = PetscHSetIHas(label->ht[j], point, &has);CHKERRQ(ierr); 2161 if (has) break; 2162 } 2163 } 2164 if ((sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) && (ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1])) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %D orientation %D not in range [%D, %D) for stratum %D",point,ornt,sl->minMaxOrients[j][0],sl->minMaxOrients[j][1],j < numStrata ? label->stratumValues[j] : label->defaultValue); 2165 if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;} 2166 if (rots) {rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;} 2167 } 2168 PetscFunctionReturn(0); 2169 } 2170 2171 PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym) 2172 { 2173 PetscSectionSym_Label *sl; 2174 PetscErrorCode ierr; 2175 2176 PetscFunctionBegin; 2177 ierr = PetscNewLog(sym,&sl);CHKERRQ(ierr); 2178 sym->ops->getpoints = PetscSectionSymGetPoints_Label; 2179 sym->ops->view = PetscSectionSymView_Label; 2180 sym->ops->destroy = PetscSectionSymDestroy_Label; 2181 sym->data = (void *) sl; 2182 PetscFunctionReturn(0); 2183 } 2184 2185 /*@ 2186 PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label 2187 2188 Collective 2189 2190 Input Parameters: 2191 + comm - the MPI communicator for the new symmetry 2192 - label - the label defining the strata 2193 2194 Output Parameters: 2195 . sym - the section symmetries 2196 2197 Level: developer 2198 2199 .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms() 2200 @*/ 2201 PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym) 2202 { 2203 PetscErrorCode ierr; 2204 2205 PetscFunctionBegin; 2206 ierr = DMInitializePackage();CHKERRQ(ierr); 2207 ierr = PetscSectionSymCreate(comm,sym);CHKERRQ(ierr); 2208 ierr = PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL);CHKERRQ(ierr); 2209 ierr = PetscSectionSymLabelSetLabel(*sym,label);CHKERRQ(ierr); 2210 PetscFunctionReturn(0); 2211 } 2212