136e5648fSToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
236e5648fSToby Isaac
PetscSpaceTensorCreateSubspace(PetscSpace space,PetscInt Nvs,PetscInt Ncs,PetscSpace * subspace)3d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceTensorCreateSubspace(PetscSpace space, PetscInt Nvs, PetscInt Ncs, PetscSpace *subspace)
4d71ae5a4SJacob Faibussowitsch {
536e5648fSToby Isaac PetscInt degree;
636e5648fSToby Isaac const char *prefix;
7417c287bSToby Isaac const char *name;
8417c287bSToby Isaac char subname[PETSC_MAX_PATH_LEN];
936e5648fSToby Isaac
1036e5648fSToby Isaac PetscFunctionBegin;
119566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(space, °ree, NULL));
129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)space, &prefix));
139566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)space), subspace));
149566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(*subspace, PETSCSPACEPOLYNOMIAL));
159566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(*subspace, Nvs));
169566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(*subspace, Ncs));
179566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(*subspace, degree, PETSC_DETERMINE));
189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*subspace, prefix));
199566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*subspace, "tensorcomp_"));
20417c287bSToby Isaac if (((PetscObject)space)->name) {
219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)space, &name));
229566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(subname, PETSC_MAX_PATH_LEN - 1, "%s tensor component", name));
239566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*subspace, subname));
241baa6e33SBarry Smith } else PetscCall(PetscObjectSetName((PetscObject)*subspace, "tensor component"));
253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2636e5648fSToby Isaac }
2736e5648fSToby Isaac
PetscSpaceSetFromOptions_Tensor(PetscSpace sp,PetscOptionItems PetscOptionsObject)28ce78bad3SBarry Smith static PetscErrorCode PetscSpaceSetFromOptions_Tensor(PetscSpace sp, PetscOptionItems PetscOptionsObject)
29d71ae5a4SJacob Faibussowitsch {
3036e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
3136e5648fSToby Isaac PetscInt Ns, Nc, i, Nv, deg;
3236e5648fSToby Isaac PetscBool uniform = PETSC_TRUE;
3336e5648fSToby Isaac
3436e5648fSToby Isaac PetscFunctionBegin;
359566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
363ba16761SJacob Faibussowitsch if (!Nv) PetscFunctionReturn(PETSC_SUCCESS);
379566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
389566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetNumSubspaces(sp, &Ns));
399566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(sp, °, NULL));
4036e5648fSToby Isaac if (Ns > 1) {
4136e5648fSToby Isaac PetscSpace s0;
4236e5648fSToby Isaac
439566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, 0, &s0));
4436e5648fSToby Isaac for (i = 1; i < Ns; i++) {
4536e5648fSToby Isaac PetscSpace si;
4636e5648fSToby Isaac
479566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, i, &si));
489371c9d4SSatish Balay if (si != s0) {
499371c9d4SSatish Balay uniform = PETSC_FALSE;
509371c9d4SSatish Balay break;
519371c9d4SSatish Balay }
5236e5648fSToby Isaac }
5336e5648fSToby Isaac }
5436e5648fSToby Isaac Ns = (Ns == PETSC_DEFAULT) ? PetscMax(Nv, 1) : Ns;
55d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace tensor options");
569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscspace_tensor_spaces", "The number of subspaces", "PetscSpaceTensorSetNumSubspaces", Ns, &Ns, NULL, 0));
579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-petscspace_tensor_uniform", "Subspaces are identical", "PetscSpaceTensorSetFromOptions", uniform, &uniform, NULL));
58d0609cedSBarry Smith PetscOptionsHeadEnd();
591dca8a05SBarry Smith PetscCheck(Ns >= 0 && (Nv <= 0 || Ns != 0), PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a tensor space made up of %" PetscInt_FMT " spaces", Ns);
601dca8a05SBarry Smith PetscCheck(Nv <= 0 || Ns <= Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a tensor space with %" PetscInt_FMT " subspaces over %" PetscInt_FMT " variables", Ns, Nv);
619566063dSJacob Faibussowitsch if (Ns != tens->numTensSpaces) PetscCall(PetscSpaceTensorSetNumSubspaces(sp, Ns));
6236e5648fSToby Isaac if (uniform) {
6336e5648fSToby Isaac PetscInt Nvs = Nv / Ns;
64b3a91243SToby Isaac PetscInt Ncs;
6536e5648fSToby Isaac PetscSpace subspace;
6636e5648fSToby Isaac
6763a3b9bcSJacob Faibussowitsch PetscCheck(Nv % Ns == 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONG, "Cannot use %" PetscInt_FMT " uniform subspaces for %" PetscInt_FMT " variable space", Ns, Nv);
68b3a91243SToby Isaac Ncs = (PetscInt)PetscPowReal((PetscReal)Nc, 1. / Ns);
6963a3b9bcSJacob Faibussowitsch PetscCheck(Nc % PetscPowInt(Ncs, Ns) == 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONG, "Cannot use %" PetscInt_FMT " uniform subspaces for %" PetscInt_FMT " component space", Ns, Nc);
709566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, 0, &subspace));
719566063dSJacob Faibussowitsch if (!subspace) PetscCall(PetscSpaceTensorCreateSubspace(sp, Nvs, Ncs, &subspace));
729566063dSJacob Faibussowitsch else PetscCall(PetscObjectReference((PetscObject)subspace));
739566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(subspace));
749566063dSJacob Faibussowitsch for (i = 0; i < Ns; i++) PetscCall(PetscSpaceTensorSetSubspace(sp, i, subspace));
759566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&subspace));
7636e5648fSToby Isaac } else {
7736e5648fSToby Isaac for (i = 0; i < Ns; i++) {
7836e5648fSToby Isaac PetscSpace subspace;
7936e5648fSToby Isaac
809566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, i, &subspace));
8136e5648fSToby Isaac if (!subspace) {
8236e5648fSToby Isaac char tprefix[128];
8336e5648fSToby Isaac
849566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorCreateSubspace(sp, 1, 1, &subspace));
85835f2295SStefano Zampini PetscCall(PetscSNPrintf(tprefix, 128, "%" PetscInt_FMT "_", i));
869566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subspace, tprefix));
871baa6e33SBarry Smith } else PetscCall(PetscObjectReference((PetscObject)subspace));
889566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(subspace));
899566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorSetSubspace(sp, i, subspace));
909566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&subspace));
9136e5648fSToby Isaac }
9236e5648fSToby Isaac }
933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9436e5648fSToby Isaac }
9536e5648fSToby Isaac
PetscSpaceTensorView_Ascii(PetscSpace sp,PetscViewer v)96d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceTensorView_Ascii(PetscSpace sp, PetscViewer v)
97d71ae5a4SJacob Faibussowitsch {
9836e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
9936e5648fSToby Isaac PetscBool uniform = PETSC_TRUE;
100c88cc932SToby Isaac PetscInt Ns = tens->numTensSpaces, i, n;
10136e5648fSToby Isaac
10236e5648fSToby Isaac PetscFunctionBegin;
10336e5648fSToby Isaac for (i = 1; i < Ns; i++) {
1049371c9d4SSatish Balay if (tens->tensspaces[i] != tens->tensspaces[0]) {
1059371c9d4SSatish Balay uniform = PETSC_FALSE;
1069371c9d4SSatish Balay break;
1079371c9d4SSatish Balay }
10836e5648fSToby Isaac }
10963a3b9bcSJacob Faibussowitsch if (uniform) PetscCall(PetscViewerASCIIPrintf(v, "Tensor space of %" PetscInt_FMT " subspaces (all identical)\n", Ns));
11063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(v, "Tensor space of %" PetscInt_FMT " subspaces\n", Ns));
11136e5648fSToby Isaac n = uniform ? 1 : Ns;
11236e5648fSToby Isaac for (i = 0; i < n; i++) {
1139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v));
1149566063dSJacob Faibussowitsch PetscCall(PetscSpaceView(tens->tensspaces[i], v));
1159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v));
11636e5648fSToby Isaac }
1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11836e5648fSToby Isaac }
11936e5648fSToby Isaac
PetscSpaceView_Tensor(PetscSpace sp,PetscViewer viewer)120d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceView_Tensor(PetscSpace sp, PetscViewer viewer)
121d71ae5a4SJacob Faibussowitsch {
122*9f196a02SMartin Diehl PetscBool isascii;
12336e5648fSToby Isaac
12436e5648fSToby Isaac PetscFunctionBegin;
125*9f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
126*9f196a02SMartin Diehl if (isascii) PetscCall(PetscSpaceTensorView_Ascii(sp, viewer));
1273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12836e5648fSToby Isaac }
12936e5648fSToby Isaac
PetscSpaceSetUp_Tensor(PetscSpace sp)130d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetUp_Tensor(PetscSpace sp)
131d71ae5a4SJacob Faibussowitsch {
13236e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
133b3a91243SToby Isaac PetscInt Nc, Nv, Ns;
13436e5648fSToby Isaac PetscBool uniform = PETSC_TRUE;
13536e5648fSToby Isaac PetscInt deg, maxDeg;
1362144e486SToby Isaac PetscInt Ncprod;
13736e5648fSToby Isaac
13836e5648fSToby Isaac PetscFunctionBegin;
139371d2eb7SMartin Diehl if (tens->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1409566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
1419566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
1429566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetNumSubspaces(sp, &Ns));
14336e5648fSToby Isaac if (Ns == PETSC_DEFAULT) {
14436e5648fSToby Isaac Ns = Nv;
1459566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorSetNumSubspaces(sp, Ns));
14636e5648fSToby Isaac }
14736e5648fSToby Isaac if (!Ns) {
148b3a91243SToby Isaac SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have zero subspaces");
14936e5648fSToby Isaac } else {
150eae3dc7dSJacob Faibussowitsch PetscSpace s0 = NULL;
15136e5648fSToby Isaac
1521dca8a05SBarry Smith PetscCheck(Nv <= 0 || Ns <= Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a tensor space with %" PetscInt_FMT " subspaces over %" PetscInt_FMT " variables", Ns, Nv);
1539566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, 0, &s0));
154b3a91243SToby Isaac for (PetscInt i = 1; i < Ns; i++) {
15536e5648fSToby Isaac PetscSpace si;
15636e5648fSToby Isaac
1579566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, i, &si));
1589371c9d4SSatish Balay if (si != s0) {
1599371c9d4SSatish Balay uniform = PETSC_FALSE;
1609371c9d4SSatish Balay break;
1619371c9d4SSatish Balay }
16236e5648fSToby Isaac }
16336e5648fSToby Isaac if (uniform) {
16436e5648fSToby Isaac PetscInt Nvs = Nv / Ns;
165b3a91243SToby Isaac PetscInt Ncs;
16636e5648fSToby Isaac
16763a3b9bcSJacob Faibussowitsch PetscCheck(Nv % Ns == 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONG, "Cannot use %" PetscInt_FMT " uniform subspaces for %" PetscInt_FMT " variable space", Ns, Nv);
168b3a91243SToby Isaac Ncs = (PetscInt)(PetscPowReal((PetscReal)Nc, 1. / Ns));
16963a3b9bcSJacob Faibussowitsch PetscCheck(Nc % PetscPowInt(Ncs, Ns) == 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONG, "Cannot use %" PetscInt_FMT " uniform subspaces for %" PetscInt_FMT " component space", Ns, Nc);
1709566063dSJacob Faibussowitsch if (!s0) PetscCall(PetscSpaceTensorCreateSubspace(sp, Nvs, Ncs, &s0));
1719566063dSJacob Faibussowitsch else PetscCall(PetscObjectReference((PetscObject)s0));
1729566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(s0));
1739566063dSJacob Faibussowitsch for (PetscInt i = 0; i < Ns; i++) PetscCall(PetscSpaceTensorSetSubspace(sp, i, s0));
1749566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&s0));
1752144e486SToby Isaac Ncprod = PetscPowInt(Ncs, Ns);
17636e5648fSToby Isaac } else {
177b3a91243SToby Isaac PetscInt Nvsum = 0;
1782144e486SToby Isaac
1792144e486SToby Isaac Ncprod = 1;
180b3a91243SToby Isaac for (PetscInt i = 0; i < Ns; i++) {
181b3a91243SToby Isaac PetscInt Nvs, Ncs;
182eae3dc7dSJacob Faibussowitsch PetscSpace si = NULL;
18336e5648fSToby Isaac
1849566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, i, &si));
1859566063dSJacob Faibussowitsch if (!si) PetscCall(PetscSpaceTensorCreateSubspace(sp, 1, 1, &si));
1869566063dSJacob Faibussowitsch else PetscCall(PetscObjectReference((PetscObject)si));
1879566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(si));
1889566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorSetSubspace(sp, i, si));
1899566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(si, &Nvs));
1909566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(si, &Ncs));
1919566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&si));
192b3a91243SToby Isaac
193b3a91243SToby Isaac Nvsum += Nvs;
194b3a91243SToby Isaac Ncprod *= Ncs;
19536e5648fSToby Isaac }
196b3a91243SToby Isaac
19763a3b9bcSJacob Faibussowitsch PetscCheck(Nvsum == Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONG, "Sum of subspace variables %" PetscInt_FMT " does not equal the number of variables %" PetscInt_FMT, Nvsum, Nv);
19863a3b9bcSJacob Faibussowitsch PetscCheck(Nc % Ncprod == 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONG, "Product of subspace components %" PetscInt_FMT " does not divide the number of components %" PetscInt_FMT, Ncprod, Nc);
1992144e486SToby Isaac }
2002144e486SToby Isaac if (Ncprod != Nc) {
2012144e486SToby Isaac PetscInt Ncopies = Nc / Ncprod;
2022144e486SToby Isaac PetscInt Nv = sp->Nv;
2032144e486SToby Isaac const char *prefix;
2042144e486SToby Isaac const char *name;
2052144e486SToby Isaac char subname[PETSC_MAX_PATH_LEN];
2062144e486SToby Isaac PetscSpace subsp;
2072144e486SToby Isaac
2089566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subsp));
2099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
2109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subsp, prefix));
2119566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subsp, "sumcomp_"));
2122144e486SToby Isaac if (((PetscObject)sp)->name) {
2139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name));
2149566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(subname, PETSC_MAX_PATH_LEN - 1, "%s sum component", name));
2159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subsp, subname));
2161baa6e33SBarry Smith } else PetscCall(PetscObjectSetName((PetscObject)subsp, "sum component"));
2179566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(subsp, PETSCSPACETENSOR));
2189566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(subsp, Nv));
2199566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(subsp, Ncprod));
2209566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorSetNumSubspaces(subsp, Ns));
2212144e486SToby Isaac for (PetscInt i = 0; i < Ns; i++) {
2222144e486SToby Isaac PetscSpace ssp;
2232144e486SToby Isaac
2249566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, i, &ssp));
2259566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorSetSubspace(subsp, i, ssp));
2262144e486SToby Isaac }
2279566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(subsp));
2289566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(sp, PETSCSPACESUM));
2299566063dSJacob Faibussowitsch PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ncopies));
23048a46eb9SPierre Jolivet for (PetscInt i = 0; i < Ncopies; i++) PetscCall(PetscSpaceSumSetSubspace(sp, i, subsp));
2319566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&subsp));
2329566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(sp));
2333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23436e5648fSToby Isaac }
23536e5648fSToby Isaac }
2361690c2aeSBarry Smith deg = PETSC_INT_MAX;
23736e5648fSToby Isaac maxDeg = 0;
238b3a91243SToby Isaac for (PetscInt i = 0; i < Ns; i++) {
23936e5648fSToby Isaac PetscSpace si;
24036e5648fSToby Isaac PetscInt iDeg, iMaxDeg;
24136e5648fSToby Isaac
2429566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, i, &si));
2439566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(si, &iDeg, &iMaxDeg));
24436e5648fSToby Isaac deg = PetscMin(deg, iDeg);
24536e5648fSToby Isaac maxDeg += iMaxDeg;
24636e5648fSToby Isaac }
24736e5648fSToby Isaac sp->degree = deg;
24836e5648fSToby Isaac sp->maxDegree = maxDeg;
24936e5648fSToby Isaac tens->uniform = uniform;
250371d2eb7SMartin Diehl tens->setupcalled = PETSC_TRUE;
2513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
25236e5648fSToby Isaac }
25336e5648fSToby Isaac
PetscSpaceDestroy_Tensor(PetscSpace sp)254d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceDestroy_Tensor(PetscSpace sp)
255d71ae5a4SJacob Faibussowitsch {
25636e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
25736e5648fSToby Isaac PetscInt Ns, i;
25836e5648fSToby Isaac
25936e5648fSToby Isaac PetscFunctionBegin;
260c88cc932SToby Isaac Ns = tens->numTensSpaces;
261c88cc932SToby Isaac if (tens->heightsubspaces) {
262d551817dSToby Isaac PetscInt d;
263d551817dSToby Isaac
264c88cc932SToby Isaac /* sp->Nv is the spatial dimension, so it is equal to the number
265c88cc932SToby Isaac * of subspaces on higher co-dimension points */
26648a46eb9SPierre Jolivet for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&tens->heightsubspaces[d]));
267d551817dSToby Isaac }
2689566063dSJacob Faibussowitsch PetscCall(PetscFree(tens->heightsubspaces));
2699566063dSJacob Faibussowitsch for (i = 0; i < Ns; i++) PetscCall(PetscSpaceDestroy(&tens->tensspaces[i]));
2709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorSetSubspace_C", NULL));
2719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorGetSubspace_C", NULL));
2729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorSetNumSubspaces_C", NULL));
2739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorGetNumSubspaces_C", NULL));
2749566063dSJacob Faibussowitsch PetscCall(PetscFree(tens->tensspaces));
2759566063dSJacob Faibussowitsch PetscCall(PetscFree(tens));
2763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
27736e5648fSToby Isaac }
27836e5648fSToby Isaac
PetscSpaceGetDimension_Tensor(PetscSpace sp,PetscInt * dim)279d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetDimension_Tensor(PetscSpace sp, PetscInt *dim)
280d71ae5a4SJacob Faibussowitsch {
28136e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
282b3a91243SToby Isaac PetscInt i, Ns, d;
28336e5648fSToby Isaac
28436e5648fSToby Isaac PetscFunctionBegin;
2859566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(sp));
286c88cc932SToby Isaac Ns = tens->numTensSpaces;
28736e5648fSToby Isaac d = 1;
28836e5648fSToby Isaac for (i = 0; i < Ns; i++) {
28936e5648fSToby Isaac PetscInt id;
29036e5648fSToby Isaac
2919566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDimension(tens->tensspaces[i], &id));
29236e5648fSToby Isaac d *= id;
29336e5648fSToby Isaac }
29443bfef1cSToby Isaac *dim = d;
2953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
29636e5648fSToby Isaac }
29736e5648fSToby Isaac
PetscSpaceEvaluate_Tensor(PetscSpace sp,PetscInt npoints,const PetscReal points[],PetscReal B[],PetscReal D[],PetscReal H[])298d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceEvaluate_Tensor(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
299d71ae5a4SJacob Faibussowitsch {
30036e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
30136e5648fSToby Isaac DM dm = sp->dm;
30236e5648fSToby Isaac PetscInt Nc = sp->Nc;
30336e5648fSToby Isaac PetscInt Nv = sp->Nv;
30436e5648fSToby Isaac PetscInt Ns;
30536e5648fSToby Isaac PetscReal *lpoints, *sB = NULL, *sD = NULL, *sH = NULL;
306b3a91243SToby Isaac PetscInt pdim;
30736e5648fSToby Isaac
30836e5648fSToby Isaac PetscFunctionBegin;
309371d2eb7SMartin Diehl if (!tens->setupcalled) {
3109566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(sp));
3119566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
3123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
313b3a91243SToby Isaac }
314c88cc932SToby Isaac Ns = tens->numTensSpaces;
3159566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDimension(sp, &pdim));
3169566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, npoints * Nv, MPIU_REAL, &lpoints));
3179566063dSJacob Faibussowitsch if (B || D || H) PetscCall(DMGetWorkArray(dm, npoints * pdim * Nc, MPIU_REAL, &sB));
3189566063dSJacob Faibussowitsch if (D || H) PetscCall(DMGetWorkArray(dm, npoints * pdim * Nc * Nv, MPIU_REAL, &sD));
3199566063dSJacob Faibussowitsch if (H) PetscCall(DMGetWorkArray(dm, npoints * pdim * Nc * Nv * Nv, MPIU_REAL, &sH));
32036e5648fSToby Isaac if (B) {
321b3a91243SToby Isaac for (PetscInt i = 0; i < npoints * pdim * Nc; i++) B[i] = 1.;
32236e5648fSToby Isaac }
32336e5648fSToby Isaac if (D) {
324b3a91243SToby Isaac for (PetscInt i = 0; i < npoints * pdim * Nc * Nv; i++) D[i] = 1.;
32536e5648fSToby Isaac }
32636e5648fSToby Isaac if (H) {
327b3a91243SToby Isaac for (PetscInt i = 0; i < npoints * pdim * Nc * Nv * Nv; i++) H[i] = 1.;
32836e5648fSToby Isaac }
329b3a91243SToby Isaac for (PetscInt s = 0, d = 0, vstep = 1, cstep = 1; s < Ns; s++) {
330b3a91243SToby Isaac PetscInt sNv, sNc, spdim;
331b3a91243SToby Isaac PetscInt vskip, cskip;
33236e5648fSToby Isaac
3339566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(tens->tensspaces[s], &sNv));
3349566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(tens->tensspaces[s], &sNc));
3359566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDimension(tens->tensspaces[s], &spdim));
33663a3b9bcSJacob Faibussowitsch PetscCheck(!(pdim % vstep) && !(pdim % spdim), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad tensor loop: Nv %" PetscInt_FMT ", Ns %" PetscInt_FMT ", pdim %" PetscInt_FMT ", s %" PetscInt_FMT ", vstep %" PetscInt_FMT ", spdim %" PetscInt_FMT, Nv, Ns, pdim, s, vstep, spdim);
33763a3b9bcSJacob Faibussowitsch PetscCheck(!(Nc % cstep) && !(Nc % sNc), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad tensor loop: Nv %" PetscInt_FMT ", Ns %" PetscInt_FMT ", Nc %" PetscInt_FMT ", s %" PetscInt_FMT ", cstep %" PetscInt_FMT ", sNc %" PetscInt_FMT, Nv, Ns, Nc, s, cstep, spdim);
338b3a91243SToby Isaac vskip = pdim / (vstep * spdim);
339b3a91243SToby Isaac cskip = Nc / (cstep * sNc);
340b3a91243SToby Isaac for (PetscInt p = 0; p < npoints; ++p) {
341ad540459SPierre Jolivet for (PetscInt i = 0; i < sNv; i++) lpoints[p * sNv + i] = points[p * Nv + d + i];
34236e5648fSToby Isaac }
3439566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(tens->tensspaces[s], npoints, lpoints, sB, sD, sH));
34436e5648fSToby Isaac if (B) {
345b3a91243SToby Isaac for (PetscInt k = 0; k < vskip; k++) {
346b3a91243SToby Isaac for (PetscInt si = 0; si < spdim; si++) {
347b3a91243SToby Isaac for (PetscInt j = 0; j < vstep; j++) {
348b3a91243SToby Isaac PetscInt i = (k * spdim + si) * vstep + j;
349b3a91243SToby Isaac
350b3a91243SToby Isaac for (PetscInt l = 0; l < cskip; l++) {
351b3a91243SToby Isaac for (PetscInt sc = 0; sc < sNc; sc++) {
352b3a91243SToby Isaac for (PetscInt m = 0; m < cstep; m++) {
353b3a91243SToby Isaac PetscInt c = (l * sNc + sc) * cstep + m;
354b3a91243SToby Isaac
355ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) B[(pdim * p + i) * Nc + c] *= sB[(spdim * p + si) * sNc + sc];
356b3a91243SToby Isaac }
357b3a91243SToby Isaac }
35836e5648fSToby Isaac }
35936e5648fSToby Isaac }
36036e5648fSToby Isaac }
36136e5648fSToby Isaac }
36236e5648fSToby Isaac }
36336e5648fSToby Isaac if (D) {
364b3a91243SToby Isaac for (PetscInt k = 0; k < vskip; k++) {
365b3a91243SToby Isaac for (PetscInt si = 0; si < spdim; si++) {
366b3a91243SToby Isaac for (PetscInt j = 0; j < vstep; j++) {
367b3a91243SToby Isaac PetscInt i = (k * spdim + si) * vstep + j;
368b3a91243SToby Isaac
369b3a91243SToby Isaac for (PetscInt l = 0; l < cskip; l++) {
370b3a91243SToby Isaac for (PetscInt sc = 0; sc < sNc; sc++) {
371b3a91243SToby Isaac for (PetscInt m = 0; m < cstep; m++) {
372b3a91243SToby Isaac PetscInt c = (l * sNc + sc) * cstep + m;
373b3a91243SToby Isaac
374b3a91243SToby Isaac for (PetscInt der = 0; der < Nv; der++) {
37536e5648fSToby Isaac if (der >= d && der < d + sNv) {
376ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) D[((pdim * p + i) * Nc + c) * Nv + der] *= sD[((spdim * p + si) * sNc + sc) * sNv + der - d];
37736e5648fSToby Isaac } else {
378ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) D[((pdim * p + i) * Nc + c) * Nv + der] *= sB[(spdim * p + si) * sNc + sc];
379b3a91243SToby Isaac }
380b3a91243SToby Isaac }
38136e5648fSToby Isaac }
38236e5648fSToby Isaac }
38336e5648fSToby Isaac }
38436e5648fSToby Isaac }
38536e5648fSToby Isaac }
38636e5648fSToby Isaac }
38736e5648fSToby Isaac }
38836e5648fSToby Isaac if (H) {
389b3a91243SToby Isaac for (PetscInt k = 0; k < vskip; k++) {
390b3a91243SToby Isaac for (PetscInt si = 0; si < spdim; si++) {
391b3a91243SToby Isaac for (PetscInt j = 0; j < vstep; j++) {
392b3a91243SToby Isaac PetscInt i = (k * spdim + si) * vstep + j;
393b3a91243SToby Isaac
394b3a91243SToby Isaac for (PetscInt l = 0; l < cskip; l++) {
395b3a91243SToby Isaac for (PetscInt sc = 0; sc < sNc; sc++) {
396b3a91243SToby Isaac for (PetscInt m = 0; m < cstep; m++) {
397b3a91243SToby Isaac PetscInt c = (l * sNc + sc) * cstep + m;
398b3a91243SToby Isaac
399b3a91243SToby Isaac for (PetscInt der = 0; der < Nv; der++) {
400b3a91243SToby Isaac for (PetscInt der2 = 0; der2 < Nv; der2++) {
40136e5648fSToby Isaac if (der >= d && der < d + sNv && der2 >= d && der2 < d + sNv) {
402ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) H[(((pdim * p + i) * Nc + c) * Nv + der) * Nv + der2] *= sH[(((spdim * p + si) * sNc + sc) * sNv + der - d) * sNv + der2 - d];
40336e5648fSToby Isaac } else if (der >= d && der < d + sNv) {
404ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) H[(((pdim * p + i) * Nc + c) * Nv + der) * Nv + der2] *= sD[((spdim * p + si) * sNc + sc) * sNv + der - d];
40536e5648fSToby Isaac } else if (der2 >= d && der2 < d + sNv) {
406ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) H[(((pdim * p + i) * Nc + c) * Nv + der) * Nv + der2] *= sD[((spdim * p + si) * sNc + sc) * sNv + der2 - d];
40736e5648fSToby Isaac } else {
408ad540459SPierre Jolivet for (PetscInt p = 0; p < npoints; p++) H[(((pdim * p + i) * Nc + c) * Nv + der) * Nv + der2] *= sB[(spdim * p + si) * sNc + sc];
409b3a91243SToby Isaac }
410b3a91243SToby Isaac }
41136e5648fSToby Isaac }
41236e5648fSToby Isaac }
41336e5648fSToby Isaac }
41436e5648fSToby Isaac }
41536e5648fSToby Isaac }
41636e5648fSToby Isaac }
41736e5648fSToby Isaac }
41836e5648fSToby Isaac }
41936e5648fSToby Isaac d += sNv;
420b3a91243SToby Isaac vstep *= spdim;
421b3a91243SToby Isaac cstep *= sNc;
42236e5648fSToby Isaac }
4239566063dSJacob Faibussowitsch if (H) PetscCall(DMRestoreWorkArray(dm, npoints * pdim * Nc * Nv * Nv, MPIU_REAL, &sH));
4249566063dSJacob Faibussowitsch if (D || H) PetscCall(DMRestoreWorkArray(dm, npoints * pdim * Nc * Nv, MPIU_REAL, &sD));
4259566063dSJacob Faibussowitsch if (B || D || H) PetscCall(DMRestoreWorkArray(dm, npoints * pdim * Nc, MPIU_REAL, &sB));
4269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, npoints * Nv, MPIU_REAL, &lpoints));
4273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
42836e5648fSToby Isaac }
42936e5648fSToby Isaac
43029b5c115SMatthew G. Knepley /*@
431b24fb147SBarry Smith PetscSpaceTensorSetNumSubspaces - Set the number of spaces in the tensor product space
43229b5c115SMatthew G. Knepley
43329b5c115SMatthew G. Knepley Input Parameters:
43429b5c115SMatthew G. Knepley + sp - the function space object
43529b5c115SMatthew G. Knepley - numTensSpaces - the number of spaces
43629b5c115SMatthew G. Knepley
43729b5c115SMatthew G. Knepley Level: intermediate
43829b5c115SMatthew G. Knepley
439b24fb147SBarry Smith Note:
440b24fb147SBarry Smith The name NumSubspaces is misleading because it is actually setting the number of defining spaces of the tensor product space, not a number of Subspaces of it
441b24fb147SBarry Smith
442dce8aebaSBarry Smith .seealso: `PETSCSPACETENSOR`, `PetscSpace`, `PetscSpaceTensorGetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
44329b5c115SMatthew G. Knepley @*/
PetscSpaceTensorSetNumSubspaces(PetscSpace sp,PetscInt numTensSpaces)444d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceTensorSetNumSubspaces(PetscSpace sp, PetscInt numTensSpaces)
445d71ae5a4SJacob Faibussowitsch {
44636e5648fSToby Isaac PetscFunctionBegin;
44736e5648fSToby Isaac PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
448cac4c232SBarry Smith PetscTryMethod(sp, "PetscSpaceTensorSetNumSubspaces_C", (PetscSpace, PetscInt), (sp, numTensSpaces));
4493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
45036e5648fSToby Isaac }
45136e5648fSToby Isaac
45229b5c115SMatthew G. Knepley /*@
453b24fb147SBarry Smith PetscSpaceTensorGetNumSubspaces - Get the number of spaces in the tensor product space
45429b5c115SMatthew G. Knepley
45529b5c115SMatthew G. Knepley Input Parameter:
45629b5c115SMatthew G. Knepley . sp - the function space object
45729b5c115SMatthew G. Knepley
45829b5c115SMatthew G. Knepley Output Parameter:
45929b5c115SMatthew G. Knepley . numTensSpaces - the number of spaces
46029b5c115SMatthew G. Knepley
46129b5c115SMatthew G. Knepley Level: intermediate
46229b5c115SMatthew G. Knepley
463b24fb147SBarry Smith Note:
464b24fb147SBarry Smith The name NumSubspaces is misleading because it is actually getting the number of defining spaces of the tensor product space, not a number of Subspaces of it
465b24fb147SBarry Smith
466dce8aebaSBarry Smith .seealso: `PETSCSPACETENSOR`, `PetscSpace`, `PetscSpaceTensorSetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
46729b5c115SMatthew G. Knepley @*/
PetscSpaceTensorGetNumSubspaces(PetscSpace sp,PetscInt * numTensSpaces)468d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceTensorGetNumSubspaces(PetscSpace sp, PetscInt *numTensSpaces)
469d71ae5a4SJacob Faibussowitsch {
47036e5648fSToby Isaac PetscFunctionBegin;
47136e5648fSToby Isaac PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
4724f572ea9SToby Isaac PetscAssertPointer(numTensSpaces, 2);
473cac4c232SBarry Smith PetscTryMethod(sp, "PetscSpaceTensorGetNumSubspaces_C", (PetscSpace, PetscInt *), (sp, numTensSpaces));
4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
47536e5648fSToby Isaac }
47636e5648fSToby Isaac
47729b5c115SMatthew G. Knepley /*@
478b24fb147SBarry Smith PetscSpaceTensorSetSubspace - Set a space in the tensor product space
47929b5c115SMatthew G. Knepley
48029b5c115SMatthew G. Knepley Input Parameters:
48129b5c115SMatthew G. Knepley + sp - the function space object
48229b5c115SMatthew G. Knepley . s - The space number
48329b5c115SMatthew G. Knepley - subsp - the number of spaces
48429b5c115SMatthew G. Knepley
48529b5c115SMatthew G. Knepley Level: intermediate
48629b5c115SMatthew G. Knepley
487b24fb147SBarry Smith Note:
488b24fb147SBarry Smith The name SetSubspace is misleading because it is actually setting one of the defining spaces of the tensor product space, not a Subspace of it
489b24fb147SBarry Smith
490dce8aebaSBarry Smith .seealso: `PETSCSPACETENSOR`, `PetscSpace`, `PetscSpaceTensorGetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
49129b5c115SMatthew G. Knepley @*/
PetscSpaceTensorSetSubspace(PetscSpace sp,PetscInt s,PetscSpace subsp)492d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceTensorSetSubspace(PetscSpace sp, PetscInt s, PetscSpace subsp)
493d71ae5a4SJacob Faibussowitsch {
49436e5648fSToby Isaac PetscFunctionBegin;
49536e5648fSToby Isaac PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
49636e5648fSToby Isaac if (subsp) PetscValidHeaderSpecific(subsp, PETSCSPACE_CLASSID, 3);
497cac4c232SBarry Smith PetscTryMethod(sp, "PetscSpaceTensorSetSubspace_C", (PetscSpace, PetscInt, PetscSpace), (sp, s, subsp));
4983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49936e5648fSToby Isaac }
50036e5648fSToby Isaac
50129b5c115SMatthew G. Knepley /*@
502b24fb147SBarry Smith PetscSpaceTensorGetSubspace - Get a space in the tensor product space
50329b5c115SMatthew G. Knepley
50429b5c115SMatthew G. Knepley Input Parameters:
50529b5c115SMatthew G. Knepley + sp - the function space object
50629b5c115SMatthew G. Knepley - s - The space number
50729b5c115SMatthew G. Knepley
50829b5c115SMatthew G. Knepley Output Parameter:
509b24fb147SBarry Smith . subsp - the `PetscSpace`
51029b5c115SMatthew G. Knepley
51129b5c115SMatthew G. Knepley Level: intermediate
51229b5c115SMatthew G. Knepley
513b24fb147SBarry Smith Note:
514b24fb147SBarry Smith The name GetSubspace is misleading because it is actually getting one of the defining spaces of the tensor product space, not a Subspace of it
515b24fb147SBarry Smith
516dce8aebaSBarry Smith .seealso: `PETSCSPACETENSOR`, `PetscSpace`, `PetscSpaceTensorSetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
51729b5c115SMatthew G. Knepley @*/
PetscSpaceTensorGetSubspace(PetscSpace sp,PetscInt s,PetscSpace * subsp)518d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceTensorGetSubspace(PetscSpace sp, PetscInt s, PetscSpace *subsp)
519d71ae5a4SJacob Faibussowitsch {
52036e5648fSToby Isaac PetscFunctionBegin;
52136e5648fSToby Isaac PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
5224f572ea9SToby Isaac PetscAssertPointer(subsp, 3);
523cac4c232SBarry Smith PetscTryMethod(sp, "PetscSpaceTensorGetSubspace_C", (PetscSpace, PetscInt, PetscSpace *), (sp, s, subsp));
5243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
52536e5648fSToby Isaac }
52636e5648fSToby Isaac
PetscSpaceTensorSetNumSubspaces_Tensor(PetscSpace space,PetscInt numTensSpaces)527d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceTensorSetNumSubspaces_Tensor(PetscSpace space, PetscInt numTensSpaces)
528d71ae5a4SJacob Faibussowitsch {
52936e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)space->data;
53036e5648fSToby Isaac PetscInt Ns;
53136e5648fSToby Isaac
53236e5648fSToby Isaac PetscFunctionBegin;
533371d2eb7SMartin Diehl PetscCheck(!tens->setupcalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of subspaces after setup called");
534c88cc932SToby Isaac Ns = tens->numTensSpaces;
5353ba16761SJacob Faibussowitsch if (numTensSpaces == Ns) PetscFunctionReturn(PETSC_SUCCESS);
53636e5648fSToby Isaac if (Ns >= 0) {
53736e5648fSToby Isaac PetscInt s;
53836e5648fSToby Isaac
5399566063dSJacob Faibussowitsch for (s = 0; s < Ns; s++) PetscCall(PetscSpaceDestroy(&tens->tensspaces[s]));
5409566063dSJacob Faibussowitsch PetscCall(PetscFree(tens->tensspaces));
54136e5648fSToby Isaac }
542c88cc932SToby Isaac Ns = tens->numTensSpaces = numTensSpaces;
5439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Ns, &tens->tensspaces));
5443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
54536e5648fSToby Isaac }
54636e5648fSToby Isaac
PetscSpaceTensorGetNumSubspaces_Tensor(PetscSpace space,PetscInt * numTensSpaces)547d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceTensorGetNumSubspaces_Tensor(PetscSpace space, PetscInt *numTensSpaces)
548d71ae5a4SJacob Faibussowitsch {
54936e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)space->data;
55036e5648fSToby Isaac
55136e5648fSToby Isaac PetscFunctionBegin;
552c88cc932SToby Isaac *numTensSpaces = tens->numTensSpaces;
5533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
55436e5648fSToby Isaac }
55536e5648fSToby Isaac
PetscSpaceTensorSetSubspace_Tensor(PetscSpace space,PetscInt s,PetscSpace subspace)556d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceTensorSetSubspace_Tensor(PetscSpace space, PetscInt s, PetscSpace subspace)
557d71ae5a4SJacob Faibussowitsch {
55836e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)space->data;
55936e5648fSToby Isaac PetscInt Ns;
56036e5648fSToby Isaac
56136e5648fSToby Isaac PetscFunctionBegin;
562371d2eb7SMartin Diehl PetscCheck(!tens->setupcalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change subspace after setup called");
563c88cc932SToby Isaac Ns = tens->numTensSpaces;
56408401ef6SPierre Jolivet PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceTensorSetNumSubspaces() first");
5651dca8a05SBarry Smith PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
5669566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)subspace));
5679566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&tens->tensspaces[s]));
568c88cc932SToby Isaac tens->tensspaces[s] = subspace;
5693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
57036e5648fSToby Isaac }
57136e5648fSToby Isaac
PetscSpaceGetHeightSubspace_Tensor(PetscSpace sp,PetscInt height,PetscSpace * subsp)572d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetHeightSubspace_Tensor(PetscSpace sp, PetscInt height, PetscSpace *subsp)
573d71ae5a4SJacob Faibussowitsch {
574d551817dSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)sp->data;
575d551817dSToby Isaac PetscInt Nc, dim, order, i;
576d551817dSToby Isaac PetscSpace bsp;
577d551817dSToby Isaac
578d551817dSToby Isaac PetscFunctionBegin;
5799566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(sp, &dim));
5801dca8a05SBarry Smith PetscCheck(tens->uniform && tens->numTensSpaces == dim, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Can only get a generic height subspace of a uniform tensor space of 1d spaces.");
5819566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
5829566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(sp, &order, NULL));
5831dca8a05SBarry 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);
5849566063dSJacob Faibussowitsch if (!tens->heightsubspaces) PetscCall(PetscCalloc1(dim, &tens->heightsubspaces));
585d551817dSToby Isaac if (height <= dim) {
586c88cc932SToby Isaac if (!tens->heightsubspaces[height - 1]) {
587d551817dSToby Isaac PetscSpace sub;
5883f6b16c7SMatthew G. Knepley const char *name;
589d551817dSToby Isaac
5909566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorGetSubspace(sp, 0, &bsp));
5919566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
5929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name));
5939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sub, name));
5949566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(sub, PETSCSPACETENSOR));
5959566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(sub, Nc));
5969566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(sub, order, PETSC_DETERMINE));
5979566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
5989566063dSJacob Faibussowitsch PetscCall(PetscSpaceTensorSetNumSubspaces(sub, dim - height));
59948a46eb9SPierre Jolivet for (i = 0; i < dim - height; i++) PetscCall(PetscSpaceTensorSetSubspace(sub, i, bsp));
6009566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(sub));
601c88cc932SToby Isaac tens->heightsubspaces[height - 1] = sub;
602d551817dSToby Isaac }
603c88cc932SToby Isaac *subsp = tens->heightsubspaces[height - 1];
604d551817dSToby Isaac } else {
605d551817dSToby Isaac *subsp = NULL;
606d551817dSToby Isaac }
6073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
608d551817dSToby Isaac }
609d551817dSToby Isaac
PetscSpaceTensorGetSubspace_Tensor(PetscSpace space,PetscInt s,PetscSpace * subspace)610d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceTensorGetSubspace_Tensor(PetscSpace space, PetscInt s, PetscSpace *subspace)
611d71ae5a4SJacob Faibussowitsch {
61236e5648fSToby Isaac PetscSpace_Tensor *tens = (PetscSpace_Tensor *)space->data;
61336e5648fSToby Isaac PetscInt Ns;
61436e5648fSToby Isaac
61536e5648fSToby Isaac PetscFunctionBegin;
616c88cc932SToby Isaac Ns = tens->numTensSpaces;
61708401ef6SPierre Jolivet PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceTensorSetNumSubspaces() first");
6181dca8a05SBarry Smith PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
619c88cc932SToby Isaac *subspace = tens->tensspaces[s];
6203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
62136e5648fSToby Isaac }
62236e5648fSToby Isaac
PetscSpaceInitialize_Tensor(PetscSpace sp)623d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceInitialize_Tensor(PetscSpace sp)
624d71ae5a4SJacob Faibussowitsch {
62536e5648fSToby Isaac PetscFunctionBegin;
62636e5648fSToby Isaac sp->ops->setfromoptions = PetscSpaceSetFromOptions_Tensor;
62736e5648fSToby Isaac sp->ops->setup = PetscSpaceSetUp_Tensor;
62836e5648fSToby Isaac sp->ops->view = PetscSpaceView_Tensor;
62936e5648fSToby Isaac sp->ops->destroy = PetscSpaceDestroy_Tensor;
63036e5648fSToby Isaac sp->ops->getdimension = PetscSpaceGetDimension_Tensor;
63136e5648fSToby Isaac sp->ops->evaluate = PetscSpaceEvaluate_Tensor;
632d551817dSToby Isaac sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Tensor;
6339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorGetNumSubspaces_C", PetscSpaceTensorGetNumSubspaces_Tensor));
6349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorSetNumSubspaces_C", PetscSpaceTensorSetNumSubspaces_Tensor));
6359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorGetSubspace_C", PetscSpaceTensorGetSubspace_Tensor));
6369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceTensorSetSubspace_C", PetscSpaceTensorSetSubspace_Tensor));
6373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
63836e5648fSToby Isaac }
63936e5648fSToby Isaac
64036e5648fSToby Isaac /*MC
641dce8aebaSBarry Smith PETSCSPACETENSOR = "tensor" - A `PetscSpace` object that encapsulates a tensor product space.
642b3a91243SToby Isaac A tensor product is created of the components of the subspaces as well.
64336e5648fSToby Isaac
64436e5648fSToby Isaac Level: intermediate
64536e5648fSToby Isaac
646b24fb147SBarry Smith .seealso: `PetscSpace`, `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`, `PetscSpaceTensorGetSubspace()`, `PetscSpaceTensorSetSubspace()`,
647b24fb147SBarry Smith `PetscSpaceTensorGetNumSubspaces()`, `PetscSpaceTensorSetNumSubspaces()`
64836e5648fSToby Isaac M*/
64936e5648fSToby Isaac
PetscSpaceCreate_Tensor(PetscSpace sp)650d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Tensor(PetscSpace sp)
651d71ae5a4SJacob Faibussowitsch {
65236e5648fSToby Isaac PetscSpace_Tensor *tens;
65336e5648fSToby Isaac
65436e5648fSToby Isaac PetscFunctionBegin;
65536e5648fSToby Isaac PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
6564dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&tens));
65736e5648fSToby Isaac sp->data = tens;
65836e5648fSToby Isaac
659c88cc932SToby Isaac tens->numTensSpaces = PETSC_DEFAULT;
66036e5648fSToby Isaac
6619566063dSJacob Faibussowitsch PetscCall(PetscSpaceInitialize_Tensor(sp));
6623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
66336e5648fSToby Isaac }
664