1 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 2 #include <petsc/private/isimpl.h> /*I "petscis.h" I*/ 3 #include <petscsf.h> 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DMLabelCreate" 7 /*@C 8 DMLabelCreate - Create a DMLabel object, which is a multimap 9 10 Input parameter: 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(const char name[], DMLabel *label) 21 { 22 PetscErrorCode ierr; 23 24 PetscFunctionBegin; 25 ierr = PetscNew(label);CHKERRQ(ierr); 26 ierr = PetscStrallocpy(name, &(*label)->name);CHKERRQ(ierr); 27 28 (*label)->refct = 1; 29 (*label)->state = -1; 30 (*label)->numStrata = 0; 31 (*label)->defaultValue = -1; 32 (*label)->stratumValues = NULL; 33 (*label)->arrayValid = 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 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "DMLabelMakeValid_Private" 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; 62 PetscErrorCode ierr; 63 64 if (label->arrayValid[v]) return 0; 65 if (v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeValid_Private\n", v); 66 PetscFunctionBegin; 67 PetscHashISize(label->ht[v], label->stratumSizes[v]); 68 69 ierr = PetscMalloc1(label->stratumSizes[v], &label->points[v]);CHKERRQ(ierr); 70 off = 0; 71 ierr = PetscHashIGetKeys(label->ht[v], &off, &(label->points[v][0]));CHKERRQ(ierr); 72 if (off != label->stratumSizes[v]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of contributed points %D from value %D should be %D", off, label->stratumValues[v], label->stratumSizes[v]); 73 PetscHashIClear(label->ht[v]); 74 ierr = PetscSortInt(label->stratumSizes[v], label->points[v]);CHKERRQ(ierr); 75 if (label->bt) { 76 PetscInt p; 77 78 for (p = 0; p < label->stratumSizes[v]; ++p) { 79 const PetscInt point = label->points[v][p]; 80 81 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); 82 ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr); 83 } 84 } 85 label->arrayValid[v] = PETSC_TRUE; 86 ++label->state; 87 PetscFunctionReturn(0); 88 } 89 90 #undef __FUNCT__ 91 #define __FUNCT__ "DMLabelMakeAllValid_Private" 92 /* 93 DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format 94 95 Input parameter: 96 . label - The DMLabel 97 98 Output parameter: 99 . label - The DMLabel with all strata in sorted list format 100 101 Level: developer 102 103 .seealso: DMLabelCreate() 104 */ 105 static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label) 106 { 107 PetscInt v; 108 PetscErrorCode ierr; 109 110 PetscFunctionBegin; 111 for (v = 0; v < label->numStrata; v++){ 112 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 113 } 114 PetscFunctionReturn(0); 115 } 116 117 #undef __FUNCT__ 118 #define __FUNCT__ "DMLabelMakeInvalid_Private" 119 /* 120 DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format 121 122 Input parameter: 123 + label - The DMLabel 124 - v - The stratum value 125 126 Output parameter: 127 . label - The DMLabel with stratum in hash format 128 129 Level: developer 130 131 .seealso: DMLabelCreate() 132 */ 133 static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v) 134 { 135 PETSC_UNUSED PetscHashIIter ret, iter; 136 PetscInt p; 137 PetscErrorCode ierr; 138 139 PetscFunctionBegin; 140 if (!label->arrayValid[v]) PetscFunctionReturn(0); 141 for (p = 0; p < label->stratumSizes[v]; ++p) PetscHashIPut(label->ht[v], label->points[v][p], ret, iter); 142 ierr = PetscFree(label->points[v]);CHKERRQ(ierr); 143 label->arrayValid[v] = PETSC_FALSE; 144 PetscFunctionReturn(0); 145 } 146 147 #undef __FUNCT__ 148 #define __FUNCT__ "DMLabelGetState" 149 PetscErrorCode DMLabelGetState(DMLabel label, PetscObjectState *state) 150 { 151 PetscFunctionBegin; 152 PetscValidPointer(state, 2); 153 *state = label->state; 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "DMLabelAddStratum" 159 PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value) 160 { 161 PetscInt v, *tmpV, *tmpS, **tmpP; 162 PetscHashI *tmpH; 163 PetscBool *tmpB; 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 168 ierr = PetscMalloc1((label->numStrata+1), &tmpV);CHKERRQ(ierr); 169 ierr = PetscMalloc1((label->numStrata+1), &tmpS);CHKERRQ(ierr); 170 ierr = PetscMalloc1((label->numStrata+1), &tmpH);CHKERRQ(ierr); 171 ierr = PetscMalloc1((label->numStrata+1), &tmpP);CHKERRQ(ierr); 172 ierr = PetscMalloc1((label->numStrata+1), &tmpB);CHKERRQ(ierr); 173 for (v = 0; v < label->numStrata; ++v) { 174 tmpV[v] = label->stratumValues[v]; 175 tmpS[v] = label->stratumSizes[v]; 176 tmpH[v] = label->ht[v]; 177 tmpP[v] = label->points[v]; 178 tmpB[v] = label->arrayValid[v]; 179 } 180 tmpV[v] = value; 181 tmpS[v] = 0; 182 PetscHashICreate(tmpH[v]); 183 tmpP[v] = NULL; 184 tmpB[v] = PETSC_TRUE; 185 ++label->numStrata; 186 ierr = PetscFree(label->stratumValues);CHKERRQ(ierr); 187 ierr = PetscFree(label->stratumSizes);CHKERRQ(ierr); 188 ierr = PetscFree(label->ht);CHKERRQ(ierr); 189 ierr = PetscFree(label->points);CHKERRQ(ierr); 190 ierr = PetscFree(label->arrayValid);CHKERRQ(ierr); 191 label->stratumValues = tmpV; 192 label->stratumSizes = tmpS; 193 label->ht = tmpH; 194 label->points = tmpP; 195 label->arrayValid = tmpB; 196 197 PetscFunctionReturn(0); 198 } 199 200 #undef __FUNCT__ 201 #define __FUNCT__ "DMLabelGetName" 202 /*@C 203 DMLabelGetName - Return the name of a DMLabel object 204 205 Input parameter: 206 . label - The DMLabel 207 208 Output parameter: 209 . name - The label name 210 211 Level: beginner 212 213 .seealso: DMLabelCreate() 214 @*/ 215 PetscErrorCode DMLabelGetName(DMLabel label, const char **name) 216 { 217 PetscFunctionBegin; 218 PetscValidPointer(name, 2); 219 *name = label->name; 220 PetscFunctionReturn(0); 221 } 222 223 #undef __FUNCT__ 224 #define __FUNCT__ "DMLabelView_Ascii" 225 static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer) 226 { 227 PetscInt v; 228 PetscMPIInt rank; 229 PetscErrorCode ierr; 230 231 PetscFunctionBegin; 232 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr); 233 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 234 if (label) { 235 ierr = PetscViewerASCIIPrintf(viewer, "Label '%s':\n", label->name);CHKERRQ(ierr); 236 if (label->bt) {ierr = PetscViewerASCIIPrintf(viewer, " Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd);CHKERRQ(ierr);} 237 for (v = 0; v < label->numStrata; ++v) { 238 const PetscInt value = label->stratumValues[v]; 239 PetscInt p; 240 241 for (p = 0; p < label->stratumSizes[v]; ++p) { 242 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, label->points[v][p], value);CHKERRQ(ierr); 243 } 244 } 245 } 246 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 247 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 248 PetscFunctionReturn(0); 249 } 250 251 #undef __FUNCT__ 252 #define __FUNCT__ "DMLabelView" 253 /*@C 254 DMLabelView - View the label 255 256 Input Parameters: 257 + label - The DMLabel 258 - viewer - The PetscViewer 259 260 Level: intermediate 261 262 .seealso: DMLabelCreate(), DMLabelDestroy() 263 @*/ 264 PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer) 265 { 266 PetscBool iascii; 267 PetscErrorCode ierr; 268 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 271 if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);} 272 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 273 if (iascii) { 274 ierr = DMLabelView_Ascii(label, viewer);CHKERRQ(ierr); 275 } 276 PetscFunctionReturn(0); 277 } 278 279 #undef __FUNCT__ 280 #define __FUNCT__ "DMLabelDestroy" 281 PetscErrorCode DMLabelDestroy(DMLabel *label) 282 { 283 PetscInt v; 284 PetscErrorCode ierr; 285 286 PetscFunctionBegin; 287 if (!(*label)) PetscFunctionReturn(0); 288 if (--(*label)->refct > 0) PetscFunctionReturn(0); 289 ierr = PetscFree((*label)->name);CHKERRQ(ierr); 290 ierr = PetscFree((*label)->stratumValues);CHKERRQ(ierr); 291 ierr = PetscFree((*label)->stratumSizes);CHKERRQ(ierr); 292 for (v = 0; v < (*label)->numStrata; ++v) {ierr = PetscFree((*label)->points[v]);CHKERRQ(ierr);} 293 ierr = PetscFree((*label)->points);CHKERRQ(ierr); 294 ierr = PetscFree((*label)->arrayValid);CHKERRQ(ierr); 295 if ((*label)->ht) { 296 for (v = 0; v < (*label)->numStrata; ++v) {PetscHashIDestroy((*label)->ht[v]);} 297 ierr = PetscFree((*label)->ht);CHKERRQ(ierr); 298 } 299 ierr = PetscBTDestroy(&(*label)->bt);CHKERRQ(ierr); 300 ierr = PetscFree(*label);CHKERRQ(ierr); 301 PetscFunctionReturn(0); 302 } 303 304 #undef __FUNCT__ 305 #define __FUNCT__ "DMLabelDuplicate" 306 PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew) 307 { 308 PetscInt v, q; 309 PetscErrorCode ierr; 310 311 PetscFunctionBegin; 312 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 313 ierr = PetscNew(labelnew);CHKERRQ(ierr); 314 ierr = PetscStrallocpy(label->name, &(*labelnew)->name);CHKERRQ(ierr); 315 316 (*labelnew)->refct = 1; 317 (*labelnew)->numStrata = label->numStrata; 318 (*labelnew)->defaultValue = label->defaultValue; 319 if (label->numStrata) { 320 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues);CHKERRQ(ierr); 321 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes);CHKERRQ(ierr); 322 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->ht);CHKERRQ(ierr); 323 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->points);CHKERRQ(ierr); 324 ierr = PetscMalloc1(label->numStrata, &(*labelnew)->arrayValid);CHKERRQ(ierr); 325 /* Could eliminate unused space here */ 326 for (v = 0; v < label->numStrata; ++v) { 327 ierr = PetscMalloc1(label->stratumSizes[v], &(*labelnew)->points[v]);CHKERRQ(ierr); 328 PetscHashICreate((*labelnew)->ht[v]); 329 (*labelnew)->arrayValid[v] = PETSC_TRUE; 330 (*labelnew)->stratumValues[v] = label->stratumValues[v]; 331 (*labelnew)->stratumSizes[v] = label->stratumSizes[v]; 332 for (q = 0; q < label->stratumSizes[v]; ++q) { 333 (*labelnew)->points[v][q] = label->points[v][q]; 334 } 335 } 336 } 337 (*labelnew)->pStart = -1; 338 (*labelnew)->pEnd = -1; 339 (*labelnew)->bt = NULL; 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNCT__ 344 #define __FUNCT__ "DMLabelCreateIndex" 345 /* This can be hooked into SetValue(), ClearValue(), etc. for updating */ 346 PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd) 347 { 348 PetscInt v; 349 PetscErrorCode ierr; 350 351 PetscFunctionBegin; 352 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 353 if (label->bt) {ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);} 354 label->pStart = pStart; 355 label->pEnd = pEnd; 356 ierr = PetscBTCreate(pEnd - pStart, &label->bt);CHKERRQ(ierr); 357 ierr = PetscBTMemzero(pEnd - pStart, label->bt);CHKERRQ(ierr); 358 for (v = 0; v < label->numStrata; ++v) { 359 PetscInt i; 360 361 for (i = 0; i < label->stratumSizes[v]; ++i) { 362 const PetscInt point = label->points[v][i]; 363 364 if ((point < pStart) || (point >= pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, pStart, pEnd); 365 ierr = PetscBTSet(label->bt, point - pStart);CHKERRQ(ierr); 366 } 367 } 368 PetscFunctionReturn(0); 369 } 370 371 #undef __FUNCT__ 372 #define __FUNCT__ "DMLabelDestroyIndex" 373 PetscErrorCode DMLabelDestroyIndex(DMLabel label) 374 { 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 label->pStart = -1; 379 label->pEnd = -1; 380 if (label->bt) {ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);} 381 PetscFunctionReturn(0); 382 } 383 384 #undef __FUNCT__ 385 #define __FUNCT__ "DMLabelHasValue" 386 /*@ 387 DMLabelHasValue - Determine whether a label assigns the value to any point 388 389 Input Parameters: 390 + label - the DMLabel 391 - value - the value 392 393 Output Parameter: 394 . contains - Flag indicating whether the label maps this value to any point 395 396 Level: developer 397 398 .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue() 399 @*/ 400 PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains) 401 { 402 PetscInt v; 403 404 PetscFunctionBegin; 405 PetscValidPointer(contains, 3); 406 for (v = 0; v < label->numStrata; ++v) { 407 if (value == label->stratumValues[v]) break; 408 } 409 *contains = (v < label->numStrata ? PETSC_TRUE : PETSC_FALSE); 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "DMLabelHasPoint" 415 /*@ 416 DMLabelHasPoint - Determine whether a label assigns a value to a point 417 418 Input Parameters: 419 + label - the DMLabel 420 - point - the point 421 422 Output Parameter: 423 . contains - Flag indicating whether the label maps this point to a value 424 425 Note: The user must call DMLabelCreateIndex() before this function. 426 427 Level: developer 428 429 .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue() 430 @*/ 431 PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains) 432 { 433 PetscErrorCode ierr; 434 435 PetscFunctionBeginHot; 436 PetscValidPointer(contains, 3); 437 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 438 #if defined(PETSC_USE_DEBUG) 439 if (!label->bt) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()"); 440 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); 441 #endif 442 *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE; 443 PetscFunctionReturn(0); 444 } 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "DMLabelStratumHasPoint" 448 /*@ 449 DMLabelStratumHasPoint - Return true if the stratum contains a point 450 451 Input Parameters: 452 + label - the DMLabel 453 . value - the stratum value 454 - point - the point 455 456 Output Parameter: 457 . contains - true if the stratum contains the point 458 459 Level: intermediate 460 461 .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue() 462 @*/ 463 PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains) 464 { 465 PetscInt v; 466 PetscErrorCode ierr; 467 468 PetscFunctionBegin; 469 PetscValidPointer(contains, 4); 470 *contains = PETSC_FALSE; 471 for (v = 0; v < label->numStrata; ++v) { 472 if (label->stratumValues[v] == value) { 473 if (label->arrayValid[v]) { 474 PetscInt i; 475 476 ierr = PetscFindInt(point, label->stratumSizes[v], &label->points[v][0], &i);CHKERRQ(ierr); 477 if (i >= 0) { 478 *contains = PETSC_TRUE; 479 break; 480 } 481 } else { 482 PetscBool has; 483 484 PetscHashIHasKey(label->ht[v], point, has); 485 if (has) { 486 *contains = PETSC_TRUE; 487 break; 488 } 489 } 490 } 491 } 492 PetscFunctionReturn(0); 493 } 494 495 #undef __FUNCT__ 496 #define __FUNCT__ "DMLabelGetDefaultValue" 497 /* 498 DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value. 499 When a label is created, it is initialized to -1. 500 501 Input parameter: 502 . label - a DMLabel object 503 504 Output parameter: 505 . defaultValue - the default value 506 507 Level: beginner 508 509 .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue() 510 */ 511 PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue) 512 { 513 PetscFunctionBegin; 514 *defaultValue = label->defaultValue; 515 PetscFunctionReturn(0); 516 } 517 518 #undef __FUNCT__ 519 #define __FUNCT__ "DMLabelSetDefaultValue" 520 /* 521 DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value. 522 When a label is created, it is initialized to -1. 523 524 Input parameter: 525 . label - a DMLabel object 526 527 Output parameter: 528 . defaultValue - the default value 529 530 Level: beginner 531 532 .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue() 533 */ 534 PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue) 535 { 536 PetscFunctionBegin; 537 label->defaultValue = defaultValue; 538 PetscFunctionReturn(0); 539 } 540 541 #undef __FUNCT__ 542 #define __FUNCT__ "DMLabelGetValue" 543 /*@ 544 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()) 545 546 Input Parameters: 547 + label - the DMLabel 548 - point - the point 549 550 Output Parameter: 551 . value - The point value, or -1 552 553 Level: intermediate 554 555 .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue() 556 @*/ 557 PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value) 558 { 559 PetscInt v; 560 PetscErrorCode ierr; 561 562 PetscFunctionBegin; 563 PetscValidPointer(value, 3); 564 *value = label->defaultValue; 565 for (v = 0; v < label->numStrata; ++v) { 566 if (label->arrayValid[v]) { 567 PetscInt i; 568 569 ierr = PetscFindInt(point, label->stratumSizes[v], &label->points[v][0], &i);CHKERRQ(ierr); 570 if (i >= 0) { 571 *value = label->stratumValues[v]; 572 break; 573 } 574 } else { 575 PetscBool has; 576 577 PetscHashIHasKey(label->ht[v], point, has); 578 if (has) { 579 *value = label->stratumValues[v]; 580 break; 581 } 582 } 583 } 584 PetscFunctionReturn(0); 585 } 586 587 #undef __FUNCT__ 588 #define __FUNCT__ "DMLabelSetValue" 589 /*@ 590 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 somethingg different), then this function will do nothing. 591 592 Input Parameters: 593 + label - the DMLabel 594 . point - the point 595 - value - The point value 596 597 Level: intermediate 598 599 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue() 600 @*/ 601 PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value) 602 { 603 PETSC_UNUSED PetscHashIIter iter, ret; 604 PetscInt v; 605 PetscErrorCode ierr; 606 607 PetscFunctionBegin; 608 /* Find, or add, label value */ 609 if (value == label->defaultValue) PetscFunctionReturn(0); 610 for (v = 0; v < label->numStrata; ++v) { 611 if (label->stratumValues[v] == value) break; 612 } 613 /* Create new table */ 614 if (v >= label->numStrata) {ierr = DMLabelAddStratum(label, value);CHKERRQ(ierr);} 615 ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr); 616 /* Set key */ 617 PetscHashIPut(label->ht[v], point, ret, iter); 618 PetscFunctionReturn(0); 619 } 620 621 #undef __FUNCT__ 622 #define __FUNCT__ "DMLabelClearValue" 623 /*@ 624 DMLabelClearValue - Clear the value a label assigns to a point 625 626 Input Parameters: 627 + label - the DMLabel 628 . point - the point 629 - value - The point value 630 631 Level: intermediate 632 633 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue() 634 @*/ 635 PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value) 636 { 637 PetscInt v, p; 638 PetscErrorCode ierr; 639 640 PetscFunctionBegin; 641 /* Find label value */ 642 for (v = 0; v < label->numStrata; ++v) { 643 if (label->stratumValues[v] == value) break; 644 } 645 if (v >= label->numStrata) PetscFunctionReturn(0); 646 if (label->arrayValid[v]) { 647 /* Check whether point exists */ 648 ierr = PetscFindInt(point, label->stratumSizes[v], &label->points[v][0], &p);CHKERRQ(ierr); 649 if (p >= 0) { 650 ierr = PetscMemmove(&label->points[v][p], &label->points[v][p+1], (label->stratumSizes[v]-p-1) * sizeof(PetscInt));CHKERRQ(ierr); 651 --label->stratumSizes[v]; 652 if (label->bt) { 653 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); 654 ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr); 655 } 656 } 657 } else { 658 ierr = PetscHashIDelKey(label->ht[v], point);CHKERRQ(ierr); 659 } 660 PetscFunctionReturn(0); 661 } 662 663 #undef __FUNCT__ 664 #define __FUNCT__ "DMLabelInsertIS" 665 /*@ 666 DMLabelInsertIS - Set all points in the IS to a value 667 668 Input Parameters: 669 + label - the DMLabel 670 . is - the point IS 671 - value - The point value 672 673 Level: intermediate 674 675 .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue() 676 @*/ 677 PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value) 678 { 679 const PetscInt *points; 680 PetscInt n, p; 681 PetscErrorCode ierr; 682 683 PetscFunctionBegin; 684 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 685 ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr); 686 ierr = ISGetIndices(is, &points);CHKERRQ(ierr); 687 for (p = 0; p < n; ++p) {ierr = DMLabelSetValue(label, points[p], value);CHKERRQ(ierr);} 688 ierr = ISRestoreIndices(is, &points);CHKERRQ(ierr); 689 PetscFunctionReturn(0); 690 } 691 692 #undef __FUNCT__ 693 #define __FUNCT__ "DMLabelGetNumValues" 694 PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues) 695 { 696 PetscFunctionBegin; 697 PetscValidPointer(numValues, 2); 698 *numValues = label->numStrata; 699 PetscFunctionReturn(0); 700 } 701 702 #undef __FUNCT__ 703 #define __FUNCT__ "DMLabelGetValueIS" 704 PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values) 705 { 706 PetscErrorCode ierr; 707 708 PetscFunctionBegin; 709 PetscValidPointer(values, 2); 710 ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr); 711 PetscFunctionReturn(0); 712 } 713 714 #undef __FUNCT__ 715 #define __FUNCT__ "DMLabelGetStratumSize" 716 PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size) 717 { 718 PetscInt v; 719 PetscErrorCode ierr; 720 721 PetscFunctionBegin; 722 PetscValidPointer(size, 3); 723 *size = 0; 724 for (v = 0; v < label->numStrata; ++v) { 725 if (label->stratumValues[v] == value) { 726 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 727 *size = label->stratumSizes[v]; 728 break; 729 } 730 } 731 PetscFunctionReturn(0); 732 } 733 734 #undef __FUNCT__ 735 #define __FUNCT__ "DMLabelGetStratumBounds" 736 PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end) 737 { 738 PetscInt v; 739 PetscErrorCode ierr; 740 741 PetscFunctionBegin; 742 if (start) {PetscValidPointer(start, 3); *start = 0;} 743 if (end) {PetscValidPointer(end, 4); *end = 0;} 744 for (v = 0; v < label->numStrata; ++v) { 745 if (label->stratumValues[v] != value) continue; 746 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 747 if (label->stratumSizes[v] <= 0) break; 748 if (start) *start = label->points[v][0]; 749 if (end) *end = label->points[v][label->stratumSizes[v]-1]+1; 750 break; 751 } 752 PetscFunctionReturn(0); 753 } 754 755 #undef __FUNCT__ 756 #define __FUNCT__ "DMLabelGetStratumIS" 757 PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points) 758 { 759 PetscInt v; 760 PetscErrorCode ierr; 761 762 PetscFunctionBegin; 763 PetscValidPointer(points, 3); 764 *points = NULL; 765 for (v = 0; v < label->numStrata; ++v) { 766 if (label->stratumValues[v] == value) { 767 ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr); 768 if (label->arrayValid[v]) { 769 ierr = ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], &label->points[v][0], PETSC_COPY_VALUES, points);CHKERRQ(ierr); 770 ierr = PetscObjectSetName((PetscObject) *points, "indices");CHKERRQ(ierr); 771 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Need to implement this to speedup Stratify"); 772 break; 773 } 774 } 775 PetscFunctionReturn(0); 776 } 777 778 #undef __FUNCT__ 779 #define __FUNCT__ "DMLabelClearStratum" 780 PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value) 781 { 782 PetscInt v; 783 PetscErrorCode ierr; 784 785 PetscFunctionBegin; 786 for (v = 0; v < label->numStrata; ++v) { 787 if (label->stratumValues[v] == value) break; 788 } 789 if (v >= label->numStrata) PetscFunctionReturn(0); 790 if (label->bt) { 791 PetscInt i; 792 793 for (i = 0; i < label->stratumSizes[v]; ++i) { 794 const PetscInt point = label->points[v][i]; 795 796 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); 797 ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr); 798 } 799 } 800 if (label->arrayValid[v]) { 801 label->stratumSizes[v] = 0; 802 } else { 803 PetscHashIClear(label->ht[v]); 804 } 805 PetscFunctionReturn(0); 806 } 807 808 #undef __FUNCT__ 809 #define __FUNCT__ "DMLabelFilter" 810 PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end) 811 { 812 PetscInt v; 813 PetscErrorCode ierr; 814 815 PetscFunctionBegin; 816 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 817 label->pStart = start; 818 label->pEnd = end; 819 if (label->bt) {ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);} 820 /* Could squish offsets, but would only make sense if I reallocate the storage */ 821 for (v = 0; v < label->numStrata; ++v) { 822 PetscInt off, q; 823 824 for (off = 0, q = 0; q < label->stratumSizes[v]; ++q) { 825 const PetscInt point = label->points[v][q]; 826 827 if ((point < start) || (point >= end)) continue; 828 label->points[v][off++] = point; 829 } 830 label->stratumSizes[v] = off; 831 } 832 ierr = DMLabelCreateIndex(label, start, end);CHKERRQ(ierr); 833 PetscFunctionReturn(0); 834 } 835 836 #undef __FUNCT__ 837 #define __FUNCT__ "DMLabelPermute" 838 PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew) 839 { 840 const PetscInt *perm; 841 PetscInt numValues, numPoints, v, q; 842 PetscErrorCode ierr; 843 844 PetscFunctionBegin; 845 ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr); 846 ierr = DMLabelDuplicate(label, labelNew);CHKERRQ(ierr); 847 ierr = DMLabelGetNumValues(*labelNew, &numValues);CHKERRQ(ierr); 848 ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr); 849 ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr); 850 for (v = 0; v < numValues; ++v) { 851 const PetscInt size = (*labelNew)->stratumSizes[v]; 852 853 for (q = 0; q < size; ++q) { 854 const PetscInt point = (*labelNew)->points[v][q]; 855 856 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); 857 (*labelNew)->points[v][q] = perm[point]; 858 } 859 ierr = PetscSortInt(size, &(*labelNew)->points[v][0]);CHKERRQ(ierr); 860 } 861 ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr); 862 if (label->bt) { 863 ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr); 864 ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr); 865 } 866 PetscFunctionReturn(0); 867 } 868 869 #undef __FUNCT__ 870 #define __FUNCT__ "DMLabelDistribute" 871 PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew) 872 { 873 MPI_Comm comm; 874 PetscSection rootSection, leafSection; 875 PetscSF labelSF; 876 PetscInt p, pStart, pEnd, l, lStart, lEnd, s, nroots, nleaves, size, dof, offset, stratum; 877 PetscInt *remoteOffsets, *rootStrata, *rootIdx, *leafStrata, *strataIdx; 878 char *name; 879 PetscInt nameSize; 880 PetscInt bcastbuf[2]; 881 size_t len = 0; 882 PetscMPIInt rank, numProcs; 883 PetscErrorCode ierr; 884 885 PetscFunctionBegin; 886 if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);} 887 ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr); 888 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 889 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 890 /* Bcast name */ 891 if (!rank) {ierr = PetscStrlen(label->name, &len);CHKERRQ(ierr);} 892 nameSize = len; 893 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 894 ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr); 895 if (!rank) {ierr = PetscMemcpy(name, label->name, nameSize+1);CHKERRQ(ierr);} 896 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 897 ierr = DMLabelCreate(name, labelNew);CHKERRQ(ierr); 898 ierr = PetscFree(name);CHKERRQ(ierr); 899 /* Bcast numStrata */ 900 if (!rank) { 901 bcastbuf[0] = label->numStrata; 902 bcastbuf[1] = label->defaultValue; 903 } 904 ierr = MPI_Bcast(bcastbuf, 2, MPIU_INT, 0, comm);CHKERRQ(ierr); 905 (*labelNew)->numStrata = bcastbuf[0]; 906 (*labelNew)->defaultValue = bcastbuf[1]; 907 /* Bcast stratumValues */ 908 ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues);CHKERRQ(ierr); 909 if (!rank) {ierr = PetscMemcpy((*labelNew)->stratumValues, label->stratumValues, label->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 910 ierr = MPI_Bcast((*labelNew)->stratumValues, (*labelNew)->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 911 ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->arrayValid);CHKERRQ(ierr); 912 for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->arrayValid[s] = PETSC_TRUE; 913 914 /* Build a section detailing strata-per-point, distribute and build SF 915 from that and then send our points. */ 916 ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL);CHKERRQ(ierr); 917 ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 918 ierr = PetscSectionSetChart(rootSection, 0, nroots);CHKERRQ(ierr); 919 if (label) { 920 for (s = 0; s < label->numStrata; ++s) { 921 lStart = 0; 922 lEnd = label->stratumSizes[s]; 923 for (l=lStart; l<lEnd; l++) { 924 ierr = PetscSectionGetDof(rootSection, label->points[s][l], &dof);CHKERRQ(ierr); 925 ierr = PetscSectionSetDof(rootSection, label->points[s][l], dof+1);CHKERRQ(ierr); 926 } 927 } 928 } 929 ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 930 931 /* Create a point-wise array of point strata */ 932 ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr); 933 ierr = PetscMalloc1(size, &rootStrata);CHKERRQ(ierr); 934 ierr = PetscCalloc1(nroots, &rootIdx);CHKERRQ(ierr); 935 if (label) { 936 for (s = 0; s < label->numStrata; ++s) { 937 lStart = 0; 938 lEnd = label->stratumSizes[s]; 939 for (l=lStart; l<lEnd; l++) { 940 p = label->points[s][l]; 941 ierr = PetscSectionGetOffset(rootSection, p, &offset);CHKERRQ(ierr); 942 rootStrata[offset+rootIdx[p]++] = s; 943 } 944 } 945 } 946 947 /* Build SF that maps label points to remote processes */ 948 ierr = PetscSectionCreate(comm, &leafSection);CHKERRQ(ierr); 949 ierr = PetscSFDistributeSection(sf, rootSection, &remoteOffsets, leafSection);CHKERRQ(ierr); 950 ierr = PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, leafSection, &labelSF);CHKERRQ(ierr); 951 952 /* Send the strata for each point over the derived SF */ 953 ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr); 954 ierr = PetscMalloc1(size, &leafStrata);CHKERRQ(ierr); 955 ierr = PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, leafStrata);CHKERRQ(ierr); 956 ierr = PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, leafStrata);CHKERRQ(ierr); 957 958 /* Rebuild the point strata on the receiver */ 959 ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes);CHKERRQ(ierr); 960 ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr); 961 for (p=pStart; p<pEnd; p++) { 962 ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr); 963 ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr); 964 for (s=0; s<dof; s++) { 965 (*labelNew)->stratumSizes[leafStrata[offset+s]]++; 966 } 967 } 968 ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht);CHKERRQ(ierr); 969 ierr = PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points);CHKERRQ(ierr); 970 for (s = 0; s < (*labelNew)->numStrata; ++s) { 971 PetscHashICreate((*labelNew)->ht[s]); 972 ierr = PetscMalloc1((*labelNew)->stratumSizes[s], &(*labelNew)->points[s]);CHKERRQ(ierr); 973 } 974 975 /* Insert points into new strata */ 976 ierr = PetscCalloc1((*labelNew)->numStrata, &strataIdx);CHKERRQ(ierr); 977 ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr); 978 for (p=pStart; p<pEnd; p++) { 979 ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr); 980 ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr); 981 for (s=0; s<dof; s++) { 982 stratum = leafStrata[offset+s]; 983 (*labelNew)->points[stratum][strataIdx[stratum]++] = p; 984 } 985 } 986 ierr = PetscFree(rootStrata);CHKERRQ(ierr); 987 ierr = PetscFree(leafStrata);CHKERRQ(ierr); 988 ierr = PetscFree(rootIdx);CHKERRQ(ierr); 989 ierr = PetscFree(strataIdx);CHKERRQ(ierr); 990 ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 991 ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 992 ierr = PetscSFDestroy(&labelSF);CHKERRQ(ierr); 993 PetscFunctionReturn(0); 994 } 995 996 #undef __FUNCT__ 997 #define __FUNCT__ "DMLabelConvertToSection" 998 PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is) 999 { 1000 IS vIS; 1001 const PetscInt *values; 1002 PetscInt *points; 1003 PetscInt nV, vS = 0, vE = 0, v, N; 1004 PetscErrorCode ierr; 1005 1006 PetscFunctionBegin; 1007 ierr = DMLabelGetNumValues(label, &nV);CHKERRQ(ierr); 1008 ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr); 1009 ierr = ISGetIndices(vIS, &values);CHKERRQ(ierr); 1010 if (nV) {vS = values[0]; vE = values[0]+1;} 1011 for (v = 1; v < nV; ++v) { 1012 vS = PetscMin(vS, values[v]); 1013 vE = PetscMax(vE, values[v]+1); 1014 } 1015 ierr = PetscSectionCreate(PETSC_COMM_SELF, section);CHKERRQ(ierr); 1016 ierr = PetscSectionSetChart(*section, vS, vE);CHKERRQ(ierr); 1017 for (v = 0; v < nV; ++v) { 1018 PetscInt n; 1019 1020 ierr = DMLabelGetStratumSize(label, values[v], &n);CHKERRQ(ierr); 1021 ierr = PetscSectionSetDof(*section, values[v], n);CHKERRQ(ierr); 1022 } 1023 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 1024 ierr = PetscSectionGetStorageSize(*section, &N);CHKERRQ(ierr); 1025 ierr = PetscMalloc1(N, &points);CHKERRQ(ierr); 1026 for (v = 0; v < nV; ++v) { 1027 IS is; 1028 const PetscInt *spoints; 1029 PetscInt dof, off, p; 1030 1031 ierr = PetscSectionGetDof(*section, values[v], &dof);CHKERRQ(ierr); 1032 ierr = PetscSectionGetOffset(*section, values[v], &off);CHKERRQ(ierr); 1033 ierr = DMLabelGetStratumIS(label, values[v], &is);CHKERRQ(ierr); 1034 ierr = ISGetIndices(is, &spoints);CHKERRQ(ierr); 1035 for (p = 0; p < dof; ++p) points[off+p] = spoints[p]; 1036 ierr = ISRestoreIndices(is, &spoints);CHKERRQ(ierr); 1037 ierr = ISDestroy(&is);CHKERRQ(ierr); 1038 } 1039 ierr = ISRestoreIndices(vIS, &values);CHKERRQ(ierr); 1040 ierr = ISDestroy(&vIS);CHKERRQ(ierr); 1041 ierr = ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 1042 PetscFunctionReturn(0); 1043 } 1044 1045 #undef __FUNCT__ 1046 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 1047 /*@C 1048 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 1049 the local section and an SF describing the section point overlap. 1050 1051 Input Parameters: 1052 + s - The PetscSection for the local field layout 1053 . sf - The SF describing parallel layout of the section points 1054 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 1055 . label - The label specifying the points 1056 - labelValue - The label stratum specifying the points 1057 1058 Output Parameter: 1059 . gsection - The PetscSection for the global field layout 1060 1061 Note: This gives negative sizes and offsets to points not owned by this process 1062 1063 Level: developer 1064 1065 .seealso: PetscSectionCreate() 1066 @*/ 1067 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 1068 { 1069 PetscInt *neg = NULL, *tmpOff = NULL; 1070 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 1071 PetscErrorCode ierr; 1072 1073 PetscFunctionBegin; 1074 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); 1075 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1076 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 1077 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 1078 if (nroots >= 0) { 1079 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 1080 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 1081 if (nroots > pEnd-pStart) { 1082 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 1083 } else { 1084 tmpOff = &(*gsection)->atlasDof[-pStart]; 1085 } 1086 } 1087 /* Mark ghost points with negative dof */ 1088 for (p = pStart; p < pEnd; ++p) { 1089 PetscInt value; 1090 1091 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 1092 if (value != labelValue) continue; 1093 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 1094 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 1095 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 1096 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 1097 if (neg) neg[p] = -(dof+1); 1098 } 1099 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 1100 if (nroots >= 0) { 1101 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 1102 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 1103 if (nroots > pEnd-pStart) { 1104 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 1105 } 1106 } 1107 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 1108 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1109 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 1110 (*gsection)->atlasOff[p] = off; 1111 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 1112 } 1113 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr); 1114 globalOff -= off; 1115 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1116 (*gsection)->atlasOff[p] += globalOff; 1117 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 1118 } 1119 /* Put in negative offsets for ghost points */ 1120 if (nroots >= 0) { 1121 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 1122 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 1123 if (nroots > pEnd-pStart) { 1124 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 1125 } 1126 } 1127 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 1128 ierr = PetscFree(neg);CHKERRQ(ierr); 1129 PetscFunctionReturn(0); 1130 } 1131 1132