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