xref: /petsc/src/dm/dt/space/impls/poly/spacepoly.c (revision dce8aeba1c9b69b19f651c53d8a6b674bd7e9cbd)
120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
220cf1dd8SToby Isaac 
3d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetFromOptions_Polynomial(PetscSpace sp, PetscOptionItems *PetscOptionsObject)
4d71ae5a4SJacob Faibussowitsch {
520cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
620cf1dd8SToby Isaac 
720cf1dd8SToby Isaac   PetscFunctionBegin;
8d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace polynomial options");
99566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-petscspace_poly_tensor", "Use the tensor product polynomials", "PetscSpacePolynomialSetTensor", poly->tensor, &poly->tensor, NULL));
10d0609cedSBarry Smith   PetscOptionsHeadEnd();
1120cf1dd8SToby Isaac   PetscFunctionReturn(0);
1220cf1dd8SToby Isaac }
1320cf1dd8SToby Isaac 
14d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpacePolynomialView_Ascii(PetscSpace sp, PetscViewer v)
15d71ae5a4SJacob Faibussowitsch {
1620cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
1720cf1dd8SToby Isaac 
1820cf1dd8SToby Isaac   PetscFunctionBegin;
1963a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(v, "%s space of degree %" PetscInt_FMT "\n", poly->tensor ? "Tensor polynomial" : "Polynomial", sp->degree));
2020cf1dd8SToby Isaac   PetscFunctionReturn(0);
2120cf1dd8SToby Isaac }
2220cf1dd8SToby Isaac 
23d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceView_Polynomial(PetscSpace sp, PetscViewer viewer)
24d71ae5a4SJacob Faibussowitsch {
2520cf1dd8SToby Isaac   PetscBool iascii;
2620cf1dd8SToby Isaac 
2720cf1dd8SToby Isaac   PetscFunctionBegin;
2820cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
2920cf1dd8SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
319566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscSpacePolynomialView_Ascii(sp, viewer));
3220cf1dd8SToby Isaac   PetscFunctionReturn(0);
3320cf1dd8SToby Isaac }
3420cf1dd8SToby Isaac 
35d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceDestroy_Polynomial(PetscSpace sp)
36d71ae5a4SJacob Faibussowitsch {
3720cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
3820cf1dd8SToby Isaac 
3920cf1dd8SToby Isaac   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePolynomialGetTensor_C", NULL));
419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePolynomialSetTensor_C", NULL));
4220cf1dd8SToby Isaac   if (poly->subspaces) {
4320cf1dd8SToby Isaac     PetscInt d;
4420cf1dd8SToby Isaac 
4548a46eb9SPierre Jolivet     for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&poly->subspaces[d]));
4620cf1dd8SToby Isaac   }
479566063dSJacob Faibussowitsch   PetscCall(PetscFree(poly->subspaces));
489566063dSJacob Faibussowitsch   PetscCall(PetscFree(poly));
4920cf1dd8SToby Isaac   PetscFunctionReturn(0);
5020cf1dd8SToby Isaac }
5120cf1dd8SToby Isaac 
52d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetUp_Polynomial(PetscSpace sp)
53d71ae5a4SJacob Faibussowitsch {
54f1436e55SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
55f1436e55SToby Isaac 
56f1436e55SToby Isaac   PetscFunctionBegin;
57f1436e55SToby Isaac   if (poly->setupCalled) PetscFunctionReturn(0);
58ad540459SPierre Jolivet   if (sp->Nv <= 1) poly->tensor = PETSC_FALSE;
59f1436e55SToby Isaac   if (sp->Nc != 1) {
60f1436e55SToby Isaac     PetscInt    Nc     = sp->Nc;
61f1436e55SToby Isaac     PetscBool   tensor = poly->tensor;
62f1436e55SToby Isaac     PetscInt    Nv     = sp->Nv;
63f1436e55SToby Isaac     PetscInt    degree = sp->degree;
64417c287bSToby Isaac     const char *prefix;
65417c287bSToby Isaac     const char *name;
66417c287bSToby Isaac     char        subname[PETSC_MAX_PATH_LEN];
67f1436e55SToby Isaac     PetscSpace  subsp;
68f1436e55SToby Isaac 
699566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACESUM));
709566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetNumSubspaces(sp, Nc));
719566063dSJacob Faibussowitsch     PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subsp));
729566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
739566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subsp, prefix));
749566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subsp, "sumcomp_"));
75417c287bSToby Isaac     if (((PetscObject)sp)->name) {
769566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
779566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(subname, PETSC_MAX_PATH_LEN - 1, "%s sum component", name));
789566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)subsp, subname));
791baa6e33SBarry Smith     } else PetscCall(PetscObjectSetName((PetscObject)subsp, "sum component"));
809566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(subsp, PETSCSPACEPOLYNOMIAL));
819566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetDegree(subsp, degree, PETSC_DETERMINE));
829566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumComponents(subsp, 1));
839566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumVariables(subsp, Nv));
849566063dSJacob Faibussowitsch     PetscCall(PetscSpacePolynomialSetTensor(subsp, tensor));
859566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(subsp));
8648a46eb9SPierre Jolivet     for (PetscInt i = 0; i < Nc; i++) PetscCall(PetscSpaceSumSetSubspace(sp, i, subsp));
879566063dSJacob Faibussowitsch     PetscCall(PetscSpaceDestroy(&subsp));
889566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
89f1436e55SToby Isaac     PetscFunctionReturn(0);
90f1436e55SToby Isaac   }
91f1436e55SToby Isaac   if (poly->tensor) {
92f1436e55SToby Isaac     sp->maxDegree = PETSC_DETERMINE;
939566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACETENSOR));
949566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
95f1436e55SToby Isaac     PetscFunctionReturn(0);
96f1436e55SToby Isaac   }
9763a3b9bcSJacob Faibussowitsch   PetscCheck(sp->degree >= 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Negative degree %" PetscInt_FMT " invalid", sp->degree);
98f1436e55SToby Isaac   sp->maxDegree     = sp->degree;
99f1436e55SToby Isaac   poly->setupCalled = PETSC_TRUE;
100f1436e55SToby Isaac   PetscFunctionReturn(0);
101f1436e55SToby Isaac }
102f1436e55SToby Isaac 
103d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetDimension_Polynomial(PetscSpace sp, PetscInt *dim)
104d71ae5a4SJacob Faibussowitsch {
10520cf1dd8SToby Isaac   PetscInt deg = sp->degree;
106f1436e55SToby Isaac   PetscInt n   = sp->Nv;
10720cf1dd8SToby Isaac 
10820cf1dd8SToby Isaac   PetscFunctionBegin;
1099566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(n + deg, n, dim));
110f1436e55SToby Isaac   *dim *= sp->Nc;
11120cf1dd8SToby Isaac   PetscFunctionReturn(0);
11220cf1dd8SToby Isaac }
11320cf1dd8SToby Isaac 
114d71ae5a4SJacob Faibussowitsch static PetscErrorCode CoordinateBasis(PetscInt dim, PetscInt npoints, const PetscReal points[], PetscInt jet, PetscInt Njet, PetscReal pScalar[])
115d71ae5a4SJacob Faibussowitsch {
11620cf1dd8SToby Isaac   PetscFunctionBegin;
1179566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pScalar, (1 + dim) * Njet * npoints));
118f1436e55SToby Isaac   for (PetscInt b = 0; b < 1 + dim; b++) {
119f1436e55SToby Isaac     for (PetscInt j = 0; j < PetscMin(1 + dim, Njet); j++) {
120f1436e55SToby Isaac       if (j == 0) {
121f1436e55SToby Isaac         if (b == 0) {
122ad540459SPierre Jolivet           for (PetscInt pt = 0; pt < npoints; pt++) pScalar[b * Njet * npoints + j * npoints + pt] = 1.;
12320cf1dd8SToby Isaac         } else {
124ad540459SPierre Jolivet           for (PetscInt pt = 0; pt < npoints; pt++) pScalar[b * Njet * npoints + j * npoints + pt] = points[pt * dim + (b - 1)];
125f1436e55SToby Isaac         }
126f1436e55SToby Isaac       } else if (j == b) {
127ad540459SPierre Jolivet         for (PetscInt pt = 0; pt < npoints; pt++) pScalar[b * Njet * npoints + j * npoints + pt] = 1.;
128f1436e55SToby Isaac       }
12920cf1dd8SToby Isaac     }
13020cf1dd8SToby Isaac   }
13120cf1dd8SToby Isaac   PetscFunctionReturn(0);
13220cf1dd8SToby Isaac }
13320cf1dd8SToby Isaac 
134d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceEvaluate_Polynomial(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
135d71ae5a4SJacob Faibussowitsch {
13620cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
13720cf1dd8SToby Isaac   DM               dm   = sp->dm;
13820cf1dd8SToby Isaac   PetscInt         dim  = sp->Nv;
139f1436e55SToby Isaac   PetscInt         Nb, jet, Njet;
140f1436e55SToby Isaac   PetscReal       *pScalar;
14120cf1dd8SToby Isaac 
14220cf1dd8SToby Isaac   PetscFunctionBegin;
143f1436e55SToby Isaac   if (!poly->setupCalled) {
1449566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
1459566063dSJacob Faibussowitsch     PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
146f1436e55SToby Isaac     PetscFunctionReturn(0);
14720cf1dd8SToby Isaac   }
1481dca8a05SBarry Smith   PetscCheck(!poly->tensor && sp->Nc == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "tensor and multicomponent spaces should have been converted");
1499566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim + sp->degree, dim, &Nb));
150f1436e55SToby Isaac   if (H) {
151f1436e55SToby Isaac     jet = 2;
152f1436e55SToby Isaac   } else if (D) {
153f1436e55SToby Isaac     jet = 1;
154f1436e55SToby Isaac   } else {
155f1436e55SToby Isaac     jet = 0;
15620cf1dd8SToby Isaac   }
1579566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim + jet, dim, &Njet));
1589566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Nb * Njet * npoints, MPIU_REAL, &pScalar));
159f1436e55SToby Isaac   // Why are we handling the case degree == 1 specially?  Because we don't want numerical noise when we evaluate hat
160f1436e55SToby Isaac   // functions at the vertices of a simplex, which happens when we invert the Vandermonde matrix of the PKD basis.
161f1436e55SToby Isaac   // We don't make any promise about which basis is used.
162f1436e55SToby Isaac   if (sp->degree == 1) {
1639566063dSJacob Faibussowitsch     PetscCall(CoordinateBasis(dim, npoints, points, jet, Njet, pScalar));
164f1436e55SToby Isaac   } else {
1659566063dSJacob Faibussowitsch     PetscCall(PetscDTPKDEvalJet(dim, npoints, points, sp->degree, jet, pScalar));
16620cf1dd8SToby Isaac   }
16720cf1dd8SToby Isaac   if (B) {
168f1436e55SToby Isaac     PetscInt p_strl = Nb;
169f1436e55SToby Isaac     PetscInt b_strl = 1;
1703596293dSMatthew G. Knepley 
171f1436e55SToby Isaac     PetscInt b_strr = Njet * npoints;
172f1436e55SToby Isaac     PetscInt p_strr = 1;
173f1436e55SToby Isaac 
1749566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(B, npoints * Nb));
175f1436e55SToby Isaac     for (PetscInt b = 0; b < Nb; b++) {
176ad540459SPierre Jolivet       for (PetscInt p = 0; p < npoints; p++) B[p * p_strl + b * b_strl] = pScalar[b * b_strr + p * p_strr];
1773596293dSMatthew G. Knepley     }
17820cf1dd8SToby Isaac   }
17920cf1dd8SToby Isaac   if (D) {
180f1436e55SToby Isaac     PetscInt p_strl = dim * Nb;
181f1436e55SToby Isaac     PetscInt b_strl = dim;
182f1436e55SToby Isaac     PetscInt d_strl = 1;
183f1436e55SToby Isaac 
184f1436e55SToby Isaac     PetscInt b_strr = Njet * npoints;
185f1436e55SToby Isaac     PetscInt d_strr = npoints;
186f1436e55SToby Isaac     PetscInt p_strr = 1;
187f1436e55SToby Isaac 
1889566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(D, npoints * Nb * dim));
189f1436e55SToby Isaac     for (PetscInt d = 0; d < dim; d++) {
190f1436e55SToby Isaac       for (PetscInt b = 0; b < Nb; b++) {
191ad540459SPierre Jolivet         for (PetscInt p = 0; p < npoints; p++) D[p * p_strl + b * b_strl + d * d_strl] = pScalar[b * b_strr + (1 + d) * d_strr + p * p_strr];
19220cf1dd8SToby Isaac       }
19320cf1dd8SToby Isaac     }
19420cf1dd8SToby Isaac   }
19520cf1dd8SToby Isaac   if (H) {
196f1436e55SToby Isaac     PetscInt p_strl  = dim * dim * Nb;
197f1436e55SToby Isaac     PetscInt b_strl  = dim * dim;
198f1436e55SToby Isaac     PetscInt d1_strl = dim;
199f1436e55SToby Isaac     PetscInt d2_strl = 1;
200f1436e55SToby Isaac 
201f1436e55SToby Isaac     PetscInt b_strr = Njet * npoints;
202f1436e55SToby Isaac     PetscInt j_strr = npoints;
203f1436e55SToby Isaac     PetscInt p_strr = 1;
204f1436e55SToby Isaac 
205f1436e55SToby Isaac     PetscInt *derivs;
2069566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(dim, &derivs));
2079566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(H, npoints * Nb * dim * dim));
208f1436e55SToby Isaac     for (PetscInt d1 = 0; d1 < dim; d1++) {
209f1436e55SToby Isaac       for (PetscInt d2 = 0; d2 < dim; d2++) {
210f1436e55SToby Isaac         PetscInt j;
211f1436e55SToby Isaac         derivs[d1]++;
212f1436e55SToby Isaac         derivs[d2]++;
2139566063dSJacob Faibussowitsch         PetscCall(PetscDTGradedOrderToIndex(dim, derivs, &j));
214f1436e55SToby Isaac         derivs[d1]--;
215f1436e55SToby Isaac         derivs[d2]--;
216f1436e55SToby Isaac         for (PetscInt b = 0; b < Nb; b++) {
217ad540459SPierre Jolivet           for (PetscInt p = 0; p < npoints; p++) H[p * p_strl + b * b_strl + d1 * d1_strl + d2 * d2_strl] = pScalar[b * b_strr + j * j_strr + p * p_strr];
21820cf1dd8SToby Isaac         }
21920cf1dd8SToby Isaac       }
22020cf1dd8SToby Isaac     }
2219566063dSJacob Faibussowitsch     PetscCall(PetscFree(derivs));
22220cf1dd8SToby Isaac   }
2239566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, Nb * Njet * npoints, MPIU_REAL, &pScalar));
22420cf1dd8SToby Isaac   PetscFunctionReturn(0);
22520cf1dd8SToby Isaac }
22620cf1dd8SToby Isaac 
22720cf1dd8SToby Isaac /*@
22820cf1dd8SToby Isaac   PetscSpacePolynomialSetTensor - Set whether a function space is a space of tensor polynomials (the space is spanned
229f1436e55SToby Isaac   by polynomials whose degree in each variable is bounded by the given order), as opposed to polynomials (the space is
23020cf1dd8SToby Isaac   spanned by polynomials whose total degree---summing over all variables---is bounded by the given order).
23120cf1dd8SToby Isaac 
23220cf1dd8SToby Isaac   Input Parameters:
23320cf1dd8SToby Isaac + sp     - the function space object
234*dce8aebaSBarry Smith - tensor - `PETSC_TRUE` for a tensor polynomial space, `PETSC_FALSE` for a polynomial space
23520cf1dd8SToby Isaac 
236*dce8aebaSBarry Smith   Options Database Key:
2374ab77754SMatthew G. Knepley . -petscspace_poly_tensor <bool> - Whether to use tensor product polynomials in higher dimension
2384ab77754SMatthew G. Knepley 
23929b5c115SMatthew G. Knepley   Level: intermediate
24020cf1dd8SToby Isaac 
241*dce8aebaSBarry Smith .seealso: `PetscSpace`, `PetscSpacePolynomialGetTensor()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
24220cf1dd8SToby Isaac @*/
243d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpacePolynomialSetTensor(PetscSpace sp, PetscBool tensor)
244d71ae5a4SJacob Faibussowitsch {
24520cf1dd8SToby Isaac   PetscFunctionBegin;
24620cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
247cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpacePolynomialSetTensor_C", (PetscSpace, PetscBool), (sp, tensor));
24820cf1dd8SToby Isaac   PetscFunctionReturn(0);
24920cf1dd8SToby Isaac }
25020cf1dd8SToby Isaac 
25120cf1dd8SToby Isaac /*@
25220cf1dd8SToby Isaac   PetscSpacePolynomialGetTensor - Get whether a function space is a space of tensor polynomials (the space is spanned
25320cf1dd8SToby Isaac   by polynomials whose degree in each variabl is bounded by the given order), as opposed to polynomials (the space is
25420cf1dd8SToby Isaac   spanned by polynomials whose total degree---summing over all variables---is bounded by the given order).
25520cf1dd8SToby Isaac 
25620cf1dd8SToby Isaac   Input Parameters:
25720cf1dd8SToby Isaac . sp     - the function space object
25820cf1dd8SToby Isaac 
25920cf1dd8SToby Isaac   Output Parameters:
260*dce8aebaSBarry Smith . tensor - `PETSC_TRUE` for a tensor polynomial space, `PETSC_FALSE` for a polynomial space
26120cf1dd8SToby Isaac 
26229b5c115SMatthew G. Knepley   Level: intermediate
26320cf1dd8SToby Isaac 
264*dce8aebaSBarry Smith .seealso: `PetscSpace`, `PetscSpacePolynomialSetTensor()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
26520cf1dd8SToby Isaac @*/
266d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpacePolynomialGetTensor(PetscSpace sp, PetscBool *tensor)
267d71ae5a4SJacob Faibussowitsch {
26820cf1dd8SToby Isaac   PetscFunctionBegin;
26920cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
270dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(tensor, 2);
271cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpacePolynomialGetTensor_C", (PetscSpace, PetscBool *), (sp, tensor));
27220cf1dd8SToby Isaac   PetscFunctionReturn(0);
27320cf1dd8SToby Isaac }
27420cf1dd8SToby Isaac 
275d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpacePolynomialSetTensor_Polynomial(PetscSpace sp, PetscBool tensor)
276d71ae5a4SJacob Faibussowitsch {
27720cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
27820cf1dd8SToby Isaac 
27920cf1dd8SToby Isaac   PetscFunctionBegin;
28020cf1dd8SToby Isaac   poly->tensor = tensor;
28120cf1dd8SToby Isaac   PetscFunctionReturn(0);
28220cf1dd8SToby Isaac }
28320cf1dd8SToby Isaac 
284d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpacePolynomialGetTensor_Polynomial(PetscSpace sp, PetscBool *tensor)
285d71ae5a4SJacob Faibussowitsch {
28620cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
28720cf1dd8SToby Isaac 
28820cf1dd8SToby Isaac   PetscFunctionBegin;
28920cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
290dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(tensor, 2);
29120cf1dd8SToby Isaac   *tensor = poly->tensor;
29220cf1dd8SToby Isaac   PetscFunctionReturn(0);
29320cf1dd8SToby Isaac }
29420cf1dd8SToby Isaac 
295d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetHeightSubspace_Polynomial(PetscSpace sp, PetscInt height, PetscSpace *subsp)
296d71ae5a4SJacob Faibussowitsch {
29720cf1dd8SToby Isaac   PetscSpace_Poly *poly = (PetscSpace_Poly *)sp->data;
29820cf1dd8SToby Isaac   PetscInt         Nc, dim, order;
29920cf1dd8SToby Isaac   PetscBool        tensor;
30020cf1dd8SToby Isaac 
30120cf1dd8SToby Isaac   PetscFunctionBegin;
3029566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
3039566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &dim));
3049566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(sp, &order, NULL));
3059566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
3061dca8a05SBarry Smith   PetscCheck(height <= dim && height >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %" PetscInt_FMT " for dimension %" PetscInt_FMT " space", height, dim);
3079566063dSJacob Faibussowitsch   if (!poly->subspaces) PetscCall(PetscCalloc1(dim, &poly->subspaces));
30820cf1dd8SToby Isaac   if (height <= dim) {
30920cf1dd8SToby Isaac     if (!poly->subspaces[height - 1]) {
31020cf1dd8SToby Isaac       PetscSpace  sub;
3113f6b16c7SMatthew G. Knepley       const char *name;
31220cf1dd8SToby Isaac 
3139566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
3149566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
3159566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)sub, name));
3169566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetType(sub, PETSCSPACEPOLYNOMIAL));
3179566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumComponents(sub, Nc));
3189566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetDegree(sub, order, PETSC_DETERMINE));
3199566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
3209566063dSJacob Faibussowitsch       PetscCall(PetscSpacePolynomialSetTensor(sub, tensor));
3219566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetUp(sub));
32220cf1dd8SToby Isaac       poly->subspaces[height - 1] = sub;
32320cf1dd8SToby Isaac     }
32420cf1dd8SToby Isaac     *subsp = poly->subspaces[height - 1];
32520cf1dd8SToby Isaac   } else {
32620cf1dd8SToby Isaac     *subsp = NULL;
32720cf1dd8SToby Isaac   }
32820cf1dd8SToby Isaac   PetscFunctionReturn(0);
32920cf1dd8SToby Isaac }
33020cf1dd8SToby Isaac 
331d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceInitialize_Polynomial(PetscSpace sp)
332d71ae5a4SJacob Faibussowitsch {
33320cf1dd8SToby Isaac   PetscFunctionBegin;
33420cf1dd8SToby Isaac   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Polynomial;
33520cf1dd8SToby Isaac   sp->ops->setup             = PetscSpaceSetUp_Polynomial;
33620cf1dd8SToby Isaac   sp->ops->view              = PetscSpaceView_Polynomial;
33720cf1dd8SToby Isaac   sp->ops->destroy           = PetscSpaceDestroy_Polynomial;
33820cf1dd8SToby Isaac   sp->ops->getdimension      = PetscSpaceGetDimension_Polynomial;
33920cf1dd8SToby Isaac   sp->ops->evaluate          = PetscSpaceEvaluate_Polynomial;
34020cf1dd8SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Polynomial;
3419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePolynomialGetTensor_C", PetscSpacePolynomialGetTensor_Polynomial));
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePolynomialSetTensor_C", PetscSpacePolynomialSetTensor_Polynomial));
34320cf1dd8SToby Isaac   PetscFunctionReturn(0);
34420cf1dd8SToby Isaac }
34520cf1dd8SToby Isaac 
34620cf1dd8SToby Isaac /*MC
347*dce8aebaSBarry Smith   PETSCSPACEPOLYNOMIAL = "poly" - A `PetscSpace` object that encapsulates a polynomial space, e.g. P1 is the space of
34820cf1dd8SToby Isaac   linear polynomials. The space is replicated for each component.
34920cf1dd8SToby Isaac 
35020cf1dd8SToby Isaac   Level: intermediate
35120cf1dd8SToby Isaac 
352*dce8aebaSBarry Smith .seealso: `PetscSpace`, `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`
35320cf1dd8SToby Isaac M*/
35420cf1dd8SToby Isaac 
355d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Polynomial(PetscSpace sp)
356d71ae5a4SJacob Faibussowitsch {
35720cf1dd8SToby Isaac   PetscSpace_Poly *poly;
35820cf1dd8SToby Isaac 
35920cf1dd8SToby Isaac   PetscFunctionBegin;
36020cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
3614dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&poly));
36220cf1dd8SToby Isaac   sp->data = poly;
36320cf1dd8SToby Isaac 
36420cf1dd8SToby Isaac   poly->tensor    = PETSC_FALSE;
36520cf1dd8SToby Isaac   poly->subspaces = NULL;
36620cf1dd8SToby Isaac 
3679566063dSJacob Faibussowitsch   PetscCall(PetscSpaceInitialize_Polynomial(sp));
36820cf1dd8SToby Isaac   PetscFunctionReturn(0);
36920cf1dd8SToby Isaac }
370