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