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