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