1 #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 2 #include <petscdmshell.h> 3 4 PetscClassId PETSCSPACE_CLASSID = 0; 5 6 PetscFunctionList PetscSpaceList = NULL; 7 PetscBool PetscSpaceRegisterAllCalled = PETSC_FALSE; 8 9 /*@C 10 PetscSpaceRegister - Adds a new PetscSpace implementation 11 12 Not Collective 13 14 Input Parameters: 15 + name - The name of a new user-defined creation routine 16 - create_func - The creation routine for the implementation type 17 18 Notes: 19 PetscSpaceRegister() may be called multiple times to add several user-defined types of PetscSpaces. The creation function is called 20 when the type is set to 'name'. 21 22 Sample usage: 23 .vb 24 PetscSpaceRegister("my_space", MyPetscSpaceCreate); 25 .ve 26 27 Then, your PetscSpace type can be chosen with the procedural interface via 28 .vb 29 PetscSpaceCreate(MPI_Comm, PetscSpace *); 30 PetscSpaceSetType(PetscSpace, "my_space"); 31 .ve 32 or at runtime via the option 33 .vb 34 -petscspace_type my_space 35 .ve 36 37 Level: advanced 38 39 .seealso: `PetscSpaceRegisterAll()`, `PetscSpaceRegisterDestroy()` 40 41 @*/ 42 PetscErrorCode PetscSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscSpace)) 43 { 44 PetscFunctionBegin; 45 PetscCall(PetscFunctionListAdd(&PetscSpaceList, sname, function)); 46 PetscFunctionReturn(0); 47 } 48 49 /*@C 50 PetscSpaceSetType - Builds a particular PetscSpace 51 52 Collective on sp 53 54 Input Parameters: 55 + sp - The PetscSpace object 56 - name - The kind of space 57 58 Options Database Key: 59 . -petscspace_type <type> - Sets the PetscSpace type; use -help for a list of available types 60 61 Level: intermediate 62 63 .seealso: `PetscSpaceGetType()`, `PetscSpaceCreate()` 64 @*/ 65 PetscErrorCode PetscSpaceSetType(PetscSpace sp, PetscSpaceType name) 66 { 67 PetscErrorCode (*r)(PetscSpace); 68 PetscBool match; 69 70 PetscFunctionBegin; 71 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 72 PetscCall(PetscObjectTypeCompare((PetscObject) sp, name, &match)); 73 if (match) PetscFunctionReturn(0); 74 75 PetscCall(PetscSpaceRegisterAll()); 76 PetscCall(PetscFunctionListFind(PetscSpaceList, name, &r)); 77 PetscCheck(r,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscSpace type: %s", name); 78 79 if (sp->ops->destroy) { 80 PetscCall((*sp->ops->destroy)(sp)); 81 sp->ops->destroy = NULL; 82 } 83 sp->dim = PETSC_DETERMINE; 84 PetscCall((*r)(sp)); 85 PetscCall(PetscObjectChangeTypeName((PetscObject) sp, name)); 86 PetscFunctionReturn(0); 87 } 88 89 /*@C 90 PetscSpaceGetType - Gets the PetscSpace type name (as a string) from the object. 91 92 Not Collective 93 94 Input Parameter: 95 . sp - The PetscSpace 96 97 Output Parameter: 98 . name - The PetscSpace type name 99 100 Level: intermediate 101 102 .seealso: `PetscSpaceSetType()`, `PetscSpaceCreate()` 103 @*/ 104 PetscErrorCode PetscSpaceGetType(PetscSpace sp, PetscSpaceType *name) 105 { 106 PetscFunctionBegin; 107 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 108 PetscValidPointer(name, 2); 109 if (!PetscSpaceRegisterAllCalled) { 110 PetscCall(PetscSpaceRegisterAll()); 111 } 112 *name = ((PetscObject) sp)->type_name; 113 PetscFunctionReturn(0); 114 } 115 116 /*@C 117 PetscSpaceViewFromOptions - View from Options 118 119 Collective on PetscSpace 120 121 Input Parameters: 122 + A - the PetscSpace object 123 . obj - Optional object 124 - name - command line option 125 126 Level: intermediate 127 .seealso: `PetscSpace`, `PetscSpaceView`, `PetscObjectViewFromOptions()`, `PetscSpaceCreate()` 128 @*/ 129 PetscErrorCode PetscSpaceViewFromOptions(PetscSpace A,PetscObject obj,const char name[]) 130 { 131 PetscFunctionBegin; 132 PetscValidHeaderSpecific(A,PETSCSPACE_CLASSID,1); 133 PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 134 PetscFunctionReturn(0); 135 } 136 137 /*@C 138 PetscSpaceView - Views a PetscSpace 139 140 Collective on sp 141 142 Input Parameters: 143 + sp - the PetscSpace object to view 144 - v - the viewer 145 146 Level: beginner 147 148 .seealso `PetscSpaceDestroy()` 149 @*/ 150 PetscErrorCode PetscSpaceView(PetscSpace sp, PetscViewer v) 151 { 152 PetscInt pdim; 153 PetscBool iascii; 154 155 PetscFunctionBegin; 156 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 157 if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 158 if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) sp), &v)); 159 PetscCall(PetscSpaceGetDimension(sp, &pdim)); 160 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sp,v)); 161 PetscCall(PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii)); 162 PetscCall(PetscViewerASCIIPushTab(v)); 163 if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Space in %" PetscInt_FMT " variables with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nv, sp->Nc, pdim)); 164 if (sp->ops->view) PetscCall((*sp->ops->view)(sp, v)); 165 PetscCall(PetscViewerASCIIPopTab(v)); 166 PetscFunctionReturn(0); 167 } 168 169 /*@ 170 PetscSpaceSetFromOptions - sets parameters in a PetscSpace from the options database 171 172 Collective on sp 173 174 Input Parameter: 175 . sp - the PetscSpace object to set options for 176 177 Options Database: 178 + -petscspace_degree <deg> - the approximation order of the space 179 . -petscspace_variables <n> - the number of different variables, e.g. x and y 180 - -petscspace_components <c> - the number of components, say d for a vector field 181 182 Level: intermediate 183 184 .seealso `PetscSpaceView()` 185 @*/ 186 PetscErrorCode PetscSpaceSetFromOptions(PetscSpace sp) 187 { 188 const char *defaultType; 189 char name[256]; 190 PetscBool flg; 191 192 PetscFunctionBegin; 193 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 194 if (!((PetscObject) sp)->type_name) { 195 defaultType = PETSCSPACEPOLYNOMIAL; 196 } else { 197 defaultType = ((PetscObject) sp)->type_name; 198 } 199 if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll()); 200 201 PetscObjectOptionsBegin((PetscObject) sp); 202 PetscCall(PetscOptionsFList("-petscspace_type", "Linear space", "PetscSpaceSetType", PetscSpaceList, defaultType, name, 256, &flg)); 203 if (flg) { 204 PetscCall(PetscSpaceSetType(sp, name)); 205 } else if (!((PetscObject) sp)->type_name) { 206 PetscCall(PetscSpaceSetType(sp, defaultType)); 207 } 208 { 209 PetscCall(PetscOptionsDeprecated("-petscspace_order","-petscspace_degree","3.11",NULL)); 210 PetscCall(PetscOptionsBoundedInt("-petscspace_order", "DEPRECATED: The approximation order", "PetscSpaceSetDegree", sp->degree, &sp->degree, NULL,0)); 211 } 212 PetscCall(PetscOptionsBoundedInt("-petscspace_degree", "The (maximally included) polynomial degree", "PetscSpaceSetDegree", sp->degree, &sp->degree, NULL,0)); 213 PetscCall(PetscOptionsBoundedInt("-petscspace_variables", "The number of different variables, e.g. x and y", "PetscSpaceSetNumVariables", sp->Nv, &sp->Nv, NULL,0)); 214 PetscCall(PetscOptionsBoundedInt("-petscspace_components", "The number of components", "PetscSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL,0)); 215 if (sp->ops->setfromoptions) PetscCall((*sp->ops->setfromoptions)(PetscOptionsObject,sp)); 216 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 217 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) sp)); 218 PetscOptionsEnd(); 219 PetscCall(PetscSpaceViewFromOptions(sp, NULL, "-petscspace_view")); 220 PetscFunctionReturn(0); 221 } 222 223 /*@C 224 PetscSpaceSetUp - Construct data structures for the PetscSpace 225 226 Collective on sp 227 228 Input Parameter: 229 . sp - the PetscSpace object to setup 230 231 Level: intermediate 232 233 .seealso `PetscSpaceView()`, `PetscSpaceDestroy()` 234 @*/ 235 PetscErrorCode PetscSpaceSetUp(PetscSpace sp) 236 { 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 239 if (sp->ops->setup) PetscCall((*sp->ops->setup)(sp)); 240 PetscFunctionReturn(0); 241 } 242 243 /*@ 244 PetscSpaceDestroy - Destroys a PetscSpace object 245 246 Collective on sp 247 248 Input Parameter: 249 . sp - the PetscSpace object to destroy 250 251 Level: beginner 252 253 .seealso `PetscSpaceView()` 254 @*/ 255 PetscErrorCode PetscSpaceDestroy(PetscSpace *sp) 256 { 257 PetscFunctionBegin; 258 if (!*sp) PetscFunctionReturn(0); 259 PetscValidHeaderSpecific((*sp), PETSCSPACE_CLASSID, 1); 260 261 if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);} 262 ((PetscObject) (*sp))->refct = 0; 263 PetscCall(DMDestroy(&(*sp)->dm)); 264 265 PetscCall((*(*sp)->ops->destroy)(*sp)); 266 PetscCall(PetscHeaderDestroy(sp)); 267 PetscFunctionReturn(0); 268 } 269 270 /*@ 271 PetscSpaceCreate - Creates an empty PetscSpace object. The type can then be set with PetscSpaceSetType(). 272 273 Collective 274 275 Input Parameter: 276 . comm - The communicator for the PetscSpace object 277 278 Output Parameter: 279 . sp - The PetscSpace object 280 281 Level: beginner 282 283 .seealso: `PetscSpaceSetType()`, `PETSCSPACEPOLYNOMIAL` 284 @*/ 285 PetscErrorCode PetscSpaceCreate(MPI_Comm comm, PetscSpace *sp) 286 { 287 PetscSpace s; 288 289 PetscFunctionBegin; 290 PetscValidPointer(sp, 2); 291 PetscCall(PetscCitationsRegister(FECitation,&FEcite)); 292 *sp = NULL; 293 PetscCall(PetscFEInitializePackage()); 294 295 PetscCall(PetscHeaderCreate(s, PETSCSPACE_CLASSID, "PetscSpace", "Linear Space", "PetscSpace", comm, PetscSpaceDestroy, PetscSpaceView)); 296 297 s->degree = 0; 298 s->maxDegree = PETSC_DETERMINE; 299 s->Nc = 1; 300 s->Nv = 0; 301 s->dim = PETSC_DETERMINE; 302 PetscCall(DMShellCreate(comm, &s->dm)); 303 PetscCall(PetscSpaceSetType(s, PETSCSPACEPOLYNOMIAL)); 304 305 *sp = s; 306 PetscFunctionReturn(0); 307 } 308 309 /*@ 310 PetscSpaceGetDimension - Return the dimension of this space, i.e. the number of basis vectors 311 312 Input Parameter: 313 . sp - The PetscSpace 314 315 Output Parameter: 316 . dim - The dimension 317 318 Level: intermediate 319 320 .seealso: `PetscSpaceGetDegree()`, `PetscSpaceCreate()`, `PetscSpace` 321 @*/ 322 PetscErrorCode PetscSpaceGetDimension(PetscSpace sp, PetscInt *dim) 323 { 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 326 PetscValidIntPointer(dim, 2); 327 if (sp->dim == PETSC_DETERMINE) { 328 if (sp->ops->getdimension) PetscCall((*sp->ops->getdimension)(sp, &sp->dim)); 329 } 330 *dim = sp->dim; 331 PetscFunctionReturn(0); 332 } 333 334 /*@ 335 PetscSpaceGetDegree - Return the polynomial degrees that characterize this space 336 337 Input Parameter: 338 . sp - The PetscSpace 339 340 Output Parameters: 341 + minDegree - The degree of the largest polynomial space contained in the space 342 - maxDegree - The degree of the smallest polynomial space containing the space 343 344 Level: intermediate 345 346 .seealso: `PetscSpaceSetDegree()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`, `PetscSpace` 347 @*/ 348 PetscErrorCode PetscSpaceGetDegree(PetscSpace sp, PetscInt *minDegree, PetscInt *maxDegree) 349 { 350 PetscFunctionBegin; 351 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 352 if (minDegree) PetscValidIntPointer(minDegree, 2); 353 if (maxDegree) PetscValidIntPointer(maxDegree, 3); 354 if (minDegree) *minDegree = sp->degree; 355 if (maxDegree) *maxDegree = sp->maxDegree; 356 PetscFunctionReturn(0); 357 } 358 359 /*@ 360 PetscSpaceSetDegree - Set the degree of approximation for this space. 361 362 Input Parameters: 363 + sp - The PetscSpace 364 . degree - The degree of the largest polynomial space contained in the space 365 - maxDegree - The degree of the largest polynomial space containing the space. One of degree and maxDegree can be PETSC_DETERMINE. 366 367 Level: intermediate 368 369 .seealso: `PetscSpaceGetDegree()`, `PetscSpaceCreate()`, `PetscSpace` 370 @*/ 371 PetscErrorCode PetscSpaceSetDegree(PetscSpace sp, PetscInt degree, PetscInt maxDegree) 372 { 373 PetscFunctionBegin; 374 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 375 sp->degree = degree; 376 sp->maxDegree = maxDegree; 377 PetscFunctionReturn(0); 378 } 379 380 /*@ 381 PetscSpaceGetNumComponents - Return the number of components for this space 382 383 Input Parameter: 384 . sp - The PetscSpace 385 386 Output Parameter: 387 . Nc - The number of components 388 389 Note: A vector space, for example, will have d components, where d is the spatial dimension 390 391 Level: intermediate 392 393 .seealso: `PetscSpaceSetNumComponents()`, `PetscSpaceGetNumVariables()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`, `PetscSpace` 394 @*/ 395 PetscErrorCode PetscSpaceGetNumComponents(PetscSpace sp, PetscInt *Nc) 396 { 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 399 PetscValidIntPointer(Nc, 2); 400 *Nc = sp->Nc; 401 PetscFunctionReturn(0); 402 } 403 404 /*@ 405 PetscSpaceSetNumComponents - Set the number of components for this space 406 407 Input Parameters: 408 + sp - The PetscSpace 409 - order - The number of components 410 411 Level: intermediate 412 413 .seealso: `PetscSpaceGetNumComponents()`, `PetscSpaceSetNumVariables()`, `PetscSpaceCreate()`, `PetscSpace` 414 @*/ 415 PetscErrorCode PetscSpaceSetNumComponents(PetscSpace sp, PetscInt Nc) 416 { 417 PetscFunctionBegin; 418 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 419 sp->Nc = Nc; 420 PetscFunctionReturn(0); 421 } 422 423 /*@ 424 PetscSpaceSetNumVariables - Set the number of variables for this space 425 426 Input Parameters: 427 + sp - The PetscSpace 428 - n - The number of variables, e.g. x, y, z... 429 430 Level: intermediate 431 432 .seealso: `PetscSpaceGetNumVariables()`, `PetscSpaceSetNumComponents()`, `PetscSpaceCreate()`, `PetscSpace` 433 @*/ 434 PetscErrorCode PetscSpaceSetNumVariables(PetscSpace sp, PetscInt n) 435 { 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 438 sp->Nv = n; 439 PetscFunctionReturn(0); 440 } 441 442 /*@ 443 PetscSpaceGetNumVariables - Return the number of variables for this space 444 445 Input Parameter: 446 . sp - The PetscSpace 447 448 Output Parameter: 449 . Nc - The number of variables, e.g. x, y, z... 450 451 Level: intermediate 452 453 .seealso: `PetscSpaceSetNumVariables()`, `PetscSpaceGetNumComponents()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`, `PetscSpace` 454 @*/ 455 PetscErrorCode PetscSpaceGetNumVariables(PetscSpace sp, PetscInt *n) 456 { 457 PetscFunctionBegin; 458 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 459 PetscValidIntPointer(n, 2); 460 *n = sp->Nv; 461 PetscFunctionReturn(0); 462 } 463 464 /*@C 465 PetscSpaceEvaluate - Evaluate the basis functions and their derivatives (jet) at each point 466 467 Input Parameters: 468 + sp - The PetscSpace 469 . npoints - The number of evaluation points, in reference coordinates 470 - points - The point coordinates 471 472 Output Parameters: 473 + B - The function evaluations in a npoints x nfuncs array 474 . D - The derivative evaluations in a npoints x nfuncs x dim array 475 - H - The second derivative evaluations in a npoints x nfuncs x dim x dim array 476 477 Note: Above nfuncs is the dimension of the space, and dim is the spatial dimension. The coordinates are given 478 on the reference cell, not in real space. 479 480 Level: beginner 481 482 .seealso: `PetscFECreateTabulation()`, `PetscFEGetCellTabulation()`, `PetscSpaceCreate()` 483 @*/ 484 PetscErrorCode PetscSpaceEvaluate(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[]) 485 { 486 PetscFunctionBegin; 487 if (!npoints) PetscFunctionReturn(0); 488 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 489 if (sp->Nv) PetscValidRealPointer(points, 3); 490 if (B) PetscValidRealPointer(B, 4); 491 if (D) PetscValidRealPointer(D, 5); 492 if (H) PetscValidRealPointer(H, 6); 493 if (sp->ops->evaluate) PetscCall((*sp->ops->evaluate)(sp, npoints, points, B, D, H)); 494 PetscFunctionReturn(0); 495 } 496 497 /*@ 498 PetscSpaceGetHeightSubspace - Get the subset of the primal space basis that is supported on a mesh point of a given height. 499 500 If the space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 501 pointwise values are not defined on the element boundaries), or if the implementation of PetscSpace does not 502 support extracting subspaces, then NULL is returned. 503 504 This does not increment the reference count on the returned space, and the user should not destroy it. 505 506 Not collective 507 508 Input Parameters: 509 + sp - the PetscSpace object 510 - height - the height of the mesh point for which the subspace is desired 511 512 Output Parameter: 513 . subsp - the subspace 514 515 Level: advanced 516 517 .seealso: `PetscDualSpaceGetHeightSubspace()`, `PetscSpace` 518 @*/ 519 PetscErrorCode PetscSpaceGetHeightSubspace(PetscSpace sp, PetscInt height, PetscSpace *subsp) 520 { 521 PetscFunctionBegin; 522 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 523 PetscValidPointer(subsp, 3); 524 *subsp = NULL; 525 if (sp->ops->getheightsubspace) PetscCall((*sp->ops->getheightsubspace)(sp, height, subsp)); 526 PetscFunctionReturn(0); 527 } 528