1 #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 2 #include <petscdmplex.h> 3 4 PetscClassId PETSCDUALSPACE_CLASSID = 0; 5 6 PetscFunctionList PetscDualSpaceList = NULL; 7 PetscBool PetscDualSpaceRegisterAllCalled = PETSC_FALSE; 8 9 const char *const PetscDualSpaceReferenceCells[] = {"SIMPLEX", "TENSOR", "PetscDualSpaceReferenceCell", "PETSCDUALSPACE_REFCELL_",0}; 10 11 /*@C 12 PetscDualSpaceRegister - Adds a new PetscDualSpace implementation 13 14 Not Collective 15 16 Input Parameters: 17 + name - The name of a new user-defined creation routine 18 - create_func - The creation routine itself 19 20 Notes: 21 PetscDualSpaceRegister() may be called multiple times to add several user-defined PetscDualSpaces 22 23 Sample usage: 24 .vb 25 PetscDualSpaceRegister("my_space", MyPetscDualSpaceCreate); 26 .ve 27 28 Then, your PetscDualSpace type can be chosen with the procedural interface via 29 .vb 30 PetscDualSpaceCreate(MPI_Comm, PetscDualSpace *); 31 PetscDualSpaceSetType(PetscDualSpace, "my_dual_space"); 32 .ve 33 or at runtime via the option 34 .vb 35 -petscdualspace_type my_dual_space 36 .ve 37 38 Level: advanced 39 40 .keywords: PetscDualSpace, register 41 .seealso: PetscDualSpaceRegisterAll(), PetscDualSpaceRegisterDestroy() 42 43 @*/ 44 PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) 45 { 46 PetscErrorCode ierr; 47 48 PetscFunctionBegin; 49 ierr = PetscFunctionListAdd(&PetscDualSpaceList, sname, function);CHKERRQ(ierr); 50 PetscFunctionReturn(0); 51 } 52 53 /*@C 54 PetscDualSpaceSetType - Builds a particular PetscDualSpace 55 56 Collective on PetscDualSpace 57 58 Input Parameters: 59 + sp - The PetscDualSpace object 60 - name - The kind of space 61 62 Options Database Key: 63 . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types 64 65 Level: intermediate 66 67 .keywords: PetscDualSpace, set, type 68 .seealso: PetscDualSpaceGetType(), PetscDualSpaceCreate() 69 @*/ 70 PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) 71 { 72 PetscErrorCode (*r)(PetscDualSpace); 73 PetscBool match; 74 PetscErrorCode ierr; 75 76 PetscFunctionBegin; 77 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 78 ierr = PetscObjectTypeCompare((PetscObject) sp, name, &match);CHKERRQ(ierr); 79 if (match) PetscFunctionReturn(0); 80 81 if (!PetscDualSpaceRegisterAllCalled) {ierr = PetscDualSpaceRegisterAll();CHKERRQ(ierr);} 82 ierr = PetscFunctionListFind(PetscDualSpaceList, name, &r);CHKERRQ(ierr); 83 if (!r) SETERRQ1(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name); 84 85 if (sp->ops->destroy) { 86 ierr = (*sp->ops->destroy)(sp);CHKERRQ(ierr); 87 sp->ops->destroy = NULL; 88 } 89 ierr = (*r)(sp);CHKERRQ(ierr); 90 ierr = PetscObjectChangeTypeName((PetscObject) sp, name);CHKERRQ(ierr); 91 PetscFunctionReturn(0); 92 } 93 94 /*@C 95 PetscDualSpaceGetType - Gets the PetscDualSpace type name (as a string) from the object. 96 97 Not Collective 98 99 Input Parameter: 100 . sp - The PetscDualSpace 101 102 Output Parameter: 103 . name - The PetscDualSpace type name 104 105 Level: intermediate 106 107 .keywords: PetscDualSpace, get, type, name 108 .seealso: PetscDualSpaceSetType(), PetscDualSpaceCreate() 109 @*/ 110 PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name) 111 { 112 PetscErrorCode ierr; 113 114 PetscFunctionBegin; 115 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 116 PetscValidPointer(name, 2); 117 if (!PetscDualSpaceRegisterAllCalled) { 118 ierr = PetscDualSpaceRegisterAll();CHKERRQ(ierr); 119 } 120 *name = ((PetscObject) sp)->type_name; 121 PetscFunctionReturn(0); 122 } 123 124 /*@ 125 PetscDualSpaceView - Views a PetscDualSpace 126 127 Collective on PetscDualSpace 128 129 Input Parameter: 130 + sp - the PetscDualSpace object to view 131 - v - the viewer 132 133 Level: developer 134 135 .seealso PetscDualSpaceDestroy() 136 @*/ 137 PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) 138 { 139 PetscBool iascii; 140 PetscErrorCode ierr; 141 142 PetscFunctionBegin; 143 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 144 if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 145 if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) sp), &v);CHKERRQ(ierr);} 146 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)sp, v);CHKERRQ(ierr); 147 ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 148 ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); 149 if (iascii) {ierr = PetscViewerASCIIPrintf(v, "Dual space of order %D with %D components\n", sp->order, sp->Nc);CHKERRQ(ierr);} 150 if (sp->ops->view) {ierr = (*sp->ops->view)(sp, v);CHKERRQ(ierr);} 151 ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); 152 PetscFunctionReturn(0); 153 } 154 155 /*@ 156 PetscDualSpaceSetFromOptions - sets parameters in a PetscDualSpace from the options database 157 158 Collective on PetscDualSpace 159 160 Input Parameter: 161 . sp - the PetscDualSpace object to set options for 162 163 Options Database: 164 . -petscspace_degree the approximation order of the space 165 166 Level: developer 167 168 .seealso PetscDualSpaceView() 169 @*/ 170 PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 171 { 172 PetscDualSpaceReferenceCell refCell = PETSCDUALSPACE_REFCELL_SIMPLEX; 173 PetscInt refDim = 0; 174 PetscBool flg; 175 const char *defaultType; 176 char name[256]; 177 PetscErrorCode ierr; 178 179 PetscFunctionBegin; 180 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 181 if (!((PetscObject) sp)->type_name) { 182 defaultType = PETSCDUALSPACELAGRANGE; 183 } else { 184 defaultType = ((PetscObject) sp)->type_name; 185 } 186 if (!PetscSpaceRegisterAllCalled) {ierr = PetscSpaceRegisterAll();CHKERRQ(ierr);} 187 188 ierr = PetscObjectOptionsBegin((PetscObject) sp);CHKERRQ(ierr); 189 ierr = PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg);CHKERRQ(ierr); 190 if (flg) { 191 ierr = PetscDualSpaceSetType(sp, name);CHKERRQ(ierr); 192 } else if (!((PetscObject) sp)->type_name) { 193 ierr = PetscDualSpaceSetType(sp, defaultType);CHKERRQ(ierr); 194 } 195 ierr = PetscOptionsInt("-petscdualspace_degree", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL);CHKERRQ(ierr); 196 ierr = PetscOptionsInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL);CHKERRQ(ierr); 197 if (sp->ops->setfromoptions) { 198 ierr = (*sp->ops->setfromoptions)(PetscOptionsObject,sp);CHKERRQ(ierr); 199 } 200 ierr = PetscOptionsInt("-petscdualspace_refdim", "The spatial dimension of the reference cell", "PetscDualSpaceSetReferenceCell", refDim, &refDim, NULL);CHKERRQ(ierr); 201 ierr = PetscOptionsEnum("-petscdualspace_refcell", "Reference cell", "PetscDualSpaceSetReferenceCell", PetscDualSpaceReferenceCells, (PetscEnum) refCell, (PetscEnum *) &refCell, &flg);CHKERRQ(ierr); 202 if (flg) { 203 DM K; 204 205 if (!refDim) SETERRQ(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_INCOMP, "Reference cell specified without a dimension. Use -petscdualspace_refdim."); 206 ierr = PetscDualSpaceCreateReferenceCell(sp, refDim, refCell == PETSCDUALSPACE_REFCELL_SIMPLEX ? PETSC_TRUE : PETSC_FALSE, &K);CHKERRQ(ierr); 207 ierr = PetscDualSpaceSetDM(sp, K);CHKERRQ(ierr); 208 ierr = DMDestroy(&K);CHKERRQ(ierr); 209 } 210 211 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 212 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) sp);CHKERRQ(ierr); 213 ierr = PetscOptionsEnd();CHKERRQ(ierr); 214 sp->setfromoptionscalled = PETSC_TRUE; 215 PetscFunctionReturn(0); 216 } 217 218 /*@ 219 PetscDualSpaceSetUp - Construct a basis for the PetscDualSpace 220 221 Collective on PetscDualSpace 222 223 Input Parameter: 224 . sp - the PetscDualSpace object to setup 225 226 Level: developer 227 228 .seealso PetscDualSpaceView(), PetscDualSpaceDestroy() 229 @*/ 230 PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 231 { 232 PetscErrorCode ierr; 233 234 PetscFunctionBegin; 235 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 236 if (sp->setupcalled) PetscFunctionReturn(0); 237 sp->setupcalled = PETSC_TRUE; 238 if (sp->ops->setup) {ierr = (*sp->ops->setup)(sp);CHKERRQ(ierr);} 239 if (sp->setfromoptionscalled) {ierr = PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view");CHKERRQ(ierr);} 240 PetscFunctionReturn(0); 241 } 242 243 /*@ 244 PetscDualSpaceDestroy - Destroys a PetscDualSpace object 245 246 Collective on PetscDualSpace 247 248 Input Parameter: 249 . sp - the PetscDualSpace object to destroy 250 251 Level: developer 252 253 .seealso PetscDualSpaceView() 254 @*/ 255 PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 256 { 257 PetscInt dim, f; 258 PetscErrorCode ierr; 259 260 PetscFunctionBegin; 261 if (!*sp) PetscFunctionReturn(0); 262 PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 263 264 if (--((PetscObject)(*sp))->refct > 0) {*sp = 0; PetscFunctionReturn(0);} 265 ((PetscObject) (*sp))->refct = 0; 266 267 ierr = PetscDualSpaceGetDimension(*sp, &dim);CHKERRQ(ierr); 268 for (f = 0; f < dim; ++f) { 269 ierr = PetscQuadratureDestroy(&(*sp)->functional[f]);CHKERRQ(ierr); 270 } 271 ierr = PetscFree((*sp)->functional);CHKERRQ(ierr); 272 ierr = PetscQuadratureDestroy(&(*sp)->allPoints);CHKERRQ(ierr); 273 ierr = DMDestroy(&(*sp)->dm);CHKERRQ(ierr); 274 275 if ((*sp)->ops->destroy) {ierr = (*(*sp)->ops->destroy)(*sp);CHKERRQ(ierr);} 276 ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 277 PetscFunctionReturn(0); 278 } 279 280 /*@ 281 PetscDualSpaceCreate - Creates an empty PetscDualSpace object. The type can then be set with PetscDualSpaceSetType(). 282 283 Collective on MPI_Comm 284 285 Input Parameter: 286 . comm - The communicator for the PetscDualSpace object 287 288 Output Parameter: 289 . sp - The PetscDualSpace object 290 291 Level: beginner 292 293 .seealso: PetscDualSpaceSetType(), PETSCDUALSPACELAGRANGE 294 @*/ 295 PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 296 { 297 PetscDualSpace s; 298 PetscErrorCode ierr; 299 300 PetscFunctionBegin; 301 PetscValidPointer(sp, 2); 302 ierr = PetscCitationsRegister(FECitation,&FEcite);CHKERRQ(ierr); 303 *sp = NULL; 304 ierr = PetscFEInitializePackage();CHKERRQ(ierr); 305 306 ierr = PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView);CHKERRQ(ierr); 307 308 s->order = 0; 309 s->Nc = 1; 310 s->setupcalled = PETSC_FALSE; 311 312 *sp = s; 313 PetscFunctionReturn(0); 314 } 315 316 /*@ 317 PetscDualSpaceDuplicate - Creates a duplicate PetscDualSpace object, however it is not setup. 318 319 Collective on PetscDualSpace 320 321 Input Parameter: 322 . sp - The original PetscDualSpace 323 324 Output Parameter: 325 . spNew - The duplicate PetscDualSpace 326 327 Level: beginner 328 329 .seealso: PetscDualSpaceCreate(), PetscDualSpaceSetType() 330 @*/ 331 PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 332 { 333 PetscErrorCode ierr; 334 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 337 PetscValidPointer(spNew, 2); 338 ierr = (*sp->ops->duplicate)(sp, spNew);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 /*@ 343 PetscDualSpaceGetDM - Get the DM representing the reference cell 344 345 Not collective 346 347 Input Parameter: 348 . sp - The PetscDualSpace 349 350 Output Parameter: 351 . dm - The reference cell 352 353 Level: intermediate 354 355 .seealso: PetscDualSpaceSetDM(), PetscDualSpaceCreate() 356 @*/ 357 PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 358 { 359 PetscFunctionBegin; 360 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 361 PetscValidPointer(dm, 2); 362 *dm = sp->dm; 363 PetscFunctionReturn(0); 364 } 365 366 /*@ 367 PetscDualSpaceSetDM - Get the DM representing the reference cell 368 369 Not collective 370 371 Input Parameters: 372 + sp - The PetscDualSpace 373 - dm - The reference cell 374 375 Level: intermediate 376 377 .seealso: PetscDualSpaceGetDM(), PetscDualSpaceCreate() 378 @*/ 379 PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 380 { 381 PetscErrorCode ierr; 382 383 PetscFunctionBegin; 384 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 385 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 386 ierr = DMDestroy(&sp->dm);CHKERRQ(ierr); 387 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 388 sp->dm = dm; 389 PetscFunctionReturn(0); 390 } 391 392 /*@ 393 PetscDualSpaceGetOrder - Get the order of the dual space 394 395 Not collective 396 397 Input Parameter: 398 . sp - The PetscDualSpace 399 400 Output Parameter: 401 . order - The order 402 403 Level: intermediate 404 405 .seealso: PetscDualSpaceSetOrder(), PetscDualSpaceCreate() 406 @*/ 407 PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 408 { 409 PetscFunctionBegin; 410 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 411 PetscValidPointer(order, 2); 412 *order = sp->order; 413 PetscFunctionReturn(0); 414 } 415 416 /*@ 417 PetscDualSpaceSetOrder - Set the order of the dual space 418 419 Not collective 420 421 Input Parameters: 422 + sp - The PetscDualSpace 423 - order - The order 424 425 Level: intermediate 426 427 .seealso: PetscDualSpaceGetOrder(), PetscDualSpaceCreate() 428 @*/ 429 PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 433 sp->order = order; 434 PetscFunctionReturn(0); 435 } 436 437 /*@ 438 PetscDualSpaceGetNumComponents - Return the number of components for this space 439 440 Input Parameter: 441 . sp - The PetscDualSpace 442 443 Output Parameter: 444 . Nc - The number of components 445 446 Note: A vector space, for example, will have d components, where d is the spatial dimension 447 448 Level: intermediate 449 450 .seealso: PetscDualSpaceSetNumComponents(), PetscDualSpaceGetDimension(), PetscDualSpaceCreate(), PetscDualSpace 451 @*/ 452 PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 453 { 454 PetscFunctionBegin; 455 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 456 PetscValidPointer(Nc, 2); 457 *Nc = sp->Nc; 458 PetscFunctionReturn(0); 459 } 460 461 /*@ 462 PetscDualSpaceSetNumComponents - Set the number of components for this space 463 464 Input Parameters: 465 + sp - The PetscDualSpace 466 - order - The number of components 467 468 Level: intermediate 469 470 .seealso: PetscDualSpaceGetNumComponents(), PetscDualSpaceCreate(), PetscDualSpace 471 @*/ 472 PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 473 { 474 PetscFunctionBegin; 475 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 476 sp->Nc = Nc; 477 PetscFunctionReturn(0); 478 } 479 480 /*@ 481 PetscDualSpaceLagrangeGetTensor - Get the tensor nature of the dual space 482 483 Not collective 484 485 Input Parameter: 486 . sp - The PetscDualSpace 487 488 Output Parameter: 489 . tensor - Whether the dual space has tensor layout (vs. simplicial) 490 491 Level: intermediate 492 493 .seealso: PetscDualSpaceLagrangeSetTensor(), PetscDualSpaceCreate() 494 @*/ 495 PetscErrorCode PetscDualSpaceLagrangeGetTensor(PetscDualSpace sp, PetscBool *tensor) 496 { 497 PetscErrorCode ierr; 498 499 PetscFunctionBegin; 500 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 501 PetscValidPointer(tensor, 2); 502 ierr = PetscTryMethod(sp,"PetscDualSpaceLagrangeGetTensor_C",(PetscDualSpace,PetscBool *),(sp,tensor));CHKERRQ(ierr); 503 PetscFunctionReturn(0); 504 } 505 506 /*@ 507 PetscDualSpaceLagrangeSetTensor - Set the tensor nature of the dual space 508 509 Not collective 510 511 Input Parameters: 512 + sp - The PetscDualSpace 513 - tensor - Whether the dual space has tensor layout (vs. simplicial) 514 515 Level: intermediate 516 517 .seealso: PetscDualSpaceLagrangeGetTensor(), PetscDualSpaceCreate() 518 @*/ 519 PetscErrorCode PetscDualSpaceLagrangeSetTensor(PetscDualSpace sp, PetscBool tensor) 520 { 521 PetscErrorCode ierr; 522 523 PetscFunctionBegin; 524 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 525 ierr = PetscTryMethod(sp,"PetscDualSpaceLagrangeSetTensor_C",(PetscDualSpace,PetscBool),(sp,tensor));CHKERRQ(ierr); 526 PetscFunctionReturn(0); 527 } 528 529 /*@ 530 PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 531 532 Not collective 533 534 Input Parameters: 535 + sp - The PetscDualSpace 536 - i - The basis number 537 538 Output Parameter: 539 . functional - The basis functional 540 541 Level: intermediate 542 543 .seealso: PetscDualSpaceGetDimension(), PetscDualSpaceCreate() 544 @*/ 545 PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 546 { 547 PetscInt dim; 548 PetscErrorCode ierr; 549 550 PetscFunctionBegin; 551 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 552 PetscValidPointer(functional, 3); 553 ierr = PetscDualSpaceGetDimension(sp, &dim);CHKERRQ(ierr); 554 if ((i < 0) || (i >= dim)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Functional index %d must be in [0, %d)", i, dim); 555 *functional = sp->functional[i]; 556 PetscFunctionReturn(0); 557 } 558 559 /*@ 560 PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 561 562 Not collective 563 564 Input Parameter: 565 . sp - The PetscDualSpace 566 567 Output Parameter: 568 . dim - The dimension 569 570 Level: intermediate 571 572 .seealso: PetscDualSpaceGetFunctional(), PetscDualSpaceCreate() 573 @*/ 574 PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 575 { 576 PetscErrorCode ierr; 577 578 PetscFunctionBegin; 579 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 580 PetscValidPointer(dim, 2); 581 *dim = 0; 582 if (sp->ops->getdimension) {ierr = (*sp->ops->getdimension)(sp, dim);CHKERRQ(ierr);} 583 PetscFunctionReturn(0); 584 } 585 586 /*@C 587 PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 588 589 Not collective 590 591 Input Parameter: 592 . sp - The PetscDualSpace 593 594 Output Parameter: 595 . numDof - An array of length dim+1 which holds the number of dofs for each dimension 596 597 Level: intermediate 598 599 .seealso: PetscDualSpaceGetFunctional(), PetscDualSpaceCreate() 600 @*/ 601 PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 602 { 603 PetscErrorCode ierr; 604 605 PetscFunctionBegin; 606 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 607 PetscValidPointer(numDof, 2); 608 ierr = (*sp->ops->getnumdof)(sp, numDof);CHKERRQ(ierr); 609 if (!*numDof) SETERRQ(PetscObjectComm((PetscObject) sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 610 PetscFunctionReturn(0); 611 } 612 613 PetscErrorCode PetscDualSpaceCreateSection(PetscDualSpace sp, PetscSection *section) 614 { 615 DM dm; 616 PetscInt pStart, pEnd, depth, h, offset; 617 const PetscInt *numDof; 618 PetscErrorCode ierr; 619 620 PetscFunctionBegin; 621 ierr = PetscDualSpaceGetDM(sp,&dm);CHKERRQ(ierr); 622 ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 623 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)sp),section);CHKERRQ(ierr); 624 ierr = PetscSectionSetChart(*section,pStart,pEnd);CHKERRQ(ierr); 625 ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 626 ierr = PetscDualSpaceGetNumDof(sp,&numDof);CHKERRQ(ierr); 627 for (h = 0; h <= depth; h++) { 628 PetscInt hStart, hEnd, p, dof; 629 630 ierr = DMPlexGetHeightStratum(dm,h,&hStart,&hEnd);CHKERRQ(ierr); 631 dof = numDof[depth - h]; 632 for (p = hStart; p < hEnd; p++) { 633 ierr = PetscSectionSetDof(*section,p,dof);CHKERRQ(ierr); 634 } 635 } 636 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 637 for (h = 0, offset = 0; h <= depth; h++) { 638 PetscInt hStart, hEnd, p, dof; 639 640 ierr = DMPlexGetHeightStratum(dm,h,&hStart,&hEnd);CHKERRQ(ierr); 641 dof = numDof[depth - h]; 642 for (p = hStart; p < hEnd; p++) { 643 ierr = PetscSectionGetDof(*section,p,&dof);CHKERRQ(ierr); 644 ierr = PetscSectionSetOffset(*section,p,offset);CHKERRQ(ierr); 645 offset += dof; 646 } 647 } 648 PetscFunctionReturn(0); 649 } 650 651 /*@ 652 PetscDualSpaceCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 653 654 Collective on PetscDualSpace 655 656 Input Parameters: 657 + sp - The PetscDualSpace 658 . dim - The spatial dimension 659 - simplex - Flag for simplex, otherwise use a tensor-product cell 660 661 Output Parameter: 662 . refdm - The reference cell 663 664 Level: advanced 665 666 .keywords: PetscDualSpace, reference cell 667 .seealso: PetscDualSpaceCreate(), DMPLEX 668 @*/ 669 PetscErrorCode PetscDualSpaceCreateReferenceCell(PetscDualSpace sp, PetscInt dim, PetscBool simplex, DM *refdm) 670 { 671 PetscErrorCode ierr; 672 673 PetscFunctionBeginUser; 674 ierr = DMPlexCreateReferenceCell(PetscObjectComm((PetscObject) sp), dim, simplex, refdm);CHKERRQ(ierr); 675 PetscFunctionReturn(0); 676 } 677 678 /*@C 679 PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 680 681 Input Parameters: 682 + sp - The PetscDualSpace object 683 . f - The basis functional index 684 . time - The time 685 . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) (or evaluated at the coordinates of the functional) 686 . numComp - The number of components for the function 687 . func - The input function 688 - ctx - A context for the function 689 690 Output Parameter: 691 . value - numComp output values 692 693 Note: The calling sequence for the callback func is given by: 694 695 $ func(PetscInt dim, PetscReal time, const PetscReal x[], 696 $ PetscInt numComponents, PetscScalar values[], void *ctx) 697 698 Level: developer 699 700 .seealso: PetscDualSpaceCreate() 701 @*/ 702 PetscErrorCode PetscDualSpaceApply(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt numComp, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) 703 { 704 PetscErrorCode ierr; 705 706 PetscFunctionBegin; 707 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 708 PetscValidPointer(cgeom, 4); 709 PetscValidPointer(value, 8); 710 ierr = (*sp->ops->apply)(sp, f, time, cgeom, numComp, func, ctx, value);CHKERRQ(ierr); 711 PetscFunctionReturn(0); 712 } 713 714 /*@C 715 PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllPoints() 716 717 Input Parameters: 718 + sp - The PetscDualSpace object 719 - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllPoints() 720 721 Output Parameter: 722 . spValue - The values of all dual space functionals 723 724 Level: developer 725 726 .seealso: PetscDualSpaceCreate() 727 @*/ 728 PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 729 { 730 PetscErrorCode ierr; 731 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 734 ierr = (*sp->ops->applyall)(sp, pointEval, spValue);CHKERRQ(ierr); 735 PetscFunctionReturn(0); 736 } 737 738 /*@C 739 PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 740 741 Input Parameters: 742 + sp - The PetscDualSpace object 743 . f - The basis functional index 744 . time - The time 745 . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 746 . Nc - The number of components for the function 747 . func - The input function 748 - ctx - A context for the function 749 750 Output Parameter: 751 . value - The output value 752 753 Note: The calling sequence for the callback func is given by: 754 755 $ func(PetscInt dim, PetscReal time, const PetscReal x[], 756 $ PetscInt numComponents, PetscScalar values[], void *ctx) 757 758 and the idea is to evaluate the functional as an integral 759 760 $ n(f) = int dx n(x) . f(x) 761 762 where both n and f have Nc components. 763 764 Level: developer 765 766 .seealso: PetscDualSpaceCreate() 767 @*/ 768 PetscErrorCode PetscDualSpaceApplyDefault(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) 769 { 770 DM dm; 771 PetscQuadrature n; 772 const PetscReal *points, *weights; 773 PetscReal x[3]; 774 PetscScalar *val; 775 PetscInt dim, dE, qNc, c, Nq, q; 776 PetscBool isAffine; 777 PetscErrorCode ierr; 778 779 PetscFunctionBegin; 780 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 781 PetscValidPointer(value, 5); 782 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 783 ierr = PetscDualSpaceGetFunctional(sp, f, &n);CHKERRQ(ierr); 784 ierr = PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights);CHKERRQ(ierr); 785 if (dim != cgeom->dim) SETERRQ2(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature spatial dimension %D != cell geometry dimension %D", dim, cgeom->dim); 786 if (qNc != Nc) SETERRQ2(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %D != function components %D", qNc, Nc); 787 ierr = DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val);CHKERRQ(ierr); 788 *value = 0.0; 789 isAffine = cgeom->isAffine; 790 dE = cgeom->dimEmbed; 791 for (q = 0; q < Nq; ++q) { 792 if (isAffine) { 793 CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q*dim], x); 794 ierr = (*func)(dE, time, x, Nc, val, ctx);CHKERRQ(ierr); 795 } else { 796 ierr = (*func)(dE, time, &cgeom->v[dE*q], Nc, val, ctx);CHKERRQ(ierr); 797 } 798 for (c = 0; c < Nc; ++c) { 799 *value += val[c]*weights[q*Nc+c]; 800 } 801 } 802 ierr = DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val);CHKERRQ(ierr); 803 PetscFunctionReturn(0); 804 } 805 806 /*@C 807 PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllPoints() 808 809 Input Parameters: 810 + sp - The PetscDualSpace object 811 - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllPoints() 812 813 Output Parameter: 814 . spValue - The values of all dual space functionals 815 816 Level: developer 817 818 .seealso: PetscDualSpaceCreate() 819 @*/ 820 PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 821 { 822 PetscQuadrature n; 823 const PetscReal *points, *weights; 824 PetscInt qNc, c, Nq, q, f, spdim, Nc; 825 PetscInt offset; 826 PetscErrorCode ierr; 827 828 PetscFunctionBegin; 829 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 830 PetscValidScalarPointer(pointEval, 2); 831 PetscValidScalarPointer(spValue, 5); 832 ierr = PetscDualSpaceGetDimension(sp, &spdim);CHKERRQ(ierr); 833 ierr = PetscDualSpaceGetNumComponents(sp, &Nc);CHKERRQ(ierr); 834 for (f = 0, offset = 0; f < spdim; f++) { 835 ierr = PetscDualSpaceGetFunctional(sp, f, &n);CHKERRQ(ierr); 836 ierr = PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights);CHKERRQ(ierr); 837 if (qNc != Nc) SETERRQ2(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %D != function components %D", qNc, Nc); 838 spValue[f] = 0.0; 839 for (q = 0; q < Nq; ++q) { 840 for (c = 0; c < Nc; ++c) { 841 spValue[f] += pointEval[offset++]*weights[q*Nc+c]; 842 } 843 } 844 } 845 PetscFunctionReturn(0); 846 } 847 848 PetscErrorCode PetscDualSpaceGetAllPoints(PetscDualSpace sp, PetscQuadrature *allPoints) 849 { 850 PetscErrorCode ierr; 851 852 PetscFunctionBegin; 853 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 854 PetscValidPointer(allPoints,2); 855 if (!sp->allPoints && sp->ops->createallpoints) { 856 ierr = (*sp->ops->createallpoints)(sp,&sp->allPoints);CHKERRQ(ierr); 857 } 858 *allPoints = sp->allPoints; 859 PetscFunctionReturn(0); 860 } 861 862 PetscErrorCode PetscDualSpaceCreateAllPointsDefault(PetscDualSpace sp, PetscQuadrature *allPoints) 863 { 864 PetscInt spdim; 865 PetscInt numPoints, offset; 866 PetscReal *points; 867 PetscInt f, dim; 868 PetscQuadrature q; 869 PetscErrorCode ierr; 870 871 PetscFunctionBegin; 872 ierr = PetscDualSpaceGetDimension(sp,&spdim);CHKERRQ(ierr); 873 if (!spdim) { 874 ierr = PetscQuadratureCreate(PETSC_COMM_SELF,allPoints);CHKERRQ(ierr); 875 ierr = PetscQuadratureSetData(*allPoints,0,0,0,NULL,NULL);CHKERRQ(ierr); 876 } 877 ierr = PetscDualSpaceGetFunctional(sp,0,&q);CHKERRQ(ierr); 878 ierr = PetscQuadratureGetData(q,&dim,NULL,&numPoints,NULL,NULL);CHKERRQ(ierr); 879 for (f = 1; f < spdim; f++) { 880 PetscInt Np; 881 882 ierr = PetscDualSpaceGetFunctional(sp,f,&q);CHKERRQ(ierr); 883 ierr = PetscQuadratureGetData(q,NULL,NULL,&Np,NULL,NULL);CHKERRQ(ierr); 884 numPoints += Np; 885 } 886 ierr = PetscMalloc1(dim*numPoints,&points);CHKERRQ(ierr); 887 for (f = 0, offset = 0; f < spdim; f++) { 888 const PetscReal *p; 889 PetscInt Np, i; 890 891 ierr = PetscDualSpaceGetFunctional(sp,f,&q);CHKERRQ(ierr); 892 ierr = PetscQuadratureGetData(q,NULL,NULL,&Np,&p,NULL);CHKERRQ(ierr); 893 for (i = 0; i < Np * dim; i++) { 894 points[offset + i] = p[i]; 895 } 896 offset += Np * dim; 897 } 898 ierr = PetscQuadratureCreate(PETSC_COMM_SELF,allPoints);CHKERRQ(ierr); 899 ierr = PetscQuadratureSetData(*allPoints,dim,0,numPoints,points,NULL);CHKERRQ(ierr); 900 PetscFunctionReturn(0); 901 } 902 903 /*@C 904 PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 905 906 Input Parameters: 907 + sp - The PetscDualSpace object 908 . f - The basis functional index 909 . time - The time 910 . cgeom - A context with geometric information for this cell, we currently just use the centroid 911 . Nc - The number of components for the function 912 . func - The input function 913 - ctx - A context for the function 914 915 Output Parameter: 916 . value - The output value (scalar) 917 918 Note: The calling sequence for the callback func is given by: 919 920 $ func(PetscInt dim, PetscReal time, const PetscReal x[], 921 $ PetscInt numComponents, PetscScalar values[], void *ctx) 922 923 and the idea is to evaluate the functional as an integral 924 925 $ n(f) = int dx n(x) . f(x) 926 927 where both n and f have Nc components. 928 929 Level: developer 930 931 .seealso: PetscDualSpaceCreate() 932 @*/ 933 PetscErrorCode PetscDualSpaceApplyFVM(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFVCellGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) 934 { 935 DM dm; 936 PetscQuadrature n; 937 const PetscReal *points, *weights; 938 PetscScalar *val; 939 PetscInt dimEmbed, qNc, c, Nq, q; 940 PetscErrorCode ierr; 941 942 PetscFunctionBegin; 943 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 944 PetscValidPointer(value, 5); 945 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 946 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 947 ierr = PetscDualSpaceGetFunctional(sp, f, &n);CHKERRQ(ierr); 948 ierr = PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights);CHKERRQ(ierr); 949 if (qNc != Nc) SETERRQ2(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %D != function components %D", qNc, Nc); 950 ierr = DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val);CHKERRQ(ierr); 951 *value = 0.; 952 for (q = 0; q < Nq; ++q) { 953 ierr = (*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx);CHKERRQ(ierr); 954 for (c = 0; c < Nc; ++c) { 955 *value += val[c]*weights[q*Nc+c]; 956 } 957 } 958 ierr = DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val);CHKERRQ(ierr); 959 PetscFunctionReturn(0); 960 } 961 962 /*@ 963 PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 964 given height. This assumes that the reference cell is symmetric over points of this height. 965 966 If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 967 pointwise values are not defined on the element boundaries), or if the implementation of PetscDualSpace does not 968 support extracting subspaces, then NULL is returned. 969 970 This does not increment the reference count on the returned dual space, and the user should not destroy it. 971 972 Not collective 973 974 Input Parameters: 975 + sp - the PetscDualSpace object 976 - height - the height of the mesh point for which the subspace is desired 977 978 Output Parameter: 979 . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 980 point, which will be of lesser dimension if height > 0. 981 982 Level: advanced 983 984 .seealso: PetscSpaceGetHeightSubspace(), PetscDualSpace 985 @*/ 986 PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 987 { 988 PetscErrorCode ierr; 989 990 PetscFunctionBegin; 991 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 992 PetscValidPointer(subsp, 3); 993 *subsp = NULL; 994 if (sp->ops->getheightsubspace) { 995 ierr = (*sp->ops->getheightsubspace)(sp, height, subsp);CHKERRQ(ierr); 996 } 997 PetscFunctionReturn(0); 998 } 999 1000 /*@ 1001 PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 1002 1003 If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 1004 defined on the element boundaries), or if the implementation of PetscDualSpace does not support extracting 1005 subspaces, then NULL is returned. 1006 1007 This does not increment the reference count on the returned dual space, and the user should not destroy it. 1008 1009 Not collective 1010 1011 Input Parameters: 1012 + sp - the PetscDualSpace object 1013 - point - the point (in the dual space's DM) for which the subspace is desired 1014 1015 Output Parameters: 1016 bdsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 1017 point, which will be of lesser dimension if height > 0. 1018 1019 Level: advanced 1020 1021 .seealso: PetscDualSpace 1022 @*/ 1023 PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 1024 { 1025 PetscErrorCode ierr; 1026 1027 PetscFunctionBegin; 1028 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1029 PetscValidPointer(bdsp,2); 1030 *bdsp = NULL; 1031 if (sp->ops->getpointsubspace) { 1032 ierr = (*sp->ops->getpointsubspace)(sp,point,bdsp);CHKERRQ(ierr); 1033 } else if (sp->ops->getheightsubspace) { 1034 DM dm; 1035 DMLabel label; 1036 PetscInt dim, depth, height; 1037 1038 ierr = PetscDualSpaceGetDM(sp,&dm);CHKERRQ(ierr); 1039 ierr = DMPlexGetDepth(dm,&dim);CHKERRQ(ierr); 1040 ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr); 1041 ierr = DMLabelGetValue(label,point,&depth);CHKERRQ(ierr); 1042 height = dim - depth; 1043 ierr = (*sp->ops->getheightsubspace)(sp,height,bdsp);CHKERRQ(ierr); 1044 } 1045 PetscFunctionReturn(0); 1046 } 1047 1048