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 .keywords: PetscFE, register 86 .seealso: PetscFERegisterAll(), PetscFERegisterDestroy() 87 88 @*/ 89 PetscErrorCode PetscFERegister(const char sname[], PetscErrorCode (*function)(PetscFE)) 90 { 91 PetscErrorCode ierr; 92 93 PetscFunctionBegin; 94 ierr = PetscFunctionListAdd(&PetscFEList, sname, function);CHKERRQ(ierr); 95 PetscFunctionReturn(0); 96 } 97 98 /*@C 99 PetscFESetType - Builds a particular PetscFE 100 101 Collective on PetscFE 102 103 Input Parameters: 104 + fem - The PetscFE object 105 - name - The kind of FEM space 106 107 Options Database Key: 108 . -petscfe_type <type> - Sets the PetscFE type; use -help for a list of available types 109 110 Level: intermediate 111 112 .keywords: PetscFE, set, type 113 .seealso: PetscFEGetType(), PetscFECreate() 114 @*/ 115 PetscErrorCode PetscFESetType(PetscFE fem, PetscFEType name) 116 { 117 PetscErrorCode (*r)(PetscFE); 118 PetscBool match; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 123 ierr = PetscObjectTypeCompare((PetscObject) fem, name, &match);CHKERRQ(ierr); 124 if (match) PetscFunctionReturn(0); 125 126 if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);} 127 ierr = PetscFunctionListFind(PetscFEList, name, &r);CHKERRQ(ierr); 128 if (!r) SETERRQ1(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFE type: %s", name); 129 130 if (fem->ops->destroy) { 131 ierr = (*fem->ops->destroy)(fem);CHKERRQ(ierr); 132 fem->ops->destroy = NULL; 133 } 134 ierr = (*r)(fem);CHKERRQ(ierr); 135 ierr = PetscObjectChangeTypeName((PetscObject) fem, name);CHKERRQ(ierr); 136 PetscFunctionReturn(0); 137 } 138 139 /*@C 140 PetscFEGetType - Gets the PetscFE type name (as a string) from the object. 141 142 Not Collective 143 144 Input Parameter: 145 . fem - The PetscFE 146 147 Output Parameter: 148 . name - The PetscFE type name 149 150 Level: intermediate 151 152 .keywords: PetscFE, get, type, name 153 .seealso: PetscFESetType(), PetscFECreate() 154 @*/ 155 PetscErrorCode PetscFEGetType(PetscFE fem, PetscFEType *name) 156 { 157 PetscErrorCode ierr; 158 159 PetscFunctionBegin; 160 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 161 PetscValidPointer(name, 2); 162 if (!PetscFERegisterAllCalled) { 163 ierr = PetscFERegisterAll();CHKERRQ(ierr); 164 } 165 *name = ((PetscObject) fem)->type_name; 166 PetscFunctionReturn(0); 167 } 168 169 /*@C 170 PetscFEView - Views a PetscFE 171 172 Collective on PetscFE 173 174 Input Parameter: 175 + fem - the PetscFE object to view 176 - v - the viewer 177 178 Level: developer 179 180 .seealso PetscFEDestroy() 181 @*/ 182 PetscErrorCode PetscFEView(PetscFE fem, PetscViewer v) 183 { 184 PetscErrorCode ierr; 185 186 PetscFunctionBegin; 187 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 188 if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) fem), &v);CHKERRQ(ierr);} 189 if (fem->ops->view) {ierr = (*fem->ops->view)(fem, v);CHKERRQ(ierr);} 190 PetscFunctionReturn(0); 191 } 192 193 /*@ 194 PetscFESetFromOptions - sets parameters in a PetscFE from the options database 195 196 Collective on PetscFE 197 198 Input Parameter: 199 . fem - the PetscFE object to set options for 200 201 Options Database: 202 . -petscfe_num_blocks the number of cell blocks to integrate concurrently 203 . -petscfe_num_batches the number of cell batches to integrate serially 204 205 Level: developer 206 207 .seealso PetscFEView() 208 @*/ 209 PetscErrorCode PetscFESetFromOptions(PetscFE fem) 210 { 211 const char *defaultType; 212 char name[256]; 213 PetscBool flg; 214 PetscErrorCode ierr; 215 216 PetscFunctionBegin; 217 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 218 if (!((PetscObject) fem)->type_name) { 219 defaultType = PETSCFEBASIC; 220 } else { 221 defaultType = ((PetscObject) fem)->type_name; 222 } 223 if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);} 224 225 ierr = PetscObjectOptionsBegin((PetscObject) fem);CHKERRQ(ierr); 226 ierr = PetscOptionsFList("-petscfe_type", "Finite element space", "PetscFESetType", PetscFEList, defaultType, name, 256, &flg);CHKERRQ(ierr); 227 if (flg) { 228 ierr = PetscFESetType(fem, name);CHKERRQ(ierr); 229 } else if (!((PetscObject) fem)->type_name) { 230 ierr = PetscFESetType(fem, defaultType);CHKERRQ(ierr); 231 } 232 ierr = PetscOptionsInt("-petscfe_num_blocks", "The number of cell blocks to integrate concurrently", "PetscSpaceSetTileSizes", fem->numBlocks, &fem->numBlocks, NULL);CHKERRQ(ierr); 233 ierr = PetscOptionsInt("-petscfe_num_batches", "The number of cell batches to integrate serially", "PetscSpaceSetTileSizes", fem->numBatches, &fem->numBatches, NULL);CHKERRQ(ierr); 234 if (fem->ops->setfromoptions) { 235 ierr = (*fem->ops->setfromoptions)(PetscOptionsObject,fem);CHKERRQ(ierr); 236 } 237 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 238 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) fem);CHKERRQ(ierr); 239 ierr = PetscOptionsEnd();CHKERRQ(ierr); 240 ierr = PetscFEViewFromOptions(fem, NULL, "-petscfe_view");CHKERRQ(ierr); 241 PetscFunctionReturn(0); 242 } 243 244 /*@C 245 PetscFESetUp - Construct data structures for the PetscFE 246 247 Collective on PetscFE 248 249 Input Parameter: 250 . fem - the PetscFE object to setup 251 252 Level: developer 253 254 .seealso PetscFEView(), PetscFEDestroy() 255 @*/ 256 PetscErrorCode PetscFESetUp(PetscFE fem) 257 { 258 PetscErrorCode ierr; 259 260 PetscFunctionBegin; 261 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 262 if (fem->setupcalled) PetscFunctionReturn(0); 263 fem->setupcalled = PETSC_TRUE; 264 if (fem->ops->setup) {ierr = (*fem->ops->setup)(fem);CHKERRQ(ierr);} 265 PetscFunctionReturn(0); 266 } 267 268 /*@ 269 PetscFEDestroy - Destroys a PetscFE object 270 271 Collective on PetscFE 272 273 Input Parameter: 274 . fem - the PetscFE object to destroy 275 276 Level: developer 277 278 .seealso PetscFEView() 279 @*/ 280 PetscErrorCode PetscFEDestroy(PetscFE *fem) 281 { 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 if (!*fem) PetscFunctionReturn(0); 286 PetscValidHeaderSpecific((*fem), PETSCFE_CLASSID, 1); 287 288 if (--((PetscObject)(*fem))->refct > 0) {*fem = 0; PetscFunctionReturn(0);} 289 ((PetscObject) (*fem))->refct = 0; 290 291 if ((*fem)->subspaces) { 292 PetscInt dim, d; 293 294 ierr = PetscDualSpaceGetDimension((*fem)->dualSpace, &dim);CHKERRQ(ierr); 295 for (d = 0; d < dim; ++d) {ierr = PetscFEDestroy(&(*fem)->subspaces[d]);CHKERRQ(ierr);} 296 } 297 ierr = PetscFree((*fem)->subspaces);CHKERRQ(ierr); 298 ierr = PetscFree((*fem)->invV);CHKERRQ(ierr); 299 ierr = PetscFERestoreTabulation((*fem), 0, NULL, &(*fem)->B, &(*fem)->D, NULL /*&(*fem)->H*/);CHKERRQ(ierr); 300 ierr = PetscFERestoreTabulation((*fem), 0, NULL, &(*fem)->Bf, &(*fem)->Df, NULL /*&(*fem)->Hf*/);CHKERRQ(ierr); 301 ierr = PetscFERestoreTabulation((*fem), 0, NULL, &(*fem)->F, NULL, NULL);CHKERRQ(ierr); 302 ierr = PetscSpaceDestroy(&(*fem)->basisSpace);CHKERRQ(ierr); 303 ierr = PetscDualSpaceDestroy(&(*fem)->dualSpace);CHKERRQ(ierr); 304 ierr = PetscQuadratureDestroy(&(*fem)->quadrature);CHKERRQ(ierr); 305 ierr = PetscQuadratureDestroy(&(*fem)->faceQuadrature);CHKERRQ(ierr); 306 307 if ((*fem)->ops->destroy) {ierr = (*(*fem)->ops->destroy)(*fem);CHKERRQ(ierr);} 308 ierr = PetscHeaderDestroy(fem);CHKERRQ(ierr); 309 PetscFunctionReturn(0); 310 } 311 312 /*@ 313 PetscFECreate - Creates an empty PetscFE object. The type can then be set with PetscFESetType(). 314 315 Collective on MPI_Comm 316 317 Input Parameter: 318 . comm - The communicator for the PetscFE object 319 320 Output Parameter: 321 . fem - The PetscFE object 322 323 Level: beginner 324 325 .seealso: PetscFESetType(), PETSCFEGALERKIN 326 @*/ 327 PetscErrorCode PetscFECreate(MPI_Comm comm, PetscFE *fem) 328 { 329 PetscFE f; 330 PetscErrorCode ierr; 331 332 PetscFunctionBegin; 333 PetscValidPointer(fem, 2); 334 ierr = PetscCitationsRegister(FECitation,&FEcite);CHKERRQ(ierr); 335 *fem = NULL; 336 ierr = PetscFEInitializePackage();CHKERRQ(ierr); 337 338 ierr = PetscHeaderCreate(f, PETSCFE_CLASSID, "PetscFE", "Finite Element", "PetscFE", comm, PetscFEDestroy, PetscFEView);CHKERRQ(ierr); 339 340 f->basisSpace = NULL; 341 f->dualSpace = NULL; 342 f->numComponents = 1; 343 f->subspaces = NULL; 344 f->invV = NULL; 345 f->B = NULL; 346 f->D = NULL; 347 f->H = NULL; 348 f->Bf = NULL; 349 f->Df = NULL; 350 f->Hf = NULL; 351 ierr = PetscMemzero(&f->quadrature, sizeof(PetscQuadrature));CHKERRQ(ierr); 352 ierr = PetscMemzero(&f->faceQuadrature, sizeof(PetscQuadrature));CHKERRQ(ierr); 353 f->blockSize = 0; 354 f->numBlocks = 1; 355 f->batchSize = 0; 356 f->numBatches = 1; 357 358 *fem = f; 359 PetscFunctionReturn(0); 360 } 361 362 /*@ 363 PetscFEGetSpatialDimension - Returns the spatial dimension of the element 364 365 Not collective 366 367 Input Parameter: 368 . fem - The PetscFE object 369 370 Output Parameter: 371 . dim - The spatial dimension 372 373 Level: intermediate 374 375 .seealso: PetscFECreate() 376 @*/ 377 PetscErrorCode PetscFEGetSpatialDimension(PetscFE fem, PetscInt *dim) 378 { 379 DM dm; 380 PetscErrorCode ierr; 381 382 PetscFunctionBegin; 383 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 384 PetscValidPointer(dim, 2); 385 ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); 386 ierr = DMGetDimension(dm, dim);CHKERRQ(ierr); 387 PetscFunctionReturn(0); 388 } 389 390 /*@ 391 PetscFESetNumComponents - Sets the number of components in the element 392 393 Not collective 394 395 Input Parameters: 396 + fem - The PetscFE object 397 - comp - The number of field components 398 399 Level: intermediate 400 401 .seealso: PetscFECreate() 402 @*/ 403 PetscErrorCode PetscFESetNumComponents(PetscFE fem, PetscInt comp) 404 { 405 PetscFunctionBegin; 406 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 407 fem->numComponents = comp; 408 PetscFunctionReturn(0); 409 } 410 411 /*@ 412 PetscFEGetNumComponents - Returns the number of components in the element 413 414 Not collective 415 416 Input Parameter: 417 . fem - The PetscFE object 418 419 Output Parameter: 420 . comp - The number of field components 421 422 Level: intermediate 423 424 .seealso: PetscFECreate() 425 @*/ 426 PetscErrorCode PetscFEGetNumComponents(PetscFE fem, PetscInt *comp) 427 { 428 PetscFunctionBegin; 429 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 430 PetscValidPointer(comp, 2); 431 *comp = fem->numComponents; 432 PetscFunctionReturn(0); 433 } 434 435 /*@ 436 PetscFESetTileSizes - Sets the tile sizes for evaluation 437 438 Not collective 439 440 Input Parameters: 441 + fem - The PetscFE object 442 . blockSize - The number of elements in a block 443 . numBlocks - The number of blocks in a batch 444 . batchSize - The number of elements in a batch 445 - numBatches - The number of batches in a chunk 446 447 Level: intermediate 448 449 .seealso: PetscFECreate() 450 @*/ 451 PetscErrorCode PetscFESetTileSizes(PetscFE fem, PetscInt blockSize, PetscInt numBlocks, PetscInt batchSize, PetscInt numBatches) 452 { 453 PetscFunctionBegin; 454 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 455 fem->blockSize = blockSize; 456 fem->numBlocks = numBlocks; 457 fem->batchSize = batchSize; 458 fem->numBatches = numBatches; 459 PetscFunctionReturn(0); 460 } 461 462 /*@ 463 PetscFEGetTileSizes - Returns the tile sizes for evaluation 464 465 Not collective 466 467 Input Parameter: 468 . fem - The PetscFE object 469 470 Output Parameters: 471 + blockSize - The number of elements in a block 472 . numBlocks - The number of blocks in a batch 473 . batchSize - The number of elements in a batch 474 - numBatches - The number of batches in a chunk 475 476 Level: intermediate 477 478 .seealso: PetscFECreate() 479 @*/ 480 PetscErrorCode PetscFEGetTileSizes(PetscFE fem, PetscInt *blockSize, PetscInt *numBlocks, PetscInt *batchSize, PetscInt *numBatches) 481 { 482 PetscFunctionBegin; 483 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 484 if (blockSize) PetscValidPointer(blockSize, 2); 485 if (numBlocks) PetscValidPointer(numBlocks, 3); 486 if (batchSize) PetscValidPointer(batchSize, 4); 487 if (numBatches) PetscValidPointer(numBatches, 5); 488 if (blockSize) *blockSize = fem->blockSize; 489 if (numBlocks) *numBlocks = fem->numBlocks; 490 if (batchSize) *batchSize = fem->batchSize; 491 if (numBatches) *numBatches = fem->numBatches; 492 PetscFunctionReturn(0); 493 } 494 495 /*@ 496 PetscFEGetBasisSpace - Returns the PetscSpace used for approximation of the solution 497 498 Not collective 499 500 Input Parameter: 501 . fem - The PetscFE object 502 503 Output Parameter: 504 . sp - The PetscSpace object 505 506 Level: intermediate 507 508 .seealso: PetscFECreate() 509 @*/ 510 PetscErrorCode PetscFEGetBasisSpace(PetscFE fem, PetscSpace *sp) 511 { 512 PetscFunctionBegin; 513 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 514 PetscValidPointer(sp, 2); 515 *sp = fem->basisSpace; 516 PetscFunctionReturn(0); 517 } 518 519 /*@ 520 PetscFESetBasisSpace - Sets the PetscSpace used for approximation of the solution 521 522 Not collective 523 524 Input Parameters: 525 + fem - The PetscFE object 526 - sp - The PetscSpace object 527 528 Level: intermediate 529 530 .seealso: PetscFECreate() 531 @*/ 532 PetscErrorCode PetscFESetBasisSpace(PetscFE fem, PetscSpace sp) 533 { 534 PetscErrorCode ierr; 535 536 PetscFunctionBegin; 537 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 538 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 2); 539 ierr = PetscSpaceDestroy(&fem->basisSpace);CHKERRQ(ierr); 540 fem->basisSpace = sp; 541 ierr = PetscObjectReference((PetscObject) fem->basisSpace);CHKERRQ(ierr); 542 PetscFunctionReturn(0); 543 } 544 545 /*@ 546 PetscFEGetDualSpace - Returns the PetscDualSpace used to define the inner product 547 548 Not collective 549 550 Input Parameter: 551 . fem - The PetscFE object 552 553 Output Parameter: 554 . sp - The PetscDualSpace object 555 556 Level: intermediate 557 558 .seealso: PetscFECreate() 559 @*/ 560 PetscErrorCode PetscFEGetDualSpace(PetscFE fem, PetscDualSpace *sp) 561 { 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 564 PetscValidPointer(sp, 2); 565 *sp = fem->dualSpace; 566 PetscFunctionReturn(0); 567 } 568 569 /*@ 570 PetscFESetDualSpace - Sets the PetscDualSpace used to define the inner product 571 572 Not collective 573 574 Input Parameters: 575 + fem - The PetscFE object 576 - sp - The PetscDualSpace object 577 578 Level: intermediate 579 580 .seealso: PetscFECreate() 581 @*/ 582 PetscErrorCode PetscFESetDualSpace(PetscFE fem, PetscDualSpace sp) 583 { 584 PetscErrorCode ierr; 585 586 PetscFunctionBegin; 587 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 588 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2); 589 ierr = PetscDualSpaceDestroy(&fem->dualSpace);CHKERRQ(ierr); 590 fem->dualSpace = sp; 591 ierr = PetscObjectReference((PetscObject) fem->dualSpace);CHKERRQ(ierr); 592 PetscFunctionReturn(0); 593 } 594 595 /*@ 596 PetscFEGetQuadrature - Returns the PetscQuadrature used to calculate inner products 597 598 Not collective 599 600 Input Parameter: 601 . fem - The PetscFE object 602 603 Output Parameter: 604 . q - The PetscQuadrature object 605 606 Level: intermediate 607 608 .seealso: PetscFECreate() 609 @*/ 610 PetscErrorCode PetscFEGetQuadrature(PetscFE fem, PetscQuadrature *q) 611 { 612 PetscFunctionBegin; 613 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 614 PetscValidPointer(q, 2); 615 *q = fem->quadrature; 616 PetscFunctionReturn(0); 617 } 618 619 /*@ 620 PetscFESetQuadrature - Sets the PetscQuadrature used to calculate inner products 621 622 Not collective 623 624 Input Parameters: 625 + fem - The PetscFE object 626 - q - The PetscQuadrature object 627 628 Level: intermediate 629 630 .seealso: PetscFECreate() 631 @*/ 632 PetscErrorCode PetscFESetQuadrature(PetscFE fem, PetscQuadrature q) 633 { 634 PetscInt Nc, qNc; 635 PetscErrorCode ierr; 636 637 PetscFunctionBegin; 638 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 639 ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr); 640 ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr); 641 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); 642 ierr = PetscFERestoreTabulation(fem, 0, NULL, &fem->B, &fem->D, NULL /*&(*fem)->H*/);CHKERRQ(ierr); 643 ierr = PetscQuadratureDestroy(&fem->quadrature);CHKERRQ(ierr); 644 fem->quadrature = q; 645 ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 649 /*@ 650 PetscFEGetFaceQuadrature - Returns the PetscQuadrature used to calculate inner products on faces 651 652 Not collective 653 654 Input Parameter: 655 . fem - The PetscFE object 656 657 Output Parameter: 658 . q - The PetscQuadrature object 659 660 Level: intermediate 661 662 .seealso: PetscFECreate() 663 @*/ 664 PetscErrorCode PetscFEGetFaceQuadrature(PetscFE fem, PetscQuadrature *q) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 668 PetscValidPointer(q, 2); 669 *q = fem->faceQuadrature; 670 PetscFunctionReturn(0); 671 } 672 673 /*@ 674 PetscFESetFaceQuadrature - Sets the PetscQuadrature used to calculate inner products on faces 675 676 Not collective 677 678 Input Parameters: 679 + fem - The PetscFE object 680 - q - The PetscQuadrature object 681 682 Level: intermediate 683 684 .seealso: PetscFECreate() 685 @*/ 686 PetscErrorCode PetscFESetFaceQuadrature(PetscFE fem, PetscQuadrature q) 687 { 688 PetscErrorCode ierr; 689 690 PetscFunctionBegin; 691 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 692 ierr = PetscFERestoreTabulation(fem, 0, NULL, &fem->Bf, &fem->Df, NULL /*&(*fem)->Hf*/);CHKERRQ(ierr); 693 ierr = PetscQuadratureDestroy(&fem->faceQuadrature);CHKERRQ(ierr); 694 fem->faceQuadrature = q; 695 ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr); 696 PetscFunctionReturn(0); 697 } 698 699 /*@C 700 PetscFEGetNumDof - Returns the number of dofs (dual basis vectors) associated to mesh points on the reference cell of a given dimension 701 702 Not collective 703 704 Input Parameter: 705 . fem - The PetscFE object 706 707 Output Parameter: 708 . numDof - Array with the number of dofs per dimension 709 710 Level: intermediate 711 712 .seealso: PetscFECreate() 713 @*/ 714 PetscErrorCode PetscFEGetNumDof(PetscFE fem, const PetscInt **numDof) 715 { 716 PetscErrorCode ierr; 717 718 PetscFunctionBegin; 719 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 720 PetscValidPointer(numDof, 2); 721 ierr = PetscDualSpaceGetNumDof(fem->dualSpace, numDof);CHKERRQ(ierr); 722 PetscFunctionReturn(0); 723 } 724 725 /*@C 726 PetscFEGetDefaultTabulation - Returns the tabulation of the basis functions at the quadrature points 727 728 Not collective 729 730 Input Parameter: 731 . fem - The PetscFE object 732 733 Output Parameters: 734 + B - The basis function values at quadrature points 735 . D - The basis function derivatives at quadrature points 736 - H - The basis function second derivatives at quadrature points 737 738 Note: 739 $ B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 740 $ D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 741 $ 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 742 743 Level: intermediate 744 745 .seealso: PetscFEGetTabulation(), PetscFERestoreTabulation() 746 @*/ 747 PetscErrorCode PetscFEGetDefaultTabulation(PetscFE fem, PetscReal **B, PetscReal **D, PetscReal **H) 748 { 749 PetscInt npoints; 750 const PetscReal *points; 751 PetscErrorCode ierr; 752 753 PetscFunctionBegin; 754 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 755 if (B) PetscValidPointer(B, 2); 756 if (D) PetscValidPointer(D, 3); 757 if (H) PetscValidPointer(H, 4); 758 ierr = PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr); 759 if (!fem->B) {ierr = PetscFEGetTabulation(fem, npoints, points, &fem->B, &fem->D, NULL/*&fem->H*/);CHKERRQ(ierr);} 760 if (B) *B = fem->B; 761 if (D) *D = fem->D; 762 if (H) *H = fem->H; 763 PetscFunctionReturn(0); 764 } 765 766 PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscReal **Bf, PetscReal **Df, PetscReal **Hf) 767 { 768 PetscErrorCode ierr; 769 770 PetscFunctionBegin; 771 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 772 if (Bf) PetscValidPointer(Bf, 2); 773 if (Df) PetscValidPointer(Df, 3); 774 if (Hf) PetscValidPointer(Hf, 4); 775 if (!fem->Bf) { 776 const PetscReal xi0[3] = {-1., -1., -1.}; 777 PetscReal v0[3], J[9], detJ; 778 PetscQuadrature fq; 779 PetscDualSpace sp; 780 DM dm; 781 const PetscInt *faces; 782 PetscInt dim, numFaces, f, npoints, q; 783 const PetscReal *points; 784 PetscReal *facePoints; 785 786 ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr); 787 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 788 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 789 ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr); 790 ierr = DMPlexGetCone(dm, 0, &faces);CHKERRQ(ierr); 791 ierr = PetscFEGetFaceQuadrature(fem, &fq);CHKERRQ(ierr); 792 if (fq) { 793 ierr = PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr); 794 ierr = PetscMalloc1(numFaces*npoints*dim, &facePoints);CHKERRQ(ierr); 795 for (f = 0; f < numFaces; ++f) { 796 ierr = DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 797 for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]); 798 } 799 ierr = PetscFEGetTabulation(fem, numFaces*npoints, facePoints, &fem->Bf, &fem->Df, NULL/*&fem->Hf*/);CHKERRQ(ierr); 800 ierr = PetscFree(facePoints);CHKERRQ(ierr); 801 } 802 } 803 if (Bf) *Bf = fem->Bf; 804 if (Df) *Df = fem->Df; 805 if (Hf) *Hf = fem->Hf; 806 PetscFunctionReturn(0); 807 } 808 809 PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscReal **F) 810 { 811 PetscErrorCode ierr; 812 813 PetscFunctionBegin; 814 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 815 PetscValidPointer(F, 2); 816 if (!fem->F) { 817 PetscDualSpace sp; 818 DM dm; 819 const PetscInt *cone; 820 PetscReal *centroids; 821 PetscInt dim, numFaces, f; 822 823 ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr); 824 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 825 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 826 ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr); 827 ierr = DMPlexGetCone(dm, 0, &cone);CHKERRQ(ierr); 828 ierr = PetscMalloc1(numFaces*dim, ¢roids);CHKERRQ(ierr); 829 for (f = 0; f < numFaces; ++f) {ierr = DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, ¢roids[f*dim], NULL);CHKERRQ(ierr);} 830 ierr = PetscFEGetTabulation(fem, numFaces, centroids, &fem->F, NULL, NULL);CHKERRQ(ierr); 831 ierr = PetscFree(centroids);CHKERRQ(ierr); 832 } 833 *F = fem->F; 834 PetscFunctionReturn(0); 835 } 836 837 /*@C 838 PetscFEGetTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided. 839 840 Not collective 841 842 Input Parameters: 843 + fem - The PetscFE object 844 . npoints - The number of tabulation points 845 - points - The tabulation point coordinates 846 847 Output Parameters: 848 + B - The basis function values at tabulation points 849 . D - The basis function derivatives at tabulation points 850 - H - The basis function second derivatives at tabulation points 851 852 Note: 853 $ B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c 854 $ D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d 855 $ 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 856 857 Level: intermediate 858 859 .seealso: PetscFERestoreTabulation(), PetscFEGetDefaultTabulation() 860 @*/ 861 PetscErrorCode PetscFEGetTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscReal **B, PetscReal **D, PetscReal **H) 862 { 863 DM dm; 864 PetscInt pdim; /* Dimension of FE space P */ 865 PetscInt dim; /* Spatial dimension */ 866 PetscInt comp; /* Field components */ 867 PetscErrorCode ierr; 868 869 PetscFunctionBegin; 870 if (!npoints) { 871 if (B) *B = NULL; 872 if (D) *D = NULL; 873 if (H) *H = NULL; 874 PetscFunctionReturn(0); 875 } 876 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 877 PetscValidPointer(points, 3); 878 if (B) PetscValidPointer(B, 4); 879 if (D) PetscValidPointer(D, 5); 880 if (H) PetscValidPointer(H, 6); 881 ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); 882 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 883 ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr); 884 ierr = PetscFEGetNumComponents(fem, &comp);CHKERRQ(ierr); 885 if (B) {ierr = DMGetWorkArray(dm, npoints*pdim*comp, MPIU_REAL, B);CHKERRQ(ierr);} 886 if (!dim) { 887 if (D) *D = NULL; 888 if (H) *H = NULL; 889 } else { 890 if (D) {ierr = DMGetWorkArray(dm, npoints*pdim*comp*dim, MPIU_REAL, D);CHKERRQ(ierr);} 891 if (H) {ierr = DMGetWorkArray(dm, npoints*pdim*comp*dim*dim, MPIU_REAL, H);CHKERRQ(ierr);} 892 } 893 ierr = (*fem->ops->gettabulation)(fem, npoints, points, B ? *B : NULL, D ? *D : NULL, H ? *H : NULL);CHKERRQ(ierr); 894 PetscFunctionReturn(0); 895 } 896 897 PetscErrorCode PetscFERestoreTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscReal **B, PetscReal **D, PetscReal **H) 898 { 899 DM dm; 900 PetscErrorCode ierr; 901 902 PetscFunctionBegin; 903 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 904 ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); 905 if (B && *B) {ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, B);CHKERRQ(ierr);} 906 if (D && *D) {ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, D);CHKERRQ(ierr);} 907 if (H && *H) {ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, H);CHKERRQ(ierr);} 908 PetscFunctionReturn(0); 909 } 910 911 PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE) 912 { 913 PetscSpace bsp, bsubsp; 914 PetscDualSpace dsp, dsubsp; 915 PetscInt dim, depth, numComp, i, j, coneSize, order; 916 PetscFEType type; 917 DM dm; 918 DMLabel label; 919 PetscReal *xi, *v, *J, detJ; 920 PetscQuadrature origin, fullQuad, subQuad; 921 PetscErrorCode ierr; 922 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1); 925 PetscValidPointer(trFE,3); 926 ierr = PetscFEGetBasisSpace(fe,&bsp);CHKERRQ(ierr); 927 ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 928 ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr); 929 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 930 ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr); 931 ierr = DMLabelGetValue(label,refPoint,&depth);CHKERRQ(ierr); 932 ierr = PetscCalloc1(depth,&xi);CHKERRQ(ierr); 933 ierr = PetscMalloc1(dim,&v);CHKERRQ(ierr); 934 ierr = PetscMalloc1(dim*dim,&J);CHKERRQ(ierr); 935 for (i = 0; i < depth; i++) xi[i] = 0.; 936 ierr = PetscQuadratureCreate(PETSC_COMM_SELF,&origin);CHKERRQ(ierr); 937 ierr = PetscQuadratureSetData(origin,depth,0,1,xi,NULL);CHKERRQ(ierr); 938 ierr = DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);CHKERRQ(ierr); 939 /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */ 940 for (i = 1; i < dim; i++) { 941 for (j = 0; j < depth; j++) { 942 J[i * depth + j] = J[i * dim + j]; 943 } 944 } 945 ierr = PetscQuadratureDestroy(&origin);CHKERRQ(ierr); 946 ierr = PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);CHKERRQ(ierr); 947 ierr = PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);CHKERRQ(ierr); 948 ierr = PetscSpaceSetUp(bsubsp);CHKERRQ(ierr); 949 ierr = PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);CHKERRQ(ierr); 950 ierr = PetscFEGetType(fe,&type);CHKERRQ(ierr); 951 ierr = PetscFESetType(*trFE,type);CHKERRQ(ierr); 952 ierr = PetscFEGetNumComponents(fe,&numComp);CHKERRQ(ierr); 953 ierr = PetscFESetNumComponents(*trFE,numComp);CHKERRQ(ierr); 954 ierr = PetscFESetBasisSpace(*trFE,bsubsp);CHKERRQ(ierr); 955 ierr = PetscFESetDualSpace(*trFE,dsubsp);CHKERRQ(ierr); 956 ierr = PetscFEGetQuadrature(fe,&fullQuad);CHKERRQ(ierr); 957 ierr = PetscQuadratureGetOrder(fullQuad,&order);CHKERRQ(ierr); 958 ierr = DMPlexGetConeSize(dm,refPoint,&coneSize);CHKERRQ(ierr); 959 if (coneSize == 2 * depth) { 960 ierr = PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr); 961 } else { 962 ierr = PetscDTGaussJacobiQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr); 963 } 964 ierr = PetscFESetQuadrature(*trFE,subQuad);CHKERRQ(ierr); 965 ierr = PetscFESetUp(*trFE);CHKERRQ(ierr); 966 ierr = PetscQuadratureDestroy(&subQuad);CHKERRQ(ierr); 967 ierr = PetscSpaceDestroy(&bsubsp);CHKERRQ(ierr); 968 PetscFunctionReturn(0); 969 } 970 971 PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE) 972 { 973 PetscInt hStart, hEnd; 974 PetscDualSpace dsp; 975 DM dm; 976 PetscErrorCode ierr; 977 978 PetscFunctionBegin; 979 PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1); 980 PetscValidPointer(trFE,3); 981 *trFE = NULL; 982 ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr); 983 ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr); 984 ierr = DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);CHKERRQ(ierr); 985 if (hEnd <= hStart) PetscFunctionReturn(0); 986 ierr = PetscFECreatePointTrace(fe,hStart,trFE);CHKERRQ(ierr); 987 PetscFunctionReturn(0); 988 } 989 990 991 /*@ 992 PetscFEGetDimension - Get the dimension of the finite element space on a cell 993 994 Not collective 995 996 Input Parameter: 997 . fe - The PetscFE 998 999 Output Parameter: 1000 . dim - The dimension 1001 1002 Level: intermediate 1003 1004 .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension() 1005 @*/ 1006 PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim) 1007 { 1008 PetscErrorCode ierr; 1009 1010 PetscFunctionBegin; 1011 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1012 PetscValidPointer(dim, 2); 1013 if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);} 1014 PetscFunctionReturn(0); 1015 } 1016 1017 /* 1018 Purpose: Compute element vector for chunk of elements 1019 1020 Input: 1021 Sizes: 1022 Ne: number of elements 1023 Nf: number of fields 1024 PetscFE 1025 dim: spatial dimension 1026 Nb: number of basis functions 1027 Nc: number of field components 1028 PetscQuadrature 1029 Nq: number of quadrature points 1030 1031 Geometry: 1032 PetscFEGeom[Ne] possibly *Nq 1033 PetscReal v0s[dim] 1034 PetscReal n[dim] 1035 PetscReal jacobians[dim*dim] 1036 PetscReal jacobianInverses[dim*dim] 1037 PetscReal jacobianDeterminants 1038 FEM: 1039 PetscFE 1040 PetscQuadrature 1041 PetscReal quadPoints[Nq*dim] 1042 PetscReal quadWeights[Nq] 1043 PetscReal basis[Nq*Nb*Nc] 1044 PetscReal basisDer[Nq*Nb*Nc*dim] 1045 PetscScalar coefficients[Ne*Nb*Nc] 1046 PetscScalar elemVec[Ne*Nb*Nc] 1047 1048 Problem: 1049 PetscInt f: the active field 1050 f0, f1 1051 1052 Work Space: 1053 PetscFE 1054 PetscScalar f0[Nq*dim]; 1055 PetscScalar f1[Nq*dim*dim]; 1056 PetscScalar u[Nc]; 1057 PetscScalar gradU[Nc*dim]; 1058 PetscReal x[dim]; 1059 PetscScalar realSpaceDer[dim]; 1060 1061 Purpose: Compute element vector for N_cb batches of elements 1062 1063 Input: 1064 Sizes: 1065 N_cb: Number of serial cell batches 1066 1067 Geometry: 1068 PetscReal v0s[Ne*dim] 1069 PetscReal jacobians[Ne*dim*dim] possibly *Nq 1070 PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq 1071 PetscReal jacobianDeterminants[Ne] possibly *Nq 1072 FEM: 1073 static PetscReal quadPoints[Nq*dim] 1074 static PetscReal quadWeights[Nq] 1075 static PetscReal basis[Nq*Nb*Nc] 1076 static PetscReal basisDer[Nq*Nb*Nc*dim] 1077 PetscScalar coefficients[Ne*Nb*Nc] 1078 PetscScalar elemVec[Ne*Nb*Nc] 1079 1080 ex62.c: 1081 PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[], 1082 const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], 1083 void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]), 1084 void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[]) 1085 1086 ex52.c: 1087 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) 1088 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) 1089 1090 ex52_integrateElement.cu 1091 __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec) 1092 1093 PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[], 1094 const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[], 1095 PetscLogEvent event, PetscInt debug, PetscInt pde_op) 1096 1097 ex52_integrateElementOpenCL.c: 1098 PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[], 1099 const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[], 1100 PetscLogEvent event, PetscInt debug, PetscInt pde_op) 1101 1102 __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec) 1103 */ 1104 1105 /*@C 1106 PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration 1107 1108 Not collective 1109 1110 Input Parameters: 1111 + fem - The PetscFE object for the field being integrated 1112 . prob - The PetscDS specifying the discretizations and continuum functions 1113 . field - The field being integrated 1114 . Ne - The number of elements in the chunk 1115 . cgeom - The cell geometry for each cell in the chunk 1116 . coefficients - The array of FEM basis coefficients for the elements 1117 . probAux - The PetscDS specifying the auxiliary discretizations 1118 - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1119 1120 Output Parameter 1121 . integral - the integral for this field 1122 1123 Level: developer 1124 1125 .seealso: PetscFEIntegrateResidual() 1126 @*/ 1127 PetscErrorCode PetscFEIntegrate(PetscFE fem, PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom, 1128 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 1129 { 1130 PetscErrorCode ierr; 1131 1132 PetscFunctionBegin; 1133 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1134 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 1135 if (fem->ops->integrate) {ierr = (*fem->ops->integrate)(fem, prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);} 1136 PetscFunctionReturn(0); 1137 } 1138 1139 /*@C 1140 PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration 1141 1142 Not collective 1143 1144 Input Parameters: 1145 + fem - The PetscFE object for the field being integrated 1146 . prob - The PetscDS specifying the discretizations and continuum functions 1147 . field - The field being integrated 1148 . Ne - The number of elements in the chunk 1149 . cgeom - The cell geometry for each cell in the chunk 1150 . coefficients - The array of FEM basis coefficients for the elements 1151 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1152 . probAux - The PetscDS specifying the auxiliary discretizations 1153 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1154 - t - The time 1155 1156 Output Parameter 1157 . elemVec - the element residual vectors from each element 1158 1159 Note: 1160 $ Loop over batch of elements (e): 1161 $ Loop over quadrature points (q): 1162 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q 1163 $ Call f_0 and f_1 1164 $ Loop over element vector entries (f,fc --> i): 1165 $ elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u) 1166 1167 Level: developer 1168 1169 .seealso: PetscFEIntegrateResidual() 1170 @*/ 1171 PetscErrorCode PetscFEIntegrateResidual(PetscFE fem, PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom, 1172 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 1173 { 1174 PetscErrorCode ierr; 1175 1176 PetscFunctionBegin; 1177 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1178 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 1179 if (fem->ops->integrateresidual) {ierr = (*fem->ops->integrateresidual)(fem, prob, field, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);} 1180 PetscFunctionReturn(0); 1181 } 1182 1183 /*@C 1184 PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary 1185 1186 Not collective 1187 1188 Input Parameters: 1189 + fem - The PetscFE object for the field being integrated 1190 . prob - The PetscDS specifying the discretizations and continuum functions 1191 . field - The field being integrated 1192 . Ne - The number of elements in the chunk 1193 . fgeom - The face geometry for each cell in the chunk 1194 . coefficients - The array of FEM basis coefficients for the elements 1195 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1196 . probAux - The PetscDS specifying the auxiliary discretizations 1197 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1198 - t - The time 1199 1200 Output Parameter 1201 . elemVec - the element residual vectors from each element 1202 1203 Level: developer 1204 1205 .seealso: PetscFEIntegrateResidual() 1206 @*/ 1207 PetscErrorCode PetscFEIntegrateBdResidual(PetscFE fem, PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom, 1208 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 1209 { 1210 PetscErrorCode ierr; 1211 1212 PetscFunctionBegin; 1213 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1214 if (fem->ops->integratebdresidual) {ierr = (*fem->ops->integratebdresidual)(fem, prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);} 1215 PetscFunctionReturn(0); 1216 } 1217 1218 /*@C 1219 PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration 1220 1221 Not collective 1222 1223 Input Parameters: 1224 + fem - The PetscFE object for the field being integrated 1225 . prob - The PetscDS specifying the discretizations and continuum functions 1226 . jtype - The type of matrix pointwise functions that should be used 1227 . fieldI - The test field being integrated 1228 . fieldJ - The basis field being integrated 1229 . Ne - The number of elements in the chunk 1230 . cgeom - The cell geometry for each cell in the chunk 1231 . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point 1232 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1233 . probAux - The PetscDS specifying the auxiliary discretizations 1234 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1235 . t - The time 1236 - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term) 1237 1238 Output Parameter 1239 . elemMat - the element matrices for the Jacobian from each element 1240 1241 Note: 1242 $ Loop over batch of elements (e): 1243 $ Loop over element matrix entries (f,fc,g,gc --> i,j): 1244 $ Loop over quadrature points (q): 1245 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) 1246 $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q) 1247 $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1248 $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q) 1249 $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1250 Level: developer 1251 1252 .seealso: PetscFEIntegrateResidual() 1253 @*/ 1254 PetscErrorCode PetscFEIntegrateJacobian(PetscFE fem, PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom, 1255 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 1256 { 1257 PetscErrorCode ierr; 1258 1259 PetscFunctionBegin; 1260 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1261 if (fem->ops->integratejacobian) {ierr = (*fem->ops->integratejacobian)(fem, prob, jtype, fieldI, fieldJ, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);} 1262 PetscFunctionReturn(0); 1263 } 1264 1265 /*@C 1266 PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration 1267 1268 Not collective 1269 1270 Input Parameters: 1271 + fem = The PetscFE object for the field being integrated 1272 . prob - The PetscDS specifying the discretizations and continuum functions 1273 . fieldI - The test field being integrated 1274 . fieldJ - The basis field being integrated 1275 . Ne - The number of elements in the chunk 1276 . fgeom - The face geometry for each cell in the chunk 1277 . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point 1278 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1279 . probAux - The PetscDS specifying the auxiliary discretizations 1280 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1281 . t - The time 1282 - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term) 1283 1284 Output Parameter 1285 . elemMat - the element matrices for the Jacobian from each element 1286 1287 Note: 1288 $ Loop over batch of elements (e): 1289 $ Loop over element matrix entries (f,fc,g,gc --> i,j): 1290 $ Loop over quadrature points (q): 1291 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) 1292 $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q) 1293 $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1294 $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q) 1295 $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q) 1296 Level: developer 1297 1298 .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual() 1299 @*/ 1300 PetscErrorCode PetscFEIntegrateBdJacobian(PetscFE fem, PetscDS prob, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom, 1301 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 1302 { 1303 PetscErrorCode ierr; 1304 1305 PetscFunctionBegin; 1306 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1307 if (fem->ops->integratebdjacobian) {ierr = (*fem->ops->integratebdjacobian)(fem, prob, fieldI, fieldJ, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);} 1308 PetscFunctionReturn(0); 1309 } 1310 1311 PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe) 1312 { 1313 PetscSpace P, subP; 1314 PetscDualSpace Q, subQ; 1315 PetscQuadrature subq; 1316 PetscFEType fetype; 1317 PetscInt dim, Nc; 1318 PetscErrorCode ierr; 1319 1320 PetscFunctionBegin; 1321 PetscValidHeaderSpecific(fe, PETSCFE_CLASSID, 1); 1322 PetscValidPointer(subfe, 3); 1323 if (height == 0) { 1324 *subfe = fe; 1325 PetscFunctionReturn(0); 1326 } 1327 ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr); 1328 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1329 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1330 ierr = PetscFEGetFaceQuadrature(fe, &subq);CHKERRQ(ierr); 1331 ierr = PetscDualSpaceGetDimension(Q, &dim);CHKERRQ(ierr); 1332 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);} 1333 if (!fe->subspaces) {ierr = PetscCalloc1(dim, &fe->subspaces);CHKERRQ(ierr);} 1334 if (height <= dim) { 1335 if (!fe->subspaces[height-1]) { 1336 PetscFE sub; 1337 1338 ierr = PetscSpaceGetHeightSubspace(P, height, &subP);CHKERRQ(ierr); 1339 ierr = PetscDualSpaceGetHeightSubspace(Q, height, &subQ);CHKERRQ(ierr); 1340 ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);CHKERRQ(ierr); 1341 ierr = PetscFEGetType(fe, &fetype);CHKERRQ(ierr); 1342 ierr = PetscFESetType(sub, fetype);CHKERRQ(ierr); 1343 ierr = PetscFESetBasisSpace(sub, subP);CHKERRQ(ierr); 1344 ierr = PetscFESetDualSpace(sub, subQ);CHKERRQ(ierr); 1345 ierr = PetscFESetNumComponents(sub, Nc);CHKERRQ(ierr); 1346 ierr = PetscFESetUp(sub);CHKERRQ(ierr); 1347 ierr = PetscFESetQuadrature(sub, subq);CHKERRQ(ierr); 1348 fe->subspaces[height-1] = sub; 1349 } 1350 *subfe = fe->subspaces[height-1]; 1351 } else { 1352 *subfe = NULL; 1353 } 1354 PetscFunctionReturn(0); 1355 } 1356 1357 /*@ 1358 PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used 1359 to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more 1360 sparsity). It is also used to create an interpolation between regularly refined meshes. 1361 1362 Collective on PetscFE 1363 1364 Input Parameter: 1365 . fe - The initial PetscFE 1366 1367 Output Parameter: 1368 . feRef - The refined PetscFE 1369 1370 Level: developer 1371 1372 .seealso: PetscFEType, PetscFECreate(), PetscFESetType() 1373 @*/ 1374 PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef) 1375 { 1376 PetscSpace P, Pref; 1377 PetscDualSpace Q, Qref; 1378 DM K, Kref; 1379 PetscQuadrature q, qref; 1380 const PetscReal *v0, *jac; 1381 PetscInt numComp, numSubelements; 1382 PetscErrorCode ierr; 1383 1384 PetscFunctionBegin; 1385 ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr); 1386 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1387 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 1388 ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr); 1389 /* Create space */ 1390 ierr = PetscObjectReference((PetscObject) P);CHKERRQ(ierr); 1391 Pref = P; 1392 /* Create dual space */ 1393 ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr); 1394 ierr = DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);CHKERRQ(ierr); 1395 ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr); 1396 ierr = DMDestroy(&Kref);CHKERRQ(ierr); 1397 ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr); 1398 /* Create element */ 1399 ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);CHKERRQ(ierr); 1400 ierr = PetscFESetType(*feRef, PETSCFECOMPOSITE);CHKERRQ(ierr); 1401 ierr = PetscFESetBasisSpace(*feRef, Pref);CHKERRQ(ierr); 1402 ierr = PetscFESetDualSpace(*feRef, Qref);CHKERRQ(ierr); 1403 ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 1404 ierr = PetscFESetNumComponents(*feRef, numComp);CHKERRQ(ierr); 1405 ierr = PetscFESetUp(*feRef);CHKERRQ(ierr); 1406 ierr = PetscSpaceDestroy(&Pref);CHKERRQ(ierr); 1407 ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr); 1408 /* Create quadrature */ 1409 ierr = PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);CHKERRQ(ierr); 1410 ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr); 1411 ierr = PetscFESetQuadrature(*feRef, qref);CHKERRQ(ierr); 1412 ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr); 1413 PetscFunctionReturn(0); 1414 } 1415 1416 /*@C 1417 PetscFECreateDefault - Create a PetscFE for basic FEM computation 1418 1419 Collective on DM 1420 1421 Input Parameters: 1422 + comm - The MPI comm 1423 . dim - The spatial dimension 1424 . Nc - The number of components 1425 . isSimplex - Flag for simplex reference cell, otherwise its a tensor product 1426 . prefix - The options prefix, or NULL 1427 - qorder - The quadrature order 1428 1429 Output Parameter: 1430 . fem - The PetscFE object 1431 1432 Level: beginner 1433 1434 .keywords: PetscFE, finite element 1435 .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate() 1436 @*/ 1437 PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem) 1438 { 1439 PetscQuadrature q, fq; 1440 DM K; 1441 PetscSpace P; 1442 PetscDualSpace Q; 1443 PetscInt order, quadPointsPerEdge; 1444 PetscBool tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1445 PetscErrorCode ierr; 1446 1447 PetscFunctionBegin; 1448 /* Create space */ 1449 ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr); 1450 ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr); 1451 ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr); 1452 ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr); 1453 ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr); 1454 ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr); 1455 ierr = PetscSpaceSetUp(P);CHKERRQ(ierr); 1456 ierr = PetscSpaceGetDegree(P, &order, NULL);CHKERRQ(ierr); 1457 ierr = PetscSpacePolynomialGetTensor(P, &tensor);CHKERRQ(ierr); 1458 /* Create dual space */ 1459 ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr); 1460 ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr); 1461 ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr); 1462 ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr); 1463 ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr); 1464 ierr = DMDestroy(&K);CHKERRQ(ierr); 1465 ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr); 1466 ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr); 1467 ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr); 1468 ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr); 1469 ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr); 1470 /* Create element */ 1471 ierr = PetscFECreate(comm, fem);CHKERRQ(ierr); 1472 ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr); 1473 ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr); 1474 ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr); 1475 ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr); 1476 ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr); 1477 ierr = PetscFESetUp(*fem);CHKERRQ(ierr); 1478 ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr); 1479 ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr); 1480 /* Create quadrature (with specified order if given) */ 1481 qorder = qorder >= 0 ? qorder : order; 1482 ierr = PetscObjectOptionsBegin((PetscObject)*fem);CHKERRQ(ierr); 1483 ierr = PetscOptionsInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadture points per edge","PetscFECreateDefault",qorder,&qorder,NULL);CHKERRQ(ierr); 1484 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1485 quadPointsPerEdge = PetscMax(qorder + 1,1); 1486 if (isSimplex) { 1487 ierr = PetscDTGaussJacobiQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr); 1488 ierr = PetscDTGaussJacobiQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr); 1489 } 1490 else { 1491 ierr = PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr); 1492 ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr); 1493 } 1494 ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr); 1495 ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr); 1496 ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr); 1497 ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr); 1498 PetscFunctionReturn(0); 1499 } 1500 1501