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