1 /* Basis Jet Tabulation 2 3 We would like to tabulate the nodal basis functions and derivatives at a set of points, usually quadrature points. We 4 follow here the derviation in http://www.math.ttu.edu/~kirby/papers/fiat-toms-2004.pdf. The nodal basis $\psi_i$ can 5 be expressed in terms of a prime basis $\phi_i$ which can be stably evaluated. In PETSc, we will use the Legendre basis 6 as a prime basis. 7 8 \psi_i = \sum_k \alpha_{ki} \phi_k 9 10 Our nodal basis is defined in terms of the dual basis $n_j$ 11 12 n_j \cdot \psi_i = \delta_{ji} 13 14 and we may act on the first equation to obtain 15 16 n_j \cdot \psi_i = \sum_k \alpha_{ki} n_j \cdot \phi_k 17 \delta_{ji} = \sum_k \alpha_{ki} V_{jk} 18 I = V \alpha 19 20 so the coefficients of the nodal basis in the prime basis are 21 22 \alpha = V^{-1} 23 24 We will define the dual basis vectors $n_j$ using a quadrature rule. 25 26 Right now, we will just use the polynomial spaces P^k. I know some elements use the space of symmetric polynomials 27 (I think Nedelec), but we will neglect this for now. Constraints in the space, e.g. Arnold-Winther elements, can 28 be implemented exactly as in FIAT using functionals $L_j$. 29 30 I will have to count the degrees correctly for the Legendre product when we are on simplices. 31 32 We will have three objects: 33 - Space, P: this just need point evaluation I think 34 - Dual Space, P'+K: This looks like a set of functionals that can act on members of P, each n is defined by a Q 35 - FEM: This keeps {P, P', Q} 36 */ 37 #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 38 #include <petscdmplex.h> 39 40 PetscBool FEcite = PETSC_FALSE; 41 const char FECitation[] = "@article{kirby2004,\n" 42 " title = {Algorithm 839: FIAT, a New Paradigm for Computing Finite Element Basis Functions},\n" 43 " journal = {ACM Transactions on Mathematical Software},\n" 44 " author = {Robert C. Kirby},\n" 45 " volume = {30},\n" 46 " number = {4},\n" 47 " pages = {502--516},\n" 48 " doi = {10.1145/1039813.1039820},\n" 49 " year = {2004}\n}\n"; 50 51 PetscClassId PETSCFE_CLASSID = 0; 52 53 PetscFunctionList PetscFEList = NULL; 54 PetscBool PetscFERegisterAllCalled = PETSC_FALSE; 55 56 /*@C 57 PetscFERegister - Adds a new PetscFE implementation 58 59 Not Collective 60 61 Input Parameters: 62 + name - The name of a new user-defined creation routine 63 - create_func - The creation routine itself 64 65 Notes: 66 PetscFERegister() may be called multiple times to add several user-defined PetscFEs 67 68 Sample usage: 69 .vb 70 PetscFERegister("my_fe", MyPetscFECreate); 71 .ve 72 73 Then, your PetscFE type can be chosen with the procedural interface via 74 .vb 75 PetscFECreate(MPI_Comm, PetscFE *); 76 PetscFESetType(PetscFE, "my_fe"); 77 .ve 78 or at runtime via the option 79 .vb 80 -petscfe_type my_fe 81 .ve 82 83 Level: advanced 84 85 .seealso: PetscFERegisterAll(), PetscFERegisterDestroy() 86 87 @*/ 88 PetscErrorCode PetscFERegister(const char sname[], PetscErrorCode (*function)(PetscFE)) 89 { 90 PetscErrorCode ierr; 91 92 PetscFunctionBegin; 93 ierr = PetscFunctionListAdd(&PetscFEList, sname, function);CHKERRQ(ierr); 94 PetscFunctionReturn(0); 95 } 96 97 /*@C 98 PetscFESetType - Builds a particular PetscFE 99 100 Collective on fem 101 102 Input Parameters: 103 + fem - The PetscFE object 104 - name - The kind of FEM space 105 106 Options Database Key: 107 . -petscfe_type <type> - Sets the PetscFE type; use -help for a list of available types 108 109 Level: intermediate 110 111 .seealso: PetscFEGetType(), PetscFECreate() 112 @*/ 113 PetscErrorCode PetscFESetType(PetscFE fem, PetscFEType name) 114 { 115 PetscErrorCode (*r)(PetscFE); 116 PetscBool match; 117 PetscErrorCode ierr; 118 119 PetscFunctionBegin; 120 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 121 ierr = PetscObjectTypeCompare((PetscObject) fem, name, &match);CHKERRQ(ierr); 122 if (match) PetscFunctionReturn(0); 123 124 if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);} 125 ierr = PetscFunctionListFind(PetscFEList, name, &r);CHKERRQ(ierr); 126 if (!r) SETERRQ1(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFE type: %s", name); 127 128 if (fem->ops->destroy) { 129 ierr = (*fem->ops->destroy)(fem);CHKERRQ(ierr); 130 fem->ops->destroy = NULL; 131 } 132 ierr = (*r)(fem);CHKERRQ(ierr); 133 ierr = PetscObjectChangeTypeName((PetscObject) fem, name);CHKERRQ(ierr); 134 PetscFunctionReturn(0); 135 } 136 137 /*@C 138 PetscFEGetType - Gets the PetscFE type name (as a string) from the object. 139 140 Not Collective 141 142 Input Parameter: 143 . fem - The PetscFE 144 145 Output Parameter: 146 . name - The PetscFE type name 147 148 Level: intermediate 149 150 .seealso: PetscFESetType(), PetscFECreate() 151 @*/ 152 PetscErrorCode PetscFEGetType(PetscFE fem, PetscFEType *name) 153 { 154 PetscErrorCode ierr; 155 156 PetscFunctionBegin; 157 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 158 PetscValidPointer(name, 2); 159 if (!PetscFERegisterAllCalled) { 160 ierr = PetscFERegisterAll();CHKERRQ(ierr); 161 } 162 *name = ((PetscObject) fem)->type_name; 163 PetscFunctionReturn(0); 164 } 165 166 /*@C 167 PetscFEViewFromOptions - View from Options 168 169 Collective on PetscFE 170 171 Input Parameters: 172 + A - the PetscFE object 173 . obj - Optional object 174 - name - command line option 175 176 Level: intermediate 177 .seealso: PetscFE(), PetscFEView(), PetscObjectViewFromOptions(), PetscFECreate() 178 @*/ 179 PetscErrorCode PetscFEViewFromOptions(PetscFE A,PetscObject obj,const char name[]) 180 { 181 PetscErrorCode ierr; 182 183 PetscFunctionBegin; 184 PetscValidHeaderSpecific(A,PETSCFE_CLASSID,1); 185 ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr); 186 PetscFunctionReturn(0); 187 } 188 189 /*@C 190 PetscFEView - Views a PetscFE 191 192 Collective on fem 193 194 Input Parameter: 195 + fem - the PetscFE object to view 196 - viewer - the viewer 197 198 Level: beginner 199 200 .seealso PetscFEDestroy() 201 @*/ 202 PetscErrorCode PetscFEView(PetscFE fem, PetscViewer viewer) 203 { 204 PetscBool iascii; 205 PetscErrorCode ierr; 206 207 PetscFunctionBegin; 208 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 209 if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 210 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) fem), &viewer);CHKERRQ(ierr);} 211 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)fem, viewer);CHKERRQ(ierr); 212 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 213 if (fem->ops->view) {ierr = (*fem->ops->view)(fem, viewer);CHKERRQ(ierr);} 214 PetscFunctionReturn(0); 215 } 216 217 /*@ 218 PetscFESetFromOptions - sets parameters in a PetscFE from the options database 219 220 Collective on fem 221 222 Input Parameter: 223 . fem - the PetscFE object to set options for 224 225 Options Database: 226 + -petscfe_num_blocks - the number of cell blocks to integrate concurrently 227 - -petscfe_num_batches - the number of cell batches to integrate serially 228 229 Level: intermediate 230 231 .seealso PetscFEView() 232 @*/ 233 PetscErrorCode PetscFESetFromOptions(PetscFE fem) 234 { 235 const char *defaultType; 236 char name[256]; 237 PetscBool flg; 238 PetscErrorCode ierr; 239 240 PetscFunctionBegin; 241 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 242 if (!((PetscObject) fem)->type_name) { 243 defaultType = PETSCFEBASIC; 244 } else { 245 defaultType = ((PetscObject) fem)->type_name; 246 } 247 if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);} 248 249 ierr = PetscObjectOptionsBegin((PetscObject) fem);CHKERRQ(ierr); 250 ierr = PetscOptionsFList("-petscfe_type", "Finite element space", "PetscFESetType", PetscFEList, defaultType, name, 256, &flg);CHKERRQ(ierr); 251 if (flg) { 252 ierr = PetscFESetType(fem, name);CHKERRQ(ierr); 253 } else if (!((PetscObject) fem)->type_name) { 254 ierr = PetscFESetType(fem, defaultType);CHKERRQ(ierr); 255 } 256 ierr = PetscOptionsBoundedInt("-petscfe_num_blocks", "The number of cell blocks to integrate concurrently", "PetscSpaceSetTileSizes", fem->numBlocks, &fem->numBlocks, NULL,1);CHKERRQ(ierr); 257 ierr = PetscOptionsBoundedInt("-petscfe_num_batches", "The number of cell batches to integrate serially", "PetscSpaceSetTileSizes", fem->numBatches, &fem->numBatches, NULL,1);CHKERRQ(ierr); 258 if (fem->ops->setfromoptions) { 259 ierr = (*fem->ops->setfromoptions)(PetscOptionsObject,fem);CHKERRQ(ierr); 260 } 261 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 262 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) fem);CHKERRQ(ierr); 263 ierr = PetscOptionsEnd();CHKERRQ(ierr); 264 ierr = PetscFEViewFromOptions(fem, NULL, "-petscfe_view");CHKERRQ(ierr); 265 PetscFunctionReturn(0); 266 } 267 268 /*@C 269 PetscFESetUp - Construct data structures for the PetscFE 270 271 Collective on fem 272 273 Input Parameter: 274 . fem - the PetscFE object to setup 275 276 Level: intermediate 277 278 .seealso PetscFEView(), PetscFEDestroy() 279 @*/ 280 PetscErrorCode PetscFESetUp(PetscFE fem) 281 { 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 286 if (fem->setupcalled) PetscFunctionReturn(0); 287 fem->setupcalled = PETSC_TRUE; 288 if (fem->ops->setup) {ierr = (*fem->ops->setup)(fem);CHKERRQ(ierr);} 289 PetscFunctionReturn(0); 290 } 291 292 /*@ 293 PetscFEDestroy - Destroys a PetscFE object 294 295 Collective on fem 296 297 Input Parameter: 298 . fem - the PetscFE object to destroy 299 300 Level: beginner 301 302 .seealso PetscFEView() 303 @*/ 304 PetscErrorCode PetscFEDestroy(PetscFE *fem) 305 { 306 PetscErrorCode ierr; 307 308 PetscFunctionBegin; 309 if (!*fem) PetscFunctionReturn(0); 310 PetscValidHeaderSpecific((*fem), PETSCFE_CLASSID, 1); 311 312 if (--((PetscObject)(*fem))->refct > 0) {*fem = 0; PetscFunctionReturn(0);} 313 ((PetscObject) (*fem))->refct = 0; 314 315 if ((*fem)->subspaces) { 316 PetscInt dim, d; 317 318 ierr = PetscDualSpaceGetDimension((*fem)->dualSpace, &dim);CHKERRQ(ierr); 319 for (d = 0; d < dim; ++d) {ierr = PetscFEDestroy(&(*fem)->subspaces[d]);CHKERRQ(ierr);} 320 } 321 ierr = PetscFree((*fem)->subspaces);CHKERRQ(ierr); 322 ierr = PetscFree((*fem)->invV);CHKERRQ(ierr); 323 ierr = PetscTabulationDestroy(&(*fem)->T);CHKERRQ(ierr); 324 ierr = PetscTabulationDestroy(&(*fem)->Tf);CHKERRQ(ierr); 325 ierr = PetscTabulationDestroy(&(*fem)->Tc);CHKERRQ(ierr); 326 ierr = PetscSpaceDestroy(&(*fem)->basisSpace);CHKERRQ(ierr); 327 ierr = PetscDualSpaceDestroy(&(*fem)->dualSpace);CHKERRQ(ierr); 328 ierr = PetscQuadratureDestroy(&(*fem)->quadrature);CHKERRQ(ierr); 329 ierr = PetscQuadratureDestroy(&(*fem)->faceQuadrature);CHKERRQ(ierr); 330 331 if ((*fem)->ops->destroy) {ierr = (*(*fem)->ops->destroy)(*fem);CHKERRQ(ierr);} 332 ierr = PetscHeaderDestroy(fem);CHKERRQ(ierr); 333 PetscFunctionReturn(0); 334 } 335 336 /*@ 337 PetscFECreate - Creates an empty PetscFE object. The type can then be set with PetscFESetType(). 338 339 Collective 340 341 Input Parameter: 342 . comm - The communicator for the PetscFE object 343 344 Output Parameter: 345 . fem - The PetscFE object 346 347 Level: beginner 348 349 .seealso: PetscFESetType(), PETSCFEGALERKIN 350 @*/ 351 PetscErrorCode PetscFECreate(MPI_Comm comm, PetscFE *fem) 352 { 353 PetscFE f; 354 PetscErrorCode ierr; 355 356 PetscFunctionBegin; 357 PetscValidPointer(fem, 2); 358 ierr = PetscCitationsRegister(FECitation,&FEcite);CHKERRQ(ierr); 359 *fem = NULL; 360 ierr = PetscFEInitializePackage();CHKERRQ(ierr); 361 362 ierr = PetscHeaderCreate(f, PETSCFE_CLASSID, "PetscFE", "Finite Element", "PetscFE", comm, PetscFEDestroy, PetscFEView);CHKERRQ(ierr); 363 364 f->basisSpace = NULL; 365 f->dualSpace = NULL; 366 f->numComponents = 1; 367 f->subspaces = NULL; 368 f->invV = NULL; 369 f->T = NULL; 370 f->Tf = NULL; 371 f->Tc = NULL; 372 ierr = PetscArrayzero(&f->quadrature, 1);CHKERRQ(ierr); 373 ierr = PetscArrayzero(&f->faceQuadrature, 1);CHKERRQ(ierr); 374 f->blockSize = 0; 375 f->numBlocks = 1; 376 f->batchSize = 0; 377 f->numBatches = 1; 378 379 *fem = f; 380 PetscFunctionReturn(0); 381 } 382 383 /*@ 384 PetscFEGetSpatialDimension - Returns the spatial dimension of the element 385 386 Not collective 387 388 Input Parameter: 389 . fem - The PetscFE object 390 391 Output Parameter: 392 . dim - The spatial dimension 393 394 Level: intermediate 395 396 .seealso: PetscFECreate() 397 @*/ 398 PetscErrorCode PetscFEGetSpatialDimension(PetscFE fem, PetscInt *dim) 399 { 400 DM dm; 401 PetscErrorCode ierr; 402 403 PetscFunctionBegin; 404 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 405 PetscValidPointer(dim, 2); 406 ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); 407 ierr = DMGetDimension(dm, dim);CHKERRQ(ierr); 408 PetscFunctionReturn(0); 409 } 410 411 /*@ 412 PetscFESetNumComponents - Sets the number of components in the element 413 414 Not collective 415 416 Input Parameters: 417 + fem - The PetscFE object 418 - comp - The number of field components 419 420 Level: intermediate 421 422 .seealso: PetscFECreate() 423 @*/ 424 PetscErrorCode PetscFESetNumComponents(PetscFE fem, PetscInt comp) 425 { 426 PetscFunctionBegin; 427 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 428 fem->numComponents = comp; 429 PetscFunctionReturn(0); 430 } 431 432 /*@ 433 PetscFEGetNumComponents - Returns the number of components in the element 434 435 Not collective 436 437 Input Parameter: 438 . fem - The PetscFE object 439 440 Output Parameter: 441 . comp - The number of field components 442 443 Level: intermediate 444 445 .seealso: PetscFECreate() 446 @*/ 447 PetscErrorCode PetscFEGetNumComponents(PetscFE fem, PetscInt *comp) 448 { 449 PetscFunctionBegin; 450 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 451 PetscValidPointer(comp, 2); 452 *comp = fem->numComponents; 453 PetscFunctionReturn(0); 454 } 455 456 /*@ 457 PetscFESetTileSizes - Sets the tile sizes for evaluation 458 459 Not collective 460 461 Input Parameters: 462 + fem - The PetscFE object 463 . blockSize - The number of elements in a block 464 . numBlocks - The number of blocks in a batch 465 . batchSize - The number of elements in a batch 466 - numBatches - The number of batches in a chunk 467 468 Level: intermediate 469 470 .seealso: PetscFECreate() 471 @*/ 472 PetscErrorCode PetscFESetTileSizes(PetscFE fem, PetscInt blockSize, PetscInt numBlocks, PetscInt batchSize, PetscInt numBatches) 473 { 474 PetscFunctionBegin; 475 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 476 fem->blockSize = blockSize; 477 fem->numBlocks = numBlocks; 478 fem->batchSize = batchSize; 479 fem->numBatches = numBatches; 480 PetscFunctionReturn(0); 481 } 482 483 /*@ 484 PetscFEGetTileSizes - Returns the tile sizes for evaluation 485 486 Not collective 487 488 Input Parameter: 489 . fem - The PetscFE object 490 491 Output Parameters: 492 + blockSize - The number of elements in a block 493 . numBlocks - The number of blocks in a batch 494 . batchSize - The number of elements in a batch 495 - numBatches - The number of batches in a chunk 496 497 Level: intermediate 498 499 .seealso: PetscFECreate() 500 @*/ 501 PetscErrorCode PetscFEGetTileSizes(PetscFE fem, PetscInt *blockSize, PetscInt *numBlocks, PetscInt *batchSize, PetscInt *numBatches) 502 { 503 PetscFunctionBegin; 504 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 505 if (blockSize) PetscValidPointer(blockSize, 2); 506 if (numBlocks) PetscValidPointer(numBlocks, 3); 507 if (batchSize) PetscValidPointer(batchSize, 4); 508 if (numBatches) PetscValidPointer(numBatches, 5); 509 if (blockSize) *blockSize = fem->blockSize; 510 if (numBlocks) *numBlocks = fem->numBlocks; 511 if (batchSize) *batchSize = fem->batchSize; 512 if (numBatches) *numBatches = fem->numBatches; 513 PetscFunctionReturn(0); 514 } 515 516 /*@ 517 PetscFEGetBasisSpace - Returns the PetscSpace used for approximation of the solution 518 519 Not collective 520 521 Input Parameter: 522 . fem - The PetscFE object 523 524 Output Parameter: 525 . sp - The PetscSpace object 526 527 Level: intermediate 528 529 .seealso: PetscFECreate() 530 @*/ 531 PetscErrorCode PetscFEGetBasisSpace(PetscFE fem, PetscSpace *sp) 532 { 533 PetscFunctionBegin; 534 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 535 PetscValidPointer(sp, 2); 536 *sp = fem->basisSpace; 537 PetscFunctionReturn(0); 538 } 539 540 /*@ 541 PetscFESetBasisSpace - Sets the PetscSpace used for approximation of the solution 542 543 Not collective 544 545 Input Parameters: 546 + fem - The PetscFE object 547 - sp - The PetscSpace object 548 549 Level: intermediate 550 551 .seealso: PetscFECreate() 552 @*/ 553 PetscErrorCode PetscFESetBasisSpace(PetscFE fem, PetscSpace sp) 554 { 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 559 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 2); 560 ierr = PetscSpaceDestroy(&fem->basisSpace);CHKERRQ(ierr); 561 fem->basisSpace = sp; 562 ierr = PetscObjectReference((PetscObject) fem->basisSpace);CHKERRQ(ierr); 563 PetscFunctionReturn(0); 564 } 565 566 /*@ 567 PetscFEGetDualSpace - Returns the PetscDualSpace used to define the inner product 568 569 Not collective 570 571 Input Parameter: 572 . fem - The PetscFE object 573 574 Output Parameter: 575 . sp - The PetscDualSpace object 576 577 Level: intermediate 578 579 .seealso: PetscFECreate() 580 @*/ 581 PetscErrorCode PetscFEGetDualSpace(PetscFE fem, PetscDualSpace *sp) 582 { 583 PetscFunctionBegin; 584 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 585 PetscValidPointer(sp, 2); 586 *sp = fem->dualSpace; 587 PetscFunctionReturn(0); 588 } 589 590 /*@ 591 PetscFESetDualSpace - Sets the PetscDualSpace used to define the inner product 592 593 Not collective 594 595 Input Parameters: 596 + fem - The PetscFE object 597 - sp - The PetscDualSpace object 598 599 Level: intermediate 600 601 .seealso: PetscFECreate() 602 @*/ 603 PetscErrorCode PetscFESetDualSpace(PetscFE fem, PetscDualSpace sp) 604 { 605 PetscErrorCode ierr; 606 607 PetscFunctionBegin; 608 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 609 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2); 610 ierr = PetscDualSpaceDestroy(&fem->dualSpace);CHKERRQ(ierr); 611 fem->dualSpace = sp; 612 ierr = PetscObjectReference((PetscObject) fem->dualSpace);CHKERRQ(ierr); 613 PetscFunctionReturn(0); 614 } 615 616 /*@ 617 PetscFEGetQuadrature - Returns the PetscQuadrature used to calculate inner products 618 619 Not collective 620 621 Input Parameter: 622 . fem - The PetscFE object 623 624 Output Parameter: 625 . q - The PetscQuadrature object 626 627 Level: intermediate 628 629 .seealso: PetscFECreate() 630 @*/ 631 PetscErrorCode PetscFEGetQuadrature(PetscFE fem, PetscQuadrature *q) 632 { 633 PetscFunctionBegin; 634 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 635 PetscValidPointer(q, 2); 636 *q = fem->quadrature; 637 PetscFunctionReturn(0); 638 } 639 640 /*@ 641 PetscFESetQuadrature - Sets the PetscQuadrature used to calculate inner products 642 643 Not collective 644 645 Input Parameters: 646 + fem - The PetscFE object 647 - q - The PetscQuadrature object 648 649 Level: intermediate 650 651 .seealso: PetscFECreate() 652 @*/ 653 PetscErrorCode PetscFESetQuadrature(PetscFE fem, PetscQuadrature q) 654 { 655 PetscInt Nc, qNc; 656 PetscErrorCode ierr; 657 658 PetscFunctionBegin; 659 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 660 if (q == fem->quadrature) PetscFunctionReturn(0); 661 ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr); 662 ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr); 663 if ((qNc != 1) && (Nc != qNc)) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_SIZ, "FE components %D != Quadrature components %D and non-scalar quadrature", Nc, qNc); 664 ierr = PetscTabulationDestroy(&fem->T);CHKERRQ(ierr); 665 ierr = PetscTabulationDestroy(&fem->Tc);CHKERRQ(ierr); 666 ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr); 667 ierr = PetscQuadratureDestroy(&fem->quadrature);CHKERRQ(ierr); 668 fem->quadrature = q; 669 PetscFunctionReturn(0); 670 } 671 672 /*@ 673 PetscFEGetFaceQuadrature - Returns the PetscQuadrature used to calculate inner products on faces 674 675 Not collective 676 677 Input Parameter: 678 . fem - The PetscFE object 679 680 Output Parameter: 681 . q - The PetscQuadrature object 682 683 Level: intermediate 684 685 .seealso: PetscFECreate() 686 @*/ 687 PetscErrorCode PetscFEGetFaceQuadrature(PetscFE fem, PetscQuadrature *q) 688 { 689 PetscFunctionBegin; 690 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 691 PetscValidPointer(q, 2); 692 *q = fem->faceQuadrature; 693 PetscFunctionReturn(0); 694 } 695 696 /*@ 697 PetscFESetFaceQuadrature - Sets the PetscQuadrature used to calculate inner products on faces 698 699 Not collective 700 701 Input Parameters: 702 + fem - The PetscFE object 703 - q - The PetscQuadrature object 704 705 Level: intermediate 706 707 .seealso: PetscFECreate() 708 @*/ 709 PetscErrorCode PetscFESetFaceQuadrature(PetscFE fem, PetscQuadrature q) 710 { 711 PetscInt Nc, qNc; 712 PetscErrorCode ierr; 713 714 PetscFunctionBegin; 715 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 716 ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr); 717 ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr); 718 if ((qNc != 1) && (Nc != qNc)) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_SIZ, "FE components %D != Quadrature components %D and non-scalar quadrature", Nc, qNc); 719 ierr = PetscTabulationDestroy(&fem->Tf);CHKERRQ(ierr); 720 ierr = PetscQuadratureDestroy(&fem->faceQuadrature);CHKERRQ(ierr); 721 fem->faceQuadrature = q; 722 ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr); 723 PetscFunctionReturn(0); 724 } 725 726 /*@ 727 PetscFECopyQuadrature - Copy both volumetric and surface quadrature 728 729 Not collective 730 731 Input Parameters: 732 + sfe - The PetscFE source for the quadratures 733 - tfe - The PetscFE target for the quadratures 734 735 Level: intermediate 736 737 .seealso: PetscFECreate(), PetscFESetQuadrature(), PetscFESetFaceQuadrature() 738 @*/ 739 PetscErrorCode PetscFECopyQuadrature(PetscFE sfe, PetscFE tfe) 740 { 741 PetscQuadrature q; 742 PetscErrorCode ierr; 743 744 PetscFunctionBegin; 745 PetscValidHeaderSpecific(sfe, PETSCFE_CLASSID, 1); 746 PetscValidHeaderSpecific(tfe, PETSCFE_CLASSID, 2); 747 ierr = PetscFEGetQuadrature(sfe, &q);CHKERRQ(ierr); 748 ierr = PetscFESetQuadrature(tfe, q);CHKERRQ(ierr); 749 ierr = PetscFEGetFaceQuadrature(sfe, &q);CHKERRQ(ierr); 750 ierr = PetscFESetFaceQuadrature(tfe, q);CHKERRQ(ierr); 751 PetscFunctionReturn(0); 752 } 753 754 /*@C 755 PetscFEGetNumDof - Returns the number of dofs (dual basis vectors) associated to mesh points on the reference cell of a given dimension 756 757 Not collective 758 759 Input Parameter: 760 . fem - The PetscFE object 761 762 Output Parameter: 763 . numDof - Array with the number of dofs per dimension 764 765 Level: intermediate 766 767 .seealso: PetscFECreate() 768 @*/ 769 PetscErrorCode PetscFEGetNumDof(PetscFE fem, const PetscInt **numDof) 770 { 771 PetscErrorCode ierr; 772 773 PetscFunctionBegin; 774 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 775 PetscValidPointer(numDof, 2); 776 ierr = PetscDualSpaceGetNumDof(fem->dualSpace, numDof);CHKERRQ(ierr); 777 PetscFunctionReturn(0); 778 } 779 780 /*@C 781 PetscFEGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points on the reference cell 782 783 Not collective 784 785 Input Parameter: 786 . fem - The PetscFE object 787 788 Output Parameter: 789 . T - The basis function values and derivatives at quadrature points 790 791 Note: 792 $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 793 $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 794 $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e 795 796 Level: intermediate 797 798 .seealso: PetscFECreateTabulation(), PetscTabulationDestroy() 799 @*/ 800 PetscErrorCode PetscFEGetCellTabulation(PetscFE fem, PetscTabulation *T) 801 { 802 PetscInt npoints; 803 const PetscReal *points; 804 PetscErrorCode ierr; 805 806 PetscFunctionBegin; 807 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 808 PetscValidPointer(T, 2); 809 ierr = PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr); 810 if (!fem->T) {ierr = PetscFECreateTabulation(fem, 1, npoints, points, 1, &fem->T);CHKERRQ(ierr);} 811 *T = fem->T; 812 PetscFunctionReturn(0); 813 } 814 815 /*@C 816 PetscFEGetFaceTabulation - Returns the tabulation of the basis functions at the face quadrature points for each face of the reference cell 817 818 Not collective 819 820 Input Parameter: 821 . fem - The PetscFE object 822 823 Output Parameters: 824 . Tf - The basis function values and derviatives at face quadrature points 825 826 Note: 827 $ T->T[0] = Bf[((f*Nq + q)*pdim + i)*Nc + c] is the value at point f,q for basis function i and component c 828 $ T->T[1] = Df[(((f*Nq + q)*pdim + i)*Nc + c)*dim + d] is the derivative value at point f,q for basis function i, component c, in direction d 829 $ T->T[2] = Hf[((((f*Nq + q)*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point f,q for basis function i, component c, in directions d and e 830 831 Level: intermediate 832 833 .seealso: PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy() 834 @*/ 835 PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscTabulation *Tf) 836 { 837 PetscErrorCode ierr; 838 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 841 PetscValidPointer(Tf, 2); 842 if (!fem->Tf) { 843 const PetscReal xi0[3] = {-1., -1., -1.}; 844 PetscReal v0[3], J[9], detJ; 845 PetscQuadrature fq; 846 PetscDualSpace sp; 847 DM dm; 848 const PetscInt *faces; 849 PetscInt dim, numFaces, f, npoints, q; 850 const PetscReal *points; 851 PetscReal *facePoints; 852 853 ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr); 854 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 855 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 856 ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr); 857 ierr = DMPlexGetCone(dm, 0, &faces);CHKERRQ(ierr); 858 ierr = PetscFEGetFaceQuadrature(fem, &fq);CHKERRQ(ierr); 859 if (fq) { 860 ierr = PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr); 861 ierr = PetscMalloc1(numFaces*npoints*dim, &facePoints);CHKERRQ(ierr); 862 for (f = 0; f < numFaces; ++f) { 863 ierr = DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 864 for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]); 865 } 866 ierr = PetscFECreateTabulation(fem, numFaces, npoints, facePoints, 1, &fem->Tf);CHKERRQ(ierr); 867 ierr = PetscFree(facePoints);CHKERRQ(ierr); 868 } 869 } 870 *Tf = fem->Tf; 871 PetscFunctionReturn(0); 872 } 873 874 /*@C 875 PetscFEGetFaceCentroidTabulation - Returns the tabulation of the basis functions at the face centroid points 876 877 Not collective 878 879 Input Parameter: 880 . fem - The PetscFE object 881 882 Output Parameters: 883 . Tc - The basis function values at face centroid points 884 885 Note: 886 $ T->T[0] = Bf[(f*pdim + i)*Nc + c] is the value at point f for basis function i and component c 887 888 Level: intermediate 889 890 .seealso: PetscFEGetFaceTabulation(), PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy() 891 @*/ 892 PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscTabulation *Tc) 893 { 894 PetscErrorCode ierr; 895 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 898 PetscValidPointer(Tc, 2); 899 if (!fem->Tc) { 900 PetscDualSpace sp; 901 DM dm; 902 const PetscInt *cone; 903 PetscReal *centroids; 904 PetscInt dim, numFaces, f; 905 906 ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr); 907 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 908 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 909 ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr); 910 ierr = DMPlexGetCone(dm, 0, &cone);CHKERRQ(ierr); 911 ierr = PetscMalloc1(numFaces*dim, ¢roids);CHKERRQ(ierr); 912 for (f = 0; f < numFaces; ++f) {ierr = DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, ¢roids[f*dim], NULL);CHKERRQ(ierr);} 913 ierr = PetscFECreateTabulation(fem, 1, numFaces, centroids, 0, &fem->Tc);CHKERRQ(ierr); 914 ierr = PetscFree(centroids);CHKERRQ(ierr); 915 } 916 *Tc = fem->Tc; 917 PetscFunctionReturn(0); 918 } 919 920 /*@C 921 PetscFECreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided. 922 923 Not collective 924 925 Input Parameters: 926 + fem - The PetscFE object 927 . nrepl - The number of replicas 928 . npoints - The number of tabulation points in a replica 929 . points - The tabulation point coordinates 930 - K - The number of derivatives calculated 931 932 Output Parameter: 933 . T - The basis function values and derivatives at tabulation points 934 935 Note: 936 $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 937 $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 938 $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e 939 940 Level: intermediate 941 942 .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy() 943 @*/ 944 PetscErrorCode PetscFECreateTabulation(PetscFE fem, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T) 945 { 946 DM dm; 947 PetscDualSpace Q; 948 PetscInt Nb; /* Dimension of FE space P */ 949 PetscInt Nc; /* Field components */ 950 PetscInt cdim; /* Reference coordinate dimension */ 951 PetscInt k; 952 PetscErrorCode ierr; 953 954 PetscFunctionBegin; 955 if (!npoints || !fem->dualSpace || K < 0) { 956 *T = NULL; 957 PetscFunctionReturn(0); 958 } 959 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 960 PetscValidPointer(points, 4); 961 PetscValidPointer(T, 6); 962 ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr); 963 ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr); 964 ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr); 965 ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr); 966 ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr); 967 ierr = PetscMalloc1(1, T);CHKERRQ(ierr); 968 (*T)->K = !cdim ? 0 : K; 969 (*T)->Nr = nrepl; 970 (*T)->Np = npoints; 971 (*T)->Nb = Nb; 972 (*T)->Nc = Nc; 973 (*T)->cdim = cdim; 974 ierr = PetscMalloc1((*T)->K+1, &(*T)->T);CHKERRQ(ierr); 975 for (k = 0; k <= (*T)->K; ++k) { 976 ierr = PetscMalloc1(nrepl*npoints*Nb*Nc*PetscPowInt(cdim, k), &(*T)->T[k]);CHKERRQ(ierr); 977 } 978 ierr = (*fem->ops->createtabulation)(fem, nrepl*npoints, points, K, *T);CHKERRQ(ierr); 979 PetscFunctionReturn(0); 980 } 981 982 /*@C 983 PetscFEComputeTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided. 984 985 Not collective 986 987 Input Parameters: 988 + fem - The PetscFE object 989 . npoints - The number of tabulation points 990 . points - The tabulation point coordinates 991 . K - The number of derivatives calculated 992 - T - An existing tabulation object with enough allocated space 993 994 Output Parameter: 995 . T - The basis function values and derivatives at tabulation points 996 997 Note: 998 $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 999 $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 1000 $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e 1001 1002 Level: intermediate 1003 1004 .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy() 1005 @*/ 1006 PetscErrorCode PetscFEComputeTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T) 1007 { 1008 PetscErrorCode ierr; 1009 1010 PetscFunctionBeginHot; 1011 if (!npoints || !fem->dualSpace || K < 0) PetscFunctionReturn(0); 1012 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1013 PetscValidPointer(points, 3); 1014 PetscValidPointer(T, 5); 1015 #ifdef PETSC_USE_DEBUG 1016 { 1017 DM dm; 1018 PetscDualSpace Q; 1019 PetscInt Nb; /* Dimension of FE space P */ 1020 PetscInt Nc; /* Field components */ 1021 PetscInt cdim; /* Reference coordinate dimension */ 1022 1023 ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr); 1024 ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr); 1025 ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr); 1026 ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr); 1027 ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr); 1028 if (T->K != (!cdim ? 0 : K)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation K %D must match requested K %D", T->K, !cdim ? 0 : K); 1029 if (T->Nb != Nb) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation Nb %D must match requested Nb %D", T->Nb, Nb); 1030 if (T->Nc != Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation Nc %D must match requested Nc %D", T->Nc, Nc); 1031 if (T->cdim != cdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation cdim %D must match requested cdim %D", T->cdim, cdim); 1032 } 1033 #endif 1034 T->Nr = 1; 1035 T->Np = npoints; 1036 ierr = (*fem->ops->createtabulation)(fem, npoints, points, K, T);CHKERRQ(ierr); 1037 PetscFunctionReturn(0); 1038 } 1039 1040 /*@C 1041 PetscTabulationDestroy - Frees memory from the associated tabulation. 1042 1043 Not collective 1044 1045 Input Parameter: 1046 . T - The tabulation 1047 1048 Level: intermediate 1049 1050 .seealso: PetscFECreateTabulation(), PetscFEGetCellTabulation() 1051 @*/ 1052 PetscErrorCode PetscTabulationDestroy(PetscTabulation *T) 1053 { 1054 PetscInt k; 1055 PetscErrorCode ierr; 1056 1057 PetscFunctionBegin; 1058 PetscValidPointer(T, 1); 1059 if (!T || !(*T)) PetscFunctionReturn(0); 1060 for (k = 0; k <= (*T)->K; ++k) {ierr = PetscFree((*T)->T[k]);CHKERRQ(ierr);} 1061 ierr = PetscFree((*T)->T);CHKERRQ(ierr); 1062 ierr = PetscFree(*T);CHKERRQ(ierr); 1063 *T = NULL; 1064 PetscFunctionReturn(0); 1065 } 1066 1067 PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE) 1068 { 1069 PetscSpace bsp, bsubsp; 1070 PetscDualSpace dsp, dsubsp; 1071 PetscInt dim, depth, numComp, i, j, coneSize, order; 1072 PetscFEType type; 1073 DM dm; 1074 DMLabel label; 1075 PetscReal *xi, *v, *J, detJ; 1076 const char *name; 1077 PetscQuadrature origin, fullQuad, subQuad; 1078 PetscErrorCode ierr; 1079 1080 PetscFunctionBegin; 1081 PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1); 1082 PetscValidPointer(trFE,3); 1083 ierr = PetscFEGetBasisSpace(fe,&bsp);CHKERRQ(ierr); 1084 ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 1085 ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr); 1086 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 1087 ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr); 1088 ierr = DMLabelGetValue(label,refPoint,&depth);CHKERRQ(ierr); 1089 ierr = PetscCalloc1(depth,&xi);CHKERRQ(ierr); 1090 ierr = PetscMalloc1(dim,&v);CHKERRQ(ierr); 1091 ierr = PetscMalloc1(dim*dim,&J);CHKERRQ(ierr); 1092 for (i = 0; i < depth; i++) xi[i] = 0.; 1093 ierr = PetscQuadratureCreate(PETSC_COMM_SELF,&origin);CHKERRQ(ierr); 1094 ierr = PetscQuadratureSetData(origin,depth,0,1,xi,NULL);CHKERRQ(ierr); 1095 ierr = DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);CHKERRQ(ierr); 1096 /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */ 1097 for (i = 1; i < dim; i++) { 1098 for (j = 0; j < depth; j++) { 1099 J[i * depth + j] = J[i * dim + j]; 1100 } 1101 } 1102 ierr = PetscQuadratureDestroy(&origin);CHKERRQ(ierr); 1103 ierr = PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);CHKERRQ(ierr); 1104 ierr = PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);CHKERRQ(ierr); 1105 ierr = PetscSpaceSetUp(bsubsp);CHKERRQ(ierr); 1106 ierr = PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);CHKERRQ(ierr); 1107 ierr = PetscFEGetType(fe,&type);CHKERRQ(ierr); 1108 ierr = PetscFESetType(*trFE,type);CHKERRQ(ierr); 1109 ierr = PetscFEGetNumComponents(fe,&numComp);CHKERRQ(ierr); 1110 ierr = PetscFESetNumComponents(*trFE,numComp);CHKERRQ(ierr); 1111 ierr = PetscFESetBasisSpace(*trFE,bsubsp);CHKERRQ(ierr); 1112 ierr = PetscFESetDualSpace(*trFE,dsubsp);CHKERRQ(ierr); 1113 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 1114 if (name) {ierr = PetscFESetName(*trFE, name);CHKERRQ(ierr);} 1115 ierr = PetscFEGetQuadrature(fe,&fullQuad);CHKERRQ(ierr); 1116 ierr = PetscQuadratureGetOrder(fullQuad,&order);CHKERRQ(ierr); 1117 ierr = DMPlexGetConeSize(dm,refPoint,&coneSize);CHKERRQ(ierr); 1118 if (coneSize == 2 * depth) { 1119 ierr = PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr); 1120 } else { 1121 ierr = PetscDTStroudConicalQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr); 1122 } 1123 ierr = PetscFESetQuadrature(*trFE,subQuad);CHKERRQ(ierr); 1124 ierr = PetscFESetUp(*trFE);CHKERRQ(ierr); 1125 ierr = PetscQuadratureDestroy(&subQuad);CHKERRQ(ierr); 1126 ierr = PetscSpaceDestroy(&bsubsp);CHKERRQ(ierr); 1127 PetscFunctionReturn(0); 1128 } 1129 1130 PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE) 1131 { 1132 PetscInt hStart, hEnd; 1133 PetscDualSpace dsp; 1134 DM dm; 1135 PetscErrorCode ierr; 1136 1137 PetscFunctionBegin; 1138 PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1); 1139 PetscValidPointer(trFE,3); 1140 *trFE = NULL; 1141 ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 1142 ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr); 1143 ierr = DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);CHKERRQ(ierr); 1144 if (hEnd <= hStart) PetscFunctionReturn(0); 1145 ierr = PetscFECreatePointTrace(fe,hStart,trFE);CHKERRQ(ierr); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 1150 /*@ 1151 PetscFEGetDimension - Get the dimension of the finite element space on a cell 1152 1153 Not collective 1154 1155 Input Parameter: 1156 . fe - The PetscFE 1157 1158 Output Parameter: 1159 . dim - The dimension 1160 1161 Level: intermediate 1162 1163 .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension() 1164 @*/ 1165 PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim) 1166 { 1167 PetscErrorCode ierr; 1168 1169 PetscFunctionBegin; 1170 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1171 PetscValidPointer(dim, 2); 1172 if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);} 1173 PetscFunctionReturn(0); 1174 } 1175 1176 /*@C 1177 PetscFEPushforward - Map the reference element function to real space 1178 1179 Input Parameters: 1180 + fe - The PetscFE 1181 . fegeom - The cell geometry 1182 . Nv - The number of function values 1183 - vals - The function values 1184 1185 Output Parameter: 1186 . vals - The transformed function values 1187 1188 Level: advanced 1189 1190 Note: This just forwards the call onto PetscDualSpacePushforward(). 1191 1192 Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1193 1194 .seealso: PetscDualSpacePushforward() 1195 @*/ 1196 PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[]) 1197 { 1198 PetscErrorCode ierr; 1199 1200 PetscFunctionBeginHot; 1201 ierr = PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr); 1202 PetscFunctionReturn(0); 1203 } 1204 1205 /*@C 1206 PetscFEPushforwardGradient - Map the reference element function gradient to real space 1207 1208 Input Parameters: 1209 + fe - The PetscFE 1210 . fegeom - The cell geometry 1211 . Nv - The number of function gradient values 1212 - vals - The function gradient values 1213 1214 Output Parameter: 1215 . vals - The transformed function gradient values 1216 1217 Level: advanced 1218 1219 Note: This just forwards the call onto PetscDualSpacePushforwardGradient(). 1220 1221 Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1222 1223 .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward() 1224 @*/ 1225 PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[]) 1226 { 1227 PetscErrorCode ierr; 1228 1229 PetscFunctionBeginHot; 1230 ierr = PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr); 1231 PetscFunctionReturn(0); 1232 } 1233 1234 /* 1235 Purpose: Compute element vector for chunk of elements 1236 1237 Input: 1238 Sizes: 1239 Ne: number of elements 1240 Nf: number of fields 1241 PetscFE 1242 dim: spatial dimension 1243 Nb: number of basis functions 1244 Nc: number of field components 1245 PetscQuadrature 1246 Nq: number of quadrature points 1247 1248 Geometry: 1249 PetscFEGeom[Ne] possibly *Nq 1250 PetscReal v0s[dim] 1251 PetscReal n[dim] 1252 PetscReal jacobians[dim*dim] 1253 PetscReal jacobianInverses[dim*dim] 1254 PetscReal jacobianDeterminants 1255 FEM: 1256 PetscFE 1257 PetscQuadrature 1258 PetscReal quadPoints[Nq*dim] 1259 PetscReal quadWeights[Nq] 1260 PetscReal basis[Nq*Nb*Nc] 1261 PetscReal basisDer[Nq*Nb*Nc*dim] 1262 PetscScalar coefficients[Ne*Nb*Nc] 1263 PetscScalar elemVec[Ne*Nb*Nc] 1264 1265 Problem: 1266 PetscInt f: the active field 1267 f0, f1 1268 1269 Work Space: 1270 PetscFE 1271 PetscScalar f0[Nq*dim]; 1272 PetscScalar f1[Nq*dim*dim]; 1273 PetscScalar u[Nc]; 1274 PetscScalar gradU[Nc*dim]; 1275 PetscReal x[dim]; 1276 PetscScalar realSpaceDer[dim]; 1277 1278 Purpose: Compute element vector for N_cb batches of elements 1279 1280 Input: 1281 Sizes: 1282 N_cb: Number of serial cell batches 1283 1284 Geometry: 1285 PetscReal v0s[Ne*dim] 1286 PetscReal jacobians[Ne*dim*dim] possibly *Nq 1287 PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq 1288 PetscReal jacobianDeterminants[Ne] possibly *Nq 1289 FEM: 1290 static PetscReal quadPoints[Nq*dim] 1291 static PetscReal quadWeights[Nq] 1292 static PetscReal basis[Nq*Nb*Nc] 1293 static PetscReal basisDer[Nq*Nb*Nc*dim] 1294 PetscScalar coefficients[Ne*Nb*Nc] 1295 PetscScalar elemVec[Ne*Nb*Nc] 1296 1297 ex62.c: 1298 PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[], 1299 const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], 1300 void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]), 1301 void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[]) 1302 1303 ex52.c: 1304 PetscErrorCode IntegrateLaplacianBatchCPU(PetscInt Ne, PetscInt Nb, const PetscScalar coefficients[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscInt Nq, const PetscReal quadPoints[], const PetscReal quadWeights[], const PetscReal basisTabulation[], const PetscReal basisDerTabulation[], PetscScalar elemVec[], AppCtx *user) 1305 PetscErrorCode IntegrateElasticityBatchCPU(PetscInt Ne, PetscInt Nb, PetscInt Ncomp, const PetscScalar coefficients[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscInt Nq, const PetscReal quadPoints[], const PetscReal quadWeights[], const PetscReal basisTabulation[], const PetscReal basisDerTabulation[], PetscScalar elemVec[], AppCtx *user) 1306 1307 ex52_integrateElement.cu 1308 __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec) 1309 1310 PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[], 1311 const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[], 1312 PetscLogEvent event, PetscInt debug, PetscInt pde_op) 1313 1314 ex52_integrateElementOpenCL.c: 1315 PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[], 1316 const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[], 1317 PetscLogEvent event, PetscInt debug, PetscInt pde_op) 1318 1319 __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec) 1320 */ 1321 1322 /*@C 1323 PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration 1324 1325 Not collective 1326 1327 Input Parameters: 1328 + fem - The PetscFE object for the field being integrated 1329 . prob - The PetscDS specifying the discretizations and continuum functions 1330 . field - The field being integrated 1331 . Ne - The number of elements in the chunk 1332 . cgeom - The cell geometry for each cell in the chunk 1333 . coefficients - The array of FEM basis coefficients for the elements 1334 . probAux - The PetscDS specifying the auxiliary discretizations 1335 - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1336 1337 Output Parameter: 1338 . integral - the integral for this field 1339 1340 Level: intermediate 1341 1342 .seealso: PetscFEIntegrateResidual() 1343 @*/ 1344 PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom, 1345 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 1346 { 1347 PetscFE fe; 1348 PetscErrorCode ierr; 1349 1350 PetscFunctionBegin; 1351 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1352 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1353 if (fe->ops->integrate) {ierr = (*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);} 1354 PetscFunctionReturn(0); 1355 } 1356 1357 /*@C 1358 PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration 1359 1360 Not collective 1361 1362 Input Parameters: 1363 + fem - The PetscFE object for the field being integrated 1364 . prob - The PetscDS specifying the discretizations and continuum functions 1365 . field - The field being integrated 1366 . obj_func - The function to be integrated 1367 . Ne - The number of elements in the chunk 1368 . fgeom - The face geometry for each face in the chunk 1369 . coefficients - The array of FEM basis coefficients for the elements 1370 . probAux - The PetscDS specifying the auxiliary discretizations 1371 - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1372 1373 Output Parameter: 1374 . integral - the integral for this field 1375 1376 Level: intermediate 1377 1378 .seealso: PetscFEIntegrateResidual() 1379 @*/ 1380 PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field, 1381 void (*obj_func)(PetscInt, PetscInt, PetscInt, 1382 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 1383 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 1384 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 1385 PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 1386 { 1387 PetscFE fe; 1388 PetscErrorCode ierr; 1389 1390 PetscFunctionBegin; 1391 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1392 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1393 if (fe->ops->integratebd) {ierr = (*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);} 1394 PetscFunctionReturn(0); 1395 } 1396 1397 /*@C 1398 PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration 1399 1400 Not collective 1401 1402 Input Parameters: 1403 + fem - The PetscFE object for the field being integrated 1404 . prob - The PetscDS specifying the discretizations and continuum functions 1405 . field - The field being integrated 1406 . Ne - The number of elements in the chunk 1407 . cgeom - The cell geometry for each cell in the chunk 1408 . coefficients - The array of FEM basis coefficients for the elements 1409 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1410 . probAux - The PetscDS specifying the auxiliary discretizations 1411 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1412 - t - The time 1413 1414 Output Parameter: 1415 . elemVec - the element residual vectors from each element 1416 1417 Note: 1418 $ Loop over batch of elements (e): 1419 $ Loop over quadrature points (q): 1420 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q 1421 $ Call f_0 and f_1 1422 $ Loop over element vector entries (f,fc --> i): 1423 $ elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u) 1424 1425 Level: intermediate 1426 1427 .seealso: PetscFEIntegrateResidual() 1428 @*/ 1429 PetscErrorCode PetscFEIntegrateResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom, 1430 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 1431 { 1432 PetscFE fe; 1433 PetscErrorCode ierr; 1434 1435 PetscFunctionBegin; 1436 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1437 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1438 if (fe->ops->integrateresidual) {ierr = (*fe->ops->integrateresidual)(prob, field, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);} 1439 PetscFunctionReturn(0); 1440 } 1441 1442 /*@C 1443 PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary 1444 1445 Not collective 1446 1447 Input Parameters: 1448 + fem - The PetscFE object for the field being integrated 1449 . prob - The PetscDS specifying the discretizations and continuum functions 1450 . field - The field being integrated 1451 . Ne - The number of elements in the chunk 1452 . fgeom - The face geometry for each cell in the chunk 1453 . coefficients - The array of FEM basis coefficients for the elements 1454 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1455 . probAux - The PetscDS specifying the auxiliary discretizations 1456 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1457 - t - The time 1458 1459 Output Parameter: 1460 . elemVec - the element residual vectors from each element 1461 1462 Level: intermediate 1463 1464 .seealso: PetscFEIntegrateResidual() 1465 @*/ 1466 PetscErrorCode PetscFEIntegrateBdResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom, 1467 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 1468 { 1469 PetscFE fe; 1470 PetscErrorCode ierr; 1471 1472 PetscFunctionBegin; 1473 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1474 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1475 if (fe->ops->integratebdresidual) {ierr = (*fe->ops->integratebdresidual)(prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);} 1476 PetscFunctionReturn(0); 1477 } 1478 1479 /*@C 1480 PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration 1481 1482 Not collective 1483 1484 Input Parameters: 1485 + fem - The PetscFE object for the field being integrated 1486 . prob - The PetscDS specifying the discretizations and continuum functions 1487 . jtype - The type of matrix pointwise functions that should be used 1488 . fieldI - The test field being integrated 1489 . fieldJ - The basis field being integrated 1490 . Ne - The number of elements in the chunk 1491 . cgeom - The cell geometry for each cell in the chunk 1492 . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point 1493 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1494 . probAux - The PetscDS specifying the auxiliary discretizations 1495 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1496 . t - The time 1497 - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term) 1498 1499 Output Parameter: 1500 . elemMat - the element matrices for the Jacobian from each element 1501 1502 Note: 1503 $ Loop over batch of elements (e): 1504 $ Loop over element matrix entries (f,fc,g,gc --> i,j): 1505 $ Loop over quadrature points (q): 1506 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) 1507 $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q) 1508 $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1509 $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q) 1510 $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1511 Level: intermediate 1512 1513 .seealso: PetscFEIntegrateResidual() 1514 @*/ 1515 PetscErrorCode PetscFEIntegrateJacobian(PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom, 1516 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 1517 { 1518 PetscFE fe; 1519 PetscErrorCode ierr; 1520 1521 PetscFunctionBegin; 1522 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1523 ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 1524 if (fe->ops->integratejacobian) {ierr = (*fe->ops->integratejacobian)(prob, jtype, fieldI, fieldJ, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);} 1525 PetscFunctionReturn(0); 1526 } 1527 1528 /*@C 1529 PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration 1530 1531 Not collective 1532 1533 Input Parameters: 1534 + prob - The PetscDS specifying the discretizations and continuum functions 1535 . fieldI - The test field being integrated 1536 . fieldJ - The basis field being integrated 1537 . Ne - The number of elements in the chunk 1538 . fgeom - The face geometry for each cell in the chunk 1539 . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point 1540 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1541 . probAux - The PetscDS specifying the auxiliary discretizations 1542 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1543 . t - The time 1544 - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term) 1545 1546 Output Parameter: 1547 . elemMat - the element matrices for the Jacobian from each element 1548 1549 Note: 1550 $ Loop over batch of elements (e): 1551 $ Loop over element matrix entries (f,fc,g,gc --> i,j): 1552 $ Loop over quadrature points (q): 1553 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) 1554 $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q) 1555 $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1556 $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q) 1557 $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1558 Level: intermediate 1559 1560 .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual() 1561 @*/ 1562 PetscErrorCode PetscFEIntegrateBdJacobian(PetscDS prob, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom, 1563 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 1564 { 1565 PetscFE fe; 1566 PetscErrorCode ierr; 1567 1568 PetscFunctionBegin; 1569 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1570 ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 1571 if (fe->ops->integratebdjacobian) {ierr = (*fe->ops->integratebdjacobian)(prob, fieldI, fieldJ, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);} 1572 PetscFunctionReturn(0); 1573 } 1574 1575 /*@ 1576 PetscFEGetHeightSubspace - Get the subspace of this space for a mesh point of a given height 1577 1578 Input Parameters: 1579 + fe - The finite element space 1580 - height - The height of the Plex point 1581 1582 Output Parameter: 1583 . subfe - The subspace of this FE space 1584 1585 Note: For example, if we want the subspace of this space for a face, we would choose height = 1. 1586 1587 Level: advanced 1588 1589 .seealso: PetscFECreateDefault() 1590 @*/ 1591 PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe) 1592 { 1593 PetscSpace P, subP; 1594 PetscDualSpace Q, subQ; 1595 PetscQuadrature subq; 1596 PetscFEType fetype; 1597 PetscInt dim, Nc; 1598 PetscErrorCode ierr; 1599 1600 PetscFunctionBegin; 1601 PetscValidHeaderSpecific(fe, PETSCFE_CLASSID, 1); 1602 PetscValidPointer(subfe, 3); 1603 if (height == 0) { 1604 *subfe = fe; 1605 PetscFunctionReturn(0); 1606 } 1607 ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr); 1608 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1609 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1610 ierr = PetscFEGetFaceQuadrature(fe, &subq);CHKERRQ(ierr); 1611 ierr = PetscDualSpaceGetDimension(Q, &dim);CHKERRQ(ierr); 1612 if (height > dim || height < 0) {SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %D for dimension %D space", height, dim);} 1613 if (!fe->subspaces) {ierr = PetscCalloc1(dim, &fe->subspaces);CHKERRQ(ierr);} 1614 if (height <= dim) { 1615 if (!fe->subspaces[height-1]) { 1616 PetscFE sub; 1617 const char *name; 1618 1619 ierr = PetscSpaceGetHeightSubspace(P, height, &subP);CHKERRQ(ierr); 1620 ierr = PetscDualSpaceGetHeightSubspace(Q, height, &subQ);CHKERRQ(ierr); 1621 ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);CHKERRQ(ierr); 1622 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 1623 ierr = PetscObjectSetName((PetscObject) sub, name);CHKERRQ(ierr); 1624 ierr = PetscFEGetType(fe, &fetype);CHKERRQ(ierr); 1625 ierr = PetscFESetType(sub, fetype);CHKERRQ(ierr); 1626 ierr = PetscFESetBasisSpace(sub, subP);CHKERRQ(ierr); 1627 ierr = PetscFESetDualSpace(sub, subQ);CHKERRQ(ierr); 1628 ierr = PetscFESetNumComponents(sub, Nc);CHKERRQ(ierr); 1629 ierr = PetscFESetUp(sub);CHKERRQ(ierr); 1630 ierr = PetscFESetQuadrature(sub, subq);CHKERRQ(ierr); 1631 fe->subspaces[height-1] = sub; 1632 } 1633 *subfe = fe->subspaces[height-1]; 1634 } else { 1635 *subfe = NULL; 1636 } 1637 PetscFunctionReturn(0); 1638 } 1639 1640 /*@ 1641 PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used 1642 to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more 1643 sparsity). It is also used to create an interpolation between regularly refined meshes. 1644 1645 Collective on fem 1646 1647 Input Parameter: 1648 . fe - The initial PetscFE 1649 1650 Output Parameter: 1651 . feRef - The refined PetscFE 1652 1653 Level: advanced 1654 1655 .seealso: PetscFEType, PetscFECreate(), PetscFESetType() 1656 @*/ 1657 PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef) 1658 { 1659 PetscSpace P, Pref; 1660 PetscDualSpace Q, Qref; 1661 DM K, Kref; 1662 PetscQuadrature q, qref; 1663 const PetscReal *v0, *jac; 1664 PetscInt numComp, numSubelements; 1665 PetscInt cStart, cEnd, c; 1666 PetscDualSpace *cellSpaces; 1667 PetscErrorCode ierr; 1668 1669 PetscFunctionBegin; 1670 ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr); 1671 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1672 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 1673 ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr); 1674 /* Create space */ 1675 ierr = PetscObjectReference((PetscObject) P);CHKERRQ(ierr); 1676 Pref = P; 1677 /* Create dual space */ 1678 ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr); 1679 ierr = PetscDualSpaceSetType(Qref, PETSCDUALSPACEREFINED);CHKERRQ(ierr); 1680 ierr = DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);CHKERRQ(ierr); 1681 ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr); 1682 ierr = DMPlexGetHeightStratum(Kref, 0, &cStart, &cEnd);CHKERRQ(ierr); 1683 ierr = PetscMalloc1(cEnd - cStart, &cellSpaces);CHKERRQ(ierr); 1684 /* TODO: fix for non-uniform refinement */ 1685 for (c = 0; c < cEnd - cStart; c++) cellSpaces[c] = Q; 1686 ierr = PetscDualSpaceRefinedSetCellSpaces(Qref, cellSpaces);CHKERRQ(ierr); 1687 ierr = PetscFree(cellSpaces);CHKERRQ(ierr); 1688 ierr = DMDestroy(&Kref);CHKERRQ(ierr); 1689 ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr); 1690 /* Create element */ 1691 ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);CHKERRQ(ierr); 1692 ierr = PetscFESetType(*feRef, PETSCFECOMPOSITE);CHKERRQ(ierr); 1693 ierr = PetscFESetBasisSpace(*feRef, Pref);CHKERRQ(ierr); 1694 ierr = PetscFESetDualSpace(*feRef, Qref);CHKERRQ(ierr); 1695 ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 1696 ierr = PetscFESetNumComponents(*feRef, numComp);CHKERRQ(ierr); 1697 ierr = PetscFESetUp(*feRef);CHKERRQ(ierr); 1698 ierr = PetscSpaceDestroy(&Pref);CHKERRQ(ierr); 1699 ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr); 1700 /* Create quadrature */ 1701 ierr = PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);CHKERRQ(ierr); 1702 ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr); 1703 ierr = PetscFESetQuadrature(*feRef, qref);CHKERRQ(ierr); 1704 ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr); 1705 PetscFunctionReturn(0); 1706 } 1707 1708 /*@C 1709 PetscFECreateDefault - Create a PetscFE for basic FEM computation 1710 1711 Collective 1712 1713 Input Parameters: 1714 + comm - The MPI comm 1715 . dim - The spatial dimension 1716 . Nc - The number of components 1717 . isSimplex - Flag for simplex reference cell, otherwise its a tensor product 1718 . prefix - The options prefix, or NULL 1719 - qorder - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree 1720 1721 Output Parameter: 1722 . fem - The PetscFE object 1723 1724 Note: 1725 Each object is SetFromOption() during creation, so that the object may be customized from the command line. 1726 1727 Level: beginner 1728 1729 .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate() 1730 @*/ 1731 PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem) 1732 { 1733 PetscQuadrature q, fq; 1734 DM K; 1735 PetscSpace P; 1736 PetscDualSpace Q; 1737 PetscInt order, quadPointsPerEdge; 1738 PetscBool tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1739 PetscErrorCode ierr; 1740 1741 PetscFunctionBegin; 1742 /* Create space */ 1743 ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr); 1744 ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr); 1745 ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr); 1746 ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr); 1747 ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr); 1748 ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr); 1749 ierr = PetscSpaceSetUp(P);CHKERRQ(ierr); 1750 ierr = PetscSpaceGetDegree(P, &order, NULL);CHKERRQ(ierr); 1751 ierr = PetscSpacePolynomialGetTensor(P, &tensor);CHKERRQ(ierr); 1752 /* Create dual space */ 1753 ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr); 1754 ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr); 1755 ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr); 1756 ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr); 1757 ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr); 1758 ierr = DMDestroy(&K);CHKERRQ(ierr); 1759 ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr); 1760 ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr); 1761 ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr); 1762 ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr); 1763 ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr); 1764 /* Create element */ 1765 ierr = PetscFECreate(comm, fem);CHKERRQ(ierr); 1766 ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr); 1767 ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr); 1768 ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr); 1769 ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr); 1770 ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr); 1771 ierr = PetscFESetUp(*fem);CHKERRQ(ierr); 1772 ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr); 1773 ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr); 1774 /* Create quadrature (with specified order if given) */ 1775 qorder = qorder >= 0 ? qorder : order; 1776 ierr = PetscObjectOptionsBegin((PetscObject)*fem);CHKERRQ(ierr); 1777 ierr = PetscOptionsBoundedInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadrature points per edge","PetscFECreateDefault",qorder,&qorder,NULL,0);CHKERRQ(ierr); 1778 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1779 quadPointsPerEdge = PetscMax(qorder + 1,1); 1780 if (isSimplex) { 1781 ierr = PetscDTStroudConicalQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr); 1782 ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr); 1783 } else { 1784 ierr = PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr); 1785 ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr); 1786 } 1787 ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr); 1788 ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr); 1789 ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr); 1790 ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr); 1791 PetscFunctionReturn(0); 1792 } 1793 1794 /*@ 1795 PetscFECreateLagrange - Create a PetscFE for the basic Lagrange space of degree k 1796 1797 Collective 1798 1799 Input Parameters: 1800 + comm - The MPI comm 1801 . dim - The spatial dimension 1802 . Nc - The number of components 1803 . isSimplex - Flag for simplex reference cell, otherwise its a tensor product 1804 . k - The degree k of the space 1805 - qorder - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree 1806 1807 Output Parameter: 1808 . fem - The PetscFE object 1809 1810 Level: beginner 1811 1812 Notes: 1813 For simplices, this element is the space of maximum polynomial degree k, otherwise it is a tensor product of 1D polynomials, each with maximal degree k. 1814 1815 .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate() 1816 @*/ 1817 PetscErrorCode PetscFECreateLagrange(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, PetscInt k, PetscInt qorder, PetscFE *fem) 1818 { 1819 PetscQuadrature q, fq; 1820 DM K; 1821 PetscSpace P; 1822 PetscDualSpace Q; 1823 PetscInt quadPointsPerEdge; 1824 PetscBool tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1825 char name[64]; 1826 PetscErrorCode ierr; 1827 1828 PetscFunctionBegin; 1829 /* Create space */ 1830 ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr); 1831 ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr); 1832 ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr); 1833 ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr); 1834 ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr); 1835 ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr); 1836 ierr = PetscSpaceSetUp(P);CHKERRQ(ierr); 1837 /* Create dual space */ 1838 ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr); 1839 ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr); 1840 ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr); 1841 ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr); 1842 ierr = DMDestroy(&K);CHKERRQ(ierr); 1843 ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr); 1844 ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr); 1845 ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr); 1846 ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr); 1847 /* Create element */ 1848 ierr = PetscFECreate(comm, fem);CHKERRQ(ierr); 1849 ierr = PetscSNPrintf(name, 64, "P%d", (int) k);CHKERRQ(ierr); 1850 ierr = PetscObjectSetName((PetscObject) *fem, name);CHKERRQ(ierr); 1851 ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr); 1852 ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr); 1853 ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr); 1854 ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr); 1855 ierr = PetscFESetUp(*fem);CHKERRQ(ierr); 1856 ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr); 1857 ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr); 1858 /* Create quadrature (with specified order if given) */ 1859 qorder = qorder >= 0 ? qorder : k; 1860 quadPointsPerEdge = PetscMax(qorder + 1,1); 1861 if (isSimplex) { 1862 ierr = PetscDTStroudConicalQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr); 1863 ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr); 1864 } else { 1865 ierr = PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr); 1866 ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr); 1867 } 1868 ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr); 1869 ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr); 1870 ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr); 1871 ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr); 1872 PetscFunctionReturn(0); 1873 } 1874 1875 /*@C 1876 PetscFESetName - Names the FE and its subobjects 1877 1878 Not collective 1879 1880 Input Parameters: 1881 + fe - The PetscFE 1882 - name - The name 1883 1884 Level: intermediate 1885 1886 .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate() 1887 @*/ 1888 PetscErrorCode PetscFESetName(PetscFE fe, const char name[]) 1889 { 1890 PetscSpace P; 1891 PetscDualSpace Q; 1892 PetscErrorCode ierr; 1893 1894 PetscFunctionBegin; 1895 ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr); 1896 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1897 ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr); 1898 ierr = PetscObjectSetName((PetscObject) P, name);CHKERRQ(ierr); 1899 ierr = PetscObjectSetName((PetscObject) Q, name);CHKERRQ(ierr); 1900 PetscFunctionReturn(0); 1901 } 1902 1903 PetscErrorCode PetscFEEvaluateFieldJets_Internal(PetscDS ds, PetscInt Nf, PetscInt r, PetscInt q, PetscTabulation T[], PetscFEGeom *fegeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscScalar u[], PetscScalar u_x[], PetscScalar u_t[]) 1904 { 1905 PetscInt dOffset = 0, fOffset = 0, f; 1906 PetscErrorCode ierr; 1907 1908 for (f = 0; f < Nf; ++f) { 1909 PetscFE fe; 1910 const PetscInt cdim = T[f]->cdim; 1911 const PetscInt Nq = T[f]->Np; 1912 const PetscInt Nbf = T[f]->Nb; 1913 const PetscInt Ncf = T[f]->Nc; 1914 const PetscReal *Bq = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf]; 1915 const PetscReal *Dq = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim]; 1916 PetscInt b, c, d; 1917 1918 ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr); 1919 for (c = 0; c < Ncf; ++c) u[fOffset+c] = 0.0; 1920 for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0; 1921 for (b = 0; b < Nbf; ++b) { 1922 for (c = 0; c < Ncf; ++c) { 1923 const PetscInt cidx = b*Ncf+c; 1924 1925 u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b]; 1926 for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b]; 1927 } 1928 } 1929 ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr); 1930 ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr); 1931 if (u_t) { 1932 for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0; 1933 for (b = 0; b < Nbf; ++b) { 1934 for (c = 0; c < Ncf; ++c) { 1935 const PetscInt cidx = b*Ncf+c; 1936 1937 u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b]; 1938 } 1939 } 1940 ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr); 1941 } 1942 fOffset += Ncf; 1943 dOffset += Nbf; 1944 } 1945 return 0; 1946 } 1947 1948 PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS prob, PetscInt field, PetscInt faceLoc, const PetscScalar coefficients[], PetscScalar u[]) 1949 { 1950 PetscFE fe; 1951 PetscTabulation Tc; 1952 PetscInt b, c; 1953 PetscErrorCode ierr; 1954 1955 if (!prob) return 0; 1956 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1957 ierr = PetscFEGetFaceCentroidTabulation(fe, &Tc);CHKERRQ(ierr); 1958 { 1959 const PetscReal *faceBasis = Tc->T[0]; 1960 const PetscInt Nb = Tc->Nb; 1961 const PetscInt Nc = Tc->Nc; 1962 1963 for (c = 0; c < Nc; ++c) {u[c] = 0.0;} 1964 for (b = 0; b < Nb; ++b) { 1965 for (c = 0; c < Nc; ++c) { 1966 const PetscInt cidx = b*Nc+c; 1967 1968 u[c] += coefficients[cidx]*faceBasis[faceLoc*Nb*Nc+cidx]; 1969 } 1970 } 1971 } 1972 return 0; 1973 } 1974 1975 PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[]) 1976 { 1977 const PetscInt dim = T->cdim; 1978 const PetscInt Nq = T->Np; 1979 const PetscInt Nb = T->Nb; 1980 const PetscInt Nc = T->Nc; 1981 const PetscReal *basis = &T->T[0][r*Nq*Nb*Nc]; 1982 const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dim]; 1983 PetscInt q, b, c, d; 1984 PetscErrorCode ierr; 1985 1986 for (b = 0; b < Nb; ++b) elemVec[b] = 0.0; 1987 for (q = 0; q < Nq; ++q) { 1988 for (b = 0; b < Nb; ++b) { 1989 for (c = 0; c < Nc; ++c) { 1990 const PetscInt bcidx = b*Nc+c; 1991 1992 tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx]; 1993 for (d = 0; d < dim; ++d) tmpBasisDer[bcidx*dim+d] = basisDer[q*Nb*Nc*dim+bcidx*dim+d]; 1994 } 1995 } 1996 ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr); 1997 ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr); 1998 for (b = 0; b < Nb; ++b) { 1999 for (c = 0; c < Nc; ++c) { 2000 const PetscInt bcidx = b*Nc+c; 2001 const PetscInt qcidx = q*Nc+c; 2002 2003 elemVec[b] += tmpBasis[bcidx]*f0[qcidx]; 2004 for (d = 0; d < dim; ++d) elemVec[b] += tmpBasisDer[bcidx*dim+d]*f1[qcidx*dim+d]; 2005 } 2006 } 2007 } 2008 return(0); 2009 } 2010 2011 PetscErrorCode PetscFEUpdateElementMat_Internal(PetscFE feI, PetscFE feJ, PetscInt r, PetscInt q, PetscTabulation TI, PetscScalar tmpBasisI[], PetscScalar tmpBasisDerI[], PetscTabulation TJ, PetscScalar tmpBasisJ[], PetscScalar tmpBasisDerJ[], PetscFEGeom *fegeom, const PetscScalar g0[], const PetscScalar g1[], const PetscScalar g2[], const PetscScalar g3[], PetscInt eOffset, PetscInt totDim, PetscInt offsetI, PetscInt offsetJ, PetscScalar elemMat[]) 2012 { 2013 const PetscInt dim = TI->cdim; 2014 const PetscInt NqI = TI->Np; 2015 const PetscInt NbI = TI->Nb; 2016 const PetscInt NcI = TI->Nc; 2017 const PetscReal *basisI = &TI->T[0][(r*NqI+q)*NbI*NcI]; 2018 const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dim]; 2019 const PetscInt NqJ = TJ->Np; 2020 const PetscInt NbJ = TJ->Nb; 2021 const PetscInt NcJ = TJ->Nc; 2022 const PetscReal *basisJ = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ]; 2023 const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dim]; 2024 PetscInt f, fc, g, gc, df, dg; 2025 PetscErrorCode ierr; 2026 2027 for (f = 0; f < NbI; ++f) { 2028 for (fc = 0; fc < NcI; ++fc) { 2029 const PetscInt fidx = f*NcI+fc; /* Test function basis index */ 2030 2031 tmpBasisI[fidx] = basisI[fidx]; 2032 for (df = 0; df < dim; ++df) tmpBasisDerI[fidx*dim+df] = basisDerI[fidx*dim+df]; 2033 } 2034 } 2035 ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr); 2036 ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr); 2037 for (g = 0; g < NbJ; ++g) { 2038 for (gc = 0; gc < NcJ; ++gc) { 2039 const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */ 2040 2041 tmpBasisJ[gidx] = basisJ[gidx]; 2042 for (dg = 0; dg < dim; ++dg) tmpBasisDerJ[gidx*dim+dg] = basisDerJ[gidx*dim+dg]; 2043 } 2044 } 2045 ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr); 2046 ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr); 2047 for (f = 0; f < NbI; ++f) { 2048 for (fc = 0; fc < NcI; ++fc) { 2049 const PetscInt fidx = f*NcI+fc; /* Test function basis index */ 2050 const PetscInt i = offsetI+f; /* Element matrix row */ 2051 for (g = 0; g < NbJ; ++g) { 2052 for (gc = 0; gc < NcJ; ++gc) { 2053 const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */ 2054 const PetscInt j = offsetJ+g; /* Element matrix column */ 2055 const PetscInt fOff = eOffset+i*totDim+j; 2056 2057 elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx]; 2058 for (df = 0; df < dim; ++df) { 2059 elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dim+df]*tmpBasisDerJ[gidx*dim+df]; 2060 elemMat[fOff] += tmpBasisDerI[fidx*dim+df]*g2[(fc*NcJ+gc)*dim+df]*tmpBasisJ[gidx]; 2061 for (dg = 0; dg < dim; ++dg) { 2062 elemMat[fOff] += tmpBasisDerI[fidx*dim+df]*g3[((fc*NcJ+gc)*dim+df)*dim+dg]*tmpBasisDerJ[gidx*dim+dg]; 2063 } 2064 } 2065 } 2066 } 2067 } 2068 } 2069 return(0); 2070 } 2071 2072 PetscErrorCode PetscFECreateCellGeometry(PetscFE fe, PetscQuadrature quad, PetscFEGeom *cgeom) 2073 { 2074 PetscDualSpace dsp; 2075 DM dm; 2076 PetscQuadrature quadDef; 2077 PetscInt dim, cdim, Nq; 2078 PetscErrorCode ierr; 2079 2080 PetscFunctionBegin; 2081 ierr = PetscFEGetDualSpace(fe, &dsp);CHKERRQ(ierr); 2082 ierr = PetscDualSpaceGetDM(dsp, &dm);CHKERRQ(ierr); 2083 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2084 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 2085 ierr = PetscFEGetQuadrature(fe, &quadDef);CHKERRQ(ierr); 2086 quad = quad ? quad : quadDef; 2087 ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 2088 ierr = PetscMalloc1(Nq*cdim, &cgeom->v);CHKERRQ(ierr); 2089 ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->J);CHKERRQ(ierr); 2090 ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->invJ);CHKERRQ(ierr); 2091 ierr = PetscMalloc1(Nq, &cgeom->detJ);CHKERRQ(ierr); 2092 cgeom->dim = dim; 2093 cgeom->dimEmbed = cdim; 2094 cgeom->numCells = 1; 2095 cgeom->numPoints = Nq; 2096 ierr = DMPlexComputeCellGeometryFEM(dm, 0, quad, cgeom->v, cgeom->J, cgeom->invJ, cgeom->detJ);CHKERRQ(ierr); 2097 PetscFunctionReturn(0); 2098 } 2099 2100 PetscErrorCode PetscFEDestroyCellGeometry(PetscFE fe, PetscFEGeom *cgeom) 2101 { 2102 PetscErrorCode ierr; 2103 2104 PetscFunctionBegin; 2105 ierr = PetscFree(cgeom->v);CHKERRQ(ierr); 2106 ierr = PetscFree(cgeom->J);CHKERRQ(ierr); 2107 ierr = PetscFree(cgeom->invJ);CHKERRQ(ierr); 2108 ierr = PetscFree(cgeom->detJ);CHKERRQ(ierr); 2109 PetscFunctionReturn(0); 2110 } 2111