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 if (PetscDefined(USE_DEBUG)) { 789 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); 790 } 791 *numDof = s->atlasDof[point - s->pStart]; 792 PetscFunctionReturn(0); 793 } 794 795 /*@ 796 PetscSectionSetDof - Sets the number of degrees of freedom associated with a given point. 797 798 Not Collective 799 800 Input Parameters: 801 + s - the PetscSection 802 . point - the point 803 - numDof - the number of dof 804 805 Level: intermediate 806 807 .seealso: PetscSectionGetDof(), PetscSectionAddDof(), PetscSectionCreate() 808 @*/ 809 PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof) 810 { 811 PetscFunctionBegin; 812 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 813 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); 814 s->atlasDof[point - s->pStart] = numDof; 815 PetscFunctionReturn(0); 816 } 817 818 /*@ 819 PetscSectionAddDof - Adds to the number of degrees of freedom associated with a given point. 820 821 Not Collective 822 823 Input Parameters: 824 + s - the PetscSection 825 . point - the point 826 - numDof - the number of additional dof 827 828 Level: intermediate 829 830 .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate() 831 @*/ 832 PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof) 833 { 834 PetscFunctionBeginHot; 835 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 836 if (PetscDefined(USE_DEBUG)) { 837 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); 838 } 839 s->atlasDof[point - s->pStart] += numDof; 840 PetscFunctionReturn(0); 841 } 842 843 /*@ 844 PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point. 845 846 Not Collective 847 848 Input Parameters: 849 + s - the PetscSection 850 . point - the point 851 - field - the field 852 853 Output Parameter: 854 . numDof - the number of dof 855 856 Level: intermediate 857 858 .seealso: PetscSectionSetFieldDof(), PetscSectionCreate() 859 @*/ 860 PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof) 861 { 862 PetscFunctionBegin; 863 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 864 PetscValidIntPointer(numDof,4); 865 PetscSectionCheckValidField(field,s->numFields); 866 PetscCall(PetscSectionGetDof(s->field[field], point, numDof)); 867 PetscFunctionReturn(0); 868 } 869 870 /*@ 871 PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point. 872 873 Not Collective 874 875 Input Parameters: 876 + s - the PetscSection 877 . point - the point 878 . field - the field 879 - numDof - the number of dof 880 881 Level: intermediate 882 883 .seealso: PetscSectionGetFieldDof(), PetscSectionCreate() 884 @*/ 885 PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) 886 { 887 PetscFunctionBegin; 888 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 889 PetscSectionCheckValidField(field,s->numFields); 890 PetscCall(PetscSectionSetDof(s->field[field], point, numDof)); 891 PetscFunctionReturn(0); 892 } 893 894 /*@ 895 PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point. 896 897 Not Collective 898 899 Input Parameters: 900 + s - the PetscSection 901 . point - the point 902 . field - the field 903 - numDof - the number of dof 904 905 Level: intermediate 906 907 .seealso: PetscSectionSetFieldDof(), PetscSectionGetFieldDof(), PetscSectionCreate() 908 @*/ 909 PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) 910 { 911 PetscFunctionBegin; 912 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 913 PetscSectionCheckValidField(field,s->numFields); 914 PetscCall(PetscSectionAddDof(s->field[field], point, numDof)); 915 PetscFunctionReturn(0); 916 } 917 918 /*@ 919 PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point. 920 921 Not Collective 922 923 Input Parameters: 924 + s - the PetscSection 925 - point - the point 926 927 Output Parameter: 928 . numDof - the number of dof which are fixed by constraints 929 930 Level: intermediate 931 932 .seealso: PetscSectionGetDof(), PetscSectionSetConstraintDof(), PetscSectionCreate() 933 @*/ 934 PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof) 935 { 936 PetscFunctionBegin; 937 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 938 PetscValidIntPointer(numDof, 3); 939 if (s->bc) { 940 PetscCall(PetscSectionGetDof(s->bc, point, numDof)); 941 } else *numDof = 0; 942 PetscFunctionReturn(0); 943 } 944 945 /*@ 946 PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point. 947 948 Not Collective 949 950 Input Parameters: 951 + s - the PetscSection 952 . point - the point 953 - numDof - the number of dof which are fixed by constraints 954 955 Level: intermediate 956 957 .seealso: PetscSectionSetDof(), PetscSectionGetConstraintDof(), PetscSectionCreate() 958 @*/ 959 PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof) 960 { 961 PetscFunctionBegin; 962 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 963 if (numDof) { 964 PetscCall(PetscSectionCheckConstraints_Static(s)); 965 PetscCall(PetscSectionSetDof(s->bc, point, numDof)); 966 } 967 PetscFunctionReturn(0); 968 } 969 970 /*@ 971 PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point. 972 973 Not Collective 974 975 Input Parameters: 976 + s - the PetscSection 977 . point - the point 978 - numDof - the number of additional dof which are fixed by constraints 979 980 Level: intermediate 981 982 .seealso: PetscSectionAddDof(), PetscSectionGetConstraintDof(), PetscSectionCreate() 983 @*/ 984 PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof) 985 { 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 988 if (numDof) { 989 PetscCall(PetscSectionCheckConstraints_Static(s)); 990 PetscCall(PetscSectionAddDof(s->bc, point, numDof)); 991 } 992 PetscFunctionReturn(0); 993 } 994 995 /*@ 996 PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point. 997 998 Not Collective 999 1000 Input Parameters: 1001 + s - the PetscSection 1002 . point - the point 1003 - field - the field 1004 1005 Output Parameter: 1006 . numDof - the number of dof which are fixed by constraints 1007 1008 Level: intermediate 1009 1010 .seealso: PetscSectionGetDof(), PetscSectionSetFieldConstraintDof(), PetscSectionCreate() 1011 @*/ 1012 PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof) 1013 { 1014 PetscFunctionBegin; 1015 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1016 PetscValidIntPointer(numDof, 4); 1017 PetscSectionCheckValidField(field,s->numFields); 1018 PetscCall(PetscSectionGetConstraintDof(s->field[field], point, numDof)); 1019 PetscFunctionReturn(0); 1020 } 1021 1022 /*@ 1023 PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point. 1024 1025 Not Collective 1026 1027 Input Parameters: 1028 + s - the PetscSection 1029 . point - the point 1030 . field - the field 1031 - numDof - the number of dof which are fixed by constraints 1032 1033 Level: intermediate 1034 1035 .seealso: PetscSectionSetDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate() 1036 @*/ 1037 PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) 1038 { 1039 PetscFunctionBegin; 1040 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1041 PetscSectionCheckValidField(field,s->numFields); 1042 PetscCall(PetscSectionSetConstraintDof(s->field[field], point, numDof)); 1043 PetscFunctionReturn(0); 1044 } 1045 1046 /*@ 1047 PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point. 1048 1049 Not Collective 1050 1051 Input Parameters: 1052 + s - the PetscSection 1053 . point - the point 1054 . field - the field 1055 - numDof - the number of additional dof which are fixed by constraints 1056 1057 Level: intermediate 1058 1059 .seealso: PetscSectionAddDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate() 1060 @*/ 1061 PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof) 1062 { 1063 PetscFunctionBegin; 1064 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1065 PetscSectionCheckValidField(field,s->numFields); 1066 PetscCall(PetscSectionAddConstraintDof(s->field[field], point, numDof)); 1067 PetscFunctionReturn(0); 1068 } 1069 1070 /*@ 1071 PetscSectionSetUpBC - Setup the subsections describing boundary conditions. 1072 1073 Not Collective 1074 1075 Input Parameter: 1076 . s - the PetscSection 1077 1078 Level: advanced 1079 1080 .seealso: PetscSectionSetUp(), PetscSectionCreate() 1081 @*/ 1082 PetscErrorCode PetscSectionSetUpBC(PetscSection s) 1083 { 1084 PetscFunctionBegin; 1085 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1086 if (s->bc) { 1087 const PetscInt last = (s->bc->pEnd-s->bc->pStart) - 1; 1088 1089 PetscCall(PetscSectionSetUp(s->bc)); 1090 PetscCall(PetscMalloc1(last >= 0 ? s->bc->atlasOff[last] + s->bc->atlasDof[last] : 0, &s->bcIndices)); 1091 } 1092 PetscFunctionReturn(0); 1093 } 1094 1095 /*@ 1096 PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point. 1097 1098 Not Collective 1099 1100 Input Parameter: 1101 . s - the PetscSection 1102 1103 Level: intermediate 1104 1105 .seealso: PetscSectionCreate() 1106 @*/ 1107 PetscErrorCode PetscSectionSetUp(PetscSection s) 1108 { 1109 const PetscInt *pind = NULL; 1110 PetscInt offset = 0, foff, p, f; 1111 1112 PetscFunctionBegin; 1113 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1114 if (s->setup) PetscFunctionReturn(0); 1115 s->setup = PETSC_TRUE; 1116 /* Set offsets and field offsets for all points */ 1117 /* Assume that all fields have the same chart */ 1118 PetscCheck(s->includesConstraints,PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscSectionSetUp is currently unsupported for includesConstraints = PETSC_TRUE"); 1119 if (s->perm) PetscCall(ISGetIndices(s->perm, &pind)); 1120 if (s->pointMajor) { 1121 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1122 const PetscInt q = pind ? pind[p] : p; 1123 1124 /* Set point offset */ 1125 s->atlasOff[q] = offset; 1126 offset += s->atlasDof[q]; 1127 s->maxDof = PetscMax(s->maxDof, s->atlasDof[q]); 1128 /* Set field offset */ 1129 for (f = 0, foff = s->atlasOff[q]; f < s->numFields; ++f) { 1130 PetscSection sf = s->field[f]; 1131 1132 sf->atlasOff[q] = foff; 1133 foff += sf->atlasDof[q]; 1134 } 1135 } 1136 } else { 1137 /* Set field offsets for all points */ 1138 for (f = 0; f < s->numFields; ++f) { 1139 PetscSection sf = s->field[f]; 1140 1141 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1142 const PetscInt q = pind ? pind[p] : p; 1143 1144 sf->atlasOff[q] = offset; 1145 offset += sf->atlasDof[q]; 1146 } 1147 } 1148 /* Disable point offsets since these are unused */ 1149 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1150 s->atlasOff[p] = -1; 1151 s->maxDof = PetscMax(s->maxDof, s->atlasDof[p]); 1152 } 1153 } 1154 if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind)); 1155 /* Setup BC sections */ 1156 PetscCall(PetscSectionSetUpBC(s)); 1157 for (f = 0; f < s->numFields; ++f) PetscCall(PetscSectionSetUpBC(s->field[f])); 1158 PetscFunctionReturn(0); 1159 } 1160 1161 /*@ 1162 PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the chart 1163 1164 Not Collective 1165 1166 Input Parameters: 1167 . s - the PetscSection 1168 1169 Output Parameter: 1170 . maxDof - the maximum dof 1171 1172 Level: intermediate 1173 1174 .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate() 1175 @*/ 1176 PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof) 1177 { 1178 PetscFunctionBegin; 1179 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1180 PetscValidIntPointer(maxDof, 2); 1181 *maxDof = s->maxDof; 1182 PetscFunctionReturn(0); 1183 } 1184 1185 /*@ 1186 PetscSectionGetStorageSize - Return the size of an array or local Vec capable of holding all the degrees of freedom. 1187 1188 Not Collective 1189 1190 Input Parameter: 1191 . s - the PetscSection 1192 1193 Output Parameter: 1194 . size - the size of an array which can hold all the dofs 1195 1196 Level: intermediate 1197 1198 .seealso: PetscSectionGetOffset(), PetscSectionGetConstrainedStorageSize(), PetscSectionCreate() 1199 @*/ 1200 PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size) 1201 { 1202 PetscInt p, n = 0; 1203 1204 PetscFunctionBegin; 1205 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1206 PetscValidIntPointer(size, 2); 1207 for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0; 1208 *size = n; 1209 PetscFunctionReturn(0); 1210 } 1211 1212 /*@ 1213 PetscSectionGetConstrainedStorageSize - Return the size of an array or local Vec capable of holding all unconstrained degrees of freedom. 1214 1215 Not Collective 1216 1217 Input Parameter: 1218 . s - the PetscSection 1219 1220 Output Parameter: 1221 . size - the size of an array which can hold all unconstrained dofs 1222 1223 Level: intermediate 1224 1225 .seealso: PetscSectionGetStorageSize(), PetscSectionGetOffset(), PetscSectionCreate() 1226 @*/ 1227 PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size) 1228 { 1229 PetscInt p, n = 0; 1230 1231 PetscFunctionBegin; 1232 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1233 PetscValidIntPointer(size, 2); 1234 for (p = 0; p < s->pEnd - s->pStart; ++p) { 1235 const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0; 1236 n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0; 1237 } 1238 *size = n; 1239 PetscFunctionReturn(0); 1240 } 1241 1242 /*@ 1243 PetscSectionCreateGlobalSection - Create a section describing the global field layout using 1244 the local section and an SF describing the section point overlap. 1245 1246 Input Parameters: 1247 + s - The PetscSection for the local field layout 1248 . sf - The SF describing parallel layout of the section points (leaves are unowned local points) 1249 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 1250 - localOffsets - If PETSC_TRUE, use local rather than global offsets for the points 1251 1252 Output Parameter: 1253 . gsection - The PetscSection for the global field layout 1254 1255 Note: This gives negative sizes and offsets to points not owned by this process 1256 1257 Level: intermediate 1258 1259 .seealso: PetscSectionCreate() 1260 @*/ 1261 PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscBool localOffsets, PetscSection *gsection) 1262 { 1263 PetscSection gs; 1264 const PetscInt *pind = NULL; 1265 PetscInt *recv = NULL, *neg = NULL; 1266 PetscInt pStart, pEnd, p, dof, cdof, off, foff, globalOff = 0, nroots, nlocal, maxleaf; 1267 PetscInt numFields, f, numComponents; 1268 1269 PetscFunctionBegin; 1270 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1271 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1272 PetscValidLogicalCollectiveBool(s, includeConstraints, 3); 1273 PetscValidLogicalCollectiveBool(s, localOffsets, 4); 1274 PetscValidPointer(gsection, 5); 1275 PetscCheck(s->pointMajor,PETSC_COMM_SELF,PETSC_ERR_SUP, "No support for field major ordering"); 1276 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), &gs)); 1277 PetscCall(PetscSectionGetNumFields(s, &numFields)); 1278 if (numFields > 0) PetscCall(PetscSectionSetNumFields(gs, numFields)); 1279 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1280 PetscCall(PetscSectionSetChart(gs, pStart, pEnd)); 1281 gs->includesConstraints = includeConstraints; 1282 PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL)); 1283 nlocal = nroots; /* The local/leaf space matches global/root space */ 1284 /* Must allocate for all points visible to SF, which may be more than this section */ 1285 if (nroots >= 0) { /* nroots < 0 means that the graph has not been set, only happens in serial */ 1286 PetscCall(PetscSFGetLeafRange(sf, NULL, &maxleaf)); 1287 PetscCheckFalse(nroots < pEnd,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %" PetscInt_FMT " < pEnd %" PetscInt_FMT, nroots, pEnd); 1288 PetscCheckFalse(maxleaf >= nroots,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Max local leaf %" PetscInt_FMT " >= nroots %" PetscInt_FMT, maxleaf, nroots); 1289 PetscCall(PetscMalloc2(nroots,&neg,nlocal,&recv)); 1290 PetscCall(PetscArrayzero(neg,nroots)); 1291 } 1292 /* Mark all local points with negative dof */ 1293 for (p = pStart; p < pEnd; ++p) { 1294 PetscCall(PetscSectionGetDof(s, p, &dof)); 1295 PetscCall(PetscSectionSetDof(gs, p, dof)); 1296 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1297 if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(gs, p, cdof)); 1298 if (neg) neg[p] = -(dof+1); 1299 } 1300 PetscCall(PetscSectionSetUpBC(gs)); 1301 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])); 1302 if (nroots >= 0) { 1303 PetscCall(PetscArrayzero(recv,nlocal)); 1304 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv,MPI_REPLACE)); 1305 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv,MPI_REPLACE)); 1306 for (p = pStart; p < pEnd; ++p) { 1307 if (recv[p] < 0) { 1308 gs->atlasDof[p-pStart] = recv[p]; 1309 PetscCall(PetscSectionGetDof(s, p, &dof)); 1310 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); 1311 } 1312 } 1313 } 1314 /* Calculate new sizes, get process offset, and calculate point offsets */ 1315 if (s->perm) PetscCall(ISGetIndices(s->perm, &pind)); 1316 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1317 const PetscInt q = pind ? pind[p] : p; 1318 1319 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0; 1320 gs->atlasOff[q] = off; 1321 off += gs->atlasDof[q] > 0 ? gs->atlasDof[q]-cdof : 0; 1322 } 1323 if (!localOffsets) { 1324 PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s))); 1325 globalOff -= off; 1326 } 1327 for (p = pStart, off = 0; p < pEnd; ++p) { 1328 gs->atlasOff[p-pStart] += globalOff; 1329 if (neg) neg[p] = -(gs->atlasOff[p-pStart]+1); 1330 } 1331 if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind)); 1332 /* Put in negative offsets for ghost points */ 1333 if (nroots >= 0) { 1334 PetscCall(PetscArrayzero(recv,nlocal)); 1335 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, recv,MPI_REPLACE)); 1336 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, recv,MPI_REPLACE)); 1337 for (p = pStart; p < pEnd; ++p) { 1338 if (recv[p] < 0) gs->atlasOff[p-pStart] = recv[p]; 1339 } 1340 } 1341 PetscCall(PetscFree2(neg,recv)); 1342 /* Set field dofs/offsets/constraints */ 1343 for (f = 0; f < numFields; ++f) { 1344 gs->field[f]->includesConstraints = includeConstraints; 1345 PetscCall(PetscSectionGetFieldComponents(s, f, &numComponents)); 1346 PetscCall(PetscSectionSetFieldComponents(gs, f, numComponents)); 1347 } 1348 for (p = pStart; p < pEnd; ++p) { 1349 PetscCall(PetscSectionGetOffset(gs, p, &off)); 1350 for (f = 0, foff = off; f < numFields; ++f) { 1351 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof)); 1352 if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetFieldConstraintDof(gs, p, f, cdof)); 1353 PetscCall(PetscSectionGetFieldDof(s, p, f, &dof)); 1354 PetscCall(PetscSectionSetFieldDof(gs, p, f, off < 0 ? -(dof + 1) : dof)); 1355 PetscCall(PetscSectionSetFieldOffset(gs, p, f, foff)); 1356 PetscCall(PetscSectionGetFieldConstraintDof(gs, p, f, &cdof)); 1357 foff = off < 0 ? foff - (dof - cdof) : foff + (dof - cdof); 1358 } 1359 } 1360 for (f = 0; f < numFields; ++f) { 1361 PetscSection gfs = gs->field[f]; 1362 1363 PetscCall(PetscSectionSetUpBC(gfs)); 1364 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])); 1365 } 1366 gs->setup = PETSC_TRUE; 1367 PetscCall(PetscSectionViewFromOptions(gs, NULL, "-global_section_view")); 1368 *gsection = gs; 1369 PetscFunctionReturn(0); 1370 } 1371 1372 /*@ 1373 PetscSectionCreateGlobalSectionCensored - Create a section describing the global field layout using 1374 the local section and an SF describing the section point overlap. 1375 1376 Input Parameters: 1377 + s - The PetscSection for the local field layout 1378 . sf - The SF describing parallel layout of the section points 1379 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 1380 . numExcludes - The number of exclusion ranges 1381 - excludes - An array [start_0, end_0, start_1, end_1, ...] where there are numExcludes pairs 1382 1383 Output Parameter: 1384 . gsection - The PetscSection for the global field layout 1385 1386 Note: This gives negative sizes and offsets to points not owned by this process 1387 1388 Level: advanced 1389 1390 .seealso: PetscSectionCreate() 1391 @*/ 1392 PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection) 1393 { 1394 const PetscInt *pind = NULL; 1395 PetscInt *neg = NULL, *tmpOff = NULL; 1396 PetscInt pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots; 1397 1398 PetscFunctionBegin; 1399 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1400 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 1401 PetscValidPointer(gsection, 6); 1402 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection)); 1403 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1404 PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd)); 1405 PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL)); 1406 if (nroots >= 0) { 1407 PetscCheckFalse(nroots < pEnd-pStart,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd-pStart); 1408 PetscCall(PetscCalloc1(nroots, &neg)); 1409 if (nroots > pEnd-pStart) { 1410 PetscCall(PetscCalloc1(nroots, &tmpOff)); 1411 } else { 1412 tmpOff = &(*gsection)->atlasDof[-pStart]; 1413 } 1414 } 1415 /* Mark ghost points with negative dof */ 1416 for (p = pStart; p < pEnd; ++p) { 1417 for (e = 0; e < numExcludes; ++e) { 1418 if ((p >= excludes[e*2+0]) && (p < excludes[e*2+1])) { 1419 PetscCall(PetscSectionSetDof(*gsection, p, 0)); 1420 break; 1421 } 1422 } 1423 if (e < numExcludes) continue; 1424 PetscCall(PetscSectionGetDof(s, p, &dof)); 1425 PetscCall(PetscSectionSetDof(*gsection, p, dof)); 1426 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1427 if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof)); 1428 if (neg) neg[p] = -(dof+1); 1429 } 1430 PetscCall(PetscSectionSetUpBC(*gsection)); 1431 if (nroots >= 0) { 1432 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE)); 1433 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE)); 1434 if (nroots > pEnd - pStart) { 1435 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 1436 } 1437 } 1438 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 1439 if (s->perm) PetscCall(ISGetIndices(s->perm, &pind)); 1440 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1441 const PetscInt q = pind ? pind[p] : p; 1442 1443 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0; 1444 (*gsection)->atlasOff[q] = off; 1445 off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0; 1446 } 1447 PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s))); 1448 globalOff -= off; 1449 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 1450 (*gsection)->atlasOff[p] += globalOff; 1451 if (neg) neg[p+pStart] = -((*gsection)->atlasOff[p]+1); 1452 } 1453 if (s->perm) PetscCall(ISRestoreIndices(s->perm, &pind)); 1454 /* Put in negative offsets for ghost points */ 1455 if (nroots >= 0) { 1456 if (nroots == pEnd-pStart) tmpOff = &(*gsection)->atlasOff[-pStart]; 1457 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE)); 1458 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE)); 1459 if (nroots > pEnd - pStart) { 1460 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 1461 } 1462 } 1463 if (nroots >= 0 && nroots > pEnd-pStart) PetscCall(PetscFree(tmpOff)); 1464 PetscCall(PetscFree(neg)); 1465 PetscFunctionReturn(0); 1466 } 1467 1468 /*@ 1469 PetscSectionGetPointLayout - Get the PetscLayout associated with the section points 1470 1471 Collective on comm 1472 1473 Input Parameters: 1474 + comm - The MPI_Comm 1475 - s - The PetscSection 1476 1477 Output Parameter: 1478 . layout - The point layout for the section 1479 1480 Note: This is usually called for the default global section. 1481 1482 Level: advanced 1483 1484 .seealso: PetscSectionGetValueLayout(), PetscSectionCreate() 1485 @*/ 1486 PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout) 1487 { 1488 PetscInt pStart, pEnd, p, localSize = 0; 1489 1490 PetscFunctionBegin; 1491 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1492 for (p = pStart; p < pEnd; ++p) { 1493 PetscInt dof; 1494 1495 PetscCall(PetscSectionGetDof(s, p, &dof)); 1496 if (dof >= 0) ++localSize; 1497 } 1498 PetscCall(PetscLayoutCreate(comm, layout)); 1499 PetscCall(PetscLayoutSetLocalSize(*layout, localSize)); 1500 PetscCall(PetscLayoutSetBlockSize(*layout, 1)); 1501 PetscCall(PetscLayoutSetUp(*layout)); 1502 PetscFunctionReturn(0); 1503 } 1504 1505 /*@ 1506 PetscSectionGetValueLayout - Get the PetscLayout associated with the section dofs. 1507 1508 Collective on comm 1509 1510 Input Parameters: 1511 + comm - The MPI_Comm 1512 - s - The PetscSection 1513 1514 Output Parameter: 1515 . layout - The dof layout for the section 1516 1517 Note: This is usually called for the default global section. 1518 1519 Level: advanced 1520 1521 .seealso: PetscSectionGetPointLayout(), PetscSectionCreate() 1522 @*/ 1523 PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout) 1524 { 1525 PetscInt pStart, pEnd, p, localSize = 0; 1526 1527 PetscFunctionBegin; 1528 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2); 1529 PetscValidPointer(layout, 3); 1530 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1531 for (p = pStart; p < pEnd; ++p) { 1532 PetscInt dof,cdof; 1533 1534 PetscCall(PetscSectionGetDof(s, p, &dof)); 1535 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1536 if (dof-cdof > 0) localSize += dof-cdof; 1537 } 1538 PetscCall(PetscLayoutCreate(comm, layout)); 1539 PetscCall(PetscLayoutSetLocalSize(*layout, localSize)); 1540 PetscCall(PetscLayoutSetBlockSize(*layout, 1)); 1541 PetscCall(PetscLayoutSetUp(*layout)); 1542 PetscFunctionReturn(0); 1543 } 1544 1545 /*@ 1546 PetscSectionGetOffset - Return the offset into an array or local Vec for the dof associated with the given point. 1547 1548 Not Collective 1549 1550 Input Parameters: 1551 + s - the PetscSection 1552 - point - the point 1553 1554 Output Parameter: 1555 . offset - the offset 1556 1557 Level: intermediate 1558 1559 .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate() 1560 @*/ 1561 PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset) 1562 { 1563 PetscFunctionBegin; 1564 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1565 PetscValidIntPointer(offset, 3); 1566 if (PetscDefined(USE_DEBUG)) { 1567 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); 1568 } 1569 *offset = s->atlasOff[point - s->pStart]; 1570 PetscFunctionReturn(0); 1571 } 1572 1573 /*@ 1574 PetscSectionSetOffset - Set the offset into an array or local Vec for the dof associated with the given point. 1575 1576 Not Collective 1577 1578 Input Parameters: 1579 + s - the PetscSection 1580 . point - the point 1581 - offset - the offset 1582 1583 Note: The user usually does not call this function, but uses PetscSectionSetUp() 1584 1585 Level: intermediate 1586 1587 .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate(), PetscSectionSetUp() 1588 @*/ 1589 PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset) 1590 { 1591 PetscFunctionBegin; 1592 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1593 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); 1594 s->atlasOff[point - s->pStart] = offset; 1595 PetscFunctionReturn(0); 1596 } 1597 1598 /*@ 1599 PetscSectionGetFieldOffset - Return the offset into an array or local Vec for the dof associated with the given point. 1600 1601 Not Collective 1602 1603 Input Parameters: 1604 + s - the PetscSection 1605 . point - the point 1606 - field - the field 1607 1608 Output Parameter: 1609 . offset - the offset 1610 1611 Level: intermediate 1612 1613 .seealso: PetscSectionGetOffset(), PetscSectionCreate() 1614 @*/ 1615 PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset) 1616 { 1617 PetscFunctionBegin; 1618 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1619 PetscValidIntPointer(offset, 4); 1620 PetscSectionCheckValidField(field,s->numFields); 1621 PetscCall(PetscSectionGetOffset(s->field[field], point, offset)); 1622 PetscFunctionReturn(0); 1623 } 1624 1625 /*@ 1626 PetscSectionSetFieldOffset - Set the offset into an array or local Vec for the dof associated with the given field at a point. 1627 1628 Not Collective 1629 1630 Input Parameters: 1631 + s - the PetscSection 1632 . point - the point 1633 . field - the field 1634 - offset - the offset 1635 1636 Note: The user usually does not call this function, but uses PetscSectionSetUp() 1637 1638 Level: intermediate 1639 1640 .seealso: PetscSectionGetFieldOffset(), PetscSectionSetOffset(), PetscSectionCreate(), PetscSectionSetUp() 1641 @*/ 1642 PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset) 1643 { 1644 PetscFunctionBegin; 1645 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1646 PetscSectionCheckValidField(field,s->numFields); 1647 PetscCall(PetscSectionSetOffset(s->field[field], point, offset)); 1648 PetscFunctionReturn(0); 1649 } 1650 1651 /*@ 1652 PetscSectionGetFieldPointOffset - Return the offset on the given point for the dof associated with the given point. 1653 1654 Not Collective 1655 1656 Input Parameters: 1657 + s - the PetscSection 1658 . point - the point 1659 - field - the field 1660 1661 Output Parameter: 1662 . offset - the offset 1663 1664 Note: This gives the offset on a point of the field, ignoring constraints, meaning starting at the first dof for 1665 this point, what number is the first dof with this field. 1666 1667 Level: advanced 1668 1669 .seealso: PetscSectionGetOffset(), PetscSectionCreate() 1670 @*/ 1671 PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset) 1672 { 1673 PetscInt off, foff; 1674 1675 PetscFunctionBegin; 1676 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1677 PetscValidIntPointer(offset, 4); 1678 PetscSectionCheckValidField(field,s->numFields); 1679 PetscCall(PetscSectionGetOffset(s, point, &off)); 1680 PetscCall(PetscSectionGetOffset(s->field[field], point, &foff)); 1681 *offset = foff - off; 1682 PetscFunctionReturn(0); 1683 } 1684 1685 /*@ 1686 PetscSectionGetOffsetRange - Return the full range of offsets [start, end) 1687 1688 Not Collective 1689 1690 Input Parameter: 1691 . s - the PetscSection 1692 1693 Output Parameters: 1694 + start - the minimum offset 1695 - end - one more than the maximum offset 1696 1697 Level: intermediate 1698 1699 .seealso: PetscSectionGetOffset(), PetscSectionCreate() 1700 @*/ 1701 PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end) 1702 { 1703 PetscInt os = 0, oe = 0, pStart, pEnd, p; 1704 1705 PetscFunctionBegin; 1706 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1707 if (s->atlasOff) {os = s->atlasOff[0]; oe = s->atlasOff[0];} 1708 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1709 for (p = 0; p < pEnd-pStart; ++p) { 1710 PetscInt dof = s->atlasDof[p], off = s->atlasOff[p]; 1711 1712 if (off >= 0) { 1713 os = PetscMin(os, off); 1714 oe = PetscMax(oe, off+dof); 1715 } 1716 } 1717 if (start) *start = os; 1718 if (end) *end = oe; 1719 PetscFunctionReturn(0); 1720 } 1721 1722 /*@ 1723 PetscSectionCreateSubsection - Create a new, smaller section composed of only the selected fields 1724 1725 Collective 1726 1727 Input Parameters: 1728 + s - the PetscSection 1729 . len - the number of subfields 1730 - fields - the subfield numbers 1731 1732 Output Parameter: 1733 . subs - the subsection 1734 1735 Note: The section offsets now refer to a new, smaller vector. 1736 1737 Level: advanced 1738 1739 .seealso: PetscSectionCreateSupersection(), PetscSectionCreate() 1740 @*/ 1741 PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt len, const PetscInt fields[], PetscSection *subs) 1742 { 1743 PetscInt nF, f, c, pStart, pEnd, p, maxCdof = 0; 1744 1745 PetscFunctionBegin; 1746 if (!len) PetscFunctionReturn(0); 1747 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1748 PetscValidIntPointer(fields, 3); 1749 PetscValidPointer(subs, 4); 1750 PetscCall(PetscSectionGetNumFields(s, &nF)); 1751 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); 1752 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), subs)); 1753 PetscCall(PetscSectionSetNumFields(*subs, len)); 1754 for (f = 0; f < len; ++f) { 1755 const char *name = NULL; 1756 PetscInt numComp = 0; 1757 1758 PetscCall(PetscSectionGetFieldName(s, fields[f], &name)); 1759 PetscCall(PetscSectionSetFieldName(*subs, f, name)); 1760 PetscCall(PetscSectionGetFieldComponents(s, fields[f], &numComp)); 1761 PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp)); 1762 for (c = 0; c < s->numFieldComponents[fields[f]]; ++c) { 1763 PetscCall(PetscSectionGetComponentName(s, fields[f], c, &name)); 1764 PetscCall(PetscSectionSetComponentName(*subs, f, c, name)); 1765 } 1766 } 1767 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1768 PetscCall(PetscSectionSetChart(*subs, pStart, pEnd)); 1769 for (p = pStart; p < pEnd; ++p) { 1770 PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0; 1771 1772 for (f = 0; f < len; ++f) { 1773 PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof)); 1774 PetscCall(PetscSectionSetFieldDof(*subs, p, f, fdof)); 1775 PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof)); 1776 if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof)); 1777 dof += fdof; 1778 cdof += cfdof; 1779 } 1780 PetscCall(PetscSectionSetDof(*subs, p, dof)); 1781 if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, p, cdof)); 1782 maxCdof = PetscMax(cdof, maxCdof); 1783 } 1784 PetscCall(PetscSectionSetUp(*subs)); 1785 if (maxCdof) { 1786 PetscInt *indices; 1787 1788 PetscCall(PetscMalloc1(maxCdof, &indices)); 1789 for (p = pStart; p < pEnd; ++p) { 1790 PetscInt cdof; 1791 1792 PetscCall(PetscSectionGetConstraintDof(*subs, p, &cdof)); 1793 if (cdof) { 1794 const PetscInt *oldIndices = NULL; 1795 PetscInt fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0; 1796 1797 for (f = 0; f < len; ++f) { 1798 PetscCall(PetscSectionGetFieldDof(s, p, fields[f], &fdof)); 1799 PetscCall(PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof)); 1800 PetscCall(PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices)); 1801 PetscCall(PetscSectionSetFieldConstraintIndices(*subs, p, f, oldIndices)); 1802 for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] = oldIndices[fc] + fOff; 1803 numConst += cfdof; 1804 fOff += fdof; 1805 } 1806 PetscCall(PetscSectionSetConstraintIndices(*subs, p, indices)); 1807 } 1808 } 1809 PetscCall(PetscFree(indices)); 1810 } 1811 PetscFunctionReturn(0); 1812 } 1813 1814 /*@ 1815 PetscSectionCreateSupersection - Create a new, larger section composed of the input sections 1816 1817 Collective 1818 1819 Input Parameters: 1820 + s - the input sections 1821 - len - the number of input sections 1822 1823 Output Parameter: 1824 . supers - the supersection 1825 1826 Note: The section offsets now refer to a new, larger vector. 1827 1828 Level: advanced 1829 1830 .seealso: PetscSectionCreateSubsection(), PetscSectionCreate() 1831 @*/ 1832 PetscErrorCode PetscSectionCreateSupersection(PetscSection s[], PetscInt len, PetscSection *supers) 1833 { 1834 PetscInt Nf = 0, f, pStart = PETSC_MAX_INT, pEnd = 0, p, maxCdof = 0, i; 1835 1836 PetscFunctionBegin; 1837 if (!len) PetscFunctionReturn(0); 1838 for (i = 0; i < len; ++i) { 1839 PetscInt nf, pStarti, pEndi; 1840 1841 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1842 PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi)); 1843 pStart = PetscMin(pStart, pStarti); 1844 pEnd = PetscMax(pEnd, pEndi); 1845 Nf += nf; 1846 } 1847 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s[0]), supers)); 1848 PetscCall(PetscSectionSetNumFields(*supers, Nf)); 1849 for (i = 0, f = 0; i < len; ++i) { 1850 PetscInt nf, fi, ci; 1851 1852 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1853 for (fi = 0; fi < nf; ++fi, ++f) { 1854 const char *name = NULL; 1855 PetscInt numComp = 0; 1856 1857 PetscCall(PetscSectionGetFieldName(s[i], fi, &name)); 1858 PetscCall(PetscSectionSetFieldName(*supers, f, name)); 1859 PetscCall(PetscSectionGetFieldComponents(s[i], fi, &numComp)); 1860 PetscCall(PetscSectionSetFieldComponents(*supers, f, numComp)); 1861 for (ci = 0; ci < s[i]->numFieldComponents[fi]; ++ci) { 1862 PetscCall(PetscSectionGetComponentName(s[i], fi, ci, &name)); 1863 PetscCall(PetscSectionSetComponentName(*supers, f, ci, name)); 1864 } 1865 } 1866 } 1867 PetscCall(PetscSectionSetChart(*supers, pStart, pEnd)); 1868 for (p = pStart; p < pEnd; ++p) { 1869 PetscInt dof = 0, cdof = 0; 1870 1871 for (i = 0, f = 0; i < len; ++i) { 1872 PetscInt nf, fi, pStarti, pEndi; 1873 PetscInt fdof = 0, cfdof = 0; 1874 1875 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1876 PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi)); 1877 if ((p < pStarti) || (p >= pEndi)) continue; 1878 for (fi = 0; fi < nf; ++fi, ++f) { 1879 PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof)); 1880 PetscCall(PetscSectionAddFieldDof(*supers, p, f, fdof)); 1881 PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof)); 1882 if (cfdof) PetscCall(PetscSectionAddFieldConstraintDof(*supers, p, f, cfdof)); 1883 dof += fdof; 1884 cdof += cfdof; 1885 } 1886 } 1887 PetscCall(PetscSectionSetDof(*supers, p, dof)); 1888 if (cdof) PetscCall(PetscSectionSetConstraintDof(*supers, p, cdof)); 1889 maxCdof = PetscMax(cdof, maxCdof); 1890 } 1891 PetscCall(PetscSectionSetUp(*supers)); 1892 if (maxCdof) { 1893 PetscInt *indices; 1894 1895 PetscCall(PetscMalloc1(maxCdof, &indices)); 1896 for (p = pStart; p < pEnd; ++p) { 1897 PetscInt cdof; 1898 1899 PetscCall(PetscSectionGetConstraintDof(*supers, p, &cdof)); 1900 if (cdof) { 1901 PetscInt dof, numConst = 0, fOff = 0; 1902 1903 for (i = 0, f = 0; i < len; ++i) { 1904 const PetscInt *oldIndices = NULL; 1905 PetscInt nf, fi, pStarti, pEndi, fdof, cfdof, fc; 1906 1907 PetscCall(PetscSectionGetNumFields(s[i], &nf)); 1908 PetscCall(PetscSectionGetChart(s[i], &pStarti, &pEndi)); 1909 if ((p < pStarti) || (p >= pEndi)) continue; 1910 for (fi = 0; fi < nf; ++fi, ++f) { 1911 PetscCall(PetscSectionGetFieldDof(s[i], p, fi, &fdof)); 1912 PetscCall(PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof)); 1913 PetscCall(PetscSectionGetFieldConstraintIndices(s[i], p, fi, &oldIndices)); 1914 for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] = oldIndices[fc]; 1915 PetscCall(PetscSectionSetFieldConstraintIndices(*supers, p, f, &indices[numConst])); 1916 for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] += fOff; 1917 numConst += cfdof; 1918 } 1919 PetscCall(PetscSectionGetDof(s[i], p, &dof)); 1920 fOff += dof; 1921 } 1922 PetscCall(PetscSectionSetConstraintIndices(*supers, p, indices)); 1923 } 1924 } 1925 PetscCall(PetscFree(indices)); 1926 } 1927 PetscFunctionReturn(0); 1928 } 1929 1930 /*@ 1931 PetscSectionCreateSubmeshSection - Create a new, smaller section with support on the submesh 1932 1933 Collective 1934 1935 Input Parameters: 1936 + s - the PetscSection 1937 - subpointMap - a sorted list of points in the original mesh which are in the submesh 1938 1939 Output Parameter: 1940 . subs - the subsection 1941 1942 Note: The section offsets now refer to a new, smaller vector. 1943 1944 Level: advanced 1945 1946 .seealso: PetscSectionCreateSubsection(), DMPlexGetSubpointMap(), PetscSectionCreate() 1947 @*/ 1948 PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs) 1949 { 1950 const PetscInt *points = NULL, *indices = NULL; 1951 PetscInt numFields, f, c, numSubpoints = 0, pStart, pEnd, p, subp; 1952 1953 PetscFunctionBegin; 1954 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 1955 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 1956 PetscValidPointer(subs, 3); 1957 PetscCall(PetscSectionGetNumFields(s, &numFields)); 1958 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), subs)); 1959 if (numFields) PetscCall(PetscSectionSetNumFields(*subs, numFields)); 1960 for (f = 0; f < numFields; ++f) { 1961 const char *name = NULL; 1962 PetscInt numComp = 0; 1963 1964 PetscCall(PetscSectionGetFieldName(s, f, &name)); 1965 PetscCall(PetscSectionSetFieldName(*subs, f, name)); 1966 PetscCall(PetscSectionGetFieldComponents(s, f, &numComp)); 1967 PetscCall(PetscSectionSetFieldComponents(*subs, f, numComp)); 1968 for (c = 0; c < s->numFieldComponents[f]; ++c) { 1969 PetscCall(PetscSectionGetComponentName(s, f, c, &name)); 1970 PetscCall(PetscSectionSetComponentName(*subs, f, c, name)); 1971 } 1972 } 1973 /* For right now, we do not try to squeeze the subchart */ 1974 if (subpointMap) { 1975 PetscCall(ISGetSize(subpointMap, &numSubpoints)); 1976 PetscCall(ISGetIndices(subpointMap, &points)); 1977 } 1978 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 1979 PetscCall(PetscSectionSetChart(*subs, 0, numSubpoints)); 1980 for (p = pStart; p < pEnd; ++p) { 1981 PetscInt dof, cdof, fdof = 0, cfdof = 0; 1982 1983 PetscCall(PetscFindInt(p, numSubpoints, points, &subp)); 1984 if (subp < 0) continue; 1985 for (f = 0; f < numFields; ++f) { 1986 PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof)); 1987 PetscCall(PetscSectionSetFieldDof(*subs, subp, f, fdof)); 1988 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cfdof)); 1989 if (cfdof) PetscCall(PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof)); 1990 } 1991 PetscCall(PetscSectionGetDof(s, p, &dof)); 1992 PetscCall(PetscSectionSetDof(*subs, subp, dof)); 1993 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 1994 if (cdof) PetscCall(PetscSectionSetConstraintDof(*subs, subp, cdof)); 1995 } 1996 PetscCall(PetscSectionSetUp(*subs)); 1997 /* Change offsets to original offsets */ 1998 for (p = pStart; p < pEnd; ++p) { 1999 PetscInt off, foff = 0; 2000 2001 PetscCall(PetscFindInt(p, numSubpoints, points, &subp)); 2002 if (subp < 0) continue; 2003 for (f = 0; f < numFields; ++f) { 2004 PetscCall(PetscSectionGetFieldOffset(s, p, f, &foff)); 2005 PetscCall(PetscSectionSetFieldOffset(*subs, subp, f, foff)); 2006 } 2007 PetscCall(PetscSectionGetOffset(s, p, &off)); 2008 PetscCall(PetscSectionSetOffset(*subs, subp, off)); 2009 } 2010 /* Copy constraint indices */ 2011 for (subp = 0; subp < numSubpoints; ++subp) { 2012 PetscInt cdof; 2013 2014 PetscCall(PetscSectionGetConstraintDof(*subs, subp, &cdof)); 2015 if (cdof) { 2016 for (f = 0; f < numFields; ++f) { 2017 PetscCall(PetscSectionGetFieldConstraintIndices(s, points[subp], f, &indices)); 2018 PetscCall(PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices)); 2019 } 2020 PetscCall(PetscSectionGetConstraintIndices(s, points[subp], &indices)); 2021 PetscCall(PetscSectionSetConstraintIndices(*subs, subp, indices)); 2022 } 2023 } 2024 if (subpointMap) PetscCall(ISRestoreIndices(subpointMap, &points)); 2025 PetscFunctionReturn(0); 2026 } 2027 2028 static PetscErrorCode PetscSectionView_ASCII(PetscSection s, PetscViewer viewer) 2029 { 2030 PetscInt p; 2031 PetscMPIInt rank; 2032 2033 PetscFunctionBegin; 2034 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 2035 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 2036 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 2037 for (p = 0; p < s->pEnd - s->pStart; ++p) { 2038 if ((s->bc) && (s->bc->atlasDof[p] > 0)) { 2039 PetscInt b; 2040 2041 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT " constrained", p+s->pStart, s->atlasDof[p], s->atlasOff[p])); 2042 if (s->bcIndices) { 2043 for (b = 0; b < s->bc->atlasDof[p]; ++b) { 2044 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, s->bcIndices[s->bc->atlasOff[p]+b])); 2045 } 2046 } 2047 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 2048 } else { 2049 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT "\n", p+s->pStart, s->atlasDof[p], s->atlasOff[p])); 2050 } 2051 } 2052 PetscCall(PetscViewerFlush(viewer)); 2053 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 2054 if (s->sym) { 2055 PetscCall(PetscViewerASCIIPushTab(viewer)); 2056 PetscCall(PetscSectionSymView(s->sym,viewer)); 2057 PetscCall(PetscViewerASCIIPopTab(viewer)); 2058 } 2059 PetscFunctionReturn(0); 2060 } 2061 2062 /*@C 2063 PetscSectionViewFromOptions - View from Options 2064 2065 Collective 2066 2067 Input Parameters: 2068 + A - the PetscSection object to view 2069 . obj - Optional object 2070 - name - command line option 2071 2072 Level: intermediate 2073 .seealso: PetscSection, PetscSectionView, PetscObjectViewFromOptions(), PetscSectionCreate() 2074 @*/ 2075 PetscErrorCode PetscSectionViewFromOptions(PetscSection A,PetscObject obj,const char name[]) 2076 { 2077 PetscFunctionBegin; 2078 PetscValidHeaderSpecific(A,PETSC_SECTION_CLASSID,1); 2079 PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 2080 PetscFunctionReturn(0); 2081 } 2082 2083 /*@C 2084 PetscSectionView - Views a PetscSection 2085 2086 Collective 2087 2088 Input Parameters: 2089 + s - the PetscSection object to view 2090 - v - the viewer 2091 2092 Note: 2093 PetscSectionView(), when viewer is of type PETSCVIEWERHDF5, only saves 2094 distribution independent data, such as dofs, offsets, constraint dofs, 2095 and constraint indices. Points that have negative dofs, for instance, 2096 are not saved as they represent points owned by other processes. 2097 Point numbering and rank assignment is currently not stored. 2098 The saved section can be loaded with PetscSectionLoad(). 2099 2100 Level: beginner 2101 2102 .seealso PetscSectionCreate(), PetscSectionDestroy(), PetscSectionLoad() 2103 @*/ 2104 PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer) 2105 { 2106 PetscBool isascii, ishdf5; 2107 PetscInt f; 2108 2109 PetscFunctionBegin; 2110 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2111 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)s), &viewer)); 2112 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2113 PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii)); 2114 PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 2115 if (isascii) { 2116 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)s,viewer)); 2117 if (s->numFields) { 2118 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " fields\n", s->numFields)); 2119 for (f = 0; f < s->numFields; ++f) { 2120 PetscCall(PetscViewerASCIIPrintf(viewer, " field %" PetscInt_FMT " with %" PetscInt_FMT " components\n", f, s->numFieldComponents[f])); 2121 PetscCall(PetscSectionView_ASCII(s->field[f], viewer)); 2122 } 2123 } else { 2124 PetscCall(PetscSectionView_ASCII(s, viewer)); 2125 } 2126 } else if (ishdf5) { 2127 #if PetscDefined(HAVE_HDF5) 2128 PetscCall(PetscSectionView_HDF5_Internal(s, viewer)); 2129 #else 2130 SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2131 #endif 2132 } 2133 PetscFunctionReturn(0); 2134 } 2135 2136 /*@C 2137 PetscSectionLoad - Loads a PetscSection 2138 2139 Collective 2140 2141 Input Parameters: 2142 + s - the PetscSection object to load 2143 - v - the viewer 2144 2145 Note: 2146 PetscSectionLoad(), when viewer is of type PETSCVIEWERHDF5, loads 2147 a section saved with PetscSectionView(). The number of processes 2148 used here (N) does not need to be the same as that used when saving. 2149 After calling this function, the chart of s on rank i will be set 2150 to [0, E_i), where \sum_{i=0}^{N-1}E_i equals to the total number of 2151 saved section points. 2152 2153 Level: beginner 2154 2155 .seealso PetscSectionCreate(), PetscSectionDestroy(), PetscSectionView() 2156 @*/ 2157 PetscErrorCode PetscSectionLoad(PetscSection s, PetscViewer viewer) 2158 { 2159 PetscBool ishdf5; 2160 2161 PetscFunctionBegin; 2162 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2163 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2164 PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 2165 if (ishdf5) { 2166 #if PetscDefined(HAVE_HDF5) 2167 PetscCall(PetscSectionLoad_HDF5_Internal(s, viewer)); 2168 PetscFunctionReturn(0); 2169 #else 2170 SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2171 #endif 2172 } else SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_SUP, "Viewer type %s not yet supported for PetscSection loading", ((PetscObject)viewer)->type_name); 2173 } 2174 2175 static PetscErrorCode PetscSectionResetClosurePermutation(PetscSection section) 2176 { 2177 PetscSectionClosurePermVal clVal; 2178 2179 PetscFunctionBegin; 2180 if (!section->clHash) PetscFunctionReturn(0); 2181 kh_foreach_value(section->clHash, clVal, { 2182 PetscCall(PetscFree(clVal.perm)); 2183 PetscCall(PetscFree(clVal.invPerm)); 2184 }); 2185 kh_destroy(ClPerm, section->clHash); 2186 section->clHash = NULL; 2187 PetscFunctionReturn(0); 2188 } 2189 2190 /*@ 2191 PetscSectionReset - Frees all section data. 2192 2193 Not Collective 2194 2195 Input Parameters: 2196 . s - the PetscSection 2197 2198 Level: beginner 2199 2200 .seealso: PetscSection, PetscSectionCreate() 2201 @*/ 2202 PetscErrorCode PetscSectionReset(PetscSection s) 2203 { 2204 PetscInt f, c; 2205 2206 PetscFunctionBegin; 2207 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2208 for (f = 0; f < s->numFields; ++f) { 2209 PetscCall(PetscSectionDestroy(&s->field[f])); 2210 PetscCall(PetscFree(s->fieldNames[f])); 2211 for (c = 0; c < s->numFieldComponents[f]; ++c) { 2212 PetscCall(PetscFree(s->compNames[f][c])); 2213 } 2214 PetscCall(PetscFree(s->compNames[f])); 2215 } 2216 PetscCall(PetscFree(s->numFieldComponents)); 2217 PetscCall(PetscFree(s->fieldNames)); 2218 PetscCall(PetscFree(s->compNames)); 2219 PetscCall(PetscFree(s->field)); 2220 PetscCall(PetscSectionDestroy(&s->bc)); 2221 PetscCall(PetscFree(s->bcIndices)); 2222 PetscCall(PetscFree2(s->atlasDof, s->atlasOff)); 2223 PetscCall(PetscSectionDestroy(&s->clSection)); 2224 PetscCall(ISDestroy(&s->clPoints)); 2225 PetscCall(ISDestroy(&s->perm)); 2226 PetscCall(PetscSectionResetClosurePermutation(s)); 2227 PetscCall(PetscSectionSymDestroy(&s->sym)); 2228 PetscCall(PetscSectionDestroy(&s->clSection)); 2229 PetscCall(ISDestroy(&s->clPoints)); 2230 2231 s->pStart = -1; 2232 s->pEnd = -1; 2233 s->maxDof = 0; 2234 s->setup = PETSC_FALSE; 2235 s->numFields = 0; 2236 s->clObj = NULL; 2237 PetscFunctionReturn(0); 2238 } 2239 2240 /*@ 2241 PetscSectionDestroy - Frees a section object and frees its range if that exists. 2242 2243 Not Collective 2244 2245 Input Parameters: 2246 . s - the PetscSection 2247 2248 Level: beginner 2249 2250 .seealso: PetscSection, PetscSectionCreate() 2251 @*/ 2252 PetscErrorCode PetscSectionDestroy(PetscSection *s) 2253 { 2254 PetscFunctionBegin; 2255 if (!*s) PetscFunctionReturn(0); 2256 PetscValidHeaderSpecific(*s,PETSC_SECTION_CLASSID,1); 2257 if (--((PetscObject)(*s))->refct > 0) { 2258 *s = NULL; 2259 PetscFunctionReturn(0); 2260 } 2261 PetscCall(PetscSectionReset(*s)); 2262 PetscCall(PetscHeaderDestroy(s)); 2263 PetscFunctionReturn(0); 2264 } 2265 2266 PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values) 2267 { 2268 const PetscInt p = point - s->pStart; 2269 2270 PetscFunctionBegin; 2271 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2); 2272 *values = &baseArray[s->atlasOff[p]]; 2273 PetscFunctionReturn(0); 2274 } 2275 2276 PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode) 2277 { 2278 PetscInt *array; 2279 const PetscInt p = point - s->pStart; 2280 const PetscInt orientation = 0; /* Needs to be included for use in closure operations */ 2281 PetscInt cDim = 0; 2282 2283 PetscFunctionBegin; 2284 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2); 2285 PetscCall(PetscSectionGetConstraintDof(s, p, &cDim)); 2286 array = &baseArray[s->atlasOff[p]]; 2287 if (!cDim) { 2288 if (orientation >= 0) { 2289 const PetscInt dim = s->atlasDof[p]; 2290 PetscInt i; 2291 2292 if (mode == INSERT_VALUES) { 2293 for (i = 0; i < dim; ++i) array[i] = values[i]; 2294 } else { 2295 for (i = 0; i < dim; ++i) array[i] += values[i]; 2296 } 2297 } else { 2298 PetscInt offset = 0; 2299 PetscInt j = -1, field, i; 2300 2301 for (field = 0; field < s->numFields; ++field) { 2302 const PetscInt dim = s->field[field]->atlasDof[p]; 2303 2304 for (i = dim-1; i >= 0; --i) array[++j] = values[i+offset]; 2305 offset += dim; 2306 } 2307 } 2308 } else { 2309 if (orientation >= 0) { 2310 const PetscInt dim = s->atlasDof[p]; 2311 PetscInt cInd = 0, i; 2312 const PetscInt *cDof; 2313 2314 PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof)); 2315 if (mode == INSERT_VALUES) { 2316 for (i = 0; i < dim; ++i) { 2317 if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;} 2318 array[i] = values[i]; 2319 } 2320 } else { 2321 for (i = 0; i < dim; ++i) { 2322 if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;} 2323 array[i] += values[i]; 2324 } 2325 } 2326 } else { 2327 const PetscInt *cDof; 2328 PetscInt offset = 0; 2329 PetscInt cOffset = 0; 2330 PetscInt j = 0, field; 2331 2332 PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof)); 2333 for (field = 0; field < s->numFields; ++field) { 2334 const PetscInt dim = s->field[field]->atlasDof[p]; /* PetscSectionGetFieldDof() */ 2335 const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */ 2336 const PetscInt sDim = dim - tDim; 2337 PetscInt cInd = 0, i,k; 2338 2339 for (i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) { 2340 if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;} 2341 array[j] = values[k]; 2342 } 2343 offset += dim; 2344 cOffset += dim - tDim; 2345 } 2346 } 2347 } 2348 PetscFunctionReturn(0); 2349 } 2350 2351 /*@C 2352 PetscSectionHasConstraints - Determine whether a section has constrained dofs 2353 2354 Not Collective 2355 2356 Input Parameter: 2357 . s - The PetscSection 2358 2359 Output Parameter: 2360 . hasConstraints - flag indicating that the section has constrained dofs 2361 2362 Level: intermediate 2363 2364 .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection 2365 @*/ 2366 PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints) 2367 { 2368 PetscFunctionBegin; 2369 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2370 PetscValidBoolPointer(hasConstraints, 2); 2371 *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE; 2372 PetscFunctionReturn(0); 2373 } 2374 2375 /*@C 2376 PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained 2377 2378 Not Collective 2379 2380 Input Parameters: 2381 + s - The PetscSection 2382 - point - The point 2383 2384 Output Parameter: 2385 . indices - The constrained dofs 2386 2387 Note: In Fortran, you call PetscSectionGetConstraintIndicesF90() and PetscSectionRestoreConstraintIndicesF90() 2388 2389 Level: intermediate 2390 2391 .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection 2392 @*/ 2393 PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices) 2394 { 2395 PetscFunctionBegin; 2396 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2397 if (s->bc) { 2398 PetscCall(VecIntGetValuesSection(s->bcIndices, s->bc, point, indices)); 2399 } else *indices = NULL; 2400 PetscFunctionReturn(0); 2401 } 2402 2403 /*@C 2404 PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained 2405 2406 Not Collective 2407 2408 Input Parameters: 2409 + s - The PetscSection 2410 . point - The point 2411 - indices - The constrained dofs 2412 2413 Note: The Fortran is PetscSectionSetConstraintIndicesF90() 2414 2415 Level: intermediate 2416 2417 .seealso: PetscSectionGetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection 2418 @*/ 2419 PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[]) 2420 { 2421 PetscFunctionBegin; 2422 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2423 if (s->bc) { 2424 const PetscInt dof = s->atlasDof[point]; 2425 const PetscInt cdof = s->bc->atlasDof[point]; 2426 PetscInt d; 2427 2428 for (d = 0; d < cdof; ++d) { 2429 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]); 2430 } 2431 PetscCall(VecIntSetValuesSection(s->bcIndices, s->bc, point, indices, INSERT_VALUES)); 2432 } 2433 PetscFunctionReturn(0); 2434 } 2435 2436 /*@C 2437 PetscSectionGetFieldConstraintIndices - Get the field dof numbers, in [0, fdof), which are constrained 2438 2439 Not Collective 2440 2441 Input Parameters: 2442 + s - The PetscSection 2443 . field - The field number 2444 - point - The point 2445 2446 Output Parameter: 2447 . indices - The constrained dofs sorted in ascending order 2448 2449 Notes: 2450 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(). 2451 2452 Fortran Note: 2453 In Fortran, you call PetscSectionGetFieldConstraintIndicesF90() and PetscSectionRestoreFieldConstraintIndicesF90() 2454 2455 Level: intermediate 2456 2457 .seealso: PetscSectionSetFieldConstraintIndices(), PetscSectionGetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection 2458 @*/ 2459 PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices) 2460 { 2461 PetscFunctionBegin; 2462 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2463 PetscValidPointer(indices,4); 2464 PetscSectionCheckValidField(field,s->numFields); 2465 PetscCall(PetscSectionGetConstraintIndices(s->field[field], point, indices)); 2466 PetscFunctionReturn(0); 2467 } 2468 2469 /*@C 2470 PetscSectionSetFieldConstraintIndices - Set the field dof numbers, in [0, fdof), which are constrained 2471 2472 Not Collective 2473 2474 Input Parameters: 2475 + s - The PetscSection 2476 . point - The point 2477 . field - The field number 2478 - indices - The constrained dofs 2479 2480 Note: The Fortran is PetscSectionSetFieldConstraintIndicesF90() 2481 2482 Level: intermediate 2483 2484 .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetFieldConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection 2485 @*/ 2486 PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[]) 2487 { 2488 PetscFunctionBegin; 2489 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 2490 if (PetscDefined(USE_DEBUG)) { 2491 PetscInt nfdof; 2492 2493 PetscCall(PetscSectionGetFieldConstraintDof(s, point, field, &nfdof)); 2494 if (nfdof) PetscValidIntPointer(indices, 4); 2495 } 2496 PetscSectionCheckValidField(field,s->numFields); 2497 PetscCall(PetscSectionSetConstraintIndices(s->field[field], point, indices)); 2498 PetscFunctionReturn(0); 2499 } 2500 2501 /*@ 2502 PetscSectionPermute - Reorder the section according to the input point permutation 2503 2504 Collective 2505 2506 Input Parameters: 2507 + section - The PetscSection object 2508 - perm - The point permutation, old point p becomes new point perm[p] 2509 2510 Output Parameter: 2511 . sectionNew - The permuted PetscSection 2512 2513 Level: intermediate 2514 2515 .seealso: MatPermute() 2516 @*/ 2517 PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew) 2518 { 2519 PetscSection s = section, sNew; 2520 const PetscInt *perm; 2521 PetscInt numFields, f, c, numPoints, pStart, pEnd, p; 2522 2523 PetscFunctionBegin; 2524 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1); 2525 PetscValidHeaderSpecific(permutation, IS_CLASSID, 2); 2526 PetscValidPointer(sectionNew, 3); 2527 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), &sNew)); 2528 PetscCall(PetscSectionGetNumFields(s, &numFields)); 2529 if (numFields) PetscCall(PetscSectionSetNumFields(sNew, numFields)); 2530 for (f = 0; f < numFields; ++f) { 2531 const char *name; 2532 PetscInt numComp; 2533 2534 PetscCall(PetscSectionGetFieldName(s, f, &name)); 2535 PetscCall(PetscSectionSetFieldName(sNew, f, name)); 2536 PetscCall(PetscSectionGetFieldComponents(s, f, &numComp)); 2537 PetscCall(PetscSectionSetFieldComponents(sNew, f, numComp)); 2538 for (c = 0; c < s->numFieldComponents[f]; ++c) { 2539 PetscCall(PetscSectionGetComponentName(s, f, c, &name)); 2540 PetscCall(PetscSectionSetComponentName(sNew, f, c, name)); 2541 } 2542 } 2543 PetscCall(ISGetLocalSize(permutation, &numPoints)); 2544 PetscCall(ISGetIndices(permutation, &perm)); 2545 PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 2546 PetscCall(PetscSectionSetChart(sNew, pStart, pEnd)); 2547 PetscCheckFalse(numPoints < pEnd,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %" PetscInt_FMT " is less than largest Section point %" PetscInt_FMT, numPoints, pEnd); 2548 for (p = pStart; p < pEnd; ++p) { 2549 PetscInt dof, cdof; 2550 2551 PetscCall(PetscSectionGetDof(s, p, &dof)); 2552 PetscCall(PetscSectionSetDof(sNew, perm[p], dof)); 2553 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 2554 if (cdof) PetscCall(PetscSectionSetConstraintDof(sNew, perm[p], cdof)); 2555 for (f = 0; f < numFields; ++f) { 2556 PetscCall(PetscSectionGetFieldDof(s, p, f, &dof)); 2557 PetscCall(PetscSectionSetFieldDof(sNew, perm[p], f, dof)); 2558 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof)); 2559 if (cdof) PetscCall(PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof)); 2560 } 2561 } 2562 PetscCall(PetscSectionSetUp(sNew)); 2563 for (p = pStart; p < pEnd; ++p) { 2564 const PetscInt *cind; 2565 PetscInt cdof; 2566 2567 PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 2568 if (cdof) { 2569 PetscCall(PetscSectionGetConstraintIndices(s, p, &cind)); 2570 PetscCall(PetscSectionSetConstraintIndices(sNew, perm[p], cind)); 2571 } 2572 for (f = 0; f < numFields; ++f) { 2573 PetscCall(PetscSectionGetFieldConstraintDof(s, p, f, &cdof)); 2574 if (cdof) { 2575 PetscCall(PetscSectionGetFieldConstraintIndices(s, p, f, &cind)); 2576 PetscCall(PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind)); 2577 } 2578 } 2579 } 2580 PetscCall(ISRestoreIndices(permutation, &perm)); 2581 *sectionNew = sNew; 2582 PetscFunctionReturn(0); 2583 } 2584 2585 /*@ 2586 PetscSectionSetClosureIndex - Set a cache of points in the closure of each point in the section 2587 2588 Collective 2589 2590 Input Parameters: 2591 + section - The PetscSection 2592 . obj - A PetscObject which serves as the key for this index 2593 . clSection - Section giving the size of the closure of each point 2594 - clPoints - IS giving the points in each closure 2595 2596 Note: We compress out closure points with no dofs in this section 2597 2598 Level: advanced 2599 2600 .seealso: PetscSectionGetClosureIndex(), DMPlexCreateClosureIndex() 2601 @*/ 2602 PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints) 2603 { 2604 PetscFunctionBegin; 2605 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 2606 PetscValidHeaderSpecific(clSection,PETSC_SECTION_CLASSID,3); 2607 PetscValidHeaderSpecific(clPoints,IS_CLASSID,4); 2608 if (section->clObj != obj) PetscCall(PetscSectionResetClosurePermutation(section)); 2609 section->clObj = obj; 2610 PetscCall(PetscObjectReference((PetscObject)clSection)); 2611 PetscCall(PetscObjectReference((PetscObject)clPoints)); 2612 PetscCall(PetscSectionDestroy(§ion->clSection)); 2613 PetscCall(ISDestroy(§ion->clPoints)); 2614 section->clSection = clSection; 2615 section->clPoints = clPoints; 2616 PetscFunctionReturn(0); 2617 } 2618 2619 /*@ 2620 PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section 2621 2622 Collective 2623 2624 Input Parameters: 2625 + section - The PetscSection 2626 - obj - A PetscObject which serves as the key for this index 2627 2628 Output Parameters: 2629 + clSection - Section giving the size of the closure of each point 2630 - clPoints - IS giving the points in each closure 2631 2632 Note: We compress out closure points with no dofs in this section 2633 2634 Level: advanced 2635 2636 .seealso: PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex() 2637 @*/ 2638 PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints) 2639 { 2640 PetscFunctionBegin; 2641 if (section->clObj == obj) { 2642 if (clSection) *clSection = section->clSection; 2643 if (clPoints) *clPoints = section->clPoints; 2644 } else { 2645 if (clSection) *clSection = NULL; 2646 if (clPoints) *clPoints = NULL; 2647 } 2648 PetscFunctionReturn(0); 2649 } 2650 2651 PetscErrorCode PetscSectionSetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, PetscCopyMode mode, PetscInt *clPerm) 2652 { 2653 PetscInt i; 2654 khiter_t iter; 2655 int new_entry; 2656 PetscSectionClosurePermKey key = {depth, clSize}; 2657 PetscSectionClosurePermVal *val; 2658 2659 PetscFunctionBegin; 2660 if (section->clObj != obj) { 2661 PetscCall(PetscSectionDestroy(§ion->clSection)); 2662 PetscCall(ISDestroy(§ion->clPoints)); 2663 } 2664 section->clObj = obj; 2665 if (!section->clHash) PetscCall(PetscClPermCreate(§ion->clHash)); 2666 iter = kh_put(ClPerm, section->clHash, key, &new_entry); 2667 val = &kh_val(section->clHash, iter); 2668 if (!new_entry) { 2669 PetscCall(PetscFree(val->perm)); 2670 PetscCall(PetscFree(val->invPerm)); 2671 } 2672 if (mode == PETSC_COPY_VALUES) { 2673 PetscCall(PetscMalloc1(clSize, &val->perm)); 2674 PetscCall(PetscLogObjectMemory((PetscObject) obj, clSize*sizeof(PetscInt))); 2675 PetscCall(PetscArraycpy(val->perm, clPerm, clSize)); 2676 } else if (mode == PETSC_OWN_POINTER) { 2677 val->perm = clPerm; 2678 } else SETERRQ(PetscObjectComm(obj), PETSC_ERR_SUP, "Do not support borrowed arrays"); 2679 PetscCall(PetscMalloc1(clSize, &val->invPerm)); 2680 for (i = 0; i < clSize; ++i) val->invPerm[clPerm[i]] = i; 2681 PetscFunctionReturn(0); 2682 } 2683 2684 /*@ 2685 PetscSectionSetClosurePermutation - Set the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex. 2686 2687 Not Collective 2688 2689 Input Parameters: 2690 + section - The PetscSection 2691 . obj - A PetscObject which serves as the key for this index (usually a DM) 2692 . depth - Depth of points on which to apply the given permutation 2693 - perm - Permutation of the cell dof closure 2694 2695 Note: 2696 The specified permutation will only be applied to points at depth whose closure size matches the length of perm. In a 2697 mixed-topology or variable-degree finite element space, this function can be called multiple times at each depth for 2698 each topology and degree. 2699 2700 This approach assumes that (depth, len(perm)) uniquely identifies the desired permutation; this might not be true for 2701 exotic/enriched spaces on mixed topology meshes. 2702 2703 Level: intermediate 2704 2705 .seealso: PetscSectionGetClosurePermutation(), PetscSectionGetClosureIndex(), DMPlexCreateClosureIndex(), PetscCopyMode 2706 @*/ 2707 PetscErrorCode PetscSectionSetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, IS perm) 2708 { 2709 const PetscInt *clPerm = NULL; 2710 PetscInt clSize = 0; 2711 2712 PetscFunctionBegin; 2713 if (perm) { 2714 PetscCall(ISGetLocalSize(perm, &clSize)); 2715 PetscCall(ISGetIndices(perm, &clPerm)); 2716 } 2717 PetscCall(PetscSectionSetClosurePermutation_Internal(section, obj, depth, clSize, PETSC_COPY_VALUES, (PetscInt *) clPerm)); 2718 if (perm) PetscCall(ISRestoreIndices(perm, &clPerm)); 2719 PetscFunctionReturn(0); 2720 } 2721 2722 PetscErrorCode PetscSectionGetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[]) 2723 { 2724 PetscFunctionBegin; 2725 if (section->clObj == obj) { 2726 PetscSectionClosurePermKey k = {depth, size}; 2727 PetscSectionClosurePermVal v; 2728 PetscCall(PetscClPermGet(section->clHash, k, &v)); 2729 if (perm) *perm = v.perm; 2730 } else { 2731 if (perm) *perm = NULL; 2732 } 2733 PetscFunctionReturn(0); 2734 } 2735 2736 /*@ 2737 PetscSectionGetClosurePermutation - Get the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex. 2738 2739 Not Collective 2740 2741 Input Parameters: 2742 + section - The PetscSection 2743 . obj - A PetscObject which serves as the key for this index (usually a DM) 2744 . depth - Depth stratum on which to obtain closure permutation 2745 - clSize - Closure size to be permuted (e.g., may vary with element topology and degree) 2746 2747 Output Parameter: 2748 . perm - The dof closure permutation 2749 2750 Note: 2751 The user must destroy the IS that is returned. 2752 2753 Level: intermediate 2754 2755 .seealso: PetscSectionSetClosurePermutation(), PetscSectionGetClosureInversePermutation(), PetscSectionGetClosureIndex(), PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex() 2756 @*/ 2757 PetscErrorCode PetscSectionGetClosurePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm) 2758 { 2759 const PetscInt *clPerm; 2760 2761 PetscFunctionBegin; 2762 PetscCall(PetscSectionGetClosurePermutation_Internal(section, obj, depth, clSize, &clPerm)); 2763 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm)); 2764 PetscFunctionReturn(0); 2765 } 2766 2767 PetscErrorCode PetscSectionGetClosureInversePermutation_Internal(PetscSection section, PetscObject obj, PetscInt depth, PetscInt size, const PetscInt *perm[]) 2768 { 2769 PetscFunctionBegin; 2770 if (section->clObj == obj && section->clHash) { 2771 PetscSectionClosurePermKey k = {depth, size}; 2772 PetscSectionClosurePermVal v; 2773 PetscCall(PetscClPermGet(section->clHash, k, &v)); 2774 if (perm) *perm = v.invPerm; 2775 } else { 2776 if (perm) *perm = NULL; 2777 } 2778 PetscFunctionReturn(0); 2779 } 2780 2781 /*@ 2782 PetscSectionGetClosureInversePermutation - Get the inverse dof permutation for the closure of each cell in the section, meaning clPerm[oldIndex] = newIndex. 2783 2784 Not Collective 2785 2786 Input Parameters: 2787 + section - The PetscSection 2788 . obj - A PetscObject which serves as the key for this index (usually a DM) 2789 . depth - Depth stratum on which to obtain closure permutation 2790 - clSize - Closure size to be permuted (e.g., may vary with element topology and degree) 2791 2792 Output Parameters: 2793 . perm - The dof closure permutation 2794 2795 Note: 2796 The user must destroy the IS that is returned. 2797 2798 Level: intermediate 2799 2800 .seealso: PetscSectionSetClosurePermutation(), PetscSectionGetClosureIndex(), PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex() 2801 @*/ 2802 PetscErrorCode PetscSectionGetClosureInversePermutation(PetscSection section, PetscObject obj, PetscInt depth, PetscInt clSize, IS *perm) 2803 { 2804 const PetscInt *clPerm; 2805 2806 PetscFunctionBegin; 2807 PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, obj, depth, clSize, &clPerm)); 2808 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm)); 2809 PetscFunctionReturn(0); 2810 } 2811 2812 /*@ 2813 PetscSectionGetField - Get the subsection associated with a single field 2814 2815 Input Parameters: 2816 + s - The PetscSection 2817 - field - The field number 2818 2819 Output Parameter: 2820 . subs - The subsection for the given field 2821 2822 Level: intermediate 2823 2824 .seealso: PetscSectionSetNumFields() 2825 @*/ 2826 PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs) 2827 { 2828 PetscFunctionBegin; 2829 PetscValidHeaderSpecific(s,PETSC_SECTION_CLASSID,1); 2830 PetscValidPointer(subs,3); 2831 PetscSectionCheckValidField(field,s->numFields); 2832 *subs = s->field[field]; 2833 PetscFunctionReturn(0); 2834 } 2835 2836 PetscClassId PETSC_SECTION_SYM_CLASSID; 2837 PetscFunctionList PetscSectionSymList = NULL; 2838 2839 /*@ 2840 PetscSectionSymCreate - Creates an empty PetscSectionSym object. 2841 2842 Collective 2843 2844 Input Parameter: 2845 . comm - the MPI communicator 2846 2847 Output Parameter: 2848 . sym - pointer to the new set of symmetries 2849 2850 Level: developer 2851 2852 .seealso: PetscSectionSym, PetscSectionSymDestroy() 2853 @*/ 2854 PetscErrorCode PetscSectionSymCreate(MPI_Comm comm, PetscSectionSym *sym) 2855 { 2856 PetscFunctionBegin; 2857 PetscValidPointer(sym,2); 2858 PetscCall(ISInitializePackage()); 2859 PetscCall(PetscHeaderCreate(*sym,PETSC_SECTION_SYM_CLASSID,"PetscSectionSym","Section Symmetry","IS",comm,PetscSectionSymDestroy,PetscSectionSymView)); 2860 PetscFunctionReturn(0); 2861 } 2862 2863 /*@C 2864 PetscSectionSymSetType - Builds a PetscSection symmetry, for a particular implementation. 2865 2866 Collective 2867 2868 Input Parameters: 2869 + sym - The section symmetry object 2870 - method - The name of the section symmetry type 2871 2872 Level: developer 2873 2874 .seealso: PetscSectionSymGetType(), PetscSectionSymCreate() 2875 @*/ 2876 PetscErrorCode PetscSectionSymSetType(PetscSectionSym sym, PetscSectionSymType method) 2877 { 2878 PetscErrorCode (*r)(PetscSectionSym); 2879 PetscBool match; 2880 2881 PetscFunctionBegin; 2882 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID,1); 2883 PetscCall(PetscObjectTypeCompare((PetscObject) sym, method, &match)); 2884 if (match) PetscFunctionReturn(0); 2885 2886 PetscCall(PetscFunctionListFind(PetscSectionSymList,method,&r)); 2887 PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscSectionSym type: %s", method); 2888 if (sym->ops->destroy) { 2889 PetscCall((*sym->ops->destroy)(sym)); 2890 sym->ops->destroy = NULL; 2891 } 2892 PetscCall((*r)(sym)); 2893 PetscCall(PetscObjectChangeTypeName((PetscObject)sym,method)); 2894 PetscFunctionReturn(0); 2895 } 2896 2897 /*@C 2898 PetscSectionSymGetType - Gets the section symmetry type name (as a string) from the PetscSectionSym. 2899 2900 Not Collective 2901 2902 Input Parameter: 2903 . sym - The section symmetry 2904 2905 Output Parameter: 2906 . type - The index set type name 2907 2908 Level: developer 2909 2910 .seealso: PetscSectionSymSetType(), PetscSectionSymCreate() 2911 @*/ 2912 PetscErrorCode PetscSectionSymGetType(PetscSectionSym sym, PetscSectionSymType *type) 2913 { 2914 PetscFunctionBegin; 2915 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID,1); 2916 PetscValidPointer(type,2); 2917 *type = ((PetscObject)sym)->type_name; 2918 PetscFunctionReturn(0); 2919 } 2920 2921 /*@C 2922 PetscSectionSymRegister - Adds a new section symmetry implementation 2923 2924 Not Collective 2925 2926 Input Parameters: 2927 + name - The name of a new user-defined creation routine 2928 - create_func - The creation routine itself 2929 2930 Notes: 2931 PetscSectionSymRegister() may be called multiple times to add several user-defined vectors 2932 2933 Level: developer 2934 2935 .seealso: PetscSectionSymCreate(), PetscSectionSymSetType() 2936 @*/ 2937 PetscErrorCode PetscSectionSymRegister(const char sname[], PetscErrorCode (*function)(PetscSectionSym)) 2938 { 2939 PetscFunctionBegin; 2940 PetscCall(ISInitializePackage()); 2941 PetscCall(PetscFunctionListAdd(&PetscSectionSymList,sname,function)); 2942 PetscFunctionReturn(0); 2943 } 2944 2945 /*@ 2946 PetscSectionSymDestroy - Destroys a section symmetry. 2947 2948 Collective 2949 2950 Input Parameters: 2951 . sym - the section symmetry 2952 2953 Level: developer 2954 2955 .seealso: PetscSectionSymCreate(), PetscSectionSymDestroy() 2956 @*/ 2957 PetscErrorCode PetscSectionSymDestroy(PetscSectionSym *sym) 2958 { 2959 SymWorkLink link,next; 2960 2961 PetscFunctionBegin; 2962 if (!*sym) PetscFunctionReturn(0); 2963 PetscValidHeaderSpecific((*sym),PETSC_SECTION_SYM_CLASSID,1); 2964 if (--((PetscObject)(*sym))->refct > 0) {*sym = NULL; PetscFunctionReturn(0);} 2965 if ((*sym)->ops->destroy) { 2966 PetscCall((*(*sym)->ops->destroy)(*sym)); 2967 } 2968 PetscCheckFalse((*sym)->workout,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 2969 for (link=(*sym)->workin; link; link=next) { 2970 next = link->next; 2971 PetscCall(PetscFree2(link->perms,link->rots)); 2972 PetscCall(PetscFree(link)); 2973 } 2974 (*sym)->workin = NULL; 2975 PetscCall(PetscHeaderDestroy(sym)); 2976 PetscFunctionReturn(0); 2977 } 2978 2979 /*@C 2980 PetscSectionSymView - Displays a section symmetry 2981 2982 Collective 2983 2984 Input Parameters: 2985 + sym - the index set 2986 - viewer - viewer used to display the set, for example PETSC_VIEWER_STDOUT_SELF. 2987 2988 Level: developer 2989 2990 .seealso: PetscViewerASCIIOpen() 2991 @*/ 2992 PetscErrorCode PetscSectionSymView(PetscSectionSym sym,PetscViewer viewer) 2993 { 2994 PetscFunctionBegin; 2995 PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1); 2996 if (!viewer) { 2997 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sym),&viewer)); 2998 } 2999 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3000 PetscCheckSameComm(sym,1,viewer,2); 3001 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sym,viewer)); 3002 if (sym->ops->view) { 3003 PetscCall((*sym->ops->view)(sym,viewer)); 3004 } 3005 PetscFunctionReturn(0); 3006 } 3007 3008 /*@ 3009 PetscSectionSetSym - Set the symmetries for the data referred to by the section 3010 3011 Collective 3012 3013 Input Parameters: 3014 + section - the section describing data layout 3015 - sym - the symmetry describing the affect of orientation on the access of the data 3016 3017 Level: developer 3018 3019 .seealso: PetscSectionGetSym(), PetscSectionSymCreate() 3020 @*/ 3021 PetscErrorCode PetscSectionSetSym(PetscSection section, PetscSectionSym sym) 3022 { 3023 PetscFunctionBegin; 3024 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3025 PetscCall(PetscSectionSymDestroy(&(section->sym))); 3026 if (sym) { 3027 PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,2); 3028 PetscCheckSameComm(section,1,sym,2); 3029 PetscCall(PetscObjectReference((PetscObject) sym)); 3030 } 3031 section->sym = sym; 3032 PetscFunctionReturn(0); 3033 } 3034 3035 /*@ 3036 PetscSectionGetSym - Get the symmetries for the data referred to by the section 3037 3038 Not Collective 3039 3040 Input Parameters: 3041 . section - the section describing data layout 3042 3043 Output Parameters: 3044 . sym - the symmetry describing the affect of orientation on the access of the data 3045 3046 Level: developer 3047 3048 .seealso: PetscSectionSetSym(), PetscSectionSymCreate() 3049 @*/ 3050 PetscErrorCode PetscSectionGetSym(PetscSection section, PetscSectionSym *sym) 3051 { 3052 PetscFunctionBegin; 3053 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3054 *sym = section->sym; 3055 PetscFunctionReturn(0); 3056 } 3057 3058 /*@ 3059 PetscSectionSetFieldSym - Set the symmetries for the data referred to by a field of the section 3060 3061 Collective 3062 3063 Input Parameters: 3064 + section - the section describing data layout 3065 . field - the field number 3066 - sym - the symmetry describing the affect of orientation on the access of the data 3067 3068 Level: developer 3069 3070 .seealso: PetscSectionGetFieldSym(), PetscSectionSymCreate() 3071 @*/ 3072 PetscErrorCode PetscSectionSetFieldSym(PetscSection section, PetscInt field, PetscSectionSym sym) 3073 { 3074 PetscFunctionBegin; 3075 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3076 PetscSectionCheckValidField(field,section->numFields); 3077 PetscCall(PetscSectionSetSym(section->field[field],sym)); 3078 PetscFunctionReturn(0); 3079 } 3080 3081 /*@ 3082 PetscSectionGetFieldSym - Get the symmetries for the data referred to by a field of the section 3083 3084 Collective 3085 3086 Input Parameters: 3087 + section - the section describing data layout 3088 - field - the field number 3089 3090 Output Parameters: 3091 . sym - the symmetry describing the affect of orientation on the access of the data 3092 3093 Level: developer 3094 3095 .seealso: PetscSectionSetFieldSym(), PetscSectionSymCreate() 3096 @*/ 3097 PetscErrorCode PetscSectionGetFieldSym(PetscSection section, PetscInt field, PetscSectionSym *sym) 3098 { 3099 PetscFunctionBegin; 3100 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3101 PetscSectionCheckValidField(field,section->numFields); 3102 *sym = section->field[field]->sym; 3103 PetscFunctionReturn(0); 3104 } 3105 3106 /*@C 3107 PetscSectionGetPointSyms - Get the symmetries for a set of points in a PetscSection under specific orientations. 3108 3109 Not Collective 3110 3111 Input Parameters: 3112 + section - the section 3113 . numPoints - the number of points 3114 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3115 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3116 context, see DMPlexGetConeOrientation()). 3117 3118 Output Parameters: 3119 + perms - The permutations for the given orientations (or NULL if there is no symmetry or the permutation is the identity). 3120 - rots - The field rotations symmetries for the given orientations (or NULL if there is no symmetry or the rotations are all 3121 identity). 3122 3123 Example of usage, gathering dofs into a local array (lArray) from a section array (sArray): 3124 .vb 3125 const PetscInt **perms; 3126 const PetscScalar **rots; 3127 PetscInt lOffset; 3128 3129 PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots); 3130 for (i = 0, lOffset = 0; i < numPoints; i++) { 3131 PetscInt point = points[2*i], dof, sOffset; 3132 const PetscInt *perm = perms ? perms[i] : NULL; 3133 const PetscScalar *rot = rots ? rots[i] : NULL; 3134 3135 PetscSectionGetDof(section,point,&dof); 3136 PetscSectionGetOffset(section,point,&sOffset); 3137 3138 if (perm) {for (j = 0; j < dof; j++) {lArray[lOffset + perm[j]] = sArray[sOffset + j];}} 3139 else {for (j = 0; j < dof; j++) {lArray[lOffset + j ] = sArray[sOffset + j];}} 3140 if (rot) {for (j = 0; j < dof; j++) {lArray[lOffset + j ] *= rot[j]; }} 3141 lOffset += dof; 3142 } 3143 PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots); 3144 .ve 3145 3146 Example of usage, adding dofs into a section array (sArray) from a local array (lArray): 3147 .vb 3148 const PetscInt **perms; 3149 const PetscScalar **rots; 3150 PetscInt lOffset; 3151 3152 PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots); 3153 for (i = 0, lOffset = 0; i < numPoints; i++) { 3154 PetscInt point = points[2*i], dof, sOffset; 3155 const PetscInt *perm = perms ? perms[i] : NULL; 3156 const PetscScalar *rot = rots ? rots[i] : NULL; 3157 3158 PetscSectionGetDof(section,point,&dof); 3159 PetscSectionGetOffset(section,point,&sOff); 3160 3161 if (perm) {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + perm[j]] * (rot ? PetscConj(rot[perm[j]]) : 1.);}} 3162 else {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + j ] * (rot ? PetscConj(rot[ j ]) : 1.);}} 3163 offset += dof; 3164 } 3165 PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots); 3166 .ve 3167 3168 Level: developer 3169 3170 .seealso: PetscSectionRestorePointSyms(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym() 3171 @*/ 3172 PetscErrorCode PetscSectionGetPointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) 3173 { 3174 PetscSectionSym sym; 3175 3176 PetscFunctionBegin; 3177 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3178 if (numPoints) PetscValidIntPointer(points,3); 3179 if (perms) *perms = NULL; 3180 if (rots) *rots = NULL; 3181 sym = section->sym; 3182 if (sym && (perms || rots)) { 3183 SymWorkLink link; 3184 3185 if (sym->workin) { 3186 link = sym->workin; 3187 sym->workin = sym->workin->next; 3188 } else { 3189 PetscCall(PetscNewLog(sym,&link)); 3190 } 3191 if (numPoints > link->numPoints) { 3192 PetscCall(PetscFree2(link->perms,link->rots)); 3193 PetscCall(PetscMalloc2(numPoints,&link->perms,numPoints,&link->rots)); 3194 link->numPoints = numPoints; 3195 } 3196 link->next = sym->workout; 3197 sym->workout = link; 3198 PetscCall(PetscArrayzero((PetscInt**)link->perms,numPoints)); 3199 PetscCall(PetscArrayzero((PetscInt**)link->rots,numPoints)); 3200 PetscCall((*sym->ops->getpoints) (sym, section, numPoints, points, link->perms, link->rots)); 3201 if (perms) *perms = link->perms; 3202 if (rots) *rots = link->rots; 3203 } 3204 PetscFunctionReturn(0); 3205 } 3206 3207 /*@C 3208 PetscSectionRestorePointSyms - Restore the symmetries returned by PetscSectionGetPointSyms() 3209 3210 Not Collective 3211 3212 Input Parameters: 3213 + section - the section 3214 . numPoints - the number of points 3215 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3216 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3217 context, see DMPlexGetConeOrientation()). 3218 3219 Output Parameters: 3220 + perms - The permutations for the given orientations: set to NULL at conclusion 3221 - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion 3222 3223 Level: developer 3224 3225 .seealso: PetscSectionGetPointSyms(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym() 3226 @*/ 3227 PetscErrorCode PetscSectionRestorePointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) 3228 { 3229 PetscSectionSym sym; 3230 3231 PetscFunctionBegin; 3232 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3233 sym = section->sym; 3234 if (sym && (perms || rots)) { 3235 SymWorkLink *p,link; 3236 3237 for (p=&sym->workout; (link=*p); p=&link->next) { 3238 if ((perms && link->perms == *perms) || (rots && link->rots == *rots)) { 3239 *p = link->next; 3240 link->next = sym->workin; 3241 sym->workin = link; 3242 if (perms) *perms = NULL; 3243 if (rots) *rots = NULL; 3244 PetscFunctionReturn(0); 3245 } 3246 } 3247 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 3248 } 3249 PetscFunctionReturn(0); 3250 } 3251 3252 /*@C 3253 PetscSectionGetFieldPointSyms - Get the symmetries for a set of points in a field of a PetscSection under specific orientations. 3254 3255 Not Collective 3256 3257 Input Parameters: 3258 + section - the section 3259 . field - the field of the section 3260 . numPoints - the number of points 3261 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3262 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3263 context, see DMPlexGetConeOrientation()). 3264 3265 Output Parameters: 3266 + perms - The permutations for the given orientations (or NULL if there is no symmetry or the permutation is the identity). 3267 - rots - The field rotations symmetries for the given orientations (or NULL if there is no symmetry or the rotations are all 3268 identity). 3269 3270 Level: developer 3271 3272 .seealso: PetscSectionGetPointSyms(), PetscSectionRestoreFieldPointSyms() 3273 @*/ 3274 PetscErrorCode PetscSectionGetFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) 3275 { 3276 PetscFunctionBegin; 3277 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3278 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); 3279 PetscCall(PetscSectionGetPointSyms(section->field[field],numPoints,points,perms,rots)); 3280 PetscFunctionReturn(0); 3281 } 3282 3283 /*@C 3284 PetscSectionRestoreFieldPointSyms - Restore the symmetries returned by PetscSectionGetFieldPointSyms() 3285 3286 Not Collective 3287 3288 Input Parameters: 3289 + section - the section 3290 . field - the field number 3291 . numPoints - the number of points 3292 - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an 3293 arbitrary integer: its interpretation is up to sym. Orientations are used by DM: for their interpretation in that 3294 context, see DMPlexGetConeOrientation()). 3295 3296 Output Parameters: 3297 + perms - The permutations for the given orientations: set to NULL at conclusion 3298 - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion 3299 3300 Level: developer 3301 3302 .seealso: PetscSectionRestorePointSyms(), petscSectionGetFieldPointSyms(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym() 3303 @*/ 3304 PetscErrorCode PetscSectionRestoreFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots) 3305 { 3306 PetscFunctionBegin; 3307 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1); 3308 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); 3309 PetscCall(PetscSectionRestorePointSyms(section->field[field],numPoints,points,perms,rots)); 3310 PetscFunctionReturn(0); 3311 } 3312 3313 /*@ 3314 PetscSectionSymCopy - Copy the symmetries, assuming that the point structure is compatible 3315 3316 Not Collective 3317 3318 Input Parameter: 3319 . sym - the PetscSectionSym 3320 3321 Output Parameter: 3322 . nsym - the equivalent symmetries 3323 3324 Level: developer 3325 3326 .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms() 3327 @*/ 3328 PetscErrorCode PetscSectionSymCopy(PetscSectionSym sym, PetscSectionSym nsym) 3329 { 3330 PetscFunctionBegin; 3331 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 3332 PetscValidHeaderSpecific(nsym, PETSC_SECTION_SYM_CLASSID, 2); 3333 if (sym->ops->copy) PetscCall((*sym->ops->copy)(sym, nsym)); 3334 PetscFunctionReturn(0); 3335 } 3336 3337 /*@ 3338 PetscSectionSymDistribute - Distribute the symmetries in accordance with the input SF 3339 3340 Collective 3341 3342 Input Parameters: 3343 + sym - the PetscSectionSym 3344 - migrationSF - the distribution map from roots to leaves 3345 3346 Output Parameters: 3347 . dsym - the redistributed symmetries 3348 3349 Level: developer 3350 3351 .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms() 3352 @*/ 3353 PetscErrorCode PetscSectionSymDistribute(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym) 3354 { 3355 PetscFunctionBegin; 3356 PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1); 3357 PetscValidHeaderSpecific(migrationSF, PETSCSF_CLASSID, 2); 3358 PetscValidPointer(dsym, 3); 3359 if (sym->ops->distribute) PetscCall((*sym->ops->distribute)(sym, migrationSF, dsym)); 3360 PetscFunctionReturn(0); 3361 } 3362 3363 /*@ 3364 PetscSectionGetUseFieldOffsets - Get the flag to use field offsets directly in a global section, rather than just the point offset 3365 3366 Not Collective 3367 3368 Input Parameter: 3369 . s - the global PetscSection 3370 3371 Output Parameters: 3372 . flg - the flag 3373 3374 Level: developer 3375 3376 .seealso: PetscSectionSetChart(), PetscSectionCreate() 3377 @*/ 3378 PetscErrorCode PetscSectionGetUseFieldOffsets(PetscSection s, PetscBool *flg) 3379 { 3380 PetscFunctionBegin; 3381 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 3382 *flg = s->useFieldOff; 3383 PetscFunctionReturn(0); 3384 } 3385 3386 /*@ 3387 PetscSectionSetUseFieldOffsets - Set the flag to use field offsets directly in a global section, rather than just the point offset 3388 3389 Not Collective 3390 3391 Input Parameters: 3392 + s - the global PetscSection 3393 - flg - the flag 3394 3395 Level: developer 3396 3397 .seealso: PetscSectionGetUseFieldOffsets(), PetscSectionSetChart(), PetscSectionCreate() 3398 @*/ 3399 PetscErrorCode PetscSectionSetUseFieldOffsets(PetscSection s, PetscBool flg) 3400 { 3401 PetscFunctionBegin; 3402 PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1); 3403 s->useFieldOff = flg; 3404 PetscFunctionReturn(0); 3405 } 3406 3407 #define PetscSectionExpandPoints_Loop(TYPE) \ 3408 { \ 3409 PetscInt i, n, o0, o1, size; \ 3410 TYPE *a0 = (TYPE*)origArray, *a1; \ 3411 PetscCall(PetscSectionGetStorageSize(s, &size)); \ 3412 PetscCall(PetscMalloc1(size, &a1)); \ 3413 for (i=0; i<npoints; i++) { \ 3414 PetscCall(PetscSectionGetOffset(origSection, points_[i], &o0)); \ 3415 PetscCall(PetscSectionGetOffset(s, i, &o1)); \ 3416 PetscCall(PetscSectionGetDof(s, i, &n)); \ 3417 PetscCall(PetscMemcpy(&a1[o1], &a0[o0], n*unitsize)); \ 3418 } \ 3419 *newArray = (void*)a1; \ 3420 } 3421 3422 /*@ 3423 PetscSectionExtractDofsFromArray - Extracts elements of an array corresponding to DOFs of specified points. 3424 3425 Not Collective 3426 3427 Input Parameters: 3428 + origSection - the PetscSection describing the layout of the array 3429 . dataType - MPI_Datatype describing the data type of the array (currently only MPIU_INT, MPIU_SCALAR, MPIU_REAL) 3430 . origArray - the array; its size must be equal to the storage size of origSection 3431 - points - IS with points to extract; its indices must lie in the chart of origSection 3432 3433 Output Parameters: 3434 + newSection - the new PetscSection desribing the layout of the new array (with points renumbered 0,1,... but preserving numbers of DOFs) 3435 - newArray - the array of the extracted DOFs; its size is the storage size of newSection 3436 3437 Level: developer 3438 3439 .seealso: PetscSectionGetChart(), PetscSectionGetDof(), PetscSectionGetStorageSize(), PetscSectionCreate() 3440 @*/ 3441 PetscErrorCode PetscSectionExtractDofsFromArray(PetscSection origSection, MPI_Datatype dataType, const void *origArray, IS points, PetscSection *newSection, void *newArray[]) 3442 { 3443 PetscSection s; 3444 const PetscInt *points_; 3445 PetscInt i, n, npoints, pStart, pEnd; 3446 PetscMPIInt unitsize; 3447 3448 PetscFunctionBegin; 3449 PetscValidHeaderSpecific(origSection, PETSC_SECTION_CLASSID, 1); 3450 PetscValidPointer(origArray, 3); 3451 PetscValidHeaderSpecific(points, IS_CLASSID, 4); 3452 if (newSection) PetscValidPointer(newSection, 5); 3453 if (newArray) PetscValidPointer(newArray, 6); 3454 PetscCallMPI(MPI_Type_size(dataType, &unitsize)); 3455 PetscCall(ISGetLocalSize(points, &npoints)); 3456 PetscCall(ISGetIndices(points, &points_)); 3457 PetscCall(PetscSectionGetChart(origSection, &pStart, &pEnd)); 3458 PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 3459 PetscCall(PetscSectionSetChart(s, 0, npoints)); 3460 for (i=0; i<npoints; i++) { 3461 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); 3462 PetscCall(PetscSectionGetDof(origSection, points_[i], &n)); 3463 PetscCall(PetscSectionSetDof(s, i, n)); 3464 } 3465 PetscCall(PetscSectionSetUp(s)); 3466 if (newArray) { 3467 if (dataType == MPIU_INT) {PetscSectionExpandPoints_Loop(PetscInt);} 3468 else if (dataType == MPIU_SCALAR) {PetscSectionExpandPoints_Loop(PetscScalar);} 3469 else if (dataType == MPIU_REAL) {PetscSectionExpandPoints_Loop(PetscReal);} 3470 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "not implemented for this MPI_Datatype"); 3471 } 3472 if (newSection) { 3473 *newSection = s; 3474 } else { 3475 PetscCall(PetscSectionDestroy(&s)); 3476 } 3477 PetscCall(ISRestoreIndices(points, &points_)); 3478 PetscFunctionReturn(0); 3479 } 3480