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