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