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