xref: /petsc/src/dm/dt/space/impls/ptrimmed/spaceptrimmed.c (revision 834855d6effb0d027771461c8e947ee1ce5a1e17)
1130d5748SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2130d5748SToby Isaac 
3ce78bad3SBarry Smith static PetscErrorCode PetscSpaceSetFromOptions_Ptrimmed(PetscSpace sp, PetscOptionItems PetscOptionsObject)
4d71ae5a4SJacob Faibussowitsch {
5130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
6130d5748SToby Isaac 
7130d5748SToby Isaac   PetscFunctionBegin;
8d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace polynomial options");
9f4f49eeaSPierre Jolivet   PetscCall(PetscOptionsInt("-petscspace_ptrimmed_form_degree", "form degree of trimmed space", "PetscSpacePTrimmedSetFormDegree", pt->formDegree, &pt->formDegree, NULL));
10d0609cedSBarry Smith   PetscOptionsHeadEnd();
113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12130d5748SToby Isaac }
13130d5748SToby Isaac 
14d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpacePTrimmedView_Ascii(PetscSpace sp, PetscViewer v)
15d71ae5a4SJacob Faibussowitsch {
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)));
233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24130d5748SToby Isaac }
25130d5748SToby Isaac 
26d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceView_Ptrimmed(PetscSpace sp, PetscViewer viewer)
27d71ae5a4SJacob Faibussowitsch {
289f196a02SMartin Diehl   PetscBool isascii;
29130d5748SToby Isaac 
30130d5748SToby Isaac   PetscFunctionBegin;
31130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
32130d5748SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
339f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
349f196a02SMartin Diehl   if (isascii) PetscCall(PetscSpacePTrimmedView_Ascii(sp, viewer));
353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36130d5748SToby Isaac }
37130d5748SToby Isaac 
38d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceDestroy_Ptrimmed(PetscSpace sp)
39d71ae5a4SJacob Faibussowitsch {
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 
4848a46eb9SPierre Jolivet     for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&pt->subspaces[d]));
49130d5748SToby Isaac   }
509566063dSJacob Faibussowitsch   PetscCall(PetscFree(pt->subspaces));
519566063dSJacob Faibussowitsch   PetscCall(PetscFree(pt));
523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53130d5748SToby Isaac }
54130d5748SToby Isaac 
55d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetUp_Ptrimmed(PetscSpace sp)
56d71ae5a4SJacob Faibussowitsch {
57130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
58130d5748SToby Isaac   PetscInt             Nf;
59130d5748SToby Isaac 
60130d5748SToby Isaac   PetscFunctionBegin;
61371d2eb7SMartin Diehl   if (pt->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
621dca8a05SBarry 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);
639566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(sp->Nv, PetscAbsInt(pt->formDegree), &Nf));
64ad540459SPierre Jolivet   if (sp->Nc == PETSC_DETERMINE) sp->Nc = Nf;
6563a3b9bcSJacob 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);
66130d5748SToby Isaac   if (sp->Nc != Nf) {
67130d5748SToby Isaac     PetscSpace  subsp;
68130d5748SToby Isaac     PetscInt    nCopies = sp->Nc / Nf;
69130d5748SToby Isaac     PetscInt    Nv, deg, maxDeg;
70130d5748SToby Isaac     PetscInt    formDegree = pt->formDegree;
71130d5748SToby Isaac     const char *prefix;
72130d5748SToby Isaac     const char *name;
73130d5748SToby Isaac     char        subname[PETSC_MAX_PATH_LEN];
74130d5748SToby Isaac 
759566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACESUM));
769566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetConcatenate(sp, PETSC_TRUE));
779566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetNumSubspaces(sp, nCopies));
789566063dSJacob Faibussowitsch     PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subsp));
799566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
809566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subsp, prefix));
819566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subsp, "sumcomp_"));
82130d5748SToby Isaac     if (((PetscObject)sp)->name) {
839566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
849566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(subname, PETSC_MAX_PATH_LEN - 1, "%s sum component", name));
859566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)subsp, subname));
861baa6e33SBarry Smith     } else PetscCall(PetscObjectSetName((PetscObject)subsp, "sum component"));
879566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(subsp, PETSCSPACEPTRIMMED));
889566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
899566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumVariables(subsp, Nv));
909566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetNumComponents(subsp, Nf));
919566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(sp, &deg, &maxDeg));
929566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetDegree(subsp, deg, maxDeg));
939566063dSJacob Faibussowitsch     PetscCall(PetscSpacePTrimmedSetFormDegree(subsp, formDegree));
949566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(subsp));
9548a46eb9SPierre Jolivet     for (PetscInt i = 0; i < nCopies; i++) PetscCall(PetscSpaceSumSetSubspace(sp, i, subsp));
969566063dSJacob Faibussowitsch     PetscCall(PetscSpaceDestroy(&subsp));
979566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
983ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
99130d5748SToby Isaac   }
100*966bd95aSPierre Jolivet   if (sp->degree == PETSC_DEFAULT) sp->degree = 0;
101*966bd95aSPierre Jolivet   else PetscCheck(sp->degree >= 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Invalid negative degree %" PetscInt_FMT, sp->degree);
102ccb4e88aSToby Isaac   sp->maxDegree = (pt->formDegree == 0 || PetscAbsInt(pt->formDegree) == sp->Nv) ? sp->degree : sp->degree + 1;
103130d5748SToby Isaac   if (pt->formDegree == 0 || PetscAbsInt(pt->formDegree) == sp->Nv) {
104130d5748SToby Isaac     // Convert to regular polynomial space
1059566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetType(sp, PETSCSPACEPOLYNOMIAL));
1069566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
1073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
108130d5748SToby Isaac   }
109371d2eb7SMartin Diehl   pt->setupcalled = PETSC_TRUE;
1103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111130d5748SToby Isaac }
112130d5748SToby Isaac 
113d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetDimension_Ptrimmed(PetscSpace sp, PetscInt *dim)
114d71ae5a4SJacob Faibussowitsch {
115130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
116130d5748SToby Isaac   PetscInt             f;
117130d5748SToby Isaac   PetscInt             Nf;
118130d5748SToby Isaac 
119130d5748SToby Isaac   PetscFunctionBegin;
120130d5748SToby Isaac   f = pt->formDegree;
121130d5748SToby Isaac   // For PetscSpace, degree refers to the largest complete polynomial degree contained in the space which
122130d5748SToby Isaac   // is equal to the index of a P trimmed space only for 0-forms: otherwise, the index is degree + 1
1239566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedSize(sp->Nv, f == 0 ? sp->degree : sp->degree + 1, pt->formDegree, dim));
1249566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(sp->Nv, PetscAbsInt(pt->formDegree), &Nf));
125130d5748SToby Isaac   *dim *= (sp->Nc / Nf);
1263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
127130d5748SToby Isaac }
128130d5748SToby Isaac 
129130d5748SToby Isaac /*
130130d5748SToby Isaac   p in [0, npoints), i in [0, pdim), c in [0, Nc)
131130d5748SToby Isaac 
132130d5748SToby Isaac   B[p][i][c] = B[p][i_scalar][c][c]
133130d5748SToby Isaac */
134d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceEvaluate_Ptrimmed(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
135d71ae5a4SJacob Faibussowitsch {
136130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
137130d5748SToby Isaac   DM                   dm = sp->dm;
138130d5748SToby Isaac   PetscInt             jet, degree, Nf, Ncopies, Njet;
139130d5748SToby Isaac   PetscInt             Nc = sp->Nc;
140130d5748SToby Isaac   PetscInt             f;
141130d5748SToby Isaac   PetscInt             dim = sp->Nv;
142130d5748SToby Isaac   PetscReal           *eval;
143130d5748SToby Isaac   PetscInt             Nb;
144130d5748SToby Isaac 
145130d5748SToby Isaac   PetscFunctionBegin;
146371d2eb7SMartin Diehl   if (!pt->setupcalled) {
1479566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
1489566063dSJacob Faibussowitsch     PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
1493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
150130d5748SToby Isaac   }
151130d5748SToby Isaac   if (H) {
152130d5748SToby Isaac     jet = 2;
153130d5748SToby Isaac   } else if (D) {
154130d5748SToby Isaac     jet = 1;
155130d5748SToby Isaac   } else {
156130d5748SToby Isaac     jet = 0;
157130d5748SToby Isaac   }
158130d5748SToby Isaac   f      = pt->formDegree;
159130d5748SToby Isaac   degree = f == 0 ? sp->degree : sp->degree + 1;
1609566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(f), &Nf));
161130d5748SToby Isaac   Ncopies = Nc / Nf;
16208401ef6SPierre Jolivet   PetscCheck(Ncopies == 1, PetscObjectComm((PetscObject)sp), PETSC_ERR_PLIB, "Multicopy spaces should have been converted to PETSCSPACESUM");
1639566063dSJacob Faibussowitsch   PetscCall(PetscDTBinomialInt(dim + jet, dim, &Njet));
1649566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedSize(dim, degree, f, &Nb));
1659566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Nb * Nf * Njet * npoints, MPIU_REAL, &eval));
1669566063dSJacob Faibussowitsch   PetscCall(PetscDTPTrimmedEvalJet(dim, npoints, points, degree, f, jet, eval));
167130d5748SToby Isaac   if (B) {
168130d5748SToby Isaac     PetscInt p_strl = Nf * Nb;
169130d5748SToby Isaac     PetscInt b_strl = Nf;
170130d5748SToby Isaac     PetscInt v_strl = 1;
171130d5748SToby Isaac 
172130d5748SToby Isaac     PetscInt b_strr = Nf * Njet * npoints;
173130d5748SToby Isaac     PetscInt v_strr = Njet * npoints;
174130d5748SToby Isaac     PetscInt p_strr = 1;
175130d5748SToby Isaac 
176130d5748SToby Isaac     for (PetscInt v = 0; v < Nf; v++) {
177130d5748SToby Isaac       for (PetscInt b = 0; b < Nb; b++) {
178ad540459SPierre 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];
179130d5748SToby Isaac       }
180130d5748SToby Isaac     }
181130d5748SToby Isaac   }
182130d5748SToby Isaac   if (D) {
183ccb4e88aSToby Isaac     PetscInt p_strl = dim * Nf * Nb;
184ccb4e88aSToby Isaac     PetscInt b_strl = dim * Nf;
185130d5748SToby Isaac     PetscInt v_strl = dim;
186130d5748SToby Isaac     PetscInt d_strl = 1;
187130d5748SToby Isaac 
188130d5748SToby Isaac     PetscInt b_strr = Nf * Njet * npoints;
189130d5748SToby Isaac     PetscInt v_strr = Njet * npoints;
190130d5748SToby Isaac     PetscInt d_strr = npoints;
191130d5748SToby Isaac     PetscInt p_strr = 1;
192130d5748SToby Isaac 
193130d5748SToby Isaac     for (PetscInt v = 0; v < Nf; v++) {
194130d5748SToby Isaac       for (PetscInt d = 0; d < dim; d++) {
195130d5748SToby Isaac         for (PetscInt b = 0; b < Nb; b++) {
196ad540459SPierre 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];
197130d5748SToby Isaac         }
198130d5748SToby Isaac       }
199130d5748SToby Isaac     }
200130d5748SToby Isaac   }
201130d5748SToby Isaac   if (H) {
202ccb4e88aSToby Isaac     PetscInt p_strl  = dim * dim * Nf * Nb;
203ccb4e88aSToby Isaac     PetscInt b_strl  = dim * dim * Nf;
204ccb4e88aSToby Isaac     PetscInt v_strl  = dim * dim;
205130d5748SToby Isaac     PetscInt d1_strl = dim;
206130d5748SToby Isaac     PetscInt d2_strl = 1;
207130d5748SToby Isaac 
208130d5748SToby Isaac     PetscInt b_strr = Nf * Njet * npoints;
209130d5748SToby Isaac     PetscInt v_strr = Njet * npoints;
210130d5748SToby Isaac     PetscInt j_strr = npoints;
211130d5748SToby Isaac     PetscInt p_strr = 1;
212130d5748SToby Isaac 
213130d5748SToby Isaac     PetscInt *derivs;
2149566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(dim, &derivs));
215130d5748SToby Isaac     for (PetscInt d1 = 0; d1 < dim; d1++) {
216130d5748SToby Isaac       for (PetscInt d2 = 0; d2 < dim; d2++) {
217130d5748SToby Isaac         PetscInt j;
218130d5748SToby Isaac         derivs[d1]++;
219130d5748SToby Isaac         derivs[d2]++;
2209566063dSJacob Faibussowitsch         PetscCall(PetscDTGradedOrderToIndex(dim, derivs, &j));
221130d5748SToby Isaac         derivs[d1]--;
222130d5748SToby Isaac         derivs[d2]--;
223130d5748SToby Isaac         for (PetscInt v = 0; v < Nf; v++) {
224130d5748SToby Isaac           for (PetscInt b = 0; b < Nb; b++) {
225ad540459SPierre 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];
226130d5748SToby Isaac           }
227130d5748SToby Isaac         }
228130d5748SToby Isaac       }
229130d5748SToby Isaac     }
2309566063dSJacob Faibussowitsch     PetscCall(PetscFree(derivs));
231130d5748SToby Isaac   }
2329566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, Nb * Nf * Njet * npoints, MPIU_REAL, &eval));
2333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
234130d5748SToby Isaac }
235130d5748SToby Isaac 
236130d5748SToby Isaac /*@
237130d5748SToby Isaac   PetscSpacePTrimmedSetFormDegree - Set the form degree of the trimmed polynomials.
238130d5748SToby Isaac 
239130d5748SToby Isaac   Input Parameters:
240130d5748SToby Isaac + sp         - the function space object
241130d5748SToby Isaac - formDegree - the form degree
242130d5748SToby Isaac 
243dce8aebaSBarry Smith   Options Database Key:
244130d5748SToby Isaac . -petscspace_ptrimmed_form_degree <int> - The trimmed polynomial form degree
245130d5748SToby Isaac 
246130d5748SToby Isaac   Level: intermediate
247130d5748SToby Isaac 
248dce8aebaSBarry Smith .seealso: `PetscSpace`, `PetscDTAltV`, `PetscDTPTrimmedEvalJet()`, `PetscSpacePTrimmedGetFormDegree()`
249130d5748SToby Isaac @*/
250d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpacePTrimmedSetFormDegree(PetscSpace sp, PetscInt formDegree)
251d71ae5a4SJacob Faibussowitsch {
252130d5748SToby Isaac   PetscFunctionBegin;
253130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
254cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpacePTrimmedSetFormDegree_C", (PetscSpace, PetscInt), (sp, formDegree));
2553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256130d5748SToby Isaac }
257130d5748SToby Isaac 
258130d5748SToby Isaac /*@
259130d5748SToby Isaac   PetscSpacePTrimmedGetFormDegree - Get the form degree of the trimmed polynomials.
260130d5748SToby Isaac 
2612fe279fdSBarry Smith   Input Parameter:
262130d5748SToby Isaac . sp - the function space object
263130d5748SToby Isaac 
2642fe279fdSBarry Smith   Output Parameter:
26560225df5SJacob Faibussowitsch . formDegree - the form degree
266130d5748SToby Isaac 
267130d5748SToby Isaac   Level: intermediate
268130d5748SToby Isaac 
269dce8aebaSBarry Smith .seealso: `PetscSpace`, `PetscDTAltV`, `PetscDTPTrimmedEvalJet()`, `PetscSpacePTrimmedSetFormDegree()`
270130d5748SToby Isaac @*/
271d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpacePTrimmedGetFormDegree(PetscSpace sp, PetscInt *formDegree)
272d71ae5a4SJacob Faibussowitsch {
273130d5748SToby Isaac   PetscFunctionBegin;
274130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
2754f572ea9SToby Isaac   PetscAssertPointer(formDegree, 2);
276cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpacePTrimmedGetFormDegree_C", (PetscSpace, PetscInt *), (sp, formDegree));
2773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
278130d5748SToby Isaac }
279130d5748SToby Isaac 
280d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpacePTrimmedSetFormDegree_Ptrimmed(PetscSpace sp, PetscInt formDegree)
281d71ae5a4SJacob Faibussowitsch {
282130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
283130d5748SToby Isaac 
284130d5748SToby Isaac   PetscFunctionBegin;
285130d5748SToby Isaac   pt->formDegree = formDegree;
2863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
287130d5748SToby Isaac }
288130d5748SToby Isaac 
289d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpacePTrimmedGetFormDegree_Ptrimmed(PetscSpace sp, PetscInt *formDegree)
290d71ae5a4SJacob Faibussowitsch {
291130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
292130d5748SToby Isaac 
293130d5748SToby Isaac   PetscFunctionBegin;
294130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
2954f572ea9SToby Isaac   PetscAssertPointer(formDegree, 2);
296130d5748SToby Isaac   *formDegree = pt->formDegree;
2973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
298130d5748SToby Isaac }
299130d5748SToby Isaac 
300d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetHeightSubspace_Ptrimmed(PetscSpace sp, PetscInt height, PetscSpace *subsp)
301d71ae5a4SJacob Faibussowitsch {
302130d5748SToby Isaac   PetscSpace_Ptrimmed *pt = (PetscSpace_Ptrimmed *)sp->data;
303130d5748SToby Isaac   PetscInt             dim;
304130d5748SToby Isaac 
305130d5748SToby Isaac   PetscFunctionBegin;
3069566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &dim));
3071dca8a05SBarry 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);
308f4f49eeaSPierre Jolivet   if (!pt->subspaces) PetscCall(PetscCalloc1(dim, &pt->subspaces));
309130d5748SToby Isaac   if ((dim - height) <= PetscAbsInt(pt->formDegree)) {
310130d5748SToby Isaac     if (!pt->subspaces[height - 1]) {
311130d5748SToby Isaac       PetscInt    Nc, degree, Nf, Ncopies, Nfsub;
312130d5748SToby Isaac       PetscSpace  sub;
313130d5748SToby Isaac       const char *name;
314130d5748SToby Isaac 
3159566063dSJacob Faibussowitsch       PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
3169566063dSJacob Faibussowitsch       PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(pt->formDegree), &Nf));
31757508eceSPierre Jolivet       PetscCall(PetscDTBinomialInt(dim - height, PetscAbsInt(pt->formDegree), &Nfsub));
318130d5748SToby Isaac       Ncopies = Nf / Nc;
3199566063dSJacob Faibussowitsch       PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
320130d5748SToby Isaac 
3219566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
3229566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
3239566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)sub, name));
3249566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetType(sub, PETSCSPACEPTRIMMED));
3259566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumComponents(sub, Nfsub * Ncopies));
3269566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetDegree(sub, degree, PETSC_DETERMINE));
3279566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
3289566063dSJacob Faibussowitsch       PetscCall(PetscSpacePTrimmedSetFormDegree(sub, pt->formDegree));
3299566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetUp(sub));
330130d5748SToby Isaac       pt->subspaces[height - 1] = sub;
331130d5748SToby Isaac     }
332130d5748SToby Isaac     *subsp = pt->subspaces[height - 1];
333130d5748SToby Isaac   } else {
334130d5748SToby Isaac     *subsp = NULL;
335130d5748SToby Isaac   }
3363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
337130d5748SToby Isaac }
338130d5748SToby Isaac 
339d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceInitialize_Ptrimmed(PetscSpace sp)
340d71ae5a4SJacob Faibussowitsch {
341130d5748SToby Isaac   PetscFunctionBegin;
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePTrimmedGetFormDegree_C", PetscSpacePTrimmedGetFormDegree_Ptrimmed));
3439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpacePTrimmedSetFormDegree_C", PetscSpacePTrimmedSetFormDegree_Ptrimmed));
344130d5748SToby Isaac   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Ptrimmed;
345130d5748SToby Isaac   sp->ops->setup             = PetscSpaceSetUp_Ptrimmed;
346130d5748SToby Isaac   sp->ops->view              = PetscSpaceView_Ptrimmed;
347130d5748SToby Isaac   sp->ops->destroy           = PetscSpaceDestroy_Ptrimmed;
348130d5748SToby Isaac   sp->ops->getdimension      = PetscSpaceGetDimension_Ptrimmed;
349130d5748SToby Isaac   sp->ops->evaluate          = PetscSpaceEvaluate_Ptrimmed;
350130d5748SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Ptrimmed;
3513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
352130d5748SToby Isaac }
353130d5748SToby Isaac 
354130d5748SToby Isaac /*MC
355dce8aebaSBarry Smith   PETSCSPACEPTRIMMED = "ptrimmed" - A `PetscSpace` object that encapsulates a trimmed polynomial space.
356130d5748SToby Isaac 
357a167db91SMatthew Knepley   Trimmed polynomial spaces are defined for $k$-forms, and are defined by
358a167db91SMatthew Knepley   $
359a167db91SMatthew Knepley   \mathcal{P}^-_r \Lambda^k(\mathbb{R}^n) = mathcal{P}_{r-1} \Lambda^k(\mathbb{R}^n) \oplus \kappa [\mathcal{H}_{r-1} \Lambda^{k+1}(\mathbb{R}^n)],
360a167db91SMatthew Knepley   $
361a167db91SMatthew Knepley   where $\mathcal{H}_{r-1}$ are homogeneous polynomials and $\kappa$ is the Koszul differential.  This decomposition is detailed in ``Finite element exterior calculus'', Arnold, 2018.
362a167db91SMatthew Knepley 
363130d5748SToby Isaac   Level: intermediate
364130d5748SToby Isaac 
365a167db91SMatthew Knepley   Notes:
366a167db91SMatthew Knepley   Trimmed polynomial spaces correspond to several common conformal approximation spaces in the de Rham complex:
367a167db91SMatthew Knepley 
368a167db91SMatthew Knepley   In $H^1$ ($\sim k=0$), trimmed polynomial spaces are identical to the standard polynomial spaces, $\mathcal{P}_r^- \sim P_r$.
369a167db91SMatthew Knepley 
370a167db91SMatthew Knepley   In $H(\text{curl})$, ($\sim k=1$), trimmed polynomial spaces are equivalent to $H(\text{curl})$-Nedelec spaces of the first kind and can be written as
371a167db91SMatthew Knepley   $
372a167db91SMatthew Knepley     \begin{cases}
373a167db91SMatthew Knepley       [P_{r-1}(\mathbb{R}^2)]^2 \oplus \mathrm{rot}(\bf{x}) H_{r-1}(\mathbb{R}^2), & n = 2, \\
374a167db91SMatthew Knepley       [P_{r-1}(\mathbb{R}^3)]^3 \oplus \bf{x} \times [H_{r-1}(\mathbb{R}^3)]^3, & n = 3.
375a167db91SMatthew Knepley     \end{cases}
376a167db91SMatthew Knepley   $
377a167db91SMatthew Knepley 
378a167db91SMatthew Knepley   In $H(\text{div})$ ($\sim k=n-1$), trimmed polynomial spaces are equivalent to Raviart-Thomas spaces ($n=2$) and $H(\text{div})$-Nedelec spaces of the first kind ($n=3$), and can be written as
379a167db91SMatthew Knepley   $
380a167db91SMatthew Knepley     [P_{r-1}(\mathbb{R}^n)]^n \oplus \bf{x} H_{r-1}(\mathbb{R}^n).
381a167db91SMatthew Knepley   $
382a167db91SMatthew Knepley 
383d8b4a066SPierre Jolivet   In $L_2$, ($\sim k=n$), trimmed polynomial spaces are identical to the standard polynomial spaces of one degree less, $\mathcal{P}_r^- \sim P_{r-1}$.
384b24fb147SBarry Smith 
385dce8aebaSBarry Smith .seealso: `PetscSpace`, `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`, `PetscDTPTrimmedEvalJet()`
386130d5748SToby Isaac M*/
387130d5748SToby Isaac 
388d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Ptrimmed(PetscSpace sp)
389d71ae5a4SJacob Faibussowitsch {
390130d5748SToby Isaac   PetscSpace_Ptrimmed *pt;
391130d5748SToby Isaac 
392130d5748SToby Isaac   PetscFunctionBegin;
393130d5748SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
3944dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&pt));
395130d5748SToby Isaac   sp->data = pt;
396130d5748SToby Isaac 
397130d5748SToby Isaac   pt->subspaces = NULL;
398130d5748SToby Isaac   sp->Nc        = PETSC_DETERMINE;
399130d5748SToby Isaac 
4009566063dSJacob Faibussowitsch   PetscCall(PetscSpaceInitialize_Ptrimmed(sp));
4013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
402130d5748SToby Isaac }
403