xref: /petsc/src/dm/dt/space/interface/space.c (revision 6d5076fa512d0d8e4e12a3685978afdbfee2b1a4)
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
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
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 @*/
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 /*@C
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 @*/
147 PetscErrorCode PetscSpaceView(PetscSpace sp, PetscViewer v)
148 {
149   PetscInt  pdim;
150   PetscBool iascii;
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, &iascii));
159   PetscCall(PetscViewerASCIIPushTab(v));
160   if (iascii) 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 @*/
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     PetscCall(PetscOptionsBoundedInt("-petscspace_order", "DEPRECATED: The approximation order", "PetscSpaceSetDegree", sp->degree, &sp->degree, NULL, 0));
208   }
209   PetscCall(PetscOptionsBoundedInt("-petscspace_degree", "The (maximally included) polynomial degree", "PetscSpaceSetDegree", sp->degree, &sp->degree, NULL, 0));
210   PetscCall(PetscOptionsBoundedInt("-petscspace_variables", "The number of different variables, e.g. x and y", "PetscSpaceSetNumVariables", sp->Nv, &sp->Nv, NULL, 0));
211   PetscCall(PetscOptionsBoundedInt("-petscspace_components", "The number of components", "PetscSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL, 0));
212   PetscTryTypeMethod(sp, setfromoptions, PetscOptionsObject);
213   /* process any options handlers added with PetscObjectAddOptionsHandler() */
214   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)sp, PetscOptionsObject));
215   PetscOptionsEnd();
216   PetscCall(PetscSpaceViewFromOptions(sp, NULL, "-petscspace_view"));
217   PetscFunctionReturn(PETSC_SUCCESS);
218 }
219 
220 /*@C
221   PetscSpaceSetUp - Construct data structures for the `PetscSpace`
222 
223   Collective
224 
225   Input Parameter:
226 . sp - the `PetscSpace` object to setup
227 
228   Level: intermediate
229 
230 .seealso: `PetscSpace`, `PetscSpaceView()`, `PetscSpaceDestroy()`
231 @*/
232 PetscErrorCode PetscSpaceSetUp(PetscSpace sp)
233 {
234   PetscFunctionBegin;
235   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
236   PetscTryTypeMethod(sp, setup);
237   PetscFunctionReturn(PETSC_SUCCESS);
238 }
239 
240 /*@
241   PetscSpaceDestroy - Destroys a `PetscSpace` object
242 
243   Collective
244 
245   Input Parameter:
246 . sp - the `PetscSpace` object to destroy
247 
248   Level: beginner
249 
250 .seealso: `PetscSpace`, `PetscSpaceCreate()`
251 @*/
252 PetscErrorCode PetscSpaceDestroy(PetscSpace *sp)
253 {
254   PetscFunctionBegin;
255   if (!*sp) PetscFunctionReturn(PETSC_SUCCESS);
256   PetscValidHeaderSpecific((*sp), PETSCSPACE_CLASSID, 1);
257 
258   if (--((PetscObject)(*sp))->refct > 0) {
259     *sp = NULL;
260     PetscFunctionReturn(PETSC_SUCCESS);
261   }
262   ((PetscObject)(*sp))->refct = 0;
263   PetscCall(DMDestroy(&(*sp)->dm));
264 
265   PetscCall((*(*sp)->ops->destroy)(*sp));
266   PetscCall(PetscHeaderDestroy(sp));
267   PetscFunctionReturn(PETSC_SUCCESS);
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: `PetscSpace`, `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(PETSC_SUCCESS);
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: `PetscSpace`, `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) PetscTryTypeMethod(sp, getdimension, &sp->dim);
328   *dim = sp->dim;
329   PetscFunctionReturn(PETSC_SUCCESS);
330 }
331 
332 /*@
333   PetscSpaceGetDegree - Return the polynomial degrees that characterize this space
334 
335   Input Parameter:
336 . sp - The `PetscSpace`
337 
338   Output Parameters:
339 + minDegree - The degree of the largest polynomial space contained in the space
340 - maxDegree - The degree of the smallest polynomial space containing the space
341 
342   Level: intermediate
343 
344 .seealso: `PetscSpace`, `PetscSpaceSetDegree()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`, `PetscSpace`
345 @*/
346 PetscErrorCode PetscSpaceGetDegree(PetscSpace sp, PetscInt *minDegree, PetscInt *maxDegree)
347 {
348   PetscFunctionBegin;
349   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
350   if (minDegree) PetscValidIntPointer(minDegree, 2);
351   if (maxDegree) PetscValidIntPointer(maxDegree, 3);
352   if (minDegree) *minDegree = sp->degree;
353   if (maxDegree) *maxDegree = sp->maxDegree;
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358   PetscSpaceSetDegree - Set the degree of approximation for this space.
359 
360   Input Parameters:
361 + sp - The `PetscSpace`
362 . degree - The degree of the largest polynomial space contained in the space
363 - maxDegree - The degree of the largest polynomial space containing the space.  One of degree and maxDegree can be `PETSC_DETERMINE`.
364 
365   Level: intermediate
366 
367 .seealso: `PetscSpace`, `PetscSpaceGetDegree()`, `PetscSpaceCreate()`, `PetscSpace`
368 @*/
369 PetscErrorCode PetscSpaceSetDegree(PetscSpace sp, PetscInt degree, PetscInt maxDegree)
370 {
371   PetscFunctionBegin;
372   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
373   sp->degree    = degree;
374   sp->maxDegree = maxDegree;
375   PetscFunctionReturn(PETSC_SUCCESS);
376 }
377 
378 /*@
379   PetscSpaceGetNumComponents - Return the number of components for this space
380 
381   Input Parameter:
382 . sp - The `PetscSpace`
383 
384   Output Parameter:
385 . Nc - The number of components
386 
387   Level: intermediate
388 
389   Note:
390   A vector space, for example, will have d components, where d is the spatial dimension
391 
392 .seealso: `PetscSpace`, `PetscSpaceSetNumComponents()`, `PetscSpaceGetNumVariables()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`, `PetscSpace`
393 @*/
394 PetscErrorCode PetscSpaceGetNumComponents(PetscSpace sp, PetscInt *Nc)
395 {
396   PetscFunctionBegin;
397   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
398   PetscValidIntPointer(Nc, 2);
399   *Nc = sp->Nc;
400   PetscFunctionReturn(PETSC_SUCCESS);
401 }
402 
403 /*@
404   PetscSpaceSetNumComponents - Set the number of components for this space
405 
406   Input Parameters:
407 + sp - The `PetscSpace`
408 - order - The number of components
409 
410   Level: intermediate
411 
412 .seealso: `PetscSpace`, `PetscSpaceGetNumComponents()`, `PetscSpaceSetNumVariables()`, `PetscSpaceCreate()`, `PetscSpace`
413 @*/
414 PetscErrorCode PetscSpaceSetNumComponents(PetscSpace sp, PetscInt Nc)
415 {
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
418   sp->Nc = Nc;
419   PetscFunctionReturn(PETSC_SUCCESS);
420 }
421 
422 /*@
423   PetscSpaceSetNumVariables - Set the number of variables for this space
424 
425   Input Parameters:
426 + sp - The `PetscSpace`
427 - n - The number of variables, e.g. x, y, z...
428 
429   Level: intermediate
430 
431 .seealso: `PetscSpace`, `PetscSpaceGetNumVariables()`, `PetscSpaceSetNumComponents()`, `PetscSpaceCreate()`, `PetscSpace`
432 @*/
433 PetscErrorCode PetscSpaceSetNumVariables(PetscSpace sp, PetscInt n)
434 {
435   PetscFunctionBegin;
436   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
437   sp->Nv = n;
438   PetscFunctionReturn(PETSC_SUCCESS);
439 }
440 
441 /*@
442   PetscSpaceGetNumVariables - Return the number of variables for this space
443 
444   Input Parameter:
445 . sp - The `PetscSpace`
446 
447   Output Parameter:
448 . Nc - The number of variables, e.g. x, y, z...
449 
450   Level: intermediate
451 
452 .seealso: `PetscSpace`, `PetscSpaceSetNumVariables()`, `PetscSpaceGetNumComponents()`, `PetscSpaceGetDimension()`, `PetscSpaceCreate()`, `PetscSpace`
453 @*/
454 PetscErrorCode PetscSpaceGetNumVariables(PetscSpace sp, PetscInt *n)
455 {
456   PetscFunctionBegin;
457   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
458   PetscValidIntPointer(n, 2);
459   *n = sp->Nv;
460   PetscFunctionReturn(PETSC_SUCCESS);
461 }
462 
463 /*@C
464   PetscSpaceEvaluate - Evaluate the basis functions and their derivatives (jet) at each point
465 
466   Input Parameters:
467 + sp      - The `PetscSpace`
468 . npoints - The number of evaluation points, in reference coordinates
469 - points  - The point coordinates
470 
471   Output Parameters:
472 + B - The function evaluations in a npoints x nfuncs array
473 . D - The derivative evaluations in a npoints x nfuncs x dim array
474 - H - The second derivative evaluations in a npoints x nfuncs x dim x dim array
475 
476   Level: beginner
477 
478   Note:
479   Above nfuncs is the dimension of the space, and dim is the spatial dimension. The coordinates are given
480   on the reference cell, not in real space.
481 
482 .seealso: `PetscSpace`, `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(PETSC_SUCCESS);
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   PetscTryTypeMethod(sp, evaluate, npoints, points, B, D, H);
494   PetscFunctionReturn(PETSC_SUCCESS);
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   Not Collective
501 
502   Input Parameters:
503 + sp - the `PetscSpace` object
504 - height - the height of the mesh point for which the subspace is desired
505 
506   Output Parameter:
507 . subsp - the subspace
508 
509   Level: advanced
510 
511   Notes:
512   If the space is not defined on mesh points of the given height (e.g. if the space is discontinuous and
513   pointwise values are not defined on the element boundaries), or if the implementation of `PetscSpace` does not
514   support extracting subspaces, then NULL is returned.
515 
516   This does not increment the reference count on the returned space, and the user should not destroy it.
517 
518 .seealso: `PetscDualSpaceGetHeightSubspace()`, `PetscSpace`
519 @*/
520 PetscErrorCode PetscSpaceGetHeightSubspace(PetscSpace sp, PetscInt height, PetscSpace *subsp)
521 {
522   PetscFunctionBegin;
523   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
524   PetscValidPointer(subsp, 3);
525   *subsp = NULL;
526   PetscTryTypeMethod(sp, getheightsubspace, height, subsp);
527   PetscFunctionReturn(PETSC_SUCCESS);
528 }
529