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, °, &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, °ree, 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