xref: /petsc/src/dm/dt/space/interface/space.c (revision bcda9346efad4e5ba2d553af84eb238771ba1e25)
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, No Fortran Support
13 
14   Input Parameters:
15 + sname    - The name of a new user-defined creation routine
16 - function - The creation routine for the implementation type
17 
18   Example 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 @*/
PetscSpaceRegister(const char sname[],PetscErrorCode (* function)(PetscSpace))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 /*@
49   PetscSpaceSetType - Builds a particular `PetscSpace`
50 
51   Collective
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 @*/
PetscSpaceSetType(PetscSpace sp,PetscSpaceType name)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 /*@
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 @*/
PetscSpaceGetType(PetscSpace sp,PetscSpaceType * name)102 PetscErrorCode PetscSpaceGetType(PetscSpace sp, PetscSpaceType *name)
103 {
104   PetscFunctionBegin;
105   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
106   PetscAssertPointer(name, 2);
107   if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll());
108   *name = ((PetscObject)sp)->type_name;
109   PetscFunctionReturn(PETSC_SUCCESS);
110 }
111 
112 /*@
113   PetscSpaceViewFromOptions - View a `PetscSpace` based on values in the options database
114 
115   Collective
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 
124 .seealso: `PetscSpace`, `PetscSpaceView()`, `PetscObjectViewFromOptions()`, `PetscSpaceCreate()`
125 @*/
PetscSpaceViewFromOptions(PetscSpace A,PetscObject obj,const char name[])126 PetscErrorCode PetscSpaceViewFromOptions(PetscSpace A, PetscObject obj, const char name[])
127 {
128   PetscFunctionBegin;
129   PetscValidHeaderSpecific(A, PETSCSPACE_CLASSID, 1);
130   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
131   PetscFunctionReturn(PETSC_SUCCESS);
132 }
133 
134 /*@
135   PetscSpaceView - Views a `PetscSpace`
136 
137   Collective
138 
139   Input Parameters:
140 + sp - the `PetscSpace` object to view
141 - v  - the viewer
142 
143   Level: beginner
144 
145 .seealso: `PetscSpace`, `PetscViewer`, `PetscSpaceViewFromOptions()`, `PetscSpaceDestroy()`
146 @*/
PetscSpaceView(PetscSpace sp,PetscViewer v)147 PetscErrorCode PetscSpaceView(PetscSpace sp, PetscViewer v)
148 {
149   PetscInt  pdim;
150   PetscBool isascii;
151 
152   PetscFunctionBegin;
153   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
154   if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
155   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp), &v));
156   PetscCall(PetscSpaceGetDimension(sp, &pdim));
157   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sp, v));
158   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
159   PetscCall(PetscViewerASCIIPushTab(v));
160   if (isascii) PetscCall(PetscViewerASCIIPrintf(v, "Space in %" PetscInt_FMT " variables with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nv, sp->Nc, pdim));
161   PetscTryTypeMethod(sp, view, v);
162   PetscCall(PetscViewerASCIIPopTab(v));
163   PetscFunctionReturn(PETSC_SUCCESS);
164 }
165 
166 /*@
167   PetscSpaceSetFromOptions - sets parameters in a `PetscSpace` from the options database
168 
169   Collective
170 
171   Input Parameter:
172 . sp - the `PetscSpace` object to set options for
173 
174   Options Database Keys:
175 + -petscspace_degree <deg>   - the approximation order of the space
176 . -petscspace_variables <n>  - the number of different variables, e.g. x and y
177 - -petscspace_components <c> - the number of components, say d for a vector field
178 
179   Level: intermediate
180 
181 .seealso: `PetscSpace`, `PetscSpaceView()`
182 @*/
PetscSpaceSetFromOptions(PetscSpace sp)183 PetscErrorCode PetscSpaceSetFromOptions(PetscSpace sp)
184 {
185   const char *defaultType;
186   char        name[256];
187   PetscBool   flg;
188 
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
191   if (!((PetscObject)sp)->type_name) {
192     defaultType = PETSCSPACEPOLYNOMIAL;
193   } else {
194     defaultType = ((PetscObject)sp)->type_name;
195   }
196   if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll());
197 
198   PetscObjectOptionsBegin((PetscObject)sp);
199   PetscCall(PetscOptionsFList("-petscspace_type", "Linear space", "PetscSpaceSetType", PetscSpaceList, defaultType, name, 256, &flg));
200   if (flg) {
201     PetscCall(PetscSpaceSetType(sp, name));
202   } else if (!((PetscObject)sp)->type_name) {
203     PetscCall(PetscSpaceSetType(sp, defaultType));
204   }
205   {
206     PetscCall(PetscOptionsDeprecated("-petscspace_order", "-petscspace_degree", "3.11", NULL));
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, -1));
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 /*@
220   PetscSpaceSetUp - Construct data structures for the `PetscSpace`
221 
222   Collective
223 
224   Input Parameter:
225 . sp - the `PetscSpace` object to setup
226 
227   Level: intermediate
228 
229 .seealso: `PetscSpace`, `PetscSpaceView()`, `PetscSpaceDestroy()`
230 @*/
PetscSpaceSetUp(PetscSpace sp)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
243 
244   Input Parameter:
245 . sp - the `PetscSpace` object to destroy
246 
247   Level: beginner
248 
249 .seealso: `PetscSpace`, `PetscSpaceCreate()`
250 @*/
PetscSpaceDestroy(PetscSpace * sp)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   PetscUseTypeMethod(*sp, destroy);
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 @*/
PetscSpaceCreate(MPI_Comm comm,PetscSpace * sp)284 PetscErrorCode PetscSpaceCreate(MPI_Comm comm, PetscSpace *sp)
285 {
286   PetscSpace s;
287 
288   PetscFunctionBegin;
289   PetscAssertPointer(sp, 2);
290   PetscCall(PetscCitationsRegister(FECitation, &FEcite));
291   PetscCall(PetscFEInitializePackage());
292 
293   PetscCall(PetscHeaderCreate(s, PETSCSPACE_CLASSID, "PetscSpace", "Linear Space", "PetscSpace", comm, PetscSpaceDestroy, PetscSpaceView));
294   s->degree    = 0;
295   s->maxDegree = PETSC_DETERMINE;
296   s->Nc        = 1;
297   s->Nv        = 0;
298   s->dim       = PETSC_DETERMINE;
299   PetscCall(DMShellCreate(comm, &s->dm));
300   PetscCall(PetscSpaceSetType(s, PETSCSPACEPOLYNOMIAL));
301 
302   *sp = s;
303   PetscFunctionReturn(PETSC_SUCCESS);
304 }
305 
306 /*@
307   PetscSpaceGetDimension - Return the dimension of this space, i.e. the number of basis vectors
308 
309   Input Parameter:
310 . sp - The `PetscSpace`
311 
312   Output Parameter:
313 . dim - The dimension
314 
315   Level: intermediate
316 
317 .seealso: `PetscSpace`, `PetscSpaceGetDegree()`, `PetscSpaceCreate()`
318 @*/
PetscSpaceGetDimension(PetscSpace sp,PetscInt * dim)319 PetscErrorCode PetscSpaceGetDimension(PetscSpace sp, PetscInt *dim)
320 {
321   PetscFunctionBegin;
322   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
323   PetscAssertPointer(dim, 2);
324   if (sp->dim == PETSC_DETERMINE) PetscTryTypeMethod(sp, getdimension, &sp->dim);
325   *dim = sp->dim;
326   PetscFunctionReturn(PETSC_SUCCESS);
327 }
328 
329 /*@
330   PetscSpaceGetDegree - Return the polynomial degrees that characterize this space
331 
332   Input Parameter:
333 . sp - The `PetscSpace`
334 
335   Output Parameters:
336 + minDegree - The degree of the largest polynomial space contained in the space, pass `NULL` if not needed
337 - maxDegree - The degree of the smallest polynomial space containing the space, pass `NULL` if not needed
338 
339   Level: intermediate
340 
341 .seealso: `PetscSpace`, `PetscSpaceSetDegree()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`
342 @*/
PetscSpaceGetDegree(PetscSpace sp,PeOp PetscInt * minDegree,PeOp PetscInt * maxDegree)343 PetscErrorCode PetscSpaceGetDegree(PetscSpace sp, PeOp PetscInt *minDegree, PeOp PetscInt *maxDegree)
344 {
345   PetscFunctionBegin;
346   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
347   if (minDegree) PetscAssertPointer(minDegree, 2);
348   if (maxDegree) PetscAssertPointer(maxDegree, 3);
349   if (minDegree) *minDegree = sp->degree;
350   if (maxDegree) *maxDegree = sp->maxDegree;
351   PetscFunctionReturn(PETSC_SUCCESS);
352 }
353 
354 /*@
355   PetscSpaceSetDegree - Set the degree of approximation for this space.
356 
357   Input Parameters:
358 + sp        - The `PetscSpace`
359 . degree    - The degree of the largest polynomial space contained in the space
360 - maxDegree - The degree of the largest polynomial space containing the space.  One of degree and maxDegree can be `PETSC_DETERMINE`.
361 
362   Level: intermediate
363 
364 .seealso: `PetscSpace`, `PetscSpaceGetDegree()`, `PetscSpaceCreate()`
365 @*/
PetscSpaceSetDegree(PetscSpace sp,PetscInt degree,PetscInt maxDegree)366 PetscErrorCode PetscSpaceSetDegree(PetscSpace sp, PetscInt degree, PetscInt maxDegree)
367 {
368   PetscFunctionBegin;
369   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
370   sp->degree    = degree;
371   sp->maxDegree = maxDegree;
372   PetscFunctionReturn(PETSC_SUCCESS);
373 }
374 
375 /*@
376   PetscSpaceGetNumComponents - Return the number of components for this space
377 
378   Input Parameter:
379 . sp - The `PetscSpace`
380 
381   Output Parameter:
382 . Nc - The number of components
383 
384   Level: intermediate
385 
386   Note:
387   A vector space, for example, will have d components, where d is the spatial dimension
388 
389 .seealso: `PetscSpace`, `PetscSpaceSetNumComponents()`, `PetscSpaceGetNumVariables()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`
390 @*/
PetscSpaceGetNumComponents(PetscSpace sp,PetscInt * Nc)391 PetscErrorCode PetscSpaceGetNumComponents(PetscSpace sp, PetscInt *Nc)
392 {
393   PetscFunctionBegin;
394   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
395   PetscAssertPointer(Nc, 2);
396   *Nc = sp->Nc;
397   PetscFunctionReturn(PETSC_SUCCESS);
398 }
399 
400 /*@
401   PetscSpaceSetNumComponents - Set the number of components for this space
402 
403   Input Parameters:
404 + sp - The `PetscSpace`
405 - Nc - The number of components
406 
407   Level: intermediate
408 
409 .seealso: `PetscSpace`, `PetscSpaceGetNumComponents()`, `PetscSpaceSetNumVariables()`, `PetscSpaceCreate()`
410 @*/
PetscSpaceSetNumComponents(PetscSpace sp,PetscInt Nc)411 PetscErrorCode PetscSpaceSetNumComponents(PetscSpace sp, PetscInt Nc)
412 {
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
415   sp->Nc = Nc;
416   PetscFunctionReturn(PETSC_SUCCESS);
417 }
418 
419 /*@
420   PetscSpaceSetNumVariables - Set the number of variables for this space
421 
422   Input Parameters:
423 + sp - The `PetscSpace`
424 - n  - The number of variables, e.g. x, y, z...
425 
426   Level: intermediate
427 
428 .seealso: `PetscSpace`, `PetscSpaceGetNumVariables()`, `PetscSpaceSetNumComponents()`, `PetscSpaceCreate()`
429 @*/
PetscSpaceSetNumVariables(PetscSpace sp,PetscInt n)430 PetscErrorCode PetscSpaceSetNumVariables(PetscSpace sp, PetscInt n)
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
434   sp->Nv = n;
435   PetscFunctionReturn(PETSC_SUCCESS);
436 }
437 
438 /*@
439   PetscSpaceGetNumVariables - Return the number of variables for this space
440 
441   Input Parameter:
442 . sp - The `PetscSpace`
443 
444   Output Parameter:
445 . n - The number of variables, e.g. x, y, z...
446 
447   Level: intermediate
448 
449 .seealso: `PetscSpace`, `PetscSpaceSetNumVariables()`, `PetscSpaceGetNumComponents()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`
450 @*/
PetscSpaceGetNumVariables(PetscSpace sp,PetscInt * n)451 PetscErrorCode PetscSpaceGetNumVariables(PetscSpace sp, PetscInt *n)
452 {
453   PetscFunctionBegin;
454   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
455   PetscAssertPointer(n, 2);
456   *n = sp->Nv;
457   PetscFunctionReturn(PETSC_SUCCESS);
458 }
459 
460 /*@
461   PetscSpaceEvaluate - Evaluate the basis functions and their derivatives (jet) at each point
462 
463   Input Parameters:
464 + sp      - The `PetscSpace`
465 . npoints - The number of evaluation points, in reference coordinates
466 - points  - The point coordinates
467 
468   Output Parameters:
469 + B - The function evaluations in a `npoints` x `nfuncs` array
470 . D - The derivative evaluations in a `npoints` x `nfuncs` x `dim` array
471 - H - The second derivative evaluations in a `npoints` x `nfuncs` x `dim` x `dim` array
472 
473   Level: beginner
474 
475   Note:
476   Above `nfuncs` is the dimension of the space, and `dim` is the spatial dimension. The coordinates are given
477   on the reference cell, not in real space.
478 
479 .seealso: `PetscSpace`, `PetscFECreateTabulation()`, `PetscFEGetCellTabulation()`, `PetscSpaceCreate()`
480 @*/
PetscSpaceEvaluate(PetscSpace sp,PetscInt npoints,const PetscReal points[],PeOp PetscReal B[],PeOp PetscReal D[],PeOp PetscReal H[])481 PetscErrorCode PetscSpaceEvaluate(PetscSpace sp, PetscInt npoints, const PetscReal points[], PeOp PetscReal B[], PeOp PetscReal D[], PeOp PetscReal H[])
482 {
483   PetscFunctionBegin;
484   if (!npoints) PetscFunctionReturn(PETSC_SUCCESS);
485   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
486   if (sp->Nv) PetscAssertPointer(points, 3);
487   if (B) PetscAssertPointer(B, 4);
488   if (D) PetscAssertPointer(D, 5);
489   if (H) PetscAssertPointer(H, 6);
490   PetscTryTypeMethod(sp, evaluate, npoints, points, B, D, H);
491   PetscFunctionReturn(PETSC_SUCCESS);
492 }
493 
494 /*@
495   PetscSpaceGetHeightSubspace - Get the subset of the primal space basis that is supported on a mesh point of a given height.
496 
497   Not Collective
498 
499   Input Parameters:
500 + sp     - the `PetscSpace` object
501 - height - the height of the mesh point for which the subspace is desired
502 
503   Output Parameter:
504 . subsp - the subspace
505 
506   Level: advanced
507 
508   Notes:
509   If the space is not defined on mesh points of the given height (e.g. if the space is discontinuous and
510   pointwise values are not defined on the element boundaries), or if the implementation of `PetscSpace` does not
511   support extracting subspaces, then NULL is returned.
512 
513   This does not increment the reference count on the returned space, and the user should not destroy it.
514 
515 .seealso: `PetscDualSpaceGetHeightSubspace()`, `PetscSpace`
516 @*/
PetscSpaceGetHeightSubspace(PetscSpace sp,PetscInt height,PetscSpace * subsp)517 PetscErrorCode PetscSpaceGetHeightSubspace(PetscSpace sp, PetscInt height, PetscSpace *subsp)
518 {
519   PetscFunctionBegin;
520   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
521   PetscAssertPointer(subsp, 3);
522   *subsp = NULL;
523   PetscTryTypeMethod(sp, getheightsubspace, height, subsp);
524   PetscFunctionReturn(PETSC_SUCCESS);
525 }
526