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