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