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