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