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