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