xref: /petsc/src/dm/dt/space/impls/ptrimmed/spaceptrimmed.c (revision ad540459ab38c4a232710a68077e487eb6627fe2)
1130d5748SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2130d5748SToby Isaac 
39371c9d4SSatish Balay static PetscErrorCode PetscSpaceSetFromOptions_Ptrimmed(PetscSpace sp, PetscOptionItems *PetscOptionsObject) {
4130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
5130d5748SToby Isaac 
6130d5748SToby Isaac   PetscFunctionBegin;
7d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace polynomial options");
89566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-petscspace_ptrimmed_form_degree", "form degree of trimmed space", "PetscSpacePTrimmedSetFormDegree", pt->formDegree, &(pt->formDegree), NULL));
9d0609cedSBarry Smith   PetscOptionsHeadEnd();
10130d5748SToby Isaac   PetscFunctionReturn(0);
11130d5748SToby Isaac }
12130d5748SToby Isaac 
139371c9d4SSatish Balay static PetscErrorCode PetscSpacePTrimmedView_Ascii(PetscSpace sp, PetscViewer v) {
14130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
15ccb4e88aSToby Isaac   PetscInt             f, tdegree;
16130d5748SToby Isaac 
17130d5748SToby Isaac   PetscFunctionBegin;
18130d5748SToby Isaac   f       = pt->formDegree;
19ccb4e88aSToby Isaac   tdegree = f == 0 ? sp->degree : sp->degree + 1;
2063a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(v, "Trimmed polynomials %" PetscInt_FMT "%s-forms of degree %" PetscInt_FMT " (P-%" PetscInt_FMT "/\\%" PetscInt_FMT ")\n", PetscAbsInt(f), f < 0 ? "*" : "", sp->degree, tdegree, PetscAbsInt(f)));
21130d5748SToby Isaac   PetscFunctionReturn(0);
22130d5748SToby Isaac }
23130d5748SToby Isaac 
249371c9d4SSatish Balay static PetscErrorCode PetscSpaceView_Ptrimmed(PetscSpace sp, PetscViewer viewer) {
25130d5748SToby Isaac   PetscBool iascii;
26130d5748SToby Isaac 
27130d5748SToby Isaac   PetscFunctionBegin;
28130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
29130d5748SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
319566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscSpacePTrimmedView_Ascii(sp, viewer));
32130d5748SToby Isaac   PetscFunctionReturn(0);
33130d5748SToby Isaac }
34130d5748SToby Isaac 
359371c9d4SSatish Balay static PetscErrorCode PetscSpaceDestroy_Ptrimmed(PetscSpace sp) {
36130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
37130d5748SToby Isaac 
38130d5748SToby Isaac   PetscFunctionBegin;
399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePTrimmedGetFormDegree_C", NULL));
409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePTrimmedSetFormDegree_C", NULL));
41130d5748SToby Isaac   if (pt->subspaces) {
42130d5748SToby Isaac     PetscInt d;
43130d5748SToby Isaac 
4448a46eb9SPierre Jolivet     for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&pt->subspaces[d]));
45130d5748SToby Isaac   }
469566063dSJacob Faibussowitsch   PetscCall(PetscFree(pt->subspaces));
479566063dSJacob Faibussowitsch   PetscCall(PetscFree(pt));
48130d5748SToby Isaac   PetscFunctionReturn(0);
49130d5748SToby Isaac }
50130d5748SToby Isaac 
519371c9d4SSatish Balay static PetscErrorCode PetscSpaceSetUp_Ptrimmed(PetscSpace sp) {
52130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
53130d5748SToby Isaac   PetscInt             Nf;
54130d5748SToby Isaac 
55130d5748SToby Isaac   PetscFunctionBegin;
56130d5748SToby Isaac   if (pt->setupCalled) PetscFunctionReturn(0);
571dca8a05SBarry Smith   PetscCheck(pt->formDegree >= -sp->Nv && pt->formDegree <= sp->Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Form degree %" PetscInt_FMT " not in valid range [%" PetscInt_FMT ",%" PetscInt_FMT "]", pt->formDegree, sp->Nv, sp->Nv);
589566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(sp->Nv, PetscAbsInt(pt->formDegree), &Nf));
59*ad540459SPierre Jolivet   if (sp->Nc == PETSC_DETERMINE) sp->Nc = Nf;
6063a3b9bcSJacob Faibussowitsch   PetscCheck(sp->Nc % Nf == 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "Number of components %" PetscInt_FMT " is not a multiple of form dimension %" PetscInt_FMT, sp->Nc, Nf);
61130d5748SToby Isaac   if (sp->Nc != Nf) {
62130d5748SToby Isaac     PetscSpace  subsp;
63130d5748SToby Isaac     PetscInt    nCopies = sp->Nc / Nf;
64130d5748SToby Isaac     PetscInt    Nv, deg, maxDeg;
65130d5748SToby Isaac     PetscInt    formDegree = pt->formDegree;
66130d5748SToby Isaac     const char *prefix;
67130d5748SToby Isaac     const char *name;
68130d5748SToby Isaac     char        subname[PETSC_MAX_PATH_LEN];
69130d5748SToby Isaac 
709566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACESUM));
719566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetConcatenate(sp, PETSC_TRUE));
729566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetNumSubspaces(sp, nCopies));
739566063dSJacob Faibussowitsch     PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subsp));
749566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
759566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subsp, prefix));
769566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subsp, "sumcomp_"));
77130d5748SToby Isaac     if (((PetscObject)sp)->name) {
789566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
799566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(subname, PETSC_MAX_PATH_LEN - 1, "%s sum component", name));
809566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)subsp, subname));
811baa6e33SBarry Smith     } else PetscCall(PetscObjectSetName((PetscObject)subsp, "sum component"));
829566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(subsp, PETSCSPACEPTRIMMED));
839566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
849566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumVariables(subsp, Nv));
859566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumComponents(subsp, Nf));
869566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(sp, &deg, &maxDeg));
879566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetDegree(subsp, deg, maxDeg));
889566063dSJacob Faibussowitsch     PetscCall(PetscSpacePTrimmedSetFormDegree(subsp, formDegree));
899566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(subsp));
9048a46eb9SPierre Jolivet     for (PetscInt i = 0; i < nCopies; i++) PetscCall(PetscSpaceSumSetSubspace(sp, i, subsp));
919566063dSJacob Faibussowitsch     PetscCall(PetscSpaceDestroy(&subsp));
929566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
93130d5748SToby Isaac     PetscFunctionReturn(0);
94130d5748SToby Isaac   }
95130d5748SToby Isaac   if (sp->degree == PETSC_DEFAULT) {
96130d5748SToby Isaac     sp->degree = 0;
97130d5748SToby Isaac   } else if (sp->degree < 0) {
9863a3b9bcSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Invalid negative degree %" PetscInt_FMT, sp->degree);
99130d5748SToby Isaac   }
100ccb4e88aSToby Isaac   sp->maxDegree = (pt->formDegree == 0 || PetscAbsInt(pt->formDegree) == sp->Nv) ? sp->degree : sp->degree + 1;
101130d5748SToby Isaac   if (pt->formDegree == 0 || PetscAbsInt(pt->formDegree) == sp->Nv) {
102130d5748SToby Isaac     // Convert to regular polynomial space
1039566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACEPOLYNOMIAL));
1049566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
105130d5748SToby Isaac     PetscFunctionReturn(0);
106130d5748SToby Isaac   }
107130d5748SToby Isaac   pt->setupCalled = PETSC_TRUE;
108130d5748SToby Isaac   PetscFunctionReturn(0);
109130d5748SToby Isaac }
110130d5748SToby Isaac 
1119371c9d4SSatish Balay static PetscErrorCode PetscSpaceGetDimension_Ptrimmed(PetscSpace sp, PetscInt *dim) {
112130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
113130d5748SToby Isaac   PetscInt             f;
114130d5748SToby Isaac   PetscInt             Nf;
115130d5748SToby Isaac 
116130d5748SToby Isaac   PetscFunctionBegin;
117130d5748SToby Isaac   f = pt->formDegree;
118130d5748SToby Isaac   // For PetscSpace, degree refers to the largest complete polynomial degree contained in the space which
119130d5748SToby Isaac   // is equal to the index of a P trimmed space only for 0-forms: otherwise, the index is degree + 1
1209566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedSize(sp->Nv, f == 0 ? sp->degree : sp->degree + 1, pt->formDegree, dim));
1219566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(sp->Nv, PetscAbsInt(pt->formDegree), &Nf));
122130d5748SToby Isaac   *dim *= (sp->Nc / Nf);
123130d5748SToby Isaac   PetscFunctionReturn(0);
124130d5748SToby Isaac }
125130d5748SToby Isaac 
126130d5748SToby Isaac /*
127130d5748SToby Isaac   p in [0, npoints), i in [0, pdim), c in [0, Nc)
128130d5748SToby Isaac 
129130d5748SToby Isaac   B[p][i][c] = B[p][i_scalar][c][c]
130130d5748SToby Isaac */
1319371c9d4SSatish Balay static PetscErrorCode PetscSpaceEvaluate_Ptrimmed(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[]) {
132130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
133130d5748SToby Isaac   DM                   dm = sp->dm;
134130d5748SToby Isaac   PetscInt             jet, degree, Nf, Ncopies, Njet;
135130d5748SToby Isaac   PetscInt             Nc = sp->Nc;
136130d5748SToby Isaac   PetscInt             f;
137130d5748SToby Isaac   PetscInt             dim = sp->Nv;
138130d5748SToby Isaac   PetscReal           *eval;
139130d5748SToby Isaac   PetscInt             Nb;
140130d5748SToby Isaac 
141130d5748SToby Isaac   PetscFunctionBegin;
142130d5748SToby Isaac   if (!pt->setupCalled) {
1439566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
1449566063dSJacob Faibussowitsch     PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
145130d5748SToby Isaac     PetscFunctionReturn(0);
146130d5748SToby Isaac   }
147130d5748SToby Isaac   if (H) {
148130d5748SToby Isaac     jet = 2;
149130d5748SToby Isaac   } else if (D) {
150130d5748SToby Isaac     jet = 1;
151130d5748SToby Isaac   } else {
152130d5748SToby Isaac     jet = 0;
153130d5748SToby Isaac   }
154130d5748SToby Isaac   f      = pt->formDegree;
155130d5748SToby Isaac   degree = f == 0 ? sp->degree : sp->degree + 1;
1569566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(f), &Nf));
157130d5748SToby Isaac   Ncopies = Nc / Nf;
15808401ef6SPierre Jolivet   PetscCheck(Ncopies == 1, PetscObjectComm((PetscObject)sp), PETSC_ERR_PLIB, "Multicopy spaces should have been converted to PETSCSPACESUM");
1599566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim + jet, dim, &Njet));
1609566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedSize(dim, degree, f, &Nb));
1619566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Nb * Nf * Njet * npoints, MPIU_REAL, &eval));
1629566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedEvalJet(dim, npoints, points, degree, f, jet, eval));
163130d5748SToby Isaac   if (B) {
164130d5748SToby Isaac     PetscInt p_strl = Nf * Nb;
165130d5748SToby Isaac     PetscInt b_strl = Nf;
166130d5748SToby Isaac     PetscInt v_strl = 1;
167130d5748SToby Isaac 
168130d5748SToby Isaac     PetscInt b_strr = Nf * Njet * npoints;
169130d5748SToby Isaac     PetscInt v_strr = Njet * npoints;
170130d5748SToby Isaac     PetscInt p_strr = 1;
171130d5748SToby Isaac 
172130d5748SToby Isaac     for (PetscInt v = 0; v < Nf; v++) {
173130d5748SToby Isaac       for (PetscInt b = 0; b < Nb; b++) {
174*ad540459SPierre Jolivet         for (PetscInt p = 0; p < npoints; p++) B[p * p_strl + b * b_strl + v * v_strl] = eval[b * b_strr + v * v_strr + p * p_strr];
175130d5748SToby Isaac       }
176130d5748SToby Isaac     }
177130d5748SToby Isaac   }
178130d5748SToby Isaac   if (D) {
179ccb4e88aSToby Isaac     PetscInt p_strl = dim * Nf * Nb;
180ccb4e88aSToby Isaac     PetscInt b_strl = dim * Nf;
181130d5748SToby Isaac     PetscInt v_strl = dim;
182130d5748SToby Isaac     PetscInt d_strl = 1;
183130d5748SToby Isaac 
184130d5748SToby Isaac     PetscInt b_strr = Nf * Njet * npoints;
185130d5748SToby Isaac     PetscInt v_strr = Njet * npoints;
186130d5748SToby Isaac     PetscInt d_strr = npoints;
187130d5748SToby Isaac     PetscInt p_strr = 1;
188130d5748SToby Isaac 
189130d5748SToby Isaac     for (PetscInt v = 0; v < Nf; v++) {
190130d5748SToby Isaac       for (PetscInt d = 0; d < dim; d++) {
191130d5748SToby Isaac         for (PetscInt b = 0; b < Nb; b++) {
192*ad540459SPierre Jolivet           for (PetscInt p = 0; p < npoints; p++) D[p * p_strl + b * b_strl + v * v_strl + d * d_strl] = eval[b * b_strr + v * v_strr + (1 + d) * d_strr + p * p_strr];
193130d5748SToby Isaac         }
194130d5748SToby Isaac       }
195130d5748SToby Isaac     }
196130d5748SToby Isaac   }
197130d5748SToby Isaac   if (H) {
198ccb4e88aSToby Isaac     PetscInt p_strl  = dim * dim * Nf * Nb;
199ccb4e88aSToby Isaac     PetscInt b_strl  = dim * dim * Nf;
200ccb4e88aSToby Isaac     PetscInt v_strl  = dim * dim;
201130d5748SToby Isaac     PetscInt d1_strl = dim;
202130d5748SToby Isaac     PetscInt d2_strl = 1;
203130d5748SToby Isaac 
204130d5748SToby Isaac     PetscInt b_strr = Nf * Njet * npoints;
205130d5748SToby Isaac     PetscInt v_strr = Njet * npoints;
206130d5748SToby Isaac     PetscInt j_strr = npoints;
207130d5748SToby Isaac     PetscInt p_strr = 1;
208130d5748SToby Isaac 
209130d5748SToby Isaac     PetscInt *derivs;
2109566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(dim, &derivs));
211130d5748SToby Isaac     for (PetscInt d1 = 0; d1 < dim; d1++) {
212130d5748SToby Isaac       for (PetscInt d2 = 0; d2 < dim; d2++) {
213130d5748SToby Isaac         PetscInt j;
214130d5748SToby Isaac         derivs[d1]++;
215130d5748SToby Isaac         derivs[d2]++;
2169566063dSJacob Faibussowitsch         PetscCall(PetscDTGradedOrderToIndex(dim, derivs, &j));
217130d5748SToby Isaac         derivs[d1]--;
218130d5748SToby Isaac         derivs[d2]--;
219130d5748SToby Isaac         for (PetscInt v = 0; v < Nf; v++) {
220130d5748SToby Isaac           for (PetscInt b = 0; b < Nb; b++) {
221*ad540459SPierre Jolivet             for (PetscInt p = 0; p < npoints; p++) H[p * p_strl + b * b_strl + v * v_strl + d1 * d1_strl + d2 * d2_strl] = eval[b * b_strr + v * v_strr + j * j_strr + p * p_strr];
222130d5748SToby Isaac           }
223130d5748SToby Isaac         }
224130d5748SToby Isaac       }
225130d5748SToby Isaac     }
2269566063dSJacob Faibussowitsch     PetscCall(PetscFree(derivs));
227130d5748SToby Isaac   }
2289566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, Nb * Nf * Njet * npoints, MPIU_REAL, &eval));
229130d5748SToby Isaac   PetscFunctionReturn(0);
230130d5748SToby Isaac }
231130d5748SToby Isaac 
232130d5748SToby Isaac /*@
233130d5748SToby Isaac   PetscSpacePTrimmedSetFormDegree - Set the form degree of the trimmed polynomials.
234130d5748SToby Isaac 
235130d5748SToby Isaac   Input Parameters:
236130d5748SToby Isaac + sp         - the function space object
237130d5748SToby Isaac - formDegree - the form degree
238130d5748SToby Isaac 
239130d5748SToby Isaac   Options Database:
240130d5748SToby Isaac . -petscspace_ptrimmed_form_degree <int> - The trimmed polynomial form degree
241130d5748SToby Isaac 
242130d5748SToby Isaac   Level: intermediate
243130d5748SToby Isaac 
244db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDTPTrimmedEvalJet()`, `PetscSpacePTrimmedGetFormDegree()`
245130d5748SToby Isaac @*/
2469371c9d4SSatish Balay PetscErrorCode PetscSpacePTrimmedSetFormDegree(PetscSpace sp, PetscInt formDegree) {
247130d5748SToby Isaac   PetscFunctionBegin;
248130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
249cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpacePTrimmedSetFormDegree_C", (PetscSpace, PetscInt), (sp, formDegree));
250130d5748SToby Isaac   PetscFunctionReturn(0);
251130d5748SToby Isaac }
252130d5748SToby Isaac 
253130d5748SToby Isaac /*@
254130d5748SToby Isaac   PetscSpacePTrimmedGetFormDegree - Get the form degree of the trimmed polynomials.
255130d5748SToby Isaac 
256130d5748SToby Isaac   Input Parameters:
257130d5748SToby Isaac . sp     - the function space object
258130d5748SToby Isaac 
259130d5748SToby Isaac   Output Parameters:
260130d5748SToby Isaac . formDegee - the form degree
261130d5748SToby Isaac 
262130d5748SToby Isaac   Level: intermediate
263130d5748SToby Isaac 
264db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDTPTrimmedEvalJet()`, `PetscSpacePTrimmedSetFormDegree()`
265130d5748SToby Isaac @*/
2669371c9d4SSatish Balay PetscErrorCode PetscSpacePTrimmedGetFormDegree(PetscSpace sp, PetscInt *formDegree) {
267130d5748SToby Isaac   PetscFunctionBegin;
268130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
269dadcf809SJacob Faibussowitsch   PetscValidIntPointer(formDegree, 2);
270cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpacePTrimmedGetFormDegree_C", (PetscSpace, PetscInt *), (sp, formDegree));
271130d5748SToby Isaac   PetscFunctionReturn(0);
272130d5748SToby Isaac }
273130d5748SToby Isaac 
2749371c9d4SSatish Balay static PetscErrorCode PetscSpacePTrimmedSetFormDegree_Ptrimmed(PetscSpace sp, PetscInt formDegree) {
275130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
276130d5748SToby Isaac 
277130d5748SToby Isaac   PetscFunctionBegin;
278130d5748SToby Isaac   pt->formDegree = formDegree;
279130d5748SToby Isaac   PetscFunctionReturn(0);
280130d5748SToby Isaac }
281130d5748SToby Isaac 
2829371c9d4SSatish Balay static PetscErrorCode PetscSpacePTrimmedGetFormDegree_Ptrimmed(PetscSpace sp, PetscInt *formDegree) {
283130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
284130d5748SToby Isaac 
285130d5748SToby Isaac   PetscFunctionBegin;
286130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
287dadcf809SJacob Faibussowitsch   PetscValidIntPointer(formDegree, 2);
288130d5748SToby Isaac   *formDegree = pt->formDegree;
289130d5748SToby Isaac   PetscFunctionReturn(0);
290130d5748SToby Isaac }
291130d5748SToby Isaac 
2929371c9d4SSatish Balay static PetscErrorCode PetscSpaceGetHeightSubspace_Ptrimmed(PetscSpace sp, PetscInt height, PetscSpace *subsp) {
293130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
294130d5748SToby Isaac   PetscInt             dim;
295130d5748SToby Isaac 
296130d5748SToby Isaac   PetscFunctionBegin;
2979566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &dim));
2981dca8a05SBarry 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);
2999566063dSJacob Faibussowitsch   if (!pt->subspaces) PetscCall(PetscCalloc1(dim, &(pt->subspaces)));
300130d5748SToby Isaac   if ((dim - height) <= PetscAbsInt(pt->formDegree)) {
301130d5748SToby Isaac     if (!pt->subspaces[height - 1]) {
302130d5748SToby Isaac       PetscInt    Nc, degree, Nf, Ncopies, Nfsub;
303130d5748SToby Isaac       PetscSpace  sub;
304130d5748SToby Isaac       const char *name;
305130d5748SToby Isaac 
3069566063dSJacob Faibussowitsch       PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
3079566063dSJacob Faibussowitsch       PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(pt->formDegree), &Nf));
3089566063dSJacob Faibussowitsch       PetscCall(PetscDTBinomialInt((dim - height), PetscAbsInt(pt->formDegree), &Nfsub));
309130d5748SToby Isaac       Ncopies = Nf / Nc;
3109566063dSJacob Faibussowitsch       PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
311130d5748SToby Isaac 
3129566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
3139566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
3149566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)sub, name));
3159566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetType(sub, PETSCSPACEPTRIMMED));
3169566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumComponents(sub, Nfsub * Ncopies));
3179566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetDegree(sub, degree, PETSC_DETERMINE));
3189566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
3199566063dSJacob Faibussowitsch       PetscCall(PetscSpacePTrimmedSetFormDegree(sub, pt->formDegree));
3209566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetUp(sub));
321130d5748SToby Isaac       pt->subspaces[height - 1] = sub;
322130d5748SToby Isaac     }
323130d5748SToby Isaac     *subsp = pt->subspaces[height - 1];
324130d5748SToby Isaac   } else {
325130d5748SToby Isaac     *subsp = NULL;
326130d5748SToby Isaac   }
327130d5748SToby Isaac   PetscFunctionReturn(0);
328130d5748SToby Isaac }
329130d5748SToby Isaac 
3309371c9d4SSatish Balay static PetscErrorCode PetscSpaceInitialize_Ptrimmed(PetscSpace sp) {
331130d5748SToby Isaac   PetscFunctionBegin;
3329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePTrimmedGetFormDegree_C", PetscSpacePTrimmedGetFormDegree_Ptrimmed));
3339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePTrimmedSetFormDegree_C", PetscSpacePTrimmedSetFormDegree_Ptrimmed));
334130d5748SToby Isaac   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Ptrimmed;
335130d5748SToby Isaac   sp->ops->setup             = PetscSpaceSetUp_Ptrimmed;
336130d5748SToby Isaac   sp->ops->view              = PetscSpaceView_Ptrimmed;
337130d5748SToby Isaac   sp->ops->destroy           = PetscSpaceDestroy_Ptrimmed;
338130d5748SToby Isaac   sp->ops->getdimension      = PetscSpaceGetDimension_Ptrimmed;
339130d5748SToby Isaac   sp->ops->evaluate          = PetscSpaceEvaluate_Ptrimmed;
340130d5748SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Ptrimmed;
341130d5748SToby Isaac   PetscFunctionReturn(0);
342130d5748SToby Isaac }
343130d5748SToby Isaac 
344130d5748SToby Isaac /*MC
345130d5748SToby Isaac   PETSCSPACEPTRIMMED = "ptrimmed" - A PetscSpace object that encapsulates a trimmed polynomial space.
346130d5748SToby Isaac 
347130d5748SToby Isaac   Level: intermediate
348130d5748SToby Isaac 
349db781477SPatrick Sanan .seealso: `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`, `PetscDTPTrimmedEvalJet()`
350130d5748SToby Isaac M*/
351130d5748SToby Isaac 
3529371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Ptrimmed(PetscSpace sp) {
353130d5748SToby Isaac   PetscSpace_Ptrimmed *pt;
354130d5748SToby Isaac 
355130d5748SToby Isaac   PetscFunctionBegin;
356130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
3579566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(sp, &pt));
358130d5748SToby Isaac   sp->data = pt;
359130d5748SToby Isaac 
360130d5748SToby Isaac   pt->subspaces = NULL;
361130d5748SToby Isaac   sp->Nc        = PETSC_DETERMINE;
362130d5748SToby Isaac 
3639566063dSJacob Faibussowitsch   PetscCall(PetscSpaceInitialize_Ptrimmed(sp));
364130d5748SToby Isaac   PetscFunctionReturn(0);
365130d5748SToby Isaac }
366