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