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