xref: /petsc/src/dm/dt/space/impls/ptrimmed/spaceptrimmed.c (revision 1dca8a0504492127e77eac64bc165d7372dd6d63)
1130d5748SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2130d5748SToby Isaac 
3130d5748SToby Isaac static PetscErrorCode PetscSpaceSetFromOptions_Ptrimmed(PetscOptionItems *PetscOptionsObject,PetscSpace sp)
4130d5748SToby Isaac {
5130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
6130d5748SToby Isaac 
7130d5748SToby Isaac   PetscFunctionBegin;
8d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"PetscSpace polynomial options");
99566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-petscspace_ptrimmed_form_degree", "form degree of trimmed space", "PetscSpacePTrimmedSetFormDegree", pt->formDegree, &(pt->formDegree), NULL));
10d0609cedSBarry Smith   PetscOptionsHeadEnd();
11130d5748SToby Isaac   PetscFunctionReturn(0);
12130d5748SToby Isaac }
13130d5748SToby Isaac 
14130d5748SToby Isaac static PetscErrorCode PetscSpacePTrimmedView_Ascii(PetscSpace sp, PetscViewer v)
15130d5748SToby Isaac {
16130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
17ccb4e88aSToby Isaac   PetscInt             f, tdegree;
18130d5748SToby Isaac 
19130d5748SToby Isaac   PetscFunctionBegin;
20130d5748SToby Isaac   f = pt->formDegree;
21ccb4e88aSToby Isaac   tdegree = f == 0 ? sp->degree : sp->degree + 1;
2263a3b9bcSJacob 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)));
23130d5748SToby Isaac   PetscFunctionReturn(0);
24130d5748SToby Isaac }
25130d5748SToby Isaac 
26130d5748SToby Isaac static PetscErrorCode PetscSpaceView_Ptrimmed(PetscSpace sp, PetscViewer viewer)
27130d5748SToby Isaac {
28130d5748SToby Isaac   PetscBool      iascii;
29130d5748SToby Isaac 
30130d5748SToby Isaac   PetscFunctionBegin;
31130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
32130d5748SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
349566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscSpacePTrimmedView_Ascii(sp, viewer));
35130d5748SToby Isaac   PetscFunctionReturn(0);
36130d5748SToby Isaac }
37130d5748SToby Isaac 
38130d5748SToby Isaac static PetscErrorCode PetscSpaceDestroy_Ptrimmed(PetscSpace sp)
39130d5748SToby Isaac {
40130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
41130d5748SToby Isaac 
42130d5748SToby Isaac   PetscFunctionBegin;
439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscSpacePTrimmedGetFormDegree_C", NULL));
449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscSpacePTrimmedSetFormDegree_C", NULL));
45130d5748SToby Isaac   if (pt->subspaces) {
46130d5748SToby Isaac     PetscInt d;
47130d5748SToby Isaac 
48130d5748SToby Isaac     for (d = 0; d < sp->Nv; ++d) {
499566063dSJacob Faibussowitsch       PetscCall(PetscSpaceDestroy(&pt->subspaces[d]));
50130d5748SToby Isaac     }
51130d5748SToby Isaac   }
529566063dSJacob Faibussowitsch   PetscCall(PetscFree(pt->subspaces));
539566063dSJacob Faibussowitsch   PetscCall(PetscFree(pt));
54130d5748SToby Isaac   PetscFunctionReturn(0);
55130d5748SToby Isaac }
56130d5748SToby Isaac 
57130d5748SToby Isaac static PetscErrorCode PetscSpaceSetUp_Ptrimmed(PetscSpace sp)
58130d5748SToby Isaac {
59130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
60130d5748SToby Isaac   PetscInt             Nf;
61130d5748SToby Isaac 
62130d5748SToby Isaac   PetscFunctionBegin;
63130d5748SToby Isaac   if (pt->setupCalled) PetscFunctionReturn(0);
64*1dca8a05SBarry 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);
659566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(sp->Nv, PetscAbsInt(pt->formDegree), &Nf));
66130d5748SToby Isaac   if (sp->Nc == PETSC_DETERMINE) {
67130d5748SToby Isaac     sp->Nc = Nf;
68130d5748SToby Isaac   }
6963a3b9bcSJacob 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);
70130d5748SToby Isaac   if (sp->Nc != Nf) {
71130d5748SToby Isaac     PetscSpace  subsp;
72130d5748SToby Isaac     PetscInt    nCopies = sp->Nc / Nf;
73130d5748SToby Isaac     PetscInt    Nv, deg, maxDeg;
74130d5748SToby Isaac     PetscInt    formDegree = pt->formDegree;
75130d5748SToby Isaac     const char *prefix;
76130d5748SToby Isaac     const char *name;
77130d5748SToby Isaac     char        subname[PETSC_MAX_PATH_LEN];
78130d5748SToby Isaac 
799566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACESUM));
809566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetConcatenate(sp, PETSC_TRUE));
819566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetNumSubspaces(sp, nCopies));
829566063dSJacob Faibussowitsch     PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subsp));
839566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
849566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subsp, prefix));
859566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subsp, "sumcomp_"));
86130d5748SToby Isaac     if (((PetscObject)sp)->name) {
879566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
889566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(subname, PETSC_MAX_PATH_LEN-1, "%s sum component", name));
899566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)subsp, subname));
90130d5748SToby Isaac     } else {
919566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)subsp, "sum component"));
92130d5748SToby Isaac     }
939566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(subsp, PETSCSPACEPTRIMMED));
949566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
959566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumVariables(subsp, Nv));
969566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumComponents(subsp, Nf));
979566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(sp, &deg, &maxDeg));
989566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetDegree(subsp, deg, maxDeg));
999566063dSJacob Faibussowitsch     PetscCall(PetscSpacePTrimmedSetFormDegree(subsp, formDegree));
1009566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(subsp));
101130d5748SToby Isaac     for (PetscInt i = 0; i < nCopies; i++) {
1029566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumSetSubspace(sp, i, subsp));
103130d5748SToby Isaac     }
1049566063dSJacob Faibussowitsch     PetscCall(PetscSpaceDestroy(&subsp));
1059566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
106130d5748SToby Isaac     PetscFunctionReturn(0);
107130d5748SToby Isaac   }
108130d5748SToby Isaac   if (sp->degree == PETSC_DEFAULT) {
109130d5748SToby Isaac     sp->degree = 0;
110130d5748SToby Isaac   } else if (sp->degree < 0) {
11163a3b9bcSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Invalid negative degree %" PetscInt_FMT, sp->degree);
112130d5748SToby Isaac   }
113ccb4e88aSToby Isaac   sp->maxDegree = (pt->formDegree == 0 || PetscAbsInt(pt->formDegree) == sp->Nv) ? sp->degree : sp->degree + 1;
114130d5748SToby Isaac   if (pt->formDegree == 0 || PetscAbsInt(pt->formDegree) == sp->Nv) {
115130d5748SToby Isaac     // Convert to regular polynomial space
1169566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACEPOLYNOMIAL));
1179566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
118130d5748SToby Isaac     PetscFunctionReturn(0);
119130d5748SToby Isaac   }
120130d5748SToby Isaac   pt->setupCalled = PETSC_TRUE;
121130d5748SToby Isaac   PetscFunctionReturn(0);
122130d5748SToby Isaac }
123130d5748SToby Isaac 
124130d5748SToby Isaac static PetscErrorCode PetscSpaceGetDimension_Ptrimmed(PetscSpace sp, PetscInt *dim)
125130d5748SToby Isaac {
126130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
127130d5748SToby Isaac   PetscInt             f;
128130d5748SToby Isaac   PetscInt             Nf;
129130d5748SToby Isaac 
130130d5748SToby Isaac   PetscFunctionBegin;
131130d5748SToby Isaac   f = pt->formDegree;
132130d5748SToby Isaac   // For PetscSpace, degree refers to the largest complete polynomial degree contained in the space which
133130d5748SToby Isaac   // is equal to the index of a P trimmed space only for 0-forms: otherwise, the index is degree + 1
1349566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedSize(sp->Nv, f == 0 ? sp->degree : sp->degree + 1, pt->formDegree, dim));
1359566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(sp->Nv, PetscAbsInt(pt->formDegree), &Nf));
136130d5748SToby Isaac   *dim *= (sp->Nc / Nf);
137130d5748SToby Isaac   PetscFunctionReturn(0);
138130d5748SToby Isaac }
139130d5748SToby Isaac 
140130d5748SToby Isaac /*
141130d5748SToby Isaac   p in [0, npoints), i in [0, pdim), c in [0, Nc)
142130d5748SToby Isaac 
143130d5748SToby Isaac   B[p][i][c] = B[p][i_scalar][c][c]
144130d5748SToby Isaac */
145130d5748SToby Isaac static PetscErrorCode PetscSpaceEvaluate_Ptrimmed(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
146130d5748SToby Isaac {
147130d5748SToby Isaac   PetscSpace_Ptrimmed *pt    = (PetscSpace_Ptrimmed *) sp->data;
148130d5748SToby Isaac   DM               dm      = sp->dm;
149130d5748SToby Isaac   PetscInt         jet, degree, Nf, Ncopies, Njet;
150130d5748SToby Isaac   PetscInt         Nc      = sp->Nc;
151130d5748SToby Isaac   PetscInt         f;
152130d5748SToby Isaac   PetscInt         dim     = sp->Nv;
153130d5748SToby Isaac   PetscReal       *eval;
154130d5748SToby Isaac   PetscInt         Nb;
155130d5748SToby Isaac 
156130d5748SToby Isaac   PetscFunctionBegin;
157130d5748SToby Isaac   if (!pt->setupCalled) {
1589566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
1599566063dSJacob Faibussowitsch     PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
160130d5748SToby Isaac     PetscFunctionReturn(0);
161130d5748SToby Isaac   }
162130d5748SToby Isaac   if (H) {
163130d5748SToby Isaac     jet = 2;
164130d5748SToby Isaac   } else if (D) {
165130d5748SToby Isaac     jet = 1;
166130d5748SToby Isaac   } else {
167130d5748SToby Isaac     jet = 0;
168130d5748SToby Isaac   }
169130d5748SToby Isaac   f = pt->formDegree;
170130d5748SToby Isaac   degree = f == 0 ? sp->degree : sp->degree + 1;
1719566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(f), &Nf));
172130d5748SToby Isaac   Ncopies = Nc / Nf;
17308401ef6SPierre Jolivet   PetscCheck(Ncopies == 1,PetscObjectComm((PetscObject) sp), PETSC_ERR_PLIB, "Multicopy spaces should have been converted to PETSCSPACESUM");
1749566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim + jet, dim, &Njet));
1759566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedSize(dim, degree, f, &Nb));
1769566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Nb * Nf * Njet * npoints, MPIU_REAL, &eval));
1779566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedEvalJet(dim, npoints, points, degree, f, jet, eval));
178130d5748SToby Isaac   if (B) {
179130d5748SToby Isaac     PetscInt p_strl = Nf*Nb;
180130d5748SToby Isaac     PetscInt b_strl = Nf;
181130d5748SToby Isaac     PetscInt v_strl = 1;
182130d5748SToby Isaac 
183130d5748SToby Isaac     PetscInt b_strr = Nf*Njet*npoints;
184130d5748SToby Isaac     PetscInt v_strr = Njet*npoints;
185130d5748SToby Isaac     PetscInt p_strr = 1;
186130d5748SToby Isaac 
187130d5748SToby Isaac     for (PetscInt v = 0; v < Nf; v++) {
188130d5748SToby Isaac       for (PetscInt b = 0; b < Nb; b++) {
189130d5748SToby Isaac         for (PetscInt p = 0; p < npoints; p++) {
190130d5748SToby Isaac           B[p*p_strl + b*b_strl + v*v_strl] = eval[b*b_strr + v*v_strr + p*p_strr];
191130d5748SToby Isaac         }
192130d5748SToby Isaac       }
193130d5748SToby Isaac     }
194130d5748SToby Isaac   }
195130d5748SToby Isaac   if (D) {
196ccb4e88aSToby Isaac     PetscInt p_strl = dim*Nf*Nb;
197ccb4e88aSToby Isaac     PetscInt b_strl = dim*Nf;
198130d5748SToby Isaac     PetscInt v_strl = dim;
199130d5748SToby Isaac     PetscInt d_strl = 1;
200130d5748SToby Isaac 
201130d5748SToby Isaac     PetscInt b_strr = Nf*Njet*npoints;
202130d5748SToby Isaac     PetscInt v_strr = Njet*npoints;
203130d5748SToby Isaac     PetscInt d_strr = npoints;
204130d5748SToby Isaac     PetscInt p_strr = 1;
205130d5748SToby Isaac 
206130d5748SToby Isaac     for (PetscInt v = 0; v < Nf; v++) {
207130d5748SToby Isaac       for (PetscInt d = 0; d < dim; d++) {
208130d5748SToby Isaac         for (PetscInt b = 0; b < Nb; b++) {
209130d5748SToby Isaac           for (PetscInt p = 0; p < npoints; p++) {
210ccb4e88aSToby Isaac             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];
211130d5748SToby Isaac           }
212130d5748SToby Isaac         }
213130d5748SToby Isaac       }
214130d5748SToby Isaac     }
215130d5748SToby Isaac   }
216130d5748SToby Isaac   if (H) {
217ccb4e88aSToby Isaac     PetscInt p_strl  = dim*dim*Nf*Nb;
218ccb4e88aSToby Isaac     PetscInt b_strl  = dim*dim*Nf;
219ccb4e88aSToby Isaac     PetscInt v_strl  = dim*dim;
220130d5748SToby Isaac     PetscInt d1_strl = dim;
221130d5748SToby Isaac     PetscInt d2_strl = 1;
222130d5748SToby Isaac 
223130d5748SToby Isaac     PetscInt b_strr = Nf*Njet*npoints;
224130d5748SToby Isaac     PetscInt v_strr = Njet*npoints;
225130d5748SToby Isaac     PetscInt j_strr = npoints;
226130d5748SToby Isaac     PetscInt p_strr = 1;
227130d5748SToby Isaac 
228130d5748SToby Isaac     PetscInt *derivs;
2299566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(dim, &derivs));
230130d5748SToby Isaac     for (PetscInt d1 = 0; d1 < dim; d1++) {
231130d5748SToby Isaac       for (PetscInt d2 = 0; d2 < dim; d2++) {
232130d5748SToby Isaac         PetscInt j;
233130d5748SToby Isaac         derivs[d1]++;
234130d5748SToby Isaac         derivs[d2]++;
2359566063dSJacob Faibussowitsch         PetscCall(PetscDTGradedOrderToIndex(dim, derivs, &j));
236130d5748SToby Isaac         derivs[d1]--;
237130d5748SToby Isaac         derivs[d2]--;
238130d5748SToby Isaac         for (PetscInt v = 0; v < Nf; v++) {
239130d5748SToby Isaac           for (PetscInt b = 0; b < Nb; b++) {
240130d5748SToby Isaac             for (PetscInt p = 0; p < npoints; p++) {
241ccb4e88aSToby Isaac               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];
242130d5748SToby Isaac             }
243130d5748SToby Isaac           }
244130d5748SToby Isaac         }
245130d5748SToby Isaac       }
246130d5748SToby Isaac     }
2479566063dSJacob Faibussowitsch     PetscCall(PetscFree(derivs));
248130d5748SToby Isaac   }
2499566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, Nb * Nf * Njet * npoints, MPIU_REAL, &eval));
250130d5748SToby Isaac   PetscFunctionReturn(0);
251130d5748SToby Isaac }
252130d5748SToby Isaac 
253130d5748SToby Isaac /*@
254130d5748SToby Isaac   PetscSpacePTrimmedSetFormDegree - Set the form degree of the trimmed polynomials.
255130d5748SToby Isaac 
256130d5748SToby Isaac   Input Parameters:
257130d5748SToby Isaac + sp         - the function space object
258130d5748SToby Isaac - formDegree - the form degree
259130d5748SToby Isaac 
260130d5748SToby Isaac   Options Database:
261130d5748SToby Isaac . -petscspace_ptrimmed_form_degree <int> - The trimmed polynomial form degree
262130d5748SToby Isaac 
263130d5748SToby Isaac   Level: intermediate
264130d5748SToby Isaac 
265130d5748SToby Isaac .seealso: PetscDTAltV, PetscDTPTrimmedEvalJet(), PetscSpacePTrimmedGetFormDegree()
266130d5748SToby Isaac @*/
267130d5748SToby Isaac PetscErrorCode PetscSpacePTrimmedSetFormDegree(PetscSpace sp, PetscInt formDegree)
268130d5748SToby Isaac {
269130d5748SToby Isaac   PetscFunctionBegin;
270130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
271cac4c232SBarry Smith   PetscTryMethod(sp,"PetscSpacePTrimmedSetFormDegree_C",(PetscSpace,PetscInt),(sp,formDegree));
272130d5748SToby Isaac   PetscFunctionReturn(0);
273130d5748SToby Isaac }
274130d5748SToby Isaac 
275130d5748SToby Isaac /*@
276130d5748SToby Isaac   PetscSpacePTrimmedGetFormDegree - Get the form degree of the trimmed polynomials.
277130d5748SToby Isaac 
278130d5748SToby Isaac   Input Parameters:
279130d5748SToby Isaac . sp     - the function space object
280130d5748SToby Isaac 
281130d5748SToby Isaac   Output Parameters:
282130d5748SToby Isaac . formDegee - the form degree
283130d5748SToby Isaac 
284130d5748SToby Isaac   Level: intermediate
285130d5748SToby Isaac 
286130d5748SToby Isaac .seealso: PetscDTAltV, PetscDTPTrimmedEvalJet(), PetscSpacePTrimmedSetFormDegree()
287130d5748SToby Isaac @*/
288130d5748SToby Isaac PetscErrorCode PetscSpacePTrimmedGetFormDegree(PetscSpace sp, PetscInt *formDegree)
289130d5748SToby Isaac {
290130d5748SToby Isaac   PetscFunctionBegin;
291130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
292dadcf809SJacob Faibussowitsch   PetscValidIntPointer(formDegree, 2);
293cac4c232SBarry Smith   PetscTryMethod(sp,"PetscSpacePTrimmedGetFormDegree_C",(PetscSpace,PetscInt*),(sp,formDegree));
294130d5748SToby Isaac   PetscFunctionReturn(0);
295130d5748SToby Isaac }
296130d5748SToby Isaac 
297130d5748SToby Isaac static PetscErrorCode PetscSpacePTrimmedSetFormDegree_Ptrimmed(PetscSpace sp, PetscInt formDegree)
298130d5748SToby Isaac {
299130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
300130d5748SToby Isaac 
301130d5748SToby Isaac   PetscFunctionBegin;
302130d5748SToby Isaac   pt->formDegree = formDegree;
303130d5748SToby Isaac   PetscFunctionReturn(0);
304130d5748SToby Isaac }
305130d5748SToby Isaac 
306130d5748SToby Isaac static PetscErrorCode PetscSpacePTrimmedGetFormDegree_Ptrimmed(PetscSpace sp, PetscInt *formDegree)
307130d5748SToby Isaac {
308130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
309130d5748SToby Isaac 
310130d5748SToby Isaac   PetscFunctionBegin;
311130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
312dadcf809SJacob Faibussowitsch   PetscValidIntPointer(formDegree, 2);
313130d5748SToby Isaac   *formDegree = pt->formDegree;
314130d5748SToby Isaac   PetscFunctionReturn(0);
315130d5748SToby Isaac }
316130d5748SToby Isaac 
317130d5748SToby Isaac static PetscErrorCode PetscSpaceGetHeightSubspace_Ptrimmed(PetscSpace sp, PetscInt height, PetscSpace *subsp)
318130d5748SToby Isaac {
319130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *) sp->data;
320130d5748SToby Isaac   PetscInt         dim;
321130d5748SToby Isaac 
322130d5748SToby Isaac   PetscFunctionBegin;
3239566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &dim));
324*1dca8a05SBarry 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);
3259566063dSJacob Faibussowitsch   if (!pt->subspaces) PetscCall(PetscCalloc1(dim, &(pt->subspaces)));
326130d5748SToby Isaac   if ((dim - height) <= PetscAbsInt(pt->formDegree)) {
327130d5748SToby Isaac     if (!pt->subspaces[height-1]) {
328130d5748SToby Isaac       PetscInt Nc, degree, Nf, Ncopies, Nfsub;
329130d5748SToby Isaac       PetscSpace  sub;
330130d5748SToby Isaac       const char *name;
331130d5748SToby Isaac 
3329566063dSJacob Faibussowitsch       PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
3339566063dSJacob Faibussowitsch       PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(pt->formDegree), &Nf));
3349566063dSJacob Faibussowitsch       PetscCall(PetscDTBinomialInt((dim-height), PetscAbsInt(pt->formDegree), &Nfsub));
335130d5748SToby Isaac       Ncopies = Nf / Nc;
3369566063dSJacob Faibussowitsch       PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
337130d5748SToby Isaac 
3389566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject) sp), &sub));
3399566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) sp,  &name));
3409566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject) sub,  name));
3419566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetType(sub, PETSCSPACEPTRIMMED));
3429566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumComponents(sub, Nfsub * Ncopies));
3439566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetDegree(sub, degree, PETSC_DETERMINE));
3449566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumVariables(sub, dim-height));
3459566063dSJacob Faibussowitsch       PetscCall(PetscSpacePTrimmedSetFormDegree(sub, pt->formDegree));
3469566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetUp(sub));
347130d5748SToby Isaac       pt->subspaces[height-1] = sub;
348130d5748SToby Isaac     }
349130d5748SToby Isaac     *subsp = pt->subspaces[height-1];
350130d5748SToby Isaac   } else {
351130d5748SToby Isaac     *subsp = NULL;
352130d5748SToby Isaac   }
353130d5748SToby Isaac   PetscFunctionReturn(0);
354130d5748SToby Isaac }
355130d5748SToby Isaac 
356130d5748SToby Isaac static PetscErrorCode PetscSpaceInitialize_Ptrimmed(PetscSpace sp)
357130d5748SToby Isaac {
358130d5748SToby Isaac   PetscFunctionBegin;
3599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscSpacePTrimmedGetFormDegree_C", PetscSpacePTrimmedGetFormDegree_Ptrimmed));
3609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscSpacePTrimmedSetFormDegree_C", PetscSpacePTrimmedSetFormDegree_Ptrimmed));
361130d5748SToby Isaac   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Ptrimmed;
362130d5748SToby Isaac   sp->ops->setup             = PetscSpaceSetUp_Ptrimmed;
363130d5748SToby Isaac   sp->ops->view              = PetscSpaceView_Ptrimmed;
364130d5748SToby Isaac   sp->ops->destroy           = PetscSpaceDestroy_Ptrimmed;
365130d5748SToby Isaac   sp->ops->getdimension      = PetscSpaceGetDimension_Ptrimmed;
366130d5748SToby Isaac   sp->ops->evaluate          = PetscSpaceEvaluate_Ptrimmed;
367130d5748SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Ptrimmed;
368130d5748SToby Isaac   PetscFunctionReturn(0);
369130d5748SToby Isaac }
370130d5748SToby Isaac 
371130d5748SToby Isaac /*MC
372130d5748SToby Isaac   PETSCSPACEPTRIMMED = "ptrimmed" - A PetscSpace object that encapsulates a trimmed polynomial space.
373130d5748SToby Isaac 
374130d5748SToby Isaac   Level: intermediate
375130d5748SToby Isaac 
376130d5748SToby Isaac .seealso: PetscSpaceType, PetscSpaceCreate(), PetscSpaceSetType(), PetscDTPTrimmedEvalJet()
377130d5748SToby Isaac M*/
378130d5748SToby Isaac 
379130d5748SToby Isaac PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Ptrimmed(PetscSpace sp)
380130d5748SToby Isaac {
381130d5748SToby Isaac   PetscSpace_Ptrimmed *pt;
382130d5748SToby Isaac 
383130d5748SToby Isaac   PetscFunctionBegin;
384130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
3859566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(sp,&pt));
386130d5748SToby Isaac   sp->data = pt;
387130d5748SToby Isaac 
388130d5748SToby Isaac   pt->subspaces = NULL;
389130d5748SToby Isaac   sp->Nc        = PETSC_DETERMINE;
390130d5748SToby Isaac 
3919566063dSJacob Faibussowitsch   PetscCall(PetscSpaceInitialize_Ptrimmed(sp));
392130d5748SToby Isaac   PetscFunctionReturn(0);
393130d5748SToby Isaac }
394