1 /* 2 This file contains routines for basic section object implementation. 3 */ 4 5 #include <petsc/private/sectionimpl.h> /*I "petscsection.h" I*/ 6 #include <petscsf.h> 7 8 PetscClassId PETSC_SECTION_CLASSID; 9 10 /*@ 11 PetscSectionCreate - Allocates PetscSection space and sets the map contents to the default. 12 13 Collective 14 15 Input Parameters: 16 + comm - the MPI communicator 17 - s - pointer to the section 18 19 Level: beginner 20 21 Notes: 22 Typical calling sequence 23 $ PetscSectionCreate(MPI_Comm,PetscSection *); 24 $ PetscSectionSetNumFields(PetscSection, numFields); 25 $ PetscSectionSetChart(PetscSection,low,high); 26 $ PetscSectionSetDof(PetscSection,point,numdof); 27 $ PetscSectionSetUp(PetscSection); 28 $ PetscSectionGetOffset(PetscSection,point,PetscInt *); 29 $ PetscSectionDestroy(PetscSection); 30 31 The PetscSection object and methods are intended to be used in the PETSc Vec and Mat implementations; it is 32 recommended they not be used in user codes unless you really gain something in their use. 33 34 .seealso: `PetscSection`, `PetscSectionDestroy()` 35 @*/ 36 PetscErrorCode PetscSectionCreate(MPI_Comm comm, PetscSection *s) { 37 PetscFunctionBegin; 38 PetscValidPointer(s, 2); 39 PetscCall(ISInitializePackage()); 40 41 PetscCall(PetscHeaderCreate(*s, PETSC_SECTION_CLASSID, "PetscSection", "Section", "IS", comm, PetscSectionDestroy, PetscSectionView)); 42 43 (*s)->pStart = -1; 44 (*s)->pEnd = -1; 45 (*s)->perm = NULL; 46 (*s)->pointMajor = PETSC_TRUE; 47 (*s)->includesConstraints = PETSC_TRUE; 48 (*s)->atlasDof = NULL; 49 (*s)->atlasOff = NULL; 50 (*s)->bc = NULL; 51 (*s)->bcIndices = NULL; 52 (*s)->setup = PETSC_FALSE; 53 (*s)->numFields = 0; 54 (*s)->fieldNames = NULL; 55 (*s)->field = NULL; 56 (*s)->useFieldOff = PETSC_FALSE; 57 (*s)->compNames = NULL; 58 (*s)->clObj = NULL; 59 (*s)->clHash = NULL; 60 (*s)->clSection = NULL; 61 (*s)->clPoints = NULL; 62 PetscCall(PetscSectionInvalidateMaxDof_Internal(*s)); 63 PetscFunctionReturn(0); 64 } 65 66 /*@ 67 PetscSectionCopy - Creates a shallow (if possible) copy of the PetscSection 68 69 Collective 70 71 Input Parameter: 72 . section - the PetscSection 73 74 Output Parameter: 75 . newSection - the copy 76 77 Level: intermediate 78 79 .seealso: `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()` 80 @*/ 81 PetscErrorCode PetscSectionCopy(PetscSection section, PetscSection newSection) { 82 PetscSectionSym sym; 83 IS perm; 84 PetscInt numFields, f, c, pStart, pEnd, p; 85 86 PetscFunctionBegin; 87 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 88 PetscValidHeaderSpecific(newSection, PETSC_SECTION_CLASSID, 2); 89 PetscCall(PetscSectionReset(newSection)); 90 PetscCall(PetscSectionGetNumFields(section, &numFields)); 91 if (numFields) PetscCall(PetscSectionSetNumFields(newSection, numFields)); 92 for (f = 0; f < numFields; ++f) { 93 const char *fieldName = NULL, *compName = NULL; 94 PetscInt numComp = 0; 95 96 PetscCall(PetscSectionGetFieldName(section, f, &fieldName)); 97 PetscCall(PetscSectionSetFieldName(newSection, f, fieldName)); 98 PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 99 PetscCall(PetscSectionSetFieldComponents(newSection, f, numComp)); 100 for (c = 0; c < numComp; ++c) { 101 PetscCall(PetscSectionGetComponentName(section, f, c, &compName)); 102 PetscCall(PetscSectionSetComponentName(newSection, f, c, compName)); 103 } 104 PetscCall(PetscSectionGetFieldSym(section, f, &sym)); 105 PetscCall(PetscSectionSetFieldSym(newSection, f, sym)); 106 } 107 PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 108 PetscCall(PetscSectionSetChart(newSection, pStart, pEnd)); 109 PetscCall(PetscSectionGetPermutation(section, &perm)); 110 PetscCall(PetscSectionSetPermutation(newSection, perm)); 111 PetscCall(PetscSectionGetSym(section, &sym)); 112 PetscCall(PetscSectionSetSym(newSection, sym)); 113 for (p = pStart; p < pEnd; ++p) { 114 PetscInt dof, cdof, fcdof = 0; 115 116 PetscCall(PetscSectionGetDof(section, p, &dof)); 117 PetscCall(PetscSectionSetDof(newSection, p, dof)); 118 PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 119 if (cdof) PetscCall(PetscSectionSetConstraintDof(newSection, p, cdof)); 120 for (f = 0; f < numFields; ++f) { 121 PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 122 PetscCall(PetscSectionSetFieldDof(newSection, p, f, dof)); 123 if (cdof) { 124 PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 125 if (fcdof) PetscCall(PetscSectionSetFieldConstraintDof(newSection, p, f, fcdof)); 126 } 127 } 128 } 129 PetscCall(PetscSectionSetUp(newSection)); 130 for (p = pStart; p < pEnd; ++p) { 131 PetscInt off, cdof, fcdof = 0; 132 const PetscInt *cInd; 133 134 /* Must set offsets in case they do not agree with the prefix sums */ 135 PetscCall(PetscSectionGetOffset(section, p, &off)); 136 PetscCall(PetscSectionSetOffset(newSection, p, off)); 137 PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 138 if (cdof) { 139 PetscCall(PetscSectionGetConstraintIndices(section, p, &cInd)); 140 PetscCall(PetscSectionSetConstraintIndices(newSection, p, cInd)); 141 for (f = 0; f < numFields; ++f) { 142 PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 143 if (fcdof) { 144 PetscCall(PetscSectionGetFieldConstraintIndices(section, p, f, &cInd)); 145 PetscCall(PetscSectionSetFieldConstraintIndices(newSection, p, f, cInd)); 146 } 147 } 148 } 149 } 150 PetscFunctionReturn(0); 151 } 152 153 /*@ 154 PetscSectionClone - Creates a shallow (if possible) copy of the PetscSection 155 156 Collective 157 158 Input Parameter: 159 . section - the PetscSection 160 161 Output Parameter: 162 . newSection - the copy 163 164 Level: beginner 165 166 .seealso: `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()` 167 @*/ 168 PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection) { 169 PetscFunctionBegin; 170 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 171 PetscValidPointer(newSection, 2); 172 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), newSection)); 173 PetscCall(PetscSectionCopy(section, *newSection)); 174 PetscFunctionReturn(0); 175 } 176 177 /*@ 178 PetscSectionSetFromOptions - sets parameters in a PetscSection from the options database 179 180 Collective 181 182 Input Parameter: 183 . section - the PetscSection 184 185 Options Database: 186 . -petscsection_point_major - PETSC_TRUE for point-major order 187 188 Level: intermediate 189 190 .seealso: `PetscSection`, `PetscSectionCreate()`, `PetscSectionDestroy()` 191 @*/ 192 PetscErrorCode PetscSectionSetFromOptions(PetscSection s) { 193 PetscFunctionBegin; 194 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 195 PetscObjectOptionsBegin((PetscObject)s); 196 PetscCall(PetscOptionsBool("-petscsection_point_major", "The for ordering, either point major or field major", "PetscSectionSetPointMajor", s->pointMajor, &s->pointMajor, NULL)); 197 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 198 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)s, PetscOptionsObject)); 199 PetscOptionsEnd(); 200 PetscCall(PetscObjectViewFromOptions((PetscObject)s, NULL, "-petscsection_view")); 201 PetscFunctionReturn(0); 202 } 203 204 /*@ 205 PetscSectionCompare - Compares two sections 206 207 Collective 208 209 Input Parameters: 210 + s1 - the first PetscSection 211 - s2 - the second PetscSection 212 213 Output Parameter: 214 . congruent - PETSC_TRUE if the two sections are congruent, PETSC_FALSE otherwise 215 216 Level: intermediate 217 218 Notes: 219 Field names are disregarded. 220 221 .seealso: `PetscSection`, `PetscSectionCreate()`, `PetscSectionCopy()`, `PetscSectionClone()` 222 @*/ 223 PetscErrorCode PetscSectionCompare(PetscSection s1, PetscSection s2, PetscBool *congruent) { 224 PetscInt pStart, pEnd, nfields, ncdof, nfcdof, p, f, n1, n2; 225 const PetscInt *idx1, *idx2; 226 IS perm1, perm2; 227 PetscBool flg; 228 PetscMPIInt mflg; 229 230 PetscFunctionBegin; 231 PetscValidHeaderSpecific(s1, PETSC_SECTION_CLASSID, 1); 232 PetscValidHeaderSpecific(s2, PETSC_SECTION_CLASSID, 2); 233 PetscValidBoolPointer(congruent, 3); 234 flg = PETSC_FALSE; 235 236 PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)s1), PetscObjectComm((PetscObject)s2), &mflg)); 237 if (mflg != MPI_CONGRUENT && mflg != MPI_IDENT) { 238 *congruent = PETSC_FALSE; 239 PetscFunctionReturn(0); 240 } 241 242 PetscCall(PetscSectionGetChart(s1, &pStart, &pEnd)); 243 PetscCall(PetscSectionGetChart(s2, &n1, &n2)); 244 if (pStart != n1 || pEnd != n2) goto not_congruent; 245 246 PetscCall(PetscSectionGetPermutation(s1, &perm1)); 247 PetscCall(PetscSectionGetPermutation(s2, &perm2)); 248 if (perm1 && perm2) { 249 PetscCall(ISEqual(perm1, perm2, congruent)); 250 if (!(*congruent)) goto not_congruent; 251 } else if (perm1 != perm2) goto not_congruent; 252 253 for (p = pStart; p < pEnd; ++p) { 254 PetscCall(PetscSectionGetOffset(s1, p, &n1)); 255 PetscCall(PetscSectionGetOffset(s2, p, &n2)); 256 if (n1 != n2) goto not_congruent; 257 258 PetscCall(PetscSectionGetDof(s1, p, &n1)); 259 PetscCall(PetscSectionGetDof(s2, p, &n2)); 260 if (n1 != n2) goto not_congruent; 261 262 PetscCall(PetscSectionGetConstraintDof(s1, p, &ncdof)); 263 PetscCall(PetscSectionGetConstraintDof(s2, p, &n2)); 264 if (ncdof != n2) goto not_congruent; 265 266 PetscCall(PetscSectionGetConstraintIndices(s1, p, &idx1)); 267 PetscCall(PetscSectionGetConstraintIndices(s2, p, &idx2)); 268 PetscCall(PetscArraycmp(idx1, idx2, ncdof, congruent)); 269 if (!(*congruent)) goto not_congruent; 270 } 271 272 PetscCall(PetscSectionGetNumFields(s1, &nfields)); 273 PetscCall(PetscSectionGetNumFields(s2, &n2)); 274 if (nfields != n2) goto not_congruent; 275 276 for (f = 0; f < nfields; ++f) { 277 PetscCall(PetscSectionGetFieldComponents(s1, f, &n1)); 278 PetscCall(PetscSectionGetFieldComponents(s2, f, &n2)); 279 if (n1 != n2) goto not_congruent; 280 281 for (p = pStart; p < pEnd; ++p) { 282 PetscCall(PetscSectionGetFieldOffset(s1, p, f, &n1)); 283 PetscCall(PetscSectionGetFieldOffset(s2, p, f, &n2)); 284 if (n1 != n2) goto not_congruent; 285 286 PetscCall(PetscSectionGetFieldDof(s1, p, f, &n1)); 287 PetscCall(PetscSectionGetFieldDof(s2, p, f, &n2)); 288 if (n1 != n2) goto not_congruent; 289 290 PetscCall(PetscSectionGetFieldConstraintDof(s1, p, f, &nfcdof)); 291 PetscCall(PetscSectionGetFieldConstraintDof(s2, p, f, &n2)); 292 if (nfcdof != n2) goto not_congruent; 293 294 PetscCall(PetscSectionGetFieldConstraintIndices(s1, p, f, &idx1)); 295 PetscCall(PetscSectionGetFieldConstraintIndices(s2, p, f, &idx2)); 296 PetscCall(PetscArraycmp(idx1, idx2, nfcdof, congruent)); 297 if (!(*congruent)) goto not_congruent; 298 } 299 } 300 301 flg = PETSC_TRUE; 302 not_congruent: 303 PetscCall(MPIU_Allreduce(&flg, congruent, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)s1))); 304 PetscFunctionReturn(0); 305 } 306 307 /*@ 308 PetscSectionGetNumFields - Returns the number of fields, or 0 if no fields were defined. 309 310 Not Collective 311 312 Input Parameter: 313 . s - the PetscSection 314 315 Output Parameter: 316 . numFields - the number of fields defined, or 0 if none were defined 317 318 Level: intermediate 319 320 .seealso: `PetscSectionSetNumFields()` 321 @*/ 322 PetscErrorCode PetscSectionGetNumFields(PetscSection s, PetscInt *numFields) { 323 PetscFunctionBegin; 324 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 325 PetscValidIntPointer(numFields, 2); 326 *numFields = s->numFields; 327 PetscFunctionReturn(0); 328 } 329 330 /*@ 331 PetscSectionSetNumFields - Sets the number of fields. 332 333 Not Collective 334 335 Input Parameters: 336 + s - the PetscSection 337 - numFields - the number of fields 338 339 Level: intermediate 340 341 .seealso: `PetscSectionGetNumFields()` 342 @*/ 343 PetscErrorCode PetscSectionSetNumFields(PetscSection s, PetscInt numFields) { 344 PetscInt f; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 348 PetscCheck(numFields > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "The number of fields %" PetscInt_FMT " must be positive", numFields); 349 PetscCall(PetscSectionReset(s)); 350 351 s->numFields = numFields; 352 PetscCall(PetscMalloc1(s->numFields, &s->numFieldComponents)); 353 PetscCall(PetscMalloc1(s->numFields, &s->fieldNames)); 354 PetscCall(PetscMalloc1(s->numFields, &s->compNames)); 355 PetscCall(PetscMalloc1(s->numFields, &s->field)); 356 for (f = 0; f < s->numFields; ++f) { 357 char name[64]; 358 359 s->numFieldComponents[f] = 1; 360 361 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &s->field[f])); 362 PetscCall(PetscSNPrintf(name, 64, "Field_%" PetscInt_FMT, f)); 363 PetscCall(PetscStrallocpy(name, (char **)&s->fieldNames[f])); 364 PetscCall(PetscSNPrintf(name, 64, "Component_0")); 365 PetscCall(PetscMalloc1(s->numFieldComponents[f], &s->compNames[f])); 366 PetscCall(PetscStrallocpy(name, (char **)&s->compNames[f][0])); 367 } 368 PetscFunctionReturn(0); 369 } 370 371 /*@C 372 PetscSectionGetFieldName - Returns the name of a field in the PetscSection 373 374 Not Collective 375 376 Input Parameters: 377 + s - the PetscSection 378 - field - the field number 379 380 Output Parameter: 381 . fieldName - the field name 382 383 Level: intermediate 384 385 .seealso: `PetscSectionSetFieldName()` 386 @*/ 387 PetscErrorCode PetscSectionGetFieldName(PetscSection s, PetscInt field, const char *fieldName[]) { 388 PetscFunctionBegin; 389 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 390 PetscValidPointer(fieldName, 3); 391 PetscSectionCheckValidField(field, s->numFields); 392 *fieldName = s->fieldNames[field]; 393 PetscFunctionReturn(0); 394 } 395 396 /*@C 397 PetscSectionSetFieldName - Sets the name of a field in the PetscSection 398 399 Not Collective 400 401 Input Parameters: 402 + s - the PetscSection 403 . field - the field number 404 - fieldName - the field name 405 406 Level: intermediate 407 408 .seealso: `PetscSectionGetFieldName()` 409 @*/ 410 PetscErrorCode PetscSectionSetFieldName(PetscSection s, PetscInt field, const char fieldName[]) { 411 PetscFunctionBegin; 412 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 413 if (fieldName) PetscValidCharPointer(fieldName, 3); 414 PetscSectionCheckValidField(field, s->numFields); 415 PetscCall(PetscFree(s->fieldNames[field])); 416 PetscCall(PetscStrallocpy(fieldName, (char **)&s->fieldNames[field])); 417 PetscFunctionReturn(0); 418 } 419 420 /*@C 421 PetscSectionGetComponentName - Gets the name of a field component in the PetscSection 422 423 Not Collective 424 425 Input Parameters: 426 + s - the PetscSection 427 . field - the field number 428 . comp - the component number 429 - compName - the component name 430 431 Level: intermediate 432 433 .seealso: `PetscSectionSetComponentName()` 434 @*/ 435 PetscErrorCode PetscSectionGetComponentName(PetscSection s, PetscInt field, PetscInt comp, const char *compName[]) { 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 438 PetscValidPointer(compName, 4); 439 PetscSectionCheckValidField(field, s->numFields); 440 PetscSectionCheckValidFieldComponent(comp, s->numFieldComponents[field]); 441 *compName = s->compNames[field][comp]; 442 PetscFunctionReturn(0); 443 } 444 445 /*@C 446 PetscSectionSetComponentName - Sets the name of a field component in the PetscSection 447 448 Not Collective 449 450 Input Parameters: 451 + s - the PetscSection 452 . field - the field number 453 . comp - the component number 454 - compName - the component name 455 456 Level: intermediate 457 458 .seealso: `PetscSectionGetComponentName()` 459 @*/ 460 PetscErrorCode PetscSectionSetComponentName(PetscSection s, PetscInt field, PetscInt comp, const char compName[]) { 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 463 if (compName) PetscValidCharPointer(compName, 4); 464 PetscSectionCheckValidField(field, s->numFields); 465 PetscSectionCheckValidFieldComponent(comp, s->numFieldComponents[field]); 466 PetscCall(PetscFree(s->compNames[field][comp])); 467 PetscCall(PetscStrallocpy(compName, (char **)&s->compNames[field][comp])); 468 PetscFunctionReturn(0); 469 } 470 471 /*@ 472 PetscSectionGetFieldComponents - Returns the number of field components for the given field. 473 474 Not Collective 475 476 Input Parameters: 477 + s - the PetscSection 478 - field - the field number 479 480 Output Parameter: 481 . numComp - the number of field components 482 483 Level: intermediate 484 485 .seealso: `PetscSectionSetFieldComponents()`, `PetscSectionGetNumFields()` 486 @*/ 487 PetscErrorCode PetscSectionGetFieldComponents(PetscSection s, PetscInt field, PetscInt *numComp) { 488 PetscFunctionBegin; 489 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 490 PetscValidIntPointer(numComp, 3); 491 PetscSectionCheckValidField(field, s->numFields); 492 *numComp = s->numFieldComponents[field]; 493 PetscFunctionReturn(0); 494 } 495 496 /*@ 497 PetscSectionSetFieldComponents - Sets the number of field components for the given field. 498 499 Not Collective 500 501 Input Parameters: 502 + s - the PetscSection 503 . field - the field number 504 - numComp - the number of field components 505 506 Level: intermediate 507 508 .seealso: `PetscSectionGetFieldComponents()`, `PetscSectionGetNumFields()` 509 @*/ 510 PetscErrorCode PetscSectionSetFieldComponents(PetscSection s, PetscInt field, PetscInt numComp) { 511 PetscInt c; 512 513 PetscFunctionBegin; 514 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 515 PetscSectionCheckValidField(field, s->numFields); 516 if (s->compNames) { 517 for (c = 0; c < s->numFieldComponents[field]; ++c) PetscCall(PetscFree(s->compNames[field][c])); 518 PetscCall(PetscFree(s->compNames[field])); 519 } 520 521 s->numFieldComponents[field] = numComp; 522 if (numComp) { 523 PetscCall(PetscMalloc1(numComp, (char ***)&s->compNames[field])); 524 for (c = 0; c < numComp; ++c) { 525 char name[64]; 526 527 PetscCall(PetscSNPrintf(name, 64, "%" PetscInt_FMT, c)); 528 PetscCall(PetscStrallocpy(name, (char **)&s->compNames[field][c])); 529 } 530 } 531 PetscFunctionReturn(0); 532 } 533 534 /*@ 535 PetscSectionGetChart - Returns the range [pStart, pEnd) in which points lie. 536 537 Not Collective 538 539 Input Parameter: 540 . s - the PetscSection 541 542 Output Parameters: 543 + pStart - the first point 544 - pEnd - one past the last point 545 546 Level: intermediate 547 548 .seealso: `PetscSectionSetChart()`, `PetscSectionCreate()` 549 @*/ 550 PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd) { 551 PetscFunctionBegin; 552 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 553 if (pStart) *pStart = s->pStart; 554 if (pEnd) *pEnd = s->pEnd; 555 PetscFunctionReturn(0); 556 } 557 558 /*@ 559 PetscSectionSetChart - Sets the range [pStart, pEnd) in which points lie. 560 561 Not Collective 562 563 Input Parameters: 564 + s - the PetscSection 565 . pStart - the first point 566 - pEnd - one past the last point 567 568 Level: intermediate 569 570 .seealso: `PetscSectionGetChart()`, `PetscSectionCreate()` 571 @*/ 572 PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd) { 573 PetscInt f; 574 575 PetscFunctionBegin; 576 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 577 if (pStart == s->pStart && pEnd == s->pEnd) PetscFunctionReturn(0); 578 /* Cannot Reset() because it destroys field information */ 579 s->setup = PETSC_FALSE; 580 PetscCall(PetscSectionDestroy(&s->bc)); 581 PetscCall(PetscFree(s->bcIndices)); 582 PetscCall(PetscFree2(s->atlasDof, s->atlasOff)); 583 584 s->pStart = pStart; 585 s->pEnd = pEnd; 586 PetscCall(PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff)); 587 PetscCall(PetscArrayzero(s->atlasDof, pEnd - pStart)); 588 for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetChart(s->field[f], pStart, pEnd)); 589 PetscFunctionReturn(0); 590 } 591 592 /*@ 593 PetscSectionGetPermutation - Returns the permutation of [0, pEnd-pStart) or NULL 594 595 Not Collective 596 597 Input Parameter: 598 . s - the PetscSection 599 600 Output Parameters: 601 . perm - The permutation as an IS 602 603 Level: intermediate 604 605 .seealso: `PetscSectionSetPermutation()`, `PetscSectionCreate()` 606 @*/ 607 PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm) { 608 PetscFunctionBegin; 609 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 610 if (perm) { 611 PetscValidPointer(perm, 2); 612 *perm = s->perm; 613 } 614 PetscFunctionReturn(0); 615 } 616 617 /*@ 618 PetscSectionSetPermutation - Sets the permutation for [0, pEnd-pStart) 619 620 Not Collective 621 622 Input Parameters: 623 + s - the PetscSection 624 - perm - the permutation of points 625 626 Level: intermediate 627 628 .seealso: `PetscSectionGetPermutation()`, `PetscSectionCreate()` 629 @*/ 630 PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm) { 631 PetscFunctionBegin; 632 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 633 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 634 PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup"); 635 if (s->perm != perm) { 636 PetscCall(ISDestroy(&s->perm)); 637 if (perm) { 638 s->perm = perm; 639 PetscCall(PetscObjectReference((PetscObject)s->perm)); 640 } 641 } 642 PetscFunctionReturn(0); 643 } 644 645 /*@ 646 PetscSectionGetPointMajor - Returns the flag for dof ordering, true if it is point major, otherwise field major 647 648 Not Collective 649 650 Input Parameter: 651 . s - the PetscSection 652 653 Output Parameter: 654 . pm - the flag for point major ordering 655 656 Level: intermediate 657 658 .seealso: `PetscSectionSetPointMajor()` 659 @*/ 660 PetscErrorCode PetscSectionGetPointMajor(PetscSection s, PetscBool *pm) { 661 PetscFunctionBegin; 662 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 663 PetscValidBoolPointer(pm, 2); 664 *pm = s->pointMajor; 665 PetscFunctionReturn(0); 666 } 667 668 /*@ 669 PetscSectionSetPointMajor - Sets the flag for dof ordering, true if it is point major, otherwise field major 670 671 Not Collective 672 673 Input Parameters: 674 + s - the PetscSection 675 - pm - the flag for point major ordering 676 677 Level: intermediate 678 679 .seealso: `PetscSectionGetPointMajor()` 680 @*/ 681 PetscErrorCode PetscSectionSetPointMajor(PetscSection s, PetscBool pm) { 682 PetscFunctionBegin; 683 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 684 PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set the dof ordering after the section is setup"); 685 s->pointMajor = pm; 686 PetscFunctionReturn(0); 687 } 688 689 /*@ 690 PetscSectionGetIncludesConstraints - Returns the flag indicating if constrained dofs were included when computing offsets 691 692 Not Collective 693 694 Input Parameter: 695 . s - the PetscSection 696 697 Output Parameter: 698 . includesConstraints - the flag indicating if constrained dofs were included when computing offsets 699 700 Level: intermediate 701 702 .seealso: `PetscSectionSetIncludesConstraints()` 703 @*/ 704 PetscErrorCode PetscSectionGetIncludesConstraints(PetscSection s, PetscBool *includesConstraints) { 705 PetscFunctionBegin; 706 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 707 PetscValidBoolPointer(includesConstraints, 2); 708 *includesConstraints = s->includesConstraints; 709 PetscFunctionReturn(0); 710 } 711 712 /*@ 713 PetscSectionSetIncludesConstraints - Sets the flag indicating if constrained dofs are to be included when computing offsets 714 715 Not Collective 716 717 Input Parameters: 718 + s - the PetscSection 719 - includesConstraints - the flag indicating if constrained dofs are to be included when computing offsets 720 721 Level: intermediate 722 723 .seealso: `PetscSectionGetIncludesConstraints()` 724 @*/ 725 PetscErrorCode PetscSectionSetIncludesConstraints(PetscSection s, PetscBool includesConstraints) { 726 PetscFunctionBegin; 727 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 728 PetscCheck(!s->setup, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set includesConstraints after the section is set up"); 729 s->includesConstraints = includesConstraints; 730 PetscFunctionReturn(0); 731 } 732 733 /*@ 734 PetscSectionGetDof - Return the number of degrees of freedom associated with a given point. 735 736 Not Collective 737 738 Input Parameters: 739 + s - the PetscSection 740 - point - the point 741 742 Output Parameter: 743 . numDof - the number of dof 744 745 Level: intermediate 746 747 .seealso: `PetscSectionSetDof()`, `PetscSectionCreate()` 748 @*/ 749 PetscErrorCode PetscSectionGetDof(PetscSection s, PetscInt point, PetscInt *numDof) { 750 PetscFunctionBeginHot; 751 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 752 PetscValidIntPointer(numDof, 3); 753 PetscAssert(point >= s->pStart && point < s->pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd); 754 *numDof = s->atlasDof[point - s->pStart]; 755 PetscFunctionReturn(0); 756 } 757 758 /*@ 759 PetscSectionSetDof - Sets the number of degrees of freedom associated with a given point. 760 761 Not Collective 762 763 Input Parameters: 764 + s - the PetscSection 765 . point - the point 766 - numDof - the number of dof 767 768 Level: intermediate 769 770 .seealso: `PetscSectionGetDof()`, `PetscSectionAddDof()`, `PetscSectionCreate()` 771 @*/ 772 PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof) { 773 PetscFunctionBegin; 774 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 775 PetscAssert(point >= s->pStart && point < s->pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd); 776 s->atlasDof[point - s->pStart] = numDof; 777 PetscCall(PetscSectionInvalidateMaxDof_Internal(s)); 778 PetscFunctionReturn(0); 779 } 780 781 /*@ 782 PetscSectionAddDof - Adds to the number of degrees of freedom associated with a given point. 783 784 Not Collective 785 786 Input Parameters: 787 + s - the PetscSection 788 . point - the point 789 - numDof - the number of additional dof 790 791 Level: intermediate 792 793 .seealso: `PetscSectionGetDof()`, `PetscSectionSetDof()`, `PetscSectionCreate()` 794 @*/ 795 PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof) { 796 PetscFunctionBeginHot; 797 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 798 PetscAssert(point >= s->pStart && point < s->pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd); 799 s->atlasDof[point - s->pStart] += numDof; 800 PetscCall(PetscSectionInvalidateMaxDof_Internal(s)); 801 PetscFunctionReturn(0); 802 } 803 804 /*@ 805 PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point. 806 807 Not Collective 808 809 Input Parameters: 810 + s - the PetscSection 811 . point - the point 812 - field - the field 813 814 Output Parameter: 815 . numDof - the number of dof 816 817 Level: intermediate 818 819 .seealso: `PetscSectionSetFieldDof()`, `PetscSectionCreate()` 820 @*/ 821 PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof) { 822 PetscFunctionBegin; 823 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 824 PetscValidIntPointer(numDof, 4); 825 PetscSectionCheckValidField(field, s->numFields); 826 PetscCall(PetscSectionGetDof(s->field[field], point, numDof)); 827 PetscFunctionReturn(0); 828 } 829 830 /*@ 831 PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point. 832 833 Not Collective 834 835 Input Parameters: 836 + s - the PetscSection 837 . point - the point 838 . field - the field 839 - numDof - the number of dof 840 841 Level: intermediate 842 843 .seealso: `PetscSectionGetFieldDof()`, `PetscSectionCreate()` 844 @*/ 845 PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) { 846 PetscFunctionBegin; 847 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 848 PetscSectionCheckValidField(field, s->numFields); 849 PetscCall(PetscSectionSetDof(s->field[field], point, numDof)); 850 PetscFunctionReturn(0); 851 } 852 853 /*@ 854 PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point. 855 856 Not Collective 857 858 Input Parameters: 859 + s - the PetscSection 860 . point - the point 861 . field - the field 862 - numDof - the number of dof 863 864 Level: intermediate 865 866 .seealso: `PetscSectionSetFieldDof()`, `PetscSectionGetFieldDof()`, `PetscSectionCreate()` 867 @*/ 868 PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) { 869 PetscFunctionBegin; 870 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 871 PetscSectionCheckValidField(field, s->numFields); 872 PetscCall(PetscSectionAddDof(s->field[field], point, numDof)); 873 PetscFunctionReturn(0); 874 } 875 876 /*@ 877 PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point. 878 879 Not Collective 880 881 Input Parameters: 882 + s - the PetscSection 883 - point - the point 884 885 Output Parameter: 886 . numDof - the number of dof which are fixed by constraints 887 888 Level: intermediate 889 890 .seealso: `PetscSectionGetDof()`, `PetscSectionSetConstraintDof()`, `PetscSectionCreate()` 891 @*/ 892 PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof) { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 895 PetscValidIntPointer(numDof, 3); 896 if (s->bc) { 897 PetscCall(PetscSectionGetDof(s->bc, point, numDof)); 898 } else *numDof = 0; 899 PetscFunctionReturn(0); 900 } 901 902 /*@ 903 PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point. 904 905 Not Collective 906 907 Input Parameters: 908 + s - the PetscSection 909 . point - the point 910 - numDof - the number of dof which are fixed by constraints 911 912 Level: intermediate 913 914 .seealso: `PetscSectionSetDof()`, `PetscSectionGetConstraintDof()`, `PetscSectionCreate()` 915 @*/ 916 PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof) { 917 PetscFunctionBegin; 918 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 919 if (numDof) { 920 PetscCall(PetscSectionCheckConstraints_Private(s)); 921 PetscCall(PetscSectionSetDof(s->bc, point, numDof)); 922 } 923 PetscFunctionReturn(0); 924 } 925 926 /*@ 927 PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point. 928 929 Not Collective 930 931 Input Parameters: 932 + s - the PetscSection 933 . point - the point 934 - numDof - the number of additional dof which are fixed by constraints 935 936 Level: intermediate 937 938 .seealso: `PetscSectionAddDof()`, `PetscSectionGetConstraintDof()`, `PetscSectionCreate()` 939 @*/ 940 PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof) { 941 PetscFunctionBegin; 942 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 943 if (numDof) { 944 PetscCall(PetscSectionCheckConstraints_Private(s)); 945 PetscCall(PetscSectionAddDof(s->bc, point, numDof)); 946 } 947 PetscFunctionReturn(0); 948 } 949 950 /*@ 951 PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point. 952 953 Not Collective 954 955 Input Parameters: 956 + s - the PetscSection 957 . point - the point 958 - field - the field 959 960 Output Parameter: 961 . numDof - the number of dof which are fixed by constraints 962 963 Level: intermediate 964 965 .seealso: `PetscSectionGetDof()`, `PetscSectionSetFieldConstraintDof()`, `PetscSectionCreate()` 966 @*/ 967 PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof) { 968 PetscFunctionBegin; 969 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 970 PetscValidIntPointer(numDof, 4); 971 PetscSectionCheckValidField(field, s->numFields); 972 PetscCall(PetscSectionGetConstraintDof(s->field[field], point, numDof)); 973 PetscFunctionReturn(0); 974 } 975 976 /*@ 977 PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point. 978 979 Not Collective 980 981 Input Parameters: 982 + s - the PetscSection 983 . point - the point 984 . field - the field 985 - numDof - the number of dof which are fixed by constraints 986 987 Level: intermediate 988 989 .seealso: `PetscSectionSetDof()`, `PetscSectionGetFieldConstraintDof()`, `PetscSectionCreate()` 990 @*/ 991 PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) { 992 PetscFunctionBegin; 993 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 994 PetscSectionCheckValidField(field, s->numFields); 995 PetscCall(PetscSectionSetConstraintDof(s->field[field], point, numDof)); 996 PetscFunctionReturn(0); 997 } 998 999 /*@ 1000 PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point. 1001 1002 Not Collective 1003 1004 Input Parameters: 1005 + s - the PetscSection 1006 . point - the point 1007 . field - the field 1008 - numDof - the number of additional dof which are fixed by constraints 1009 1010 Level: intermediate 1011 1012 .seealso: `PetscSectionAddDof()`, `PetscSectionGetFieldConstraintDof()`, `PetscSectionCreate()` 1013 @*/ 1014 PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) { 1015 PetscFunctionBegin; 1016 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1017 PetscSectionCheckValidField(field, s->numFields); 1018 PetscCall(PetscSectionAddConstraintDof(s->field[field], point, numDof)); 1019 PetscFunctionReturn(0); 1020 } 1021 1022 /*@ 1023 PetscSectionSetUpBC - Setup the subsections describing boundary conditions. 1024 1025 Not Collective 1026 1027 Input Parameter: 1028 . s - the PetscSection 1029 1030 Level: advanced 1031 1032 .seealso: `PetscSectionSetUp()`, `PetscSectionCreate()` 1033 @*/ 1034 PetscErrorCode PetscSectionSetUpBC(PetscSection s) { 1035 PetscFunctionBegin; 1036 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1037 if (s->bc) { 1038 const PetscInt last = (s->bc->pEnd - s->bc->pStart) - 1; 1039 1040 PetscCall(PetscSectionSetUp(s->bc)); 1041 PetscCall(PetscMalloc1((last >= 0 ? s->bc->atlasOff[last] + s->bc->atlasDof[last] : 0), &s->bcIndices)); 1042 } 1043 PetscFunctionReturn(0); 1044 } 1045 1046 /*@ 1047 PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point. 1048 1049 Not Collective 1050 1051 Input Parameter: 1052 . s - the PetscSection 1053 1054 Level: intermediate 1055 1056 .seealso: `PetscSectionCreate()` 1057 @*/ 1058 PetscErrorCode PetscSectionSetUp(PetscSection s) { 1059 const PetscInt *pind = NULL; 1060 PetscInt offset = 0, foff, p, f; 1061 1062 PetscFunctionBegin; 1063 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1064 if (s->setup) PetscFunctionReturn(0); 1065 s->setup = PETSC_TRUE; 1066 /* Set offsets and field offsets for all points */ 1067 /* Assume that all fields have the same chart */ 1068 PetscCheck(s->includesConstraints, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscSectionSetUp is currently unsupported for includesConstraints = PETSC_TRUE"); 1069 if (s->perm) PetscCall(ISGetIndices(s->perm, &pind)); 1070 if (s->pointMajor) { 1071 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1072 const PetscInt q = pind ? pind[p] : p; 1073 1074 /* Set point offset */ 1075 s->atlasOff[q] = offset; 1076 offset += s->atlasDof[q]; 1077 /* Set field offset */ 1078 for (f = 0, foff = s->atlasOff[q]; f < s->numFields; ++f) { 1079 PetscSection sf = s->field[f]; 1080 1081 sf->atlasOff[q] = foff; 1082 foff += sf->atlasDof[q]; 1083 } 1084 } 1085 } else { 1086 /* Set field offsets for all points */ 1087 for (f = 0; f < s->numFields; ++f) { 1088 PetscSection sf = s->field[f]; 1089 1090 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1091 const PetscInt q = pind ? pind[p] : p; 1092 1093 sf->atlasOff[q] = offset; 1094 offset += sf->atlasDof[q]; 1095 } 1096 } 1097 /* Disable point offsets since these are unused */ 1098 for (p = 0; p < s->pEnd - s->pStart; ++p) s->atlasOff[p] = -1; 1099 } 1100 if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind)); 1101 /* Setup BC sections */ 1102 PetscCall(PetscSectionSetUpBC(s)); 1103 for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetUpBC(s->field[f])); 1104 PetscFunctionReturn(0); 1105 } 1106 1107 /*@ 1108 PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the chart 1109 1110 Not Collective 1111 1112 Input Parameters: 1113 . s - the PetscSection 1114 1115 Output Parameter: 1116 . maxDof - the maximum dof 1117 1118 Level: intermediate 1119 1120 Notes: 1121 The returned number is up-to-date without need for PetscSectionSetUp(). 1122 1123 Developer Notes: 1124 The returned number is calculated lazily and stashed. 1125 A call to PetscSectionInvalidateMaxDof_Internal() invalidates the stashed value. 1126 PetscSectionInvalidateMaxDof_Internal() is called in PetscSectionSetDof(), PetscSectionAddDof() and PetscSectionReset(). 1127 It should also be called every time atlasDof is modified directly. 1128 1129 .seealso: `PetscSectionGetDof()`, `PetscSectionSetDof()`, `PetscSectionAddDof()`, `PetscSectionCreate()` 1130 @*/ 1131 PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof) { 1132 PetscInt p; 1133 1134 PetscFunctionBegin; 1135 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1136 PetscValidIntPointer(maxDof, 2); 1137 if (s->maxDof == PETSC_MIN_INT) { 1138 s->maxDof = 0; 1139 for (p = 0; p < s->pEnd - s->pStart; ++p) s->maxDof = PetscMax(s->maxDof, s->atlasDof[p]); 1140 } 1141 *maxDof = s->maxDof; 1142 PetscFunctionReturn(0); 1143 } 1144 1145 /*@ 1146 PetscSectionGetStorageSize - Return the size of an array or local Vec capable of holding all the degrees of freedom. 1147 1148 Not Collective 1149 1150 Input Parameter: 1151 . s - the PetscSection 1152 1153 Output Parameter: 1154 . size - the size of an array which can hold all the dofs 1155 1156 Level: intermediate 1157 1158 .seealso: `PetscSectionGetOffset()`, `PetscSectionGetConstrainedStorageSize()`, `PetscSectionCreate()` 1159 @*/ 1160 PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size) { 1161 PetscInt p, n = 0; 1162 1163 PetscFunctionBegin; 1164 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1165 PetscValidIntPointer(size, 2); 1166 for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0; 1167 *size = n; 1168 PetscFunctionReturn(0); 1169 } 1170 1171 /*@ 1172 PetscSectionGetConstrainedStorageSize - Return the size of an array or local Vec capable of holding all unconstrained degrees of freedom. 1173 1174 Not Collective 1175 1176 Input Parameter: 1177 . s - the PetscSection 1178 1179 Output Parameter: 1180 . size - the size of an array which can hold all unconstrained dofs 1181 1182 Level: intermediate 1183 1184 .seealso: `PetscSectionGetStorageSize()`, `PetscSectionGetOffset()`, `PetscSectionCreate()` 1185 @*/ 1186 PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size) { 1187 PetscInt p, n = 0; 1188 1189 PetscFunctionBegin; 1190 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1191 PetscValidIntPointer(size, 2); 1192 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1193 const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0; 1194 n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0; 1195 } 1196 *size = n; 1197 PetscFunctionReturn(0); 1198 } 1199 1200 /*@ 1201 PetscSectionCreateGlobalSection - Create a section describing the global field layout using 1202 the local section and an SF describing the section point overlap. 1203 1204 Input Parameters: 1205 + s - The PetscSection for the local field layout 1206 . sf - The SF describing parallel layout of the section points (leaves are unowned local points) 1207 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 1208 - localOffsets - If PETSC_TRUE, use local rather than global offsets for the points 1209 1210 Output Parameter: 1211 . gsection - The PetscSection for the global field layout 1212 1213 Note: This gives negative sizes and offsets to points not owned by this process 1214 1215 Level: intermediate 1216 1217 .seealso: `PetscSectionCreate()` 1218 @*/ 1219 PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscBool localOffsets, PetscSection *gsection) { 1220 PetscSection gs; 1221 const PetscInt *pind = NULL; 1222 PetscInt *recv = NULL, *neg = NULL; 1223 PetscInt pStart, pEnd, p, dof, cdof, off, foff, globalOff = 0, nroots, nlocal, maxleaf; 1224 PetscInt numFields, f, numComponents; 1225 1226 PetscFunctionBegin; 1227 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1228 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1229 PetscValidLogicalCollectiveBool(s, includeConstraints, 3); 1230 PetscValidLogicalCollectiveBool(s, localOffsets, 4); 1231 PetscValidPointer(gsection, 5); 1232 PetscCheck(s->pointMajor, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for field major ordering"); 1233 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &gs)); 1234 PetscCall(PetscSectionGetNumFields(s, &numFields)); 1235 if (numFields > 0) PetscCall(PetscSectionSetNumFields(gs, numFields)); 1236 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1237 PetscCall(PetscSectionSetChart(gs, pStart, pEnd)); 1238 gs->includesConstraints = includeConstraints; 1239 PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL)); 1240 nlocal = nroots; /* The local/leaf space matches global/root space */ 1241 /* Must allocate for all points visible to SF, which may be more than this section */ 1242 if (nroots >= 0) { /* nroots < 0 means that the graph has not been set, only happens in serial */ 1243 PetscCall(PetscSFGetLeafRange(sf, NULL, &maxleaf)); 1244 PetscCheck(nroots >= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %" PetscInt_FMT " < pEnd %" PetscInt_FMT, nroots, pEnd); 1245 PetscCheck(maxleaf < nroots, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Max local leaf %" PetscInt_FMT " >= nroots %" PetscInt_FMT, maxleaf, nroots); 1246 PetscCall(PetscMalloc2(nroots, &neg, nlocal, &recv)); 1247 PetscCall(PetscArrayzero(neg, nroots)); 1248 } 1249 /* Mark all local points with negative dof */ 1250 for (p = pStart; p < pEnd; ++p) { 1251 PetscCall(PetscSectionGetDof(s, p, &dof)); 1252 PetscCall(PetscSectionSetDof(gs, p, dof)); 1253 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1254 if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(gs, p, cdof)); 1255 if (neg) neg[p] = -(dof + 1); 1256 } 1257 PetscCall(PetscSectionSetUpBC(gs)); 1258 if (gs->bcIndices) PetscCall(PetscArraycpy(gs->bcIndices, s->bcIndices, gs->bc->atlasOff[gs->bc->pEnd - gs->bc->pStart - 1] + gs->bc->atlasDof[gs->bc->pEnd - gs->bc->pStart - 1])); 1259 if (nroots >= 0) { 1260 PetscCall(PetscArrayzero(recv, nlocal)); 1261 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv, MPI_REPLACE)); 1262 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv, MPI_REPLACE)); 1263 for (p = pStart; p < pEnd; ++p) { 1264 if (recv[p] < 0) { 1265 gs->atlasDof[p - pStart] = recv[p]; 1266 PetscCall(PetscSectionGetDof(s, p, &dof)); 1267 PetscCheck(-(recv[p] + 1) == dof, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global dof %" PetscInt_FMT " for point %" PetscInt_FMT " is not the unconstrained %" PetscInt_FMT, -(recv[p] + 1), p, dof); 1268 } 1269 } 1270 } 1271 /* Calculate new sizes, get process offset, and calculate point offsets */ 1272 if (s->perm) PetscCall(ISGetIndices(s->perm, &pind)); 1273 for (p = 0, off = 0; p < pEnd - pStart; ++p) { 1274 const PetscInt q = pind ? pind[p] : p; 1275 1276 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0; 1277 gs->atlasOff[q] = off; 1278 off += gs->atlasDof[q] > 0 ? gs->atlasDof[q] - cdof : 0; 1279 } 1280 if (!localOffsets) { 1281 PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s))); 1282 globalOff -= off; 1283 } 1284 for (p = pStart, off = 0; p < pEnd; ++p) { 1285 gs->atlasOff[p - pStart] += globalOff; 1286 if (neg) neg[p] = -(gs->atlasOff[p - pStart] + 1); 1287 } 1288 if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind)); 1289 /* Put in negative offsets for ghost points */ 1290 if (nroots >= 0) { 1291 PetscCall(PetscArrayzero(recv, nlocal)); 1292 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv, MPI_REPLACE)); 1293 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv, MPI_REPLACE)); 1294 for (p = pStart; p < pEnd; ++p) { 1295 if (recv[p] < 0) gs->atlasOff[p - pStart] = recv[p]; 1296 } 1297 } 1298 PetscCall(PetscFree2(neg, recv)); 1299 /* Set field dofs/offsets/constraints */ 1300 for (f = 0; f < numFields; ++f) { 1301 gs->field[f]->includesConstraints = includeConstraints; 1302 PetscCall(PetscSectionGetFieldComponents(s, f, &numComponents)); 1303 PetscCall(PetscSectionSetFieldComponents(gs, f, numComponents)); 1304 } 1305 for (p = pStart; p < pEnd; ++p) { 1306 PetscCall(PetscSectionGetOffset(gs, p, &off)); 1307 for (f = 0, foff = off; f < numFields; ++f) { 1308 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof)); 1309 if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetFieldConstraintDof(gs, p, f, cdof)); 1310 PetscCall(PetscSectionGetFieldDof(s, p, f, &dof)); 1311 PetscCall(PetscSectionSetFieldDof(gs, p, f, off < 0 ? -(dof + 1) : dof)); 1312 PetscCall(PetscSectionSetFieldOffset(gs, p, f, foff)); 1313 PetscCall(PetscSectionGetFieldConstraintDof(gs, p, f, &cdof)); 1314 foff = off < 0 ? foff - (dof - cdof) : foff + (dof - cdof); 1315 } 1316 } 1317 for (f = 0; f < numFields; ++f) { 1318 PetscSection gfs = gs->field[f]; 1319 1320 PetscCall(PetscSectionSetUpBC(gfs)); 1321 if (gfs->bcIndices) PetscCall(PetscArraycpy(gfs->bcIndices, s->field[f]->bcIndices, gfs->bc->atlasOff[gfs->bc->pEnd - gfs->bc->pStart - 1] + gfs->bc->atlasDof[gfs->bc->pEnd - gfs->bc->pStart - 1])); 1322 } 1323 gs->setup = PETSC_TRUE; 1324 PetscCall(PetscSectionViewFromOptions(gs, NULL, "-global_section_view")); 1325 *gsection = gs; 1326 PetscFunctionReturn(0); 1327 } 1328 1329 /*@ 1330 PetscSectionCreateGlobalSectionCensored - Create a section describing the global field layout using 1331 the local section and an SF describing the section point overlap. 1332 1333 Input Parameters: 1334 + s - The PetscSection for the local field layout 1335 . sf - The SF describing parallel layout of the section points 1336 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 1337 . numExcludes - The number of exclusion ranges 1338 - excludes - An array [start_0, end_0, start_1, end_1, ...] where there are numExcludes pairs 1339 1340 Output Parameter: 1341 . gsection - The PetscSection for the global field layout 1342 1343 Note: This gives negative sizes and offsets to points not owned by this process 1344 1345 Level: advanced 1346 1347 .seealso: `PetscSectionCreate()` 1348 @*/ 1349 PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection) { 1350 const PetscInt *pind = NULL; 1351 PetscInt *neg = NULL, *tmpOff = NULL; 1352 PetscInt pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots; 1353 1354 PetscFunctionBegin; 1355 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1356 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1357 PetscValidPointer(gsection, 6); 1358 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection)); 1359 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1360 PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd)); 1361 PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL)); 1362 if (nroots >= 0) { 1363 PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart); 1364 PetscCall(PetscCalloc1(nroots, &neg)); 1365 if (nroots > pEnd - pStart) { 1366 PetscCall(PetscCalloc1(nroots, &tmpOff)); 1367 } else { 1368 tmpOff = &(*gsection)->atlasDof[-pStart]; 1369 } 1370 } 1371 /* Mark ghost points with negative dof */ 1372 for (p = pStart; p < pEnd; ++p) { 1373 for (e = 0; e < numExcludes; ++e) { 1374 if ((p >= excludes[e * 2 + 0]) && (p < excludes[e * 2 + 1])) { 1375 PetscCall(PetscSectionSetDof(*gsection, p, 0)); 1376 break; 1377 } 1378 } 1379 if (e < numExcludes) continue; 1380 PetscCall(PetscSectionGetDof(s, p, &dof)); 1381 PetscCall(PetscSectionSetDof(*gsection, p, dof)); 1382 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1383 if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof)); 1384 if (neg) neg[p] = -(dof + 1); 1385 } 1386 PetscCall(PetscSectionSetUpBC(*gsection)); 1387 if (nroots >= 0) { 1388 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE)); 1389 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE)); 1390 if (nroots > pEnd - pStart) { 1391 for (p = pStart; p < pEnd; ++p) { 1392 if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p]; 1393 } 1394 } 1395 } 1396 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 1397 if (s->perm) PetscCall(ISGetIndices(s->perm, &pind)); 1398 for (p = 0, off = 0; p < pEnd - pStart; ++p) { 1399 const PetscInt q = pind ? pind[p] : p; 1400 1401 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0; 1402 (*gsection)->atlasOff[q] = off; 1403 off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q] - cdof : 0; 1404 } 1405 PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s))); 1406 globalOff -= off; 1407 for (p = 0, off = 0; p < pEnd - pStart; ++p) { 1408 (*gsection)->atlasOff[p] += globalOff; 1409 if (neg) neg[p + pStart] = -((*gsection)->atlasOff[p] + 1); 1410 } 1411 if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind)); 1412 /* Put in negative offsets for ghost points */ 1413 if (nroots >= 0) { 1414 if (nroots == pEnd - pStart) tmpOff = &(*gsection)->atlasOff[-pStart]; 1415 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE)); 1416 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE)); 1417 if (nroots > pEnd - pStart) { 1418 for (p = pStart; p < pEnd; ++p) { 1419 if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p]; 1420 } 1421 } 1422 } 1423 if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff)); 1424 PetscCall(PetscFree(neg)); 1425 PetscFunctionReturn(0); 1426 } 1427 1428 /*@ 1429 PetscSectionGetPointLayout - Get the PetscLayout associated with the section points 1430 1431 Collective on comm 1432 1433 Input Parameters: 1434 + comm - The MPI_Comm 1435 - s - The PetscSection 1436 1437 Output Parameter: 1438 . layout - The point layout for the section 1439 1440 Note: This is usually called for the default global section. 1441 1442 Level: advanced 1443 1444 .seealso: `PetscSectionGetValueLayout()`, `PetscSectionCreate()` 1445 @*/ 1446 PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout) { 1447 PetscInt pStart, pEnd, p, localSize = 0; 1448 1449 PetscFunctionBegin; 1450 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1451 for (p = pStart; p < pEnd; ++p) { 1452 PetscInt dof; 1453 1454 PetscCall(PetscSectionGetDof(s, p, &dof)); 1455 if (dof >= 0) ++localSize; 1456 } 1457 PetscCall(PetscLayoutCreate(comm, layout)); 1458 PetscCall(PetscLayoutSetLocalSize(*layout, localSize)); 1459 PetscCall(PetscLayoutSetBlockSize(*layout, 1)); 1460 PetscCall(PetscLayoutSetUp(*layout)); 1461 PetscFunctionReturn(0); 1462 } 1463 1464 /*@ 1465 PetscSectionGetValueLayout - Get the PetscLayout associated with the section dofs. 1466 1467 Collective on comm 1468 1469 Input Parameters: 1470 + comm - The MPI_Comm 1471 - s - The PetscSection 1472 1473 Output Parameter: 1474 . layout - The dof layout for the section 1475 1476 Note: This is usually called for the default global section. 1477 1478 Level: advanced 1479 1480 .seealso: `PetscSectionGetPointLayout()`, `PetscSectionCreate()` 1481 @*/ 1482 PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout) { 1483 PetscInt pStart, pEnd, p, localSize = 0; 1484 1485 PetscFunctionBegin; 1486 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2); 1487 PetscValidPointer(layout, 3); 1488 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1489 for (p = pStart; p < pEnd; ++p) { 1490 PetscInt dof, cdof; 1491 1492 PetscCall(PetscSectionGetDof(s, p, &dof)); 1493 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1494 if (dof - cdof > 0) localSize += dof - cdof; 1495 } 1496 PetscCall(PetscLayoutCreate(comm, layout)); 1497 PetscCall(PetscLayoutSetLocalSize(*layout, localSize)); 1498 PetscCall(PetscLayoutSetBlockSize(*layout, 1)); 1499 PetscCall(PetscLayoutSetUp(*layout)); 1500 PetscFunctionReturn(0); 1501 } 1502 1503 /*@ 1504 PetscSectionGetOffset - Return the offset into an array or local Vec for the dof associated with the given point. 1505 1506 Not Collective 1507 1508 Input Parameters: 1509 + s - the PetscSection 1510 - point - the point 1511 1512 Output Parameter: 1513 . offset - the offset 1514 1515 Level: intermediate 1516 1517 .seealso: `PetscSectionGetFieldOffset()`, `PetscSectionCreate()` 1518 @*/ 1519 PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset) { 1520 PetscFunctionBegin; 1521 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1522 PetscValidIntPointer(offset, 3); 1523 if (PetscDefined(USE_DEBUG)) PetscCheck(!(point < s->pStart) && !(point >= s->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd); 1524 *offset = s->atlasOff[point - s->pStart]; 1525 PetscFunctionReturn(0); 1526 } 1527 1528 /*@ 1529 PetscSectionSetOffset - Set the offset into an array or local Vec for the dof associated with the given point. 1530 1531 Not Collective 1532 1533 Input Parameters: 1534 + s - the PetscSection 1535 . point - the point 1536 - offset - the offset 1537 1538 Note: The user usually does not call this function, but uses PetscSectionSetUp() 1539 1540 Level: intermediate 1541 1542 .seealso: `PetscSectionGetFieldOffset()`, `PetscSectionCreate()`, `PetscSectionSetUp()` 1543 @*/ 1544 PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset) { 1545 PetscFunctionBegin; 1546 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1547 PetscCheck(!(point < s->pStart) && !(point >= s->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %" PetscInt_FMT " should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, s->pStart, s->pEnd); 1548 s->atlasOff[point - s->pStart] = offset; 1549 PetscFunctionReturn(0); 1550 } 1551 1552 /*@ 1553 PetscSectionGetFieldOffset - Return the offset into an array or local Vec for the dof associated with the given point. 1554 1555 Not Collective 1556 1557 Input Parameters: 1558 + s - the PetscSection 1559 . point - the point 1560 - field - the field 1561 1562 Output Parameter: 1563 . offset - the offset 1564 1565 Level: intermediate 1566 1567 .seealso: `PetscSectionGetOffset()`, `PetscSectionCreate()` 1568 @*/ 1569 PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset) { 1570 PetscFunctionBegin; 1571 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1572 PetscValidIntPointer(offset, 4); 1573 PetscSectionCheckValidField(field, s->numFields); 1574 PetscCall(PetscSectionGetOffset(s->field[field], point, offset)); 1575 PetscFunctionReturn(0); 1576 } 1577 1578 /*@ 1579 PetscSectionSetFieldOffset - Set the offset into an array or local Vec for the dof associated with the given field at a point. 1580 1581 Not Collective 1582 1583 Input Parameters: 1584 + s - the PetscSection 1585 . point - the point 1586 . field - the field 1587 - offset - the offset 1588 1589 Note: The user usually does not call this function, but uses PetscSectionSetUp() 1590 1591 Level: intermediate 1592 1593 .seealso: `PetscSectionGetFieldOffset()`, `PetscSectionSetOffset()`, `PetscSectionCreate()`, `PetscSectionSetUp()` 1594 @*/ 1595 PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset) { 1596 PetscFunctionBegin; 1597 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1598 PetscSectionCheckValidField(field, s->numFields); 1599 PetscCall(PetscSectionSetOffset(s->field[field], point, offset)); 1600 PetscFunctionReturn(0); 1601 } 1602 1603 /*@ 1604 PetscSectionGetFieldPointOffset - Return the offset on the given point for the dof associated with the given point. 1605 1606 Not Collective 1607 1608 Input Parameters: 1609 + s - the PetscSection 1610 . point - the point 1611 - field - the field 1612 1613 Output Parameter: 1614 . offset - the offset 1615 1616 Note: This gives the offset on a point of the field, ignoring constraints, meaning starting at the first dof for 1617 this point, what number is the first dof with this field. 1618 1619 Level: advanced 1620 1621 .seealso: `PetscSectionGetOffset()`, `PetscSectionCreate()` 1622 @*/ 1623 PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset) { 1624 PetscInt off, foff; 1625 1626 PetscFunctionBegin; 1627 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1628 PetscValidIntPointer(offset, 4); 1629 PetscSectionCheckValidField(field, s->numFields); 1630 PetscCall(PetscSectionGetOffset(s, point, &off)); 1631 PetscCall(PetscSectionGetOffset(s->field[field], point, &foff)); 1632 *offset = foff - off; 1633 PetscFunctionReturn(0); 1634 } 1635 1636 /*@ 1637 PetscSectionGetOffsetRange - Return the full range of offsets [start, end) 1638 1639 Not Collective 1640 1641 Input Parameter: 1642 . s - the PetscSection 1643 1644 Output Parameters: 1645 + start - the minimum offset 1646 - end - one more than the maximum offset 1647 1648 Level: intermediate 1649 1650 .seealso: `PetscSectionGetOffset()`, `PetscSectionCreate()` 1651 @*/ 1652 PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end) { 1653 PetscInt os = 0, oe = 0, pStart, pEnd, p; 1654 1655 PetscFunctionBegin; 1656 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1657 if (s->atlasOff) { 1658 os = s->atlasOff[0]; 1659 oe = s->atlasOff[0]; 1660 } 1661 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1662 for (p = 0; p < pEnd - pStart; ++p) { 1663 PetscInt dof = s->atlasDof[p], off = s->atlasOff[p]; 1664 1665 if (off >= 0) { 1666 os = PetscMin(os, off); 1667 oe = PetscMax(oe, off + dof); 1668 } 1669 } 1670 if (start) *start = os; 1671 if (end) *end = oe; 1672 PetscFunctionReturn(0); 1673 } 1674 1675 /*@ 1676 PetscSectionCreateSubsection - Create a new, smaller section composed of only the selected fields 1677 1678 Collective 1679 1680 Input Parameters: 1681 + s - the PetscSection 1682 . len - the number of subfields 1683 - fields - the subfield numbers 1684 1685 Output Parameter: 1686 . subs - the subsection 1687 1688 Note: The section offsets now refer to a new, smaller vector. 1689 1690 Level: advanced 1691 1692 .seealso: `PetscSectionCreateSupersection()`, `PetscSectionCreate()` 1693 @*/ 1694 PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt len, const PetscInt fields[], PetscSection *subs) { 1695 PetscInt nF, f, c, pStart, pEnd, p, maxCdof = 0; 1696 1697 PetscFunctionBegin; 1698 if (!len) PetscFunctionReturn(0); 1699 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1700 PetscValidIntPointer(fields, 3); 1701 PetscValidPointer(subs, 4); 1702 PetscCall(PetscSectionGetNumFields(s, &nF)); 1703 PetscCheck(len <= nF, PetscObjectComm((PetscObject)s), PETSC_ERR_ARG_WRONG, "Number of requested fields %" PetscInt_FMT " greater than number of fields %" PetscInt_FMT, len, nF); 1704 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), subs)); 1705 PetscCall(PetscSectionSetNumFields(*subs, len)); 1706 for (f = 0; f < len; ++f) { 1707 const char *name = NULL; 1708 PetscInt numComp = 0; 1709 1710 PetscCall(PetscSectionGetFieldName(s, fields[f], &name)); 1711 PetscCall(PetscSectionSetFieldName(*subs, f, name)); 1712 PetscCall(PetscSectionGetFieldComponents(s, fields[f], &numComp)); 1713 PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp)); 1714 for (c = 0; c < s->numFieldComponents[fields[f]]; ++c) { 1715 PetscCall(PetscSectionGetComponentName(s, fields[f], c, &name)); 1716 PetscCall(PetscSectionSetComponentName(*subs, f, c, name)); 1717 } 1718 } 1719 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1720 PetscCall(PetscSectionSetChart(*subs, pStart, pEnd)); 1721 for (p = pStart; p < pEnd; ++p) { 1722 PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0; 1723 1724 for (f = 0; f < len; ++f) { 1725 PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof)); 1726 PetscCall(PetscSectionSetFieldDof(*subs, p, f, fdof)); 1727 PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof)); 1728 if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof)); 1729 dof += fdof; 1730 cdof += cfdof; 1731 } 1732 PetscCall(PetscSectionSetDof(*subs, p, dof)); 1733 if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, p, cdof)); 1734 maxCdof = PetscMax(cdof, maxCdof); 1735 } 1736 PetscCall(PetscSectionSetUp(*subs)); 1737 if (maxCdof) { 1738 PetscInt *indices; 1739 1740 PetscCall(PetscMalloc1(maxCdof, &indices)); 1741 for (p = pStart; p < pEnd; ++p) { 1742 PetscInt cdof; 1743 1744 PetscCall(PetscSectionGetConstraintDof(*subs, p, &cdof)); 1745 if (cdof) { 1746 const PetscInt *oldIndices = NULL; 1747 PetscInt fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0; 1748 1749 for (f = 0; f < len; ++f) { 1750 PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof)); 1751 PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof)); 1752 PetscCall(PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices)); 1753 PetscCall(PetscSectionSetFieldConstraintIndices(*subs, p, f, oldIndices)); 1754 for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] = oldIndices[fc] + fOff; 1755 numConst += cfdof; 1756 fOff += fdof; 1757 } 1758 PetscCall(PetscSectionSetConstraintIndices(*subs, p, indices)); 1759 } 1760 } 1761 PetscCall(PetscFree(indices)); 1762 } 1763 PetscFunctionReturn(0); 1764 } 1765 1766 /*@ 1767 PetscSectionCreateSupersection - Create a new, larger section composed of the input sections 1768 1769 Collective 1770 1771 Input Parameters: 1772 + s - the input sections 1773 - len - the number of input sections 1774 1775 Output Parameter: 1776 . supers - the supersection 1777 1778 Note: The section offsets now refer to a new, larger vector. 1779 1780 Level: advanced 1781 1782 .seealso: `PetscSectionCreateSubsection()`, `PetscSectionCreate()` 1783 @*/ 1784 PetscErrorCode PetscSectionCreateSupersection(PetscSection s[], PetscInt len, PetscSection *supers) { 1785 PetscInt Nf = 0, f, pStart = PETSC_MAX_INT, pEnd = 0, p, maxCdof = 0, i; 1786 1787 PetscFunctionBegin; 1788 if (!len) PetscFunctionReturn(0); 1789 for (i = 0; i < len; ++i) { 1790 PetscInt nf, pStarti, pEndi; 1791 1792 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1793 PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi)); 1794 pStart = PetscMin(pStart, pStarti); 1795 pEnd = PetscMax(pEnd, pEndi); 1796 Nf += nf; 1797 } 1798 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s[0]), supers)); 1799 PetscCall(PetscSectionSetNumFields(*supers, Nf)); 1800 for (i = 0, f = 0; i < len; ++i) { 1801 PetscInt nf, fi, ci; 1802 1803 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1804 for (fi = 0; fi < nf; ++fi, ++f) { 1805 const char *name = NULL; 1806 PetscInt numComp = 0; 1807 1808 PetscCall(PetscSectionGetFieldName(s[i], fi, &name)); 1809 PetscCall(PetscSectionSetFieldName(*supers, f, name)); 1810 PetscCall(PetscSectionGetFieldComponents(s[i], fi, &numComp)); 1811 PetscCall(PetscSectionSetFieldComponents(*supers, f, numComp)); 1812 for (ci = 0; ci < s[i]->numFieldComponents[fi]; ++ci) { 1813 PetscCall(PetscSectionGetComponentName(s[i], fi, ci, &name)); 1814 PetscCall(PetscSectionSetComponentName(*supers, f, ci, name)); 1815 } 1816 } 1817 } 1818 PetscCall(PetscSectionSetChart(*supers, pStart, pEnd)); 1819 for (p = pStart; p < pEnd; ++p) { 1820 PetscInt dof = 0, cdof = 0; 1821 1822 for (i = 0, f = 0; i < len; ++i) { 1823 PetscInt nf, fi, pStarti, pEndi; 1824 PetscInt fdof = 0, cfdof = 0; 1825 1826 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1827 PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi)); 1828 if ((p < pStarti) || (p >= pEndi)) continue; 1829 for (fi = 0; fi < nf; ++fi, ++f) { 1830 PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof)); 1831 PetscCall(PetscSectionAddFieldDof(*supers, p, f, fdof)); 1832 PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof)); 1833 if (cfdof) PetscCall(PetscSectionAddFieldConstraintDof(*supers, p, f, cfdof)); 1834 dof += fdof; 1835 cdof += cfdof; 1836 } 1837 } 1838 PetscCall(PetscSectionSetDof(*supers, p, dof)); 1839 if (cdof) PetscCall(PetscSectionSetConstraintDof(*supers, p, cdof)); 1840 maxCdof = PetscMax(cdof, maxCdof); 1841 } 1842 PetscCall(PetscSectionSetUp(*supers)); 1843 if (maxCdof) { 1844 PetscInt *indices; 1845 1846 PetscCall(PetscMalloc1(maxCdof, &indices)); 1847 for (p = pStart; p < pEnd; ++p) { 1848 PetscInt cdof; 1849 1850 PetscCall(PetscSectionGetConstraintDof(*supers, p, &cdof)); 1851 if (cdof) { 1852 PetscInt dof, numConst = 0, fOff = 0; 1853 1854 for (i = 0, f = 0; i < len; ++i) { 1855 const PetscInt *oldIndices = NULL; 1856 PetscInt nf, fi, pStarti, pEndi, fdof, cfdof, fc; 1857 1858 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1859 PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi)); 1860 if ((p < pStarti) || (p >= pEndi)) continue; 1861 for (fi = 0; fi < nf; ++fi, ++f) { 1862 PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof)); 1863 PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof)); 1864 PetscCall(PetscSectionGetFieldConstraintIndices(s[i], p, fi, &oldIndices)); 1865 for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] = oldIndices[fc]; 1866 PetscCall(PetscSectionSetFieldConstraintIndices(*supers, p, f, &indices[numConst])); 1867 for (fc = 0; fc < cfdof; ++fc) indices[numConst + fc] += fOff; 1868 numConst += cfdof; 1869 } 1870 PetscCall(PetscSectionGetDof(s[i], p, &dof)); 1871 fOff += dof; 1872 } 1873 PetscCall(PetscSectionSetConstraintIndices(*supers, p, indices)); 1874 } 1875 } 1876 PetscCall(PetscFree(indices)); 1877 } 1878 PetscFunctionReturn(0); 1879 } 1880 1881 PetscErrorCode PetscSectionCreateSubplexSection_Internal(PetscSection s, IS subpointMap, PetscBool renumberPoints, PetscSection *subs) { 1882 const PetscInt *points = NULL, *indices = NULL; 1883 PetscInt numFields, f, c, numSubpoints = 0, pStart, pEnd, p, spStart, spEnd, subp; 1884 1885 PetscFunctionBegin; 1886 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1887 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 1888 PetscValidPointer(subs, 4); 1889 PetscCall(PetscSectionGetNumFields(s, &numFields)); 1890 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), subs)); 1891 if (numFields) PetscCall(PetscSectionSetNumFields(*subs, numFields)); 1892 for (f = 0; f < numFields; ++f) { 1893 const char *name = NULL; 1894 PetscInt numComp = 0; 1895 1896 PetscCall(PetscSectionGetFieldName(s, f, &name)); 1897 PetscCall(PetscSectionSetFieldName(*subs, f, name)); 1898 PetscCall(PetscSectionGetFieldComponents(s, f, &numComp)); 1899 PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp)); 1900 for (c = 0; c < s->numFieldComponents[f]; ++c) { 1901 PetscCall(PetscSectionGetComponentName(s, f, c, &name)); 1902 PetscCall(PetscSectionSetComponentName(*subs, f, c, name)); 1903 } 1904 } 1905 /* For right now, we do not try to squeeze the subchart */ 1906 if (subpointMap) { 1907 PetscCall(ISGetSize(subpointMap, &numSubpoints)); 1908 PetscCall(ISGetIndices(subpointMap, &points)); 1909 } 1910 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1911 if (renumberPoints) { 1912 spStart = 0; 1913 spEnd = numSubpoints; 1914 } else { 1915 PetscCall(ISGetMinMax(subpointMap, &spStart, &spEnd)); 1916 ++spEnd; 1917 } 1918 PetscCall(PetscSectionSetChart(*subs, spStart, spEnd)); 1919 for (p = pStart; p < pEnd; ++p) { 1920 PetscInt dof, cdof, fdof = 0, cfdof = 0; 1921 1922 PetscCall(PetscFindInt(p, numSubpoints, points, &subp)); 1923 if (subp < 0) continue; 1924 if (!renumberPoints) subp = p; 1925 for (f = 0; f < numFields; ++f) { 1926 PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof)); 1927 PetscCall(PetscSectionSetFieldDof(*subs, subp, f, fdof)); 1928 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cfdof)); 1929 if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof)); 1930 } 1931 PetscCall(PetscSectionGetDof(s, p, &dof)); 1932 PetscCall(PetscSectionSetDof(*subs, subp, dof)); 1933 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1934 if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, subp, cdof)); 1935 } 1936 PetscCall(PetscSectionSetUp(*subs)); 1937 /* Change offsets to original offsets */ 1938 for (p = pStart; p < pEnd; ++p) { 1939 PetscInt off, foff = 0; 1940 1941 PetscCall(PetscFindInt(p, numSubpoints, points, &subp)); 1942 if (subp < 0) continue; 1943 if (!renumberPoints) subp = p; 1944 for (f = 0; f < numFields; ++f) { 1945 PetscCall(PetscSectionGetFieldOffset(s, p, f, &foff)); 1946 PetscCall(PetscSectionSetFieldOffset(*subs, subp, f, foff)); 1947 } 1948 PetscCall(PetscSectionGetOffset(s, p, &off)); 1949 PetscCall(PetscSectionSetOffset(*subs, subp, off)); 1950 } 1951 /* Copy constraint indices */ 1952 for (subp = spStart; subp < spEnd; ++subp) { 1953 PetscInt cdof; 1954 1955 PetscCall(PetscSectionGetConstraintDof(*subs, subp, &cdof)); 1956 if (cdof) { 1957 for (f = 0; f < numFields; ++f) { 1958 PetscCall(PetscSectionGetFieldConstraintIndices(s, points[subp - spStart], f, &indices)); 1959 PetscCall(PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices)); 1960 } 1961 PetscCall(PetscSectionGetConstraintIndices(s, points[subp - spStart], &indices)); 1962 PetscCall(PetscSectionSetConstraintIndices(*subs, subp, indices)); 1963 } 1964 } 1965 if (subpointMap) PetscCall(ISRestoreIndices(subpointMap, &points)); 1966 PetscFunctionReturn(0); 1967 } 1968 1969 /*@ 1970 PetscSectionCreateSubmeshSection - Create a new, smaller section with support on the submesh 1971 1972 Collective on s 1973 1974 Input Parameters: 1975 + s - the PetscSection 1976 - subpointMap - a sorted list of points in the original mesh which are in the submesh 1977 1978 Output Parameter: 1979 . subs - the subsection 1980 1981 Note: 1982 The points are renumbered from 0, and the section offsets now refer to a new, smaller vector. 1983 1984 Level: advanced 1985 1986 .seealso: `PetscSectionCreateSubdomainSection()`, `PetscSectionCreateSubsection()`, `DMPlexGetSubpointMap()`, `PetscSectionCreate()` 1987 @*/ 1988 PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs) { 1989 PetscFunctionBegin; 1990 PetscCall(PetscSectionCreateSubplexSection_Internal(s, subpointMap, PETSC_TRUE, subs)); 1991 PetscFunctionReturn(0); 1992 } 1993 1994 /*@ 1995 PetscSectionCreateSubdomainSection - Create a new, smaller section with support on a subdomain of the mesh 1996 1997 Collective on s 1998 1999 Input Parameters: 2000 + s - the PetscSection 2001 - subpointMap - a sorted list of points in the original mesh which are in the subdomain 2002 2003 Output Parameter: 2004 . subs - the subsection 2005 2006 Note: 2007 The point numbers remain the same, but the section offsets now refer to a new, smaller vector. 2008 2009 Level: advanced 2010 2011 .seealso: `PetscSectionCreateSubmeshSection()`, `PetscSectionCreateSubsection()`, `DMPlexGetSubpointMap()`, `PetscSectionCreate()` 2012 @*/ 2013 PetscErrorCode PetscSectionCreateSubdomainSection(PetscSection s, IS subpointMap, PetscSection *subs) { 2014 PetscFunctionBegin; 2015 PetscCall(PetscSectionCreateSubplexSection_Internal(s, subpointMap, PETSC_FALSE, subs)); 2016 PetscFunctionReturn(0); 2017 } 2018 2019 static PetscErrorCode PetscSectionView_ASCII(PetscSection s, PetscViewer viewer) { 2020 PetscInt p; 2021 PetscMPIInt rank; 2022 2023 PetscFunctionBegin; 2024 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 2025 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 2026 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 2027 for (p = 0; p < s->pEnd - s->pStart; ++p) { 2028 if ((s->bc) && (s->bc->atlasDof[p] > 0)) { 2029 PetscInt b; 2030 2031 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT " constrained", p + s->pStart, s->atlasDof[p], s->atlasOff[p])); 2032 if (s->bcIndices) { 2033 for (b = 0; b < s->bc->atlasDof[p]; ++b) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, s->bcIndices[s->bc->atlasOff[p] + b])); 2034 } 2035 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 2036 } else { 2037 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT "\n", p + s->pStart, s->atlasDof[p], s->atlasOff[p])); 2038 } 2039 } 2040 PetscCall(PetscViewerFlush(viewer)); 2041 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 2042 if (s->sym) { 2043 PetscCall(PetscViewerASCIIPushTab(viewer)); 2044 PetscCall(PetscSectionSymView(s->sym, viewer)); 2045 PetscCall(PetscViewerASCIIPopTab(viewer)); 2046 } 2047 PetscFunctionReturn(0); 2048 } 2049 2050 /*@C 2051 PetscSectionViewFromOptions - View from Options 2052 2053 Collective 2054 2055 Input Parameters: 2056 + A - the PetscSection object to view 2057 . obj - Optional object 2058 - name - command line option 2059 2060 Level: intermediate 2061 .seealso: `PetscSection`, `PetscSectionView`, `PetscObjectViewFromOptions()`, `PetscSectionCreate()` 2062 @*/ 2063 PetscErrorCode PetscSectionViewFromOptions(PetscSection A, PetscObject obj, const char name[]) { 2064 PetscFunctionBegin; 2065 PetscValidHeaderSpecific(A, PETSC_SECTION_CLASSID, 1); 2066 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 2067 PetscFunctionReturn(0); 2068 } 2069 2070 /*@C 2071 PetscSectionView - Views a PetscSection 2072 2073 Collective 2074 2075 Input Parameters: 2076 + s - the PetscSection object to view 2077 - v - the viewer 2078 2079 Note: 2080 PetscSectionView(), when viewer is of type PETSCVIEWERHDF5, only saves 2081 distribution independent data, such as dofs, offsets, constraint dofs, 2082 and constraint indices. Points that have negative dofs, for instance, 2083 are not saved as they represent points owned by other processes. 2084 Point numbering and rank assignment is currently not stored. 2085 The saved section can be loaded with PetscSectionLoad(). 2086 2087 Level: beginner 2088 2089 .seealso `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionLoad()` 2090 @*/ 2091 PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer) { 2092 PetscBool isascii, ishdf5; 2093 PetscInt f; 2094 2095 PetscFunctionBegin; 2096 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2097 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)s), &viewer)); 2098 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2099 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 2100 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2101 if (isascii) { 2102 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)s, viewer)); 2103 if (s->numFields) { 2104 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " fields\n", s->numFields)); 2105 for (f = 0; f < s->numFields; ++f) { 2106 PetscCall(PetscViewerASCIIPrintf(viewer, " field %" PetscInt_FMT " with %" PetscInt_FMT " components\n", f, s->numFieldComponents[f])); 2107 PetscCall(PetscSectionView_ASCII(s->field[f], viewer)); 2108 } 2109 } else { 2110 PetscCall(PetscSectionView_ASCII(s, viewer)); 2111 } 2112 } else if (ishdf5) { 2113 #if PetscDefined(HAVE_HDF5) 2114 PetscCall(PetscSectionView_HDF5_Internal(s, viewer)); 2115 #else 2116 SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2117 #endif 2118 } 2119 PetscFunctionReturn(0); 2120 } 2121 2122 /*@C 2123 PetscSectionLoad - Loads a PetscSection 2124 2125 Collective 2126 2127 Input Parameters: 2128 + s - the PetscSection object to load 2129 - v - the viewer 2130 2131 Note: 2132 PetscSectionLoad(), when viewer is of type PETSCVIEWERHDF5, loads 2133 a section saved with PetscSectionView(). The number of processes 2134 used here (N) does not need to be the same as that used when saving. 2135 After calling this function, the chart of s on rank i will be set 2136 to [0, E_i), where \sum_{i=0}^{N-1}E_i equals to the total number of 2137 saved section points. 2138 2139 Level: beginner 2140 2141 .seealso `PetscSectionCreate()`, `PetscSectionDestroy()`, `PetscSectionView()` 2142 @*/ 2143 PetscErrorCode PetscSectionLoad(PetscSection s, PetscViewer viewer) { 2144 PetscBool ishdf5; 2145 2146 PetscFunctionBegin; 2147 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2148 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2149 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2150 if (ishdf5) { 2151 #if PetscDefined(HAVE_HDF5) 2152 PetscCall(PetscSectionLoad_HDF5_Internal(s, viewer)); 2153 PetscFunctionReturn(0); 2154 #else 2155 SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2156 #endif 2157 } else SETERRQ(PetscObjectComm((PetscObject)s), PETSC_ERR_SUP, "Viewer type %s not yet supported for PetscSection loading", ((PetscObject)viewer)->type_name); 2158 } 2159 2160 static PetscErrorCode PetscSectionResetClosurePermutation(PetscSection section) { 2161 PetscSectionClosurePermVal clVal; 2162 2163 PetscFunctionBegin; 2164 if (!section->clHash) PetscFunctionReturn(0); 2165 kh_foreach_value(section->clHash, clVal, { 2166 PetscCall(PetscFree(clVal.perm)); 2167 PetscCall(PetscFree(clVal.invPerm)); 2168 }); 2169 kh_destroy(ClPerm, section->clHash); 2170 section->clHash = NULL; 2171 PetscFunctionReturn(0); 2172 } 2173 2174 /*@ 2175 PetscSectionReset - Frees all section data. 2176 2177 Not Collective 2178 2179 Input Parameters: 2180 . s - the PetscSection 2181 2182 Level: beginner 2183 2184 .seealso: `PetscSection`, `PetscSectionCreate()` 2185 @*/ 2186 PetscErrorCode PetscSectionReset(PetscSection s) { 2187 PetscInt f, c; 2188 2189 PetscFunctionBegin; 2190 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2191 for (f = 0; f < s->numFields; ++f) { 2192 PetscCall(PetscSectionDestroy(&s->field[f])); 2193 PetscCall(PetscFree(s->fieldNames[f])); 2194 for (c = 0; c < s->numFieldComponents[f]; ++c) PetscCall(PetscFree(s->compNames[f][c])); 2195 PetscCall(PetscFree(s->compNames[f])); 2196 } 2197 PetscCall(PetscFree(s->numFieldComponents)); 2198 PetscCall(PetscFree(s->fieldNames)); 2199 PetscCall(PetscFree(s->compNames)); 2200 PetscCall(PetscFree(s->field)); 2201 PetscCall(PetscSectionDestroy(&s->bc)); 2202 PetscCall(PetscFree(s->bcIndices)); 2203 PetscCall(PetscFree2(s->atlasDof, s->atlasOff)); 2204 PetscCall(PetscSectionDestroy(&s->clSection)); 2205 PetscCall(ISDestroy(&s->clPoints)); 2206 PetscCall(ISDestroy(&s->perm)); 2207 PetscCall(PetscSectionResetClosurePermutation(s)); 2208 PetscCall(PetscSectionSymDestroy(&s->sym)); 2209 PetscCall(PetscSectionDestroy(&s->clSection)); 2210 PetscCall(ISDestroy(&s->clPoints)); 2211 PetscCall(PetscSectionInvalidateMaxDof_Internal(s)); 2212 s->pStart = -1; 2213 s->pEnd = -1; 2214 s->maxDof = 0; 2215 s->setup = PETSC_FALSE; 2216 s->numFields = 0; 2217 s->clObj = NULL; 2218 PetscFunctionReturn(0); 2219 } 2220 2221 /*@ 2222 PetscSectionDestroy - Frees a section object and frees its range if that exists. 2223 2224 Not Collective 2225 2226 Input Parameters: 2227 . s - the PetscSection 2228 2229 Level: beginner 2230 2231 .seealso: `PetscSection`, `PetscSectionCreate()` 2232 @*/ 2233 PetscErrorCode PetscSectionDestroy(PetscSection *s) { 2234 PetscFunctionBegin; 2235 if (!*s) PetscFunctionReturn(0); 2236 PetscValidHeaderSpecific(*s, PETSC_SECTION_CLASSID, 1); 2237 if (--((PetscObject)(*s))->refct > 0) { 2238 *s = NULL; 2239 PetscFunctionReturn(0); 2240 } 2241 PetscCall(PetscSectionReset(*s)); 2242 PetscCall(PetscHeaderDestroy(s)); 2243 PetscFunctionReturn(0); 2244 } 2245 2246 PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values) { 2247 const PetscInt p = point - s->pStart; 2248 2249 PetscFunctionBegin; 2250 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2); 2251 *values = &baseArray[s->atlasOff[p]]; 2252 PetscFunctionReturn(0); 2253 } 2254 2255 PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode) { 2256 PetscInt *array; 2257 const PetscInt p = point - s->pStart; 2258 const PetscInt orientation = 0; /* Needs to be included for use in closure operations */ 2259 PetscInt cDim = 0; 2260 2261 PetscFunctionBegin; 2262 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2); 2263 PetscCall(PetscSectionGetConstraintDof(s, p, &cDim)); 2264 array = &baseArray[s->atlasOff[p]]; 2265 if (!cDim) { 2266 if (orientation >= 0) { 2267 const PetscInt dim = s->atlasDof[p]; 2268 PetscInt i; 2269 2270 if (mode == INSERT_VALUES) { 2271 for (i = 0; i < dim; ++i) array[i] = values[i]; 2272 } else { 2273 for (i = 0; i < dim; ++i) array[i] += values[i]; 2274 } 2275 } else { 2276 PetscInt offset = 0; 2277 PetscInt j = -1, field, i; 2278 2279 for (field = 0; field < s->numFields; ++field) { 2280 const PetscInt dim = s->field[field]->atlasDof[p]; 2281 2282 for (i = dim - 1; i >= 0; --i) array[++j] = values[i + offset]; 2283 offset += dim; 2284 } 2285 } 2286 } else { 2287 if (orientation >= 0) { 2288 const PetscInt dim = s->atlasDof[p]; 2289 PetscInt cInd = 0, i; 2290 const PetscInt *cDof; 2291 2292 PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof)); 2293 if (mode == INSERT_VALUES) { 2294 for (i = 0; i < dim; ++i) { 2295 if ((cInd < cDim) && (i == cDof[cInd])) { 2296 ++cInd; 2297 continue; 2298 } 2299 array[i] = values[i]; 2300 } 2301 } else { 2302 for (i = 0; i < dim; ++i) { 2303 if ((cInd < cDim) && (i == cDof[cInd])) { 2304 ++cInd; 2305 continue; 2306 } 2307 array[i] += values[i]; 2308 } 2309 } 2310 } else { 2311 const PetscInt *cDof; 2312 PetscInt offset = 0; 2313 PetscInt cOffset = 0; 2314 PetscInt j = 0, field; 2315 2316 PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof)); 2317 for (field = 0; field < s->numFields; ++field) { 2318 const PetscInt dim = s->field[field]->atlasDof[p]; /* PetscSectionGetFieldDof() */ 2319 const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */ 2320 const PetscInt sDim = dim - tDim; 2321 PetscInt cInd = 0, i, k; 2322 2323 for (i = 0, k = dim + offset - 1; i < dim; ++i, ++j, --k) { 2324 if ((cInd < sDim) && (j == cDof[cInd + cOffset])) { 2325 ++cInd; 2326 continue; 2327 } 2328 array[j] = values[k]; 2329 } 2330 offset += dim; 2331 cOffset += dim - tDim; 2332 } 2333 } 2334 } 2335 PetscFunctionReturn(0); 2336 } 2337 2338 /*@C 2339 PetscSectionHasConstraints - Determine whether a section has constrained dofs 2340 2341 Not Collective 2342 2343 Input Parameter: 2344 . s - The PetscSection 2345 2346 Output Parameter: 2347 . hasConstraints - flag indicating that the section has constrained dofs 2348 2349 Level: intermediate 2350 2351 .seealso: `PetscSectionSetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection` 2352 @*/ 2353 PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints) { 2354 PetscFunctionBegin; 2355 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2356 PetscValidBoolPointer(hasConstraints, 2); 2357 *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE; 2358 PetscFunctionReturn(0); 2359 } 2360 2361 /*@C 2362 PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained 2363 2364 Not Collective 2365 2366 Input Parameters: 2367 + s - The PetscSection 2368 - point - The point 2369 2370 Output Parameter: 2371 . indices - The constrained dofs 2372 2373 Note: In Fortran, you call PetscSectionGetConstraintIndicesF90() and PetscSectionRestoreConstraintIndicesF90() 2374 2375 Level: intermediate 2376 2377 .seealso: `PetscSectionSetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection` 2378 @*/ 2379 PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices) { 2380 PetscFunctionBegin; 2381 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2382 if (s->bc) { 2383 PetscCall(VecIntGetValuesSection(s->bcIndices, s->bc, point, indices)); 2384 } else *indices = NULL; 2385 PetscFunctionReturn(0); 2386 } 2387 2388 /*@C 2389 PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained 2390 2391 Not Collective 2392 2393 Input Parameters: 2394 + s - The PetscSection 2395 . point - The point 2396 - indices - The constrained dofs 2397 2398 Note: The Fortran is PetscSectionSetConstraintIndicesF90() 2399 2400 Level: intermediate 2401 2402 .seealso: `PetscSectionGetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection` 2403 @*/ 2404 PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[]) { 2405 PetscFunctionBegin; 2406 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2407 if (s->bc) { 2408 const PetscInt dof = s->atlasDof[point]; 2409 const PetscInt cdof = s->bc->atlasDof[point]; 2410 PetscInt d; 2411 2412 for (d = 0; d < cdof; ++d) PetscCheck(indices[d] < dof, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " dof %" PetscInt_FMT ", invalid constraint index[%" PetscInt_FMT "]: %" PetscInt_FMT, point, dof, d, indices[d]); 2413 PetscCall(VecIntSetValuesSection(s->bcIndices, s->bc, point, indices, INSERT_VALUES)); 2414 } 2415 PetscFunctionReturn(0); 2416 } 2417 2418 /*@C 2419 PetscSectionGetFieldConstraintIndices - Get the field dof numbers, in [0, fdof), which are constrained 2420 2421 Not Collective 2422 2423 Input Parameters: 2424 + s - The PetscSection 2425 . field - The field number 2426 - point - The point 2427 2428 Output Parameter: 2429 . indices - The constrained dofs sorted in ascending order 2430 2431 Notes: 2432 The indices array, which is provided by the caller, must have capacity to hold the number of constrained dofs, e.g., as returned by PetscSectionGetConstraintDof(). 2433 2434 Fortran Note: 2435 In Fortran, you call PetscSectionGetFieldConstraintIndicesF90() and PetscSectionRestoreFieldConstraintIndicesF90() 2436 2437 Level: intermediate 2438 2439 .seealso: `PetscSectionSetFieldConstraintIndices()`, `PetscSectionGetConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection` 2440 @*/ 2441 PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices) { 2442 PetscFunctionBegin; 2443 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2444 PetscValidPointer(indices, 4); 2445 PetscSectionCheckValidField(field, s->numFields); 2446 PetscCall(PetscSectionGetConstraintIndices(s->field[field], point, indices)); 2447 PetscFunctionReturn(0); 2448 } 2449 2450 /*@C 2451 PetscSectionSetFieldConstraintIndices - Set the field dof numbers, in [0, fdof), which are constrained 2452 2453 Not Collective 2454 2455 Input Parameters: 2456 + s - The PetscSection 2457 . point - The point 2458 . field - The field number 2459 - indices - The constrained dofs 2460 2461 Note: The Fortran is PetscSectionSetFieldConstraintIndicesF90() 2462 2463 Level: intermediate 2464 2465 .seealso: `PetscSectionSetConstraintIndices()`, `PetscSectionGetFieldConstraintIndices()`, `PetscSectionGetConstraintDof()`, `PetscSection` 2466 @*/ 2467 PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[]) { 2468 PetscFunctionBegin; 2469 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2470 if (PetscDefined(USE_DEBUG)) { 2471 PetscInt nfdof; 2472 2473 PetscCall(PetscSectionGetFieldConstraintDof(s, point, field, &nfdof)); 2474 if (nfdof) PetscValidIntPointer(indices, 4); 2475 } 2476 PetscSectionCheckValidField(field, s->numFields); 2477 PetscCall(PetscSectionSetConstraintIndices(s->field[field], point, indices)); 2478 PetscFunctionReturn(0); 2479 } 2480 2481 /*@ 2482 PetscSectionPermute - Reorder the section according to the input point permutation 2483 2484 Collective 2485 2486 Input Parameters: 2487 + section - The PetscSection object 2488 - perm - The point permutation, old point p becomes new point perm[p] 2489 2490 Output Parameter: 2491 . sectionNew - The permuted PetscSection 2492 2493 Level: intermediate 2494 2495 .seealso: `MatPermute()` 2496 @*/ 2497 PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew) { 2498 PetscSection s = section, sNew; 2499 const PetscInt *perm; 2500 PetscInt numFields, f, c, numPoints, pStart, pEnd, p; 2501 2502 PetscFunctionBegin; 2503 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 2504 PetscValidHeaderSpecific(permutation, IS_CLASSID, 2); 2505 PetscValidPointer(sectionNew, 3); 2506 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), &sNew)); 2507 PetscCall(PetscSectionGetNumFields(s, &numFields)); 2508 if (numFields) PetscCall(PetscSectionSetNumFields(sNew, numFields)); 2509 for (f = 0; f < numFields; ++f) { 2510 const char *name; 2511 PetscInt numComp; 2512 2513 PetscCall(PetscSectionGetFieldName(s, f, &name)); 2514 PetscCall(PetscSectionSetFieldName(sNew, f, name)); 2515 PetscCall(PetscSectionGetFieldComponents(s, f, &numComp)); 2516 PetscCall(PetscSectionSetFieldComponents(sNew, f, numComp)); 2517 for (c = 0; c < s->numFieldComponents[f]; ++c) { 2518 PetscCall(PetscSectionGetComponentName(s, f, c, &name)); 2519 PetscCall(PetscSectionSetComponentName(sNew, f, c, name)); 2520 } 2521 } 2522 PetscCall(ISGetLocalSize(permutation, &numPoints)); 2523 PetscCall(ISGetIndices(permutation, &perm)); 2524 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 2525 PetscCall(PetscSectionSetChart(sNew, pStart, pEnd)); 2526 PetscCheck(numPoints >= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %" PetscInt_FMT " is less than largest Section point %" PetscInt_FMT, numPoints, pEnd); 2527 for (p = pStart; p < pEnd; ++p) { 2528 PetscInt dof, cdof; 2529 2530 PetscCall(PetscSectionGetDof(s, p, &dof)); 2531 PetscCall(PetscSectionSetDof(sNew, perm[p], dof)); 2532 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 2533 if (cdof) PetscCall(PetscSectionSetConstraintDof(sNew, perm[p], cdof)); 2534 for (f = 0; f < numFields; ++f) { 2535 PetscCall(PetscSectionGetFieldDof(s, p, f, &dof)); 2536 PetscCall(PetscSectionSetFieldDof(sNew, perm[p], f, dof)); 2537 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof)); 2538 if (cdof) PetscCall(PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof)); 2539 } 2540 } 2541 PetscCall(PetscSectionSetUp(sNew)); 2542 for (p = pStart; p < pEnd; ++p) { 2543 const PetscInt *cind; 2544 PetscInt cdof; 2545 2546 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 2547 if (cdof) { 2548 PetscCall(PetscSectionGetConstraintIndices(s, p, &cind)); 2549 PetscCall(PetscSectionSetConstraintIndices(sNew, perm[p], cind)); 2550 } 2551 for (f = 0; f < numFields; ++f) { 2552 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof)); 2553 if (cdof) { 2554 PetscCall(PetscSectionGetFieldConstraintIndices(s, p, f, &cind)); 2555 PetscCall(PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind)); 2556 } 2557 } 2558 } 2559 PetscCall(ISRestoreIndices(permutation, &perm)); 2560 *sectionNew = sNew; 2561 PetscFunctionReturn(0); 2562 } 2563 2564 /*@ 2565 PetscSectionSetClosureIndex - Set a cache of points in the closure of each point in the section 2566 2567 Collective 2568 2569 Input Parameters: 2570 + section - The PetscSection 2571 . obj - A PetscObject which serves as the key for this index 2572 . clSection - Section giving the size of the closure of each point 2573 - clPoints - IS giving the points in each closure 2574 2575 Note: We compress out closure points with no dofs in this section 2576 2577 Level: advanced 2578 2579 .seealso: `PetscSectionGetClosureIndex()`, `DMPlexCreateClosureIndex()` 2580 @*/ 2581 PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints) { 2582 PetscFunctionBegin; 2583 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 2584 PetscValidHeaderSpecific(clSection, PETSC_SECTION_CLASSID, 3); 2585 PetscValidHeaderSpecific(clPoints, IS_CLASSID, 4); 2586 if (section->clObj != obj) PetscCall(PetscSectionResetClosurePermutation(section)); 2587 section->clObj = obj; 2588 PetscCall(PetscObjectReference((PetscObject)clSection)); 2589 PetscCall(PetscObjectReference((PetscObject)clPoints)); 2590 PetscCall(PetscSectionDestroy(§ion->clSection)); 2591 PetscCall(ISDestroy(§ion->clPoints)); 2592 section->clSection = clSection; 2593 section->clPoints = clPoints; 2594 PetscFunctionReturn(0); 2595 } 2596 2597 /*@ 2598 PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section 2599 2600 Collective 2601 2602 Input Parameters: 2603 + section - The PetscSection 2604 - obj - A PetscObject which serves as the key for this index 2605 2606 Output Parameters: 2607 + clSection - Section giving the size of the closure of each point 2608 - clPoints - IS giving the points in each closure 2609 2610 Note: We compress out closure points with no dofs in this section 2611 2612 Level: advanced 2613 2614 .seealso: `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()` 2615 @*/ 2616 PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints) { 2617 PetscFunctionBegin; 2618 if (section->clObj == obj) { 2619 if (clSection) *clSection = section->clSection; 2620 if (clPoints) *clPoints = section->clPoints; 2621 } else { 2622 if (clSection) *clSection = NULL; 2623 if (clPoints) *clPoints = NULL; 2624 } 2625 PetscFunctionReturn(0); 2626 } 2627 2628 PetscErrorCode PetscSectionSetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, PetscCopyMode mode, PetscInt *clPerm) { 2629 PetscInt i; 2630 khiter_t iter; 2631 int new_entry; 2632 PetscSectionClosurePermKey key = {depth, clSize}; 2633 PetscSectionClosurePermVal *val; 2634 2635 PetscFunctionBegin; 2636 if (section->clObj != obj) { 2637 PetscCall(PetscSectionDestroy(§ion->clSection)); 2638 PetscCall(ISDestroy(§ion->clPoints)); 2639 } 2640 section->clObj = obj; 2641 if (!section->clHash) PetscCall(PetscClPermCreate(§ion->clHash)); 2642 iter = kh_put(ClPerm, section->clHash, key, &new_entry); 2643 val = &kh_val(section->clHash, iter); 2644 if (!new_entry) { 2645 PetscCall(PetscFree(val->perm)); 2646 PetscCall(PetscFree(val->invPerm)); 2647 } 2648 if (mode == PETSC_COPY_VALUES) { 2649 PetscCall(PetscMalloc1(clSize, &val->perm)); 2650 PetscCall(PetscLogObjectMemory((PetscObject)obj, clSize * sizeof(PetscInt))); 2651 PetscCall(PetscArraycpy(val->perm, clPerm, clSize)); 2652 } else if (mode == PETSC_OWN_POINTER) { 2653 val->perm = clPerm; 2654 } else SETERRQ(PetscObjectComm(obj), PETSC_ERR_SUP, "Do not support borrowed arrays"); 2655 PetscCall(PetscMalloc1(clSize, &val->invPerm)); 2656 for (i = 0; i < clSize; ++i) val->invPerm[clPerm[i]] = i; 2657 PetscFunctionReturn(0); 2658 } 2659 2660 /*@ 2661 PetscSectionSetClosurePermutation - Set the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex. 2662 2663 Not Collective 2664 2665 Input Parameters: 2666 + section - The PetscSection 2667 . obj - A PetscObject which serves as the key for this index (usually a DM) 2668 . depth - Depth of points on which to apply the given permutation 2669 - perm - Permutation of the cell dof closure 2670 2671 Note: 2672 The specified permutation will only be applied to points at depth whose closure size matches the length of perm. In a 2673 mixed-topology or variable-degree finite element space, this function can be called multiple times at each depth for 2674 each topology and degree. 2675 2676 This approach assumes that (depth, len(perm)) uniquely identifies the desired permutation; this might not be true for 2677 exotic/enriched spaces on mixed topology meshes. 2678 2679 Level: intermediate 2680 2681 .seealso: `PetscSectionGetClosurePermutation()`, `PetscSectionGetClosureIndex()`, `DMPlexCreateClosureIndex()`, `PetscCopyMode` 2682 @*/ 2683 PetscErrorCode PetscSectionSetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, IS perm) { 2684 const PetscInt *clPerm = NULL; 2685 PetscInt clSize = 0; 2686 2687 PetscFunctionBegin; 2688 if (perm) { 2689 PetscCall(ISGetLocalSize(perm, &clSize)); 2690 PetscCall(ISGetIndices(perm, &clPerm)); 2691 } 2692 PetscCall(PetscSectionSetClosurePermutation_Internal(section, obj, depth, clSize, PETSC_COPY_VALUES, (PetscInt *)clPerm)); 2693 if (perm) PetscCall(ISRestoreIndices(perm, &clPerm)); 2694 PetscFunctionReturn(0); 2695 } 2696 2697 PetscErrorCode PetscSectionGetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[]) { 2698 PetscFunctionBegin; 2699 if (section->clObj == obj) { 2700 PetscSectionClosurePermKey k = {depth, size}; 2701 PetscSectionClosurePermVal v; 2702 PetscCall(PetscClPermGet(section->clHash, k, &v)); 2703 if (perm) *perm = v.perm; 2704 } else { 2705 if (perm) *perm = NULL; 2706 } 2707 PetscFunctionReturn(0); 2708 } 2709 2710 /*@ 2711 PetscSectionGetClosurePermutation - Get the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex. 2712 2713 Not Collective 2714 2715 Input Parameters: 2716 + section - The PetscSection 2717 . obj - A PetscObject which serves as the key for this index (usually a DM) 2718 . depth - Depth stratum on which to obtain closure permutation 2719 - clSize - Closure size to be permuted (e.g., may vary with element topology and degree) 2720 2721 Output Parameter: 2722 . perm - The dof closure permutation 2723 2724 Note: 2725 The user must destroy the IS that is returned. 2726 2727 Level: intermediate 2728 2729 .seealso: `PetscSectionSetClosurePermutation()`, `PetscSectionGetClosureInversePermutation()`, `PetscSectionGetClosureIndex()`, `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()` 2730 @*/ 2731 PetscErrorCode PetscSectionGetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm) { 2732 const PetscInt *clPerm; 2733 2734 PetscFunctionBegin; 2735 PetscCall(PetscSectionGetClosurePermutation_Internal(section, obj, depth, clSize, &clPerm)); 2736 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm)); 2737 PetscFunctionReturn(0); 2738 } 2739 2740 PetscErrorCode PetscSectionGetClosureInversePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[]) { 2741 PetscFunctionBegin; 2742 if (section->clObj == obj && section->clHash) { 2743 PetscSectionClosurePermKey k = {depth, size}; 2744 PetscSectionClosurePermVal v; 2745 PetscCall(PetscClPermGet(section->clHash, k, &v)); 2746 if (perm) *perm = v.invPerm; 2747 } else { 2748 if (perm) *perm = NULL; 2749 } 2750 PetscFunctionReturn(0); 2751 } 2752 2753 /*@ 2754 PetscSectionGetClosureInversePermutation - Get the inverse dof permutation for the closure of each cell in the section, meaning clPerm[oldIndex] = newIndex. 2755 2756 Not Collective 2757 2758 Input Parameters: 2759 + section - The PetscSection 2760 . obj - A PetscObject which serves as the key for this index (usually a DM) 2761 . depth - Depth stratum on which to obtain closure permutation 2762 - clSize - Closure size to be permuted (e.g., may vary with element topology and degree) 2763 2764 Output Parameters: 2765 . perm - The dof closure permutation 2766 2767 Note: 2768 The user must destroy the IS that is returned. 2769 2770 Level: intermediate 2771 2772 .seealso: `PetscSectionSetClosurePermutation()`, `PetscSectionGetClosureIndex()`, `PetscSectionSetClosureIndex()`, `DMPlexCreateClosureIndex()` 2773 @*/ 2774 PetscErrorCode PetscSectionGetClosureInversePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm) { 2775 const PetscInt *clPerm; 2776 2777 PetscFunctionBegin; 2778 PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, obj, depth, clSize, &clPerm)); 2779 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm)); 2780 PetscFunctionReturn(0); 2781 } 2782 2783 /*@ 2784 PetscSectionGetField - Get the subsection associated with a single field 2785 2786 Input Parameters: 2787 + s - The PetscSection 2788 - field - The field number 2789 2790 Output Parameter: 2791 . subs - The subsection for the given field 2792 2793 Level: intermediate 2794 2795 .seealso: `PetscSectionSetNumFields()` 2796 @*/ 2797 PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs) { 2798 PetscFunctionBegin; 2799 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2800 PetscValidPointer(subs, 3); 2801 PetscSectionCheckValidField(field, s->numFields); 2802 *subs = s->field[field]; 2803 PetscFunctionReturn(0); 2804 } 2805 2806 PetscClassId PETSC_SECTION_SYM_CLASSID; 2807 PetscFunctionList PetscSectionSymList = NULL; 2808 2809 /*@ 2810 PetscSectionSymCreate - Creates an empty PetscSectionSym object. 2811 2812 Collective 2813 2814 Input Parameter: 2815 . comm - the MPI communicator 2816 2817 Output Parameter: 2818 . sym - pointer to the new set of symmetries 2819 2820 Level: developer 2821 2822 .seealso: `PetscSectionSym`, `PetscSectionSymDestroy()` 2823 @*/ 2824 PetscErrorCode PetscSectionSymCreate(MPI_Comm comm, PetscSectionSym *sym) { 2825 PetscFunctionBegin; 2826 PetscValidPointer(sym, 2); 2827 PetscCall(ISInitializePackage()); 2828 PetscCall(PetscHeaderCreate(*sym, PETSC_SECTION_SYM_CLASSID, "PetscSectionSym", "Section Symmetry", "IS", comm, PetscSectionSymDestroy, PetscSectionSymView)); 2829 PetscFunctionReturn(0); 2830 } 2831 2832 /*@C 2833 PetscSectionSymSetType - Builds a PetscSection symmetry, for a particular implementation. 2834 2835 Collective 2836 2837 Input Parameters: 2838 + sym - The section symmetry object 2839 - method - The name of the section symmetry type 2840 2841 Level: developer 2842 2843 .seealso: `PetscSectionSymGetType()`, `PetscSectionSymCreate()` 2844 @*/ 2845 PetscErrorCode PetscSectionSymSetType(PetscSectionSym sym, PetscSectionSymType method) { 2846 PetscErrorCode (*r)(PetscSectionSym); 2847 PetscBool match; 2848 2849 PetscFunctionBegin; 2850 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 2851 PetscCall(PetscObjectTypeCompare((PetscObject)sym, method, &match)); 2852 if (match) PetscFunctionReturn(0); 2853 2854 PetscCall(PetscFunctionListFind(PetscSectionSymList, method, &r)); 2855 PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscSectionSym type: %s", method); 2856 PetscTryTypeMethod(sym, destroy); 2857 sym->ops->destroy = NULL; 2858 2859 PetscCall((*r)(sym)); 2860 PetscCall(PetscObjectChangeTypeName((PetscObject)sym, method)); 2861 PetscFunctionReturn(0); 2862 } 2863 2864 /*@C 2865 PetscSectionSymGetType - Gets the section symmetry type name (as a string) from the PetscSectionSym. 2866 2867 Not Collective 2868 2869 Input Parameter: 2870 . sym - The section symmetry 2871 2872 Output Parameter: 2873 . type - The index set type name 2874 2875 Level: developer 2876 2877 .seealso: `PetscSectionSymSetType()`, `PetscSectionSymCreate()` 2878 @*/ 2879 PetscErrorCode PetscSectionSymGetType(PetscSectionSym sym, PetscSectionSymType *type) { 2880 PetscFunctionBegin; 2881 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 2882 PetscValidPointer(type, 2); 2883 *type = ((PetscObject)sym)->type_name; 2884 PetscFunctionReturn(0); 2885 } 2886 2887 /*@C 2888 PetscSectionSymRegister - Adds a new section symmetry implementation 2889 2890 Not Collective 2891 2892 Input Parameters: 2893 + name - The name of a new user-defined creation routine 2894 - create_func - The creation routine itself 2895 2896 Notes: 2897 PetscSectionSymRegister() may be called multiple times to add several user-defined vectors 2898 2899 Level: developer 2900 2901 .seealso: `PetscSectionSymCreate()`, `PetscSectionSymSetType()` 2902 @*/ 2903 PetscErrorCode PetscSectionSymRegister(const char sname[], PetscErrorCode (*function)(PetscSectionSym)) { 2904 PetscFunctionBegin; 2905 PetscCall(ISInitializePackage()); 2906 PetscCall(PetscFunctionListAdd(&PetscSectionSymList, sname, function)); 2907 PetscFunctionReturn(0); 2908 } 2909 2910 /*@ 2911 PetscSectionSymDestroy - Destroys a section symmetry. 2912 2913 Collective 2914 2915 Input Parameters: 2916 . sym - the section symmetry 2917 2918 Level: developer 2919 2920 .seealso: `PetscSectionSymCreate()`, `PetscSectionSymDestroy()` 2921 @*/ 2922 PetscErrorCode PetscSectionSymDestroy(PetscSectionSym *sym) { 2923 SymWorkLink link, next; 2924 2925 PetscFunctionBegin; 2926 if (!*sym) PetscFunctionReturn(0); 2927 PetscValidHeaderSpecific((*sym), PETSC_SECTION_SYM_CLASSID, 1); 2928 if (--((PetscObject)(*sym))->refct > 0) { 2929 *sym = NULL; 2930 PetscFunctionReturn(0); 2931 } 2932 if ((*sym)->ops->destroy) PetscCall((*(*sym)->ops->destroy)(*sym)); 2933 PetscCheck(!(*sym)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out"); 2934 for (link = (*sym)->workin; link; link = next) { 2935 PetscInt **perms = (PetscInt **)link->perms; 2936 PetscScalar **rots = (PetscScalar **)link->rots; 2937 PetscCall(PetscFree2(perms, rots)); 2938 next = link->next; 2939 PetscCall(PetscFree(link)); 2940 } 2941 (*sym)->workin = NULL; 2942 PetscCall(PetscHeaderDestroy(sym)); 2943 PetscFunctionReturn(0); 2944 } 2945 2946 /*@C 2947 PetscSectionSymView - Displays a section symmetry 2948 2949 Collective 2950 2951 Input Parameters: 2952 + sym - the index set 2953 - viewer - viewer used to display the set, for example PETSC_VIEWER_STDOUT_SELF. 2954 2955 Level: developer 2956 2957 .seealso: `PetscViewerASCIIOpen()` 2958 @*/ 2959 PetscErrorCode PetscSectionSymView(PetscSectionSym sym, PetscViewer viewer) { 2960 PetscFunctionBegin; 2961 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 2962 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sym), &viewer)); 2963 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2964 PetscCheckSameComm(sym, 1, viewer, 2); 2965 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sym, viewer)); 2966 PetscTryTypeMethod(sym, view, viewer); 2967 PetscFunctionReturn(0); 2968 } 2969 2970 /*@ 2971 PetscSectionSetSym - Set the symmetries for the data referred to by the section 2972 2973 Collective 2974 2975 Input Parameters: 2976 + section - the section describing data layout 2977 - sym - the symmetry describing the affect of orientation on the access of the data 2978 2979 Level: developer 2980 2981 .seealso: `PetscSectionGetSym()`, `PetscSectionSymCreate()` 2982 @*/ 2983 PetscErrorCode PetscSectionSetSym(PetscSection section, PetscSectionSym sym) { 2984 PetscFunctionBegin; 2985 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 2986 PetscCall(PetscSectionSymDestroy(&(section->sym))); 2987 if (sym) { 2988 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 2); 2989 PetscCheckSameComm(section, 1, sym, 2); 2990 PetscCall(PetscObjectReference((PetscObject)sym)); 2991 } 2992 section->sym = sym; 2993 PetscFunctionReturn(0); 2994 } 2995 2996 /*@ 2997 PetscSectionGetSym - Get the symmetries for the data referred to by the section 2998 2999 Not Collective 3000 3001 Input Parameters: 3002 . section - the section describing data layout 3003 3004 Output Parameters: 3005 . sym - the symmetry describing the affect of orientation on the access of the data 3006 3007 Level: developer 3008 3009 .seealso: `PetscSectionSetSym()`, `PetscSectionSymCreate()` 3010 @*/ 3011 PetscErrorCode PetscSectionGetSym(PetscSection section, PetscSectionSym *sym) { 3012 PetscFunctionBegin; 3013 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3014 *sym = section->sym; 3015 PetscFunctionReturn(0); 3016 } 3017 3018 /*@ 3019 PetscSectionSetFieldSym - Set the symmetries for the data referred to by a field of the section 3020 3021 Collective 3022 3023 Input Parameters: 3024 + section - the section describing data layout 3025 . field - the field number 3026 - sym - the symmetry describing the affect of orientation on the access of the data 3027 3028 Level: developer 3029 3030 .seealso: `PetscSectionGetFieldSym()`, `PetscSectionSymCreate()` 3031 @*/ 3032 PetscErrorCode PetscSectionSetFieldSym(PetscSection section, PetscInt field, PetscSectionSym sym) { 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3035 PetscSectionCheckValidField(field, section->numFields); 3036 PetscCall(PetscSectionSetSym(section->field[field], sym)); 3037 PetscFunctionReturn(0); 3038 } 3039 3040 /*@ 3041 PetscSectionGetFieldSym - Get the symmetries for the data referred to by a field of the section 3042 3043 Collective 3044 3045 Input Parameters: 3046 + section - the section describing data layout 3047 - field - the field number 3048 3049 Output Parameters: 3050 . sym - the symmetry describing the affect of orientation on the access of the data 3051 3052 Level: developer 3053 3054 .seealso: `PetscSectionSetFieldSym()`, `PetscSectionSymCreate()` 3055 @*/ 3056 PetscErrorCode PetscSectionGetFieldSym(PetscSection section, PetscInt field, PetscSectionSym *sym) { 3057 PetscFunctionBegin; 3058 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3059 PetscSectionCheckValidField(field, section->numFields); 3060 *sym = section->field[field]->sym; 3061 PetscFunctionReturn(0); 3062 } 3063 3064 /*@C 3065 PetscSectionGetPointSyms - Get the symmetries for a set of points in a PetscSection under specific orientations. 3066 3067 Not Collective 3068 3069 Input Parameters: 3070 + section - the section 3071 . numPoints - the number of points 3072 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3073 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3074 context, see DMPlexGetConeOrientation()). 3075 3076 Output Parameters: 3077 + perms - The permutations for the given orientations (or NULL if there is no symmetry or the permutation is the identity). 3078 - rots - The field rotations symmetries for the given orientations (or NULL if there is no symmetry or the rotations are all 3079 identity). 3080 3081 Example of usage, gathering dofs into a local array (lArray) from a section array (sArray): 3082 .vb 3083 const PetscInt **perms; 3084 const PetscScalar **rots; 3085 PetscInt lOffset; 3086 3087 PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots); 3088 for (i = 0, lOffset = 0; i < numPoints; i++) { 3089 PetscInt point = points[2*i], dof, sOffset; 3090 const PetscInt *perm = perms ? perms[i] : NULL; 3091 const PetscScalar *rot = rots ? rots[i] : NULL; 3092 3093 PetscSectionGetDof(section,point,&dof); 3094 PetscSectionGetOffset(section,point,&sOffset); 3095 3096 if (perm) {for (j = 0; j < dof; j++) {lArray[lOffset + perm[j]] = sArray[sOffset + j];}} 3097 else {for (j = 0; j < dof; j++) {lArray[lOffset + j ] = sArray[sOffset + j];}} 3098 if (rot) {for (j = 0; j < dof; j++) {lArray[lOffset + j ] *= rot[j]; }} 3099 lOffset += dof; 3100 } 3101 PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots); 3102 .ve 3103 3104 Example of usage, adding dofs into a section array (sArray) from a local array (lArray): 3105 .vb 3106 const PetscInt **perms; 3107 const PetscScalar **rots; 3108 PetscInt lOffset; 3109 3110 PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots); 3111 for (i = 0, lOffset = 0; i < numPoints; i++) { 3112 PetscInt point = points[2*i], dof, sOffset; 3113 const PetscInt *perm = perms ? perms[i] : NULL; 3114 const PetscScalar *rot = rots ? rots[i] : NULL; 3115 3116 PetscSectionGetDof(section,point,&dof); 3117 PetscSectionGetOffset(section,point,&sOff); 3118 3119 if (perm) {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + perm[j]] * (rot ? PetscConj(rot[perm[j]]) : 1.);}} 3120 else {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + j ] * (rot ? PetscConj(rot[ j ]) : 1.);}} 3121 offset += dof; 3122 } 3123 PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots); 3124 .ve 3125 3126 Level: developer 3127 3128 .seealso: `PetscSectionRestorePointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()` 3129 @*/ 3130 PetscErrorCode PetscSectionGetPointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) { 3131 PetscSectionSym sym; 3132 3133 PetscFunctionBegin; 3134 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3135 if (numPoints) PetscValidIntPointer(points, 3); 3136 if (perms) *perms = NULL; 3137 if (rots) *rots = NULL; 3138 sym = section->sym; 3139 if (sym && (perms || rots)) { 3140 SymWorkLink link; 3141 3142 if (sym->workin) { 3143 link = sym->workin; 3144 sym->workin = sym->workin->next; 3145 } else { 3146 PetscCall(PetscNewLog(sym, &link)); 3147 } 3148 if (numPoints > link->numPoints) { 3149 PetscInt **perms = (PetscInt **)link->perms; 3150 PetscScalar **rots = (PetscScalar **)link->rots; 3151 PetscCall(PetscFree2(perms, rots)); 3152 PetscCall(PetscMalloc2(numPoints, (PetscInt ***)&link->perms, numPoints, (PetscScalar ***)&link->rots)); 3153 link->numPoints = numPoints; 3154 } 3155 link->next = sym->workout; 3156 sym->workout = link; 3157 PetscCall(PetscArrayzero((PetscInt **)link->perms, numPoints)); 3158 PetscCall(PetscArrayzero((PetscInt **)link->rots, numPoints)); 3159 PetscCall((*sym->ops->getpoints)(sym, section, numPoints, points, link->perms, link->rots)); 3160 if (perms) *perms = link->perms; 3161 if (rots) *rots = link->rots; 3162 } 3163 PetscFunctionReturn(0); 3164 } 3165 3166 /*@C 3167 PetscSectionRestorePointSyms - Restore the symmetries returned by PetscSectionGetPointSyms() 3168 3169 Not Collective 3170 3171 Input Parameters: 3172 + section - the section 3173 . numPoints - the number of points 3174 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3175 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3176 context, see DMPlexGetConeOrientation()). 3177 3178 Output Parameters: 3179 + perms - The permutations for the given orientations: set to NULL at conclusion 3180 - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion 3181 3182 Level: developer 3183 3184 .seealso: `PetscSectionGetPointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()` 3185 @*/ 3186 PetscErrorCode PetscSectionRestorePointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) { 3187 PetscSectionSym sym; 3188 3189 PetscFunctionBegin; 3190 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3191 sym = section->sym; 3192 if (sym && (perms || rots)) { 3193 SymWorkLink *p, link; 3194 3195 for (p = &sym->workout; (link = *p); p = &link->next) { 3196 if ((perms && link->perms == *perms) || (rots && link->rots == *rots)) { 3197 *p = link->next; 3198 link->next = sym->workin; 3199 sym->workin = link; 3200 if (perms) *perms = NULL; 3201 if (rots) *rots = NULL; 3202 PetscFunctionReturn(0); 3203 } 3204 } 3205 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out"); 3206 } 3207 PetscFunctionReturn(0); 3208 } 3209 3210 /*@C 3211 PetscSectionGetFieldPointSyms - Get the symmetries for a set of points in a field of a PetscSection under specific orientations. 3212 3213 Not Collective 3214 3215 Input Parameters: 3216 + section - the section 3217 . field - the field of the section 3218 . numPoints - the number of points 3219 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3220 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3221 context, see DMPlexGetConeOrientation()). 3222 3223 Output Parameters: 3224 + perms - The permutations for the given orientations (or NULL if there is no symmetry or the permutation is the identity). 3225 - rots - The field rotations symmetries for the given orientations (or NULL if there is no symmetry or the rotations are all 3226 identity). 3227 3228 Level: developer 3229 3230 .seealso: `PetscSectionGetPointSyms()`, `PetscSectionRestoreFieldPointSyms()` 3231 @*/ 3232 PetscErrorCode PetscSectionGetFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) { 3233 PetscFunctionBegin; 3234 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3235 PetscCheck(field <= section->numFields, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "field %" PetscInt_FMT " greater than number of fields (%" PetscInt_FMT ") in section", field, section->numFields); 3236 PetscCall(PetscSectionGetPointSyms(section->field[field], numPoints, points, perms, rots)); 3237 PetscFunctionReturn(0); 3238 } 3239 3240 /*@C 3241 PetscSectionRestoreFieldPointSyms - Restore the symmetries returned by PetscSectionGetFieldPointSyms() 3242 3243 Not Collective 3244 3245 Input Parameters: 3246 + section - the section 3247 . field - the field number 3248 . numPoints - the number of points 3249 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3250 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3251 context, see DMPlexGetConeOrientation()). 3252 3253 Output Parameters: 3254 + perms - The permutations for the given orientations: set to NULL at conclusion 3255 - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion 3256 3257 Level: developer 3258 3259 .seealso: `PetscSectionRestorePointSyms()`, `petscSectionGetFieldPointSyms()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()` 3260 @*/ 3261 PetscErrorCode PetscSectionRestoreFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) { 3262 PetscFunctionBegin; 3263 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 3264 PetscCheck(field <= section->numFields, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "field %" PetscInt_FMT " greater than number of fields (%" PetscInt_FMT ") in section", field, section->numFields); 3265 PetscCall(PetscSectionRestorePointSyms(section->field[field], numPoints, points, perms, rots)); 3266 PetscFunctionReturn(0); 3267 } 3268 3269 /*@ 3270 PetscSectionSymCopy - Copy the symmetries, assuming that the point structure is compatible 3271 3272 Not Collective 3273 3274 Input Parameter: 3275 . sym - the PetscSectionSym 3276 3277 Output Parameter: 3278 . nsym - the equivalent symmetries 3279 3280 Level: developer 3281 3282 .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()` 3283 @*/ 3284 PetscErrorCode PetscSectionSymCopy(PetscSectionSym sym, PetscSectionSym nsym) { 3285 PetscFunctionBegin; 3286 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 3287 PetscValidHeaderSpecific(nsym, PETSC_SECTION_SYM_CLASSID, 2); 3288 PetscTryTypeMethod(sym, copy, nsym); 3289 PetscFunctionReturn(0); 3290 } 3291 3292 /*@ 3293 PetscSectionSymDistribute - Distribute the symmetries in accordance with the input SF 3294 3295 Collective 3296 3297 Input Parameters: 3298 + sym - the PetscSectionSym 3299 - migrationSF - the distribution map from roots to leaves 3300 3301 Output Parameters: 3302 . dsym - the redistributed symmetries 3303 3304 Level: developer 3305 3306 .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()` 3307 @*/ 3308 PetscErrorCode PetscSectionSymDistribute(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym) { 3309 PetscFunctionBegin; 3310 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 3311 PetscValidHeaderSpecific(migrationSF, PETSCSF_CLASSID, 2); 3312 PetscValidPointer(dsym, 3); 3313 PetscTryTypeMethod(sym, distribute, migrationSF, dsym); 3314 PetscFunctionReturn(0); 3315 } 3316 3317 /*@ 3318 PetscSectionGetUseFieldOffsets - Get the flag to use field offsets directly in a global section, rather than just the point offset 3319 3320 Not Collective 3321 3322 Input Parameter: 3323 . s - the global PetscSection 3324 3325 Output Parameters: 3326 . flg - the flag 3327 3328 Level: developer 3329 3330 .seealso: `PetscSectionSetChart()`, `PetscSectionCreate()` 3331 @*/ 3332 PetscErrorCode PetscSectionGetUseFieldOffsets(PetscSection s, PetscBool *flg) { 3333 PetscFunctionBegin; 3334 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 3335 *flg = s->useFieldOff; 3336 PetscFunctionReturn(0); 3337 } 3338 3339 /*@ 3340 PetscSectionSetUseFieldOffsets - Set the flag to use field offsets directly in a global section, rather than just the point offset 3341 3342 Not Collective 3343 3344 Input Parameters: 3345 + s - the global PetscSection 3346 - flg - the flag 3347 3348 Level: developer 3349 3350 .seealso: `PetscSectionGetUseFieldOffsets()`, `PetscSectionSetChart()`, `PetscSectionCreate()` 3351 @*/ 3352 PetscErrorCode PetscSectionSetUseFieldOffsets(PetscSection s, PetscBool flg) { 3353 PetscFunctionBegin; 3354 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 3355 s->useFieldOff = flg; 3356 PetscFunctionReturn(0); 3357 } 3358 3359 #define PetscSectionExpandPoints_Loop(TYPE) \ 3360 { \ 3361 PetscInt i, n, o0, o1, size; \ 3362 TYPE *a0 = (TYPE *)origArray, *a1; \ 3363 PetscCall(PetscSectionGetStorageSize(s, &size)); \ 3364 PetscCall(PetscMalloc1(size, &a1)); \ 3365 for (i = 0; i < npoints; i++) { \ 3366 PetscCall(PetscSectionGetOffset(origSection, points_[i], &o0)); \ 3367 PetscCall(PetscSectionGetOffset(s, i, &o1)); \ 3368 PetscCall(PetscSectionGetDof(s, i, &n)); \ 3369 PetscCall(PetscMemcpy(&a1[o1], &a0[o0], n *unitsize)); \ 3370 } \ 3371 *newArray = (void *)a1; \ 3372 } 3373 3374 /*@ 3375 PetscSectionExtractDofsFromArray - Extracts elements of an array corresponding to DOFs of specified points. 3376 3377 Not Collective 3378 3379 Input Parameters: 3380 + origSection - the PetscSection describing the layout of the array 3381 . dataType - MPI_Datatype describing the data type of the array (currently only MPIU_INT, MPIU_SCALAR, MPIU_REAL) 3382 . origArray - the array; its size must be equal to the storage size of origSection 3383 - points - IS with points to extract; its indices must lie in the chart of origSection 3384 3385 Output Parameters: 3386 + newSection - the new PetscSection desribing the layout of the new array (with points renumbered 0,1,... but preserving numbers of DOFs) 3387 - newArray - the array of the extracted DOFs; its size is the storage size of newSection 3388 3389 Level: developer 3390 3391 .seealso: `PetscSectionGetChart()`, `PetscSectionGetDof()`, `PetscSectionGetStorageSize()`, `PetscSectionCreate()` 3392 @*/ 3393 PetscErrorCode PetscSectionExtractDofsFromArray(PetscSection origSection, MPI_Datatype dataType, const void *origArray, IS points, PetscSection *newSection, void *newArray[]) { 3394 PetscSection s; 3395 const PetscInt *points_; 3396 PetscInt i, n, npoints, pStart, pEnd; 3397 PetscMPIInt unitsize; 3398 3399 PetscFunctionBegin; 3400 PetscValidHeaderSpecific(origSection, PETSC_SECTION_CLASSID, 1); 3401 PetscValidPointer(origArray, 3); 3402 PetscValidHeaderSpecific(points, IS_CLASSID, 4); 3403 if (newSection) PetscValidPointer(newSection, 5); 3404 if (newArray) PetscValidPointer(newArray, 6); 3405 PetscCallMPI(MPI_Type_size(dataType, &unitsize)); 3406 PetscCall(ISGetLocalSize(points, &npoints)); 3407 PetscCall(ISGetIndices(points, &points_)); 3408 PetscCall(PetscSectionGetChart(origSection, &pStart, &pEnd)); 3409 PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 3410 PetscCall(PetscSectionSetChart(s, 0, npoints)); 3411 for (i = 0; i < npoints; i++) { 3412 PetscCheck(points_[i] >= pStart && points_[i] < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "point %" PetscInt_FMT " (index %" PetscInt_FMT ") in input IS out of input section's chart", points_[i], i); 3413 PetscCall(PetscSectionGetDof(origSection, points_[i], &n)); 3414 PetscCall(PetscSectionSetDof(s, i, n)); 3415 } 3416 PetscCall(PetscSectionSetUp(s)); 3417 if (newArray) { 3418 if (dataType == MPIU_INT) { 3419 PetscSectionExpandPoints_Loop(PetscInt); 3420 } else if (dataType == MPIU_SCALAR) { 3421 PetscSectionExpandPoints_Loop(PetscScalar); 3422 } else if (dataType == MPIU_REAL) { 3423 PetscSectionExpandPoints_Loop(PetscReal); 3424 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "not implemented for this MPI_Datatype"); 3425 } 3426 if (newSection) { 3427 *newSection = s; 3428 } else { 3429 PetscCall(PetscSectionDestroy(&s)); 3430 } 3431 PetscCall(ISRestoreIndices(points, &points_)); 3432 PetscFunctionReturn(0); 3433 } 3434