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 Parameters: 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 Parameters: 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 Parameters: 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 derivatives 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 PetscFEGetDimension - Get the dimension of the finite element space on a cell 1161 1162 Not collective 1163 1164 Input Parameter: 1165 . fe - The PetscFE 1166 1167 Output Parameter: 1168 . dim - The dimension 1169 1170 Level: intermediate 1171 1172 .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension() 1173 @*/ 1174 PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim) 1175 { 1176 PetscErrorCode ierr; 1177 1178 PetscFunctionBegin; 1179 PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 1180 PetscValidPointer(dim, 2); 1181 if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);} 1182 PetscFunctionReturn(0); 1183 } 1184 1185 /*@C 1186 PetscFEPushforward - Map the reference element function to real space 1187 1188 Input Parameters: 1189 + fe - The PetscFE 1190 . fegeom - The cell geometry 1191 . Nv - The number of function values 1192 - vals - The function values 1193 1194 Output Parameter: 1195 . vals - The transformed function values 1196 1197 Level: advanced 1198 1199 Note: This just forwards the call onto PetscDualSpacePushforward(). 1200 1201 Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1202 1203 .seealso: PetscDualSpacePushforward() 1204 @*/ 1205 PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[]) 1206 { 1207 PetscErrorCode ierr; 1208 1209 PetscFunctionBeginHot; 1210 ierr = PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr); 1211 PetscFunctionReturn(0); 1212 } 1213 1214 /*@C 1215 PetscFEPushforwardGradient - Map the reference element function gradient to real space 1216 1217 Input Parameters: 1218 + fe - The PetscFE 1219 . fegeom - The cell geometry 1220 . Nv - The number of function gradient values 1221 - vals - The function gradient values 1222 1223 Output Parameter: 1224 . vals - The transformed function gradient values 1225 1226 Level: advanced 1227 1228 Note: This just forwards the call onto PetscDualSpacePushforwardGradient(). 1229 1230 Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1231 1232 .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward() 1233 @*/ 1234 PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[]) 1235 { 1236 PetscErrorCode ierr; 1237 1238 PetscFunctionBeginHot; 1239 ierr = PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr); 1240 PetscFunctionReturn(0); 1241 } 1242 1243 /*@C 1244 PetscFEPushforwardHessian - Map the reference element function Hessian to real space 1245 1246 Input Parameters: 1247 + fe - The PetscFE 1248 . fegeom - The cell geometry 1249 . Nv - The number of function Hessian values 1250 - vals - The function Hessian values 1251 1252 Output Parameter: 1253 . vals - The transformed function Hessian values 1254 1255 Level: advanced 1256 1257 Note: This just forwards the call onto PetscDualSpacePushforwardHessian(). 1258 1259 Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1260 1261 .seealso: PetscFEPushforward(), PetscDualSpacePushforwardHessian(), PetscDualSpacePushforward() 1262 @*/ 1263 PetscErrorCode PetscFEPushforwardHessian(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[]) 1264 { 1265 PetscErrorCode ierr; 1266 1267 PetscFunctionBeginHot; 1268 ierr = PetscDualSpacePushforwardHessian(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr); 1269 PetscFunctionReturn(0); 1270 } 1271 1272 /* 1273 Purpose: Compute element vector for chunk of elements 1274 1275 Input: 1276 Sizes: 1277 Ne: number of elements 1278 Nf: number of fields 1279 PetscFE 1280 dim: spatial dimension 1281 Nb: number of basis functions 1282 Nc: number of field components 1283 PetscQuadrature 1284 Nq: number of quadrature points 1285 1286 Geometry: 1287 PetscFEGeom[Ne] possibly *Nq 1288 PetscReal v0s[dim] 1289 PetscReal n[dim] 1290 PetscReal jacobians[dim*dim] 1291 PetscReal jacobianInverses[dim*dim] 1292 PetscReal jacobianDeterminants 1293 FEM: 1294 PetscFE 1295 PetscQuadrature 1296 PetscReal quadPoints[Nq*dim] 1297 PetscReal quadWeights[Nq] 1298 PetscReal basis[Nq*Nb*Nc] 1299 PetscReal basisDer[Nq*Nb*Nc*dim] 1300 PetscScalar coefficients[Ne*Nb*Nc] 1301 PetscScalar elemVec[Ne*Nb*Nc] 1302 1303 Problem: 1304 PetscInt f: the active field 1305 f0, f1 1306 1307 Work Space: 1308 PetscFE 1309 PetscScalar f0[Nq*dim]; 1310 PetscScalar f1[Nq*dim*dim]; 1311 PetscScalar u[Nc]; 1312 PetscScalar gradU[Nc*dim]; 1313 PetscReal x[dim]; 1314 PetscScalar realSpaceDer[dim]; 1315 1316 Purpose: Compute element vector for N_cb batches of elements 1317 1318 Input: 1319 Sizes: 1320 N_cb: Number of serial cell batches 1321 1322 Geometry: 1323 PetscReal v0s[Ne*dim] 1324 PetscReal jacobians[Ne*dim*dim] possibly *Nq 1325 PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq 1326 PetscReal jacobianDeterminants[Ne] possibly *Nq 1327 FEM: 1328 static PetscReal quadPoints[Nq*dim] 1329 static PetscReal quadWeights[Nq] 1330 static PetscReal basis[Nq*Nb*Nc] 1331 static PetscReal basisDer[Nq*Nb*Nc*dim] 1332 PetscScalar coefficients[Ne*Nb*Nc] 1333 PetscScalar elemVec[Ne*Nb*Nc] 1334 1335 ex62.c: 1336 PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[], 1337 const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], 1338 void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]), 1339 void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[]) 1340 1341 ex52.c: 1342 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) 1343 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) 1344 1345 ex52_integrateElement.cu 1346 __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec) 1347 1348 PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[], 1349 const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[], 1350 PetscLogEvent event, PetscInt debug, PetscInt pde_op) 1351 1352 ex52_integrateElementOpenCL.c: 1353 PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[], 1354 const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[], 1355 PetscLogEvent event, PetscInt debug, PetscInt pde_op) 1356 1357 __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec) 1358 */ 1359 1360 /*@C 1361 PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration 1362 1363 Not collective 1364 1365 Input Parameters: 1366 + prob - The PetscDS specifying the discretizations and continuum functions 1367 . field - The field being integrated 1368 . Ne - The number of elements in the chunk 1369 . cgeom - The cell geometry for each cell in the chunk 1370 . coefficients - The array of FEM basis coefficients for the elements 1371 . probAux - The PetscDS specifying the auxiliary discretizations 1372 - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1373 1374 Output Parameter: 1375 . integral - the integral for this field 1376 1377 Level: intermediate 1378 1379 .seealso: PetscFEIntegrateResidual() 1380 @*/ 1381 PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom, 1382 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 1383 { 1384 PetscFE fe; 1385 PetscErrorCode ierr; 1386 1387 PetscFunctionBegin; 1388 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1389 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1390 if (fe->ops->integrate) {ierr = (*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);} 1391 PetscFunctionReturn(0); 1392 } 1393 1394 /*@C 1395 PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration 1396 1397 Not collective 1398 1399 Input Parameters: 1400 + prob - The PetscDS specifying the discretizations and continuum functions 1401 . field - The field being integrated 1402 . obj_func - The function to be integrated 1403 . Ne - The number of elements in the chunk 1404 . fgeom - The face geometry for each face in the chunk 1405 . coefficients - The array of FEM basis coefficients for the elements 1406 . probAux - The PetscDS specifying the auxiliary discretizations 1407 - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1408 1409 Output Parameter: 1410 . integral - the integral for this field 1411 1412 Level: intermediate 1413 1414 .seealso: PetscFEIntegrateResidual() 1415 @*/ 1416 PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field, 1417 void (*obj_func)(PetscInt, PetscInt, PetscInt, 1418 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 1419 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 1420 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 1421 PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 1422 { 1423 PetscFE fe; 1424 PetscErrorCode ierr; 1425 1426 PetscFunctionBegin; 1427 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1428 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1429 if (fe->ops->integratebd) {ierr = (*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);} 1430 PetscFunctionReturn(0); 1431 } 1432 1433 /*@C 1434 PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration 1435 1436 Not collective 1437 1438 Input Parameters: 1439 + ds - The PetscDS specifying the discretizations and continuum functions 1440 . key - The (label+value, field) being integrated 1441 . Ne - The number of elements in the chunk 1442 . cgeom - The cell geometry for each cell in the chunk 1443 . coefficients - The array of FEM basis coefficients for the elements 1444 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1445 . probAux - The PetscDS specifying the auxiliary discretizations 1446 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1447 - t - The time 1448 1449 Output Parameter: 1450 . elemVec - the element residual vectors from each element 1451 1452 Note: 1453 $ Loop over batch of elements (e): 1454 $ Loop over quadrature points (q): 1455 $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q 1456 $ Call f_0 and f_1 1457 $ Loop over element vector entries (f,fc --> i): 1458 $ elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u) 1459 1460 Level: intermediate 1461 1462 .seealso: PetscFEIntegrateResidual() 1463 @*/ 1464 PetscErrorCode PetscFEIntegrateResidual(PetscDS ds, PetscFormKey key, PetscInt Ne, PetscFEGeom *cgeom, 1465 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 1466 { 1467 PetscFE fe; 1468 PetscErrorCode ierr; 1469 1470 PetscFunctionBeginHot; 1471 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1472 ierr = PetscDSGetDiscretization(ds, key.field, (PetscObject *) &fe);CHKERRQ(ierr); 1473 if (fe->ops->integrateresidual) {ierr = (*fe->ops->integrateresidual)(ds, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);} 1474 PetscFunctionReturn(0); 1475 } 1476 1477 /*@C 1478 PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary 1479 1480 Not collective 1481 1482 Input Parameters: 1483 + ds - The PetscDS specifying the discretizations and continuum functions 1484 . wf - The PetscWeakForm object holding the pointwise functions 1485 . key - The (label+value, field) being integrated 1486 . Ne - The number of elements in the chunk 1487 . fgeom - The face geometry for each cell in the chunk 1488 . coefficients - The array of FEM basis coefficients for the elements 1489 . coefficients_t - The array of FEM basis time derivative coefficients for the elements 1490 . probAux - The PetscDS specifying the auxiliary discretizations 1491 . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements 1492 - t - The time 1493 1494 Output Parameter: 1495 . elemVec - the element residual vectors from each element 1496 1497 Level: intermediate 1498 1499 .seealso: PetscFEIntegrateResidual() 1500 @*/ 1501 PetscErrorCode PetscFEIntegrateBdResidual(PetscDS ds, PetscWeakForm wf, PetscFormKey key, PetscInt Ne, PetscFEGeom *fgeom, 1502 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 1503 { 1504 PetscFE fe; 1505 PetscErrorCode ierr; 1506 1507 PetscFunctionBegin; 1508 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1509 ierr = PetscDSGetDiscretization(ds, key.field, (PetscObject *) &fe);CHKERRQ(ierr); 1510 if (fe->ops->integratebdresidual) {ierr = (*fe->ops->integratebdresidual)(ds, wf, key, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);} 1511 PetscFunctionReturn(0); 1512 } 1513 1514 /*@C 1515 PetscFEIntegrateHybridResidual - Produce the element residual vector for a chunk of hybrid element faces by quadrature integration 1516 1517 Not collective 1518 1519 Input Parameters: 1520 + prob - The PetscDS specifying the discretizations and continuum functions 1521 . key - The (label+value, field) being integrated 1522 . s - The side of the cell being integrated, 0 for negative and 1 for positive 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 s, 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, s, 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[], PetscInt e, PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[]) 2165 { 2166 PetscFEGeom pgeom; 2167 const PetscInt dEt = T->cdim; 2168 const PetscInt dE = fegeom->dimEmbed; 2169 const PetscInt Nq = T->Np; 2170 const PetscInt Nb = T->Nb; 2171 const PetscInt Nc = T->Nc; 2172 const PetscReal *basis = &T->T[0][r*Nq*Nb*Nc]; 2173 const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dEt]; 2174 PetscInt q, b, c, d; 2175 PetscErrorCode ierr; 2176 2177 for (b = 0; b < Nb; ++b) elemVec[b] = 0.0; 2178 for (q = 0; q < Nq; ++q) { 2179 for (b = 0; b < Nb; ++b) { 2180 for (c = 0; c < Nc; ++c) { 2181 const PetscInt bcidx = b*Nc+c; 2182 2183 tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx]; 2184 for (d = 0; d < dEt; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dEt+bcidx*dEt+d]; 2185 } 2186 } 2187 ierr = PetscFEGeomGetCellPoint(fegeom, e, q, &pgeom);CHKERRQ(ierr); 2188 ierr = PetscFEPushforward(fe, &pgeom, Nb, tmpBasis);CHKERRQ(ierr); 2189 ierr = PetscFEPushforwardGradient(fe, &pgeom, Nb, tmpBasisDer);CHKERRQ(ierr); 2190 for (b = 0; b < Nb; ++b) { 2191 for (c = 0; c < Nc; ++c) { 2192 const PetscInt bcidx = b*Nc+c; 2193 const PetscInt qcidx = q*Nc+c; 2194 2195 elemVec[b] += tmpBasis[bcidx]*f0[qcidx]; 2196 for (d = 0; d < dE; ++d) elemVec[b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d]; 2197 } 2198 } 2199 } 2200 return(0); 2201 } 2202 2203 PetscErrorCode PetscFEUpdateElementVec_Hybrid_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscInt s, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[]) 2204 { 2205 const PetscInt dE = T->cdim; 2206 const PetscInt Nq = T->Np; 2207 const PetscInt Nb = T->Nb; 2208 const PetscInt Nc = T->Nc; 2209 const PetscReal *basis = &T->T[0][r*Nq*Nb*Nc]; 2210 const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE]; 2211 PetscInt q, b, c, d; 2212 PetscErrorCode ierr; 2213 2214 for (b = 0; b < Nb; ++b) elemVec[Nb*s+b] = 0.0; 2215 for (q = 0; q < Nq; ++q) { 2216 for (b = 0; b < Nb; ++b) { 2217 for (c = 0; c < Nc; ++c) { 2218 const PetscInt bcidx = b*Nc+c; 2219 2220 tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx]; 2221 for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d]; 2222 } 2223 } 2224 ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr); 2225 ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr); 2226 for (b = 0; b < Nb; ++b) { 2227 for (c = 0; c < Nc; ++c) { 2228 const PetscInt bcidx = b*Nc+c; 2229 const PetscInt qcidx = q*Nc+c; 2230 2231 elemVec[Nb*s+b] += tmpBasis[bcidx]*f0[qcidx]; 2232 for (d = 0; d < dE; ++d) elemVec[Nb*s+b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d]; 2233 } 2234 } 2235 } 2236 return(0); 2237 } 2238 2239 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[]) 2240 { 2241 const PetscInt dE = TI->cdim; 2242 const PetscInt NqI = TI->Np; 2243 const PetscInt NbI = TI->Nb; 2244 const PetscInt NcI = TI->Nc; 2245 const PetscReal *basisI = &TI->T[0][(r*NqI+q)*NbI*NcI]; 2246 const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE]; 2247 const PetscInt NqJ = TJ->Np; 2248 const PetscInt NbJ = TJ->Nb; 2249 const PetscInt NcJ = TJ->Nc; 2250 const PetscReal *basisJ = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ]; 2251 const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE]; 2252 PetscInt f, fc, g, gc, df, dg; 2253 PetscErrorCode ierr; 2254 2255 for (f = 0; f < NbI; ++f) { 2256 for (fc = 0; fc < NcI; ++fc) { 2257 const PetscInt fidx = f*NcI+fc; /* Test function basis index */ 2258 2259 tmpBasisI[fidx] = basisI[fidx]; 2260 for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df]; 2261 } 2262 } 2263 ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr); 2264 ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr); 2265 for (g = 0; g < NbJ; ++g) { 2266 for (gc = 0; gc < NcJ; ++gc) { 2267 const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */ 2268 2269 tmpBasisJ[gidx] = basisJ[gidx]; 2270 for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg]; 2271 } 2272 } 2273 ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr); 2274 ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr); 2275 for (f = 0; f < NbI; ++f) { 2276 for (fc = 0; fc < NcI; ++fc) { 2277 const PetscInt fidx = f*NcI+fc; /* Test function basis index */ 2278 const PetscInt i = offsetI+f; /* Element matrix row */ 2279 for (g = 0; g < NbJ; ++g) { 2280 for (gc = 0; gc < NcJ; ++gc) { 2281 const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */ 2282 const PetscInt j = offsetJ+g; /* Element matrix column */ 2283 const PetscInt fOff = eOffset+i*totDim+j; 2284 2285 elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx]; 2286 for (df = 0; df < dE; ++df) { 2287 elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dE+df]*tmpBasisDerJ[gidx*dE+df]; 2288 elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(fc*NcJ+gc)*dE+df]*tmpBasisJ[gidx]; 2289 for (dg = 0; dg < dE; ++dg) { 2290 elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((fc*NcJ+gc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg]; 2291 } 2292 } 2293 } 2294 } 2295 } 2296 } 2297 return(0); 2298 } 2299 2300 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[]) 2301 { 2302 const PetscInt dE = TI->cdim; 2303 const PetscInt NqI = TI->Np; 2304 const PetscInt NbI = TI->Nb; 2305 const PetscInt NcI = TI->Nc; 2306 const PetscReal *basisI = &TI->T[0][(r*NqI+q)*NbI*NcI]; 2307 const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE]; 2308 const PetscInt NqJ = TJ->Np; 2309 const PetscInt NbJ = TJ->Nb; 2310 const PetscInt NcJ = TJ->Nc; 2311 const PetscReal *basisJ = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ]; 2312 const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE]; 2313 const PetscInt Ns = isHybridI ? 1 : 2; 2314 const PetscInt Nt = isHybridJ ? 1 : 2; 2315 PetscInt f, fc, g, gc, df, dg, s, t; 2316 PetscErrorCode ierr; 2317 2318 for (f = 0; f < NbI; ++f) { 2319 for (fc = 0; fc < NcI; ++fc) { 2320 const PetscInt fidx = f*NcI+fc; /* Test function basis index */ 2321 2322 tmpBasisI[fidx] = basisI[fidx]; 2323 for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df]; 2324 } 2325 } 2326 ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr); 2327 ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr); 2328 for (g = 0; g < NbJ; ++g) { 2329 for (gc = 0; gc < NcJ; ++gc) { 2330 const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */ 2331 2332 tmpBasisJ[gidx] = basisJ[gidx]; 2333 for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg]; 2334 } 2335 } 2336 ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr); 2337 ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr); 2338 for (s = 0; s < Ns; ++s) { 2339 for (f = 0; f < NbI; ++f) { 2340 for (fc = 0; fc < NcI; ++fc) { 2341 const PetscInt sc = NcI*s+fc; /* components from each side of the surface */ 2342 const PetscInt fidx = f*NcI+fc; /* Test function basis index */ 2343 const PetscInt i = offsetI+NbI*s+f; /* Element matrix row */ 2344 for (t = 0; t < Nt; ++t) { 2345 for (g = 0; g < NbJ; ++g) { 2346 for (gc = 0; gc < NcJ; ++gc) { 2347 const PetscInt tc = NcJ*t+gc; /* components from each side of the surface */ 2348 const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */ 2349 const PetscInt j = offsetJ+NbJ*t+g; /* Element matrix column */ 2350 const PetscInt fOff = eOffset+i*totDim+j; 2351 2352 elemMat[fOff] += tmpBasisI[fidx]*g0[sc*NcJ*Nt+tc]*tmpBasisJ[gidx]; 2353 for (df = 0; df < dE; ++df) { 2354 elemMat[fOff] += tmpBasisI[fidx]*g1[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisDerJ[gidx*dE+df]; 2355 elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisJ[gidx]; 2356 for (dg = 0; dg < dE; ++dg) { 2357 elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((sc*NcJ*Nt+tc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg]; 2358 } 2359 } 2360 } 2361 } 2362 } 2363 } 2364 } 2365 } 2366 return(0); 2367 } 2368 2369 PetscErrorCode PetscFECreateCellGeometry(PetscFE fe, PetscQuadrature quad, PetscFEGeom *cgeom) 2370 { 2371 PetscDualSpace dsp; 2372 DM dm; 2373 PetscQuadrature quadDef; 2374 PetscInt dim, cdim, Nq; 2375 PetscErrorCode ierr; 2376 2377 PetscFunctionBegin; 2378 ierr = PetscFEGetDualSpace(fe, &dsp);CHKERRQ(ierr); 2379 ierr = PetscDualSpaceGetDM(dsp, &dm);CHKERRQ(ierr); 2380 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2381 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 2382 ierr = PetscFEGetQuadrature(fe, &quadDef);CHKERRQ(ierr); 2383 quad = quad ? quad : quadDef; 2384 ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 2385 ierr = PetscMalloc1(Nq*cdim, &cgeom->v);CHKERRQ(ierr); 2386 ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->J);CHKERRQ(ierr); 2387 ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->invJ);CHKERRQ(ierr); 2388 ierr = PetscMalloc1(Nq, &cgeom->detJ);CHKERRQ(ierr); 2389 cgeom->dim = dim; 2390 cgeom->dimEmbed = cdim; 2391 cgeom->numCells = 1; 2392 cgeom->numPoints = Nq; 2393 ierr = DMPlexComputeCellGeometryFEM(dm, 0, quad, cgeom->v, cgeom->J, cgeom->invJ, cgeom->detJ);CHKERRQ(ierr); 2394 PetscFunctionReturn(0); 2395 } 2396 2397 PetscErrorCode PetscFEDestroyCellGeometry(PetscFE fe, PetscFEGeom *cgeom) 2398 { 2399 PetscErrorCode ierr; 2400 2401 PetscFunctionBegin; 2402 ierr = PetscFree(cgeom->v);CHKERRQ(ierr); 2403 ierr = PetscFree(cgeom->J);CHKERRQ(ierr); 2404 ierr = PetscFree(cgeom->invJ);CHKERRQ(ierr); 2405 ierr = PetscFree(cgeom->detJ);CHKERRQ(ierr); 2406 PetscFunctionReturn(0); 2407 } 2408