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