xref: /petsc/src/dm/dt/space/interface/space.c (revision ebead697dbf761eb322f829370bbe90b3bd93fa3)
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