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