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