xref: /petsc/src/dm/dt/space/impls/sum/spacesum.c (revision bcda9346efad4e5ba2d553af84eb238771ba1e25)
1d092c84bSBrandon Whitchurch #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2b24fb147SBarry Smith 
3d092c84bSBrandon Whitchurch /*@
4b24fb147SBarry Smith   PetscSpaceSumGetNumSubspaces - Get the number of spaces in the sum space
5d092c84bSBrandon Whitchurch 
6d092c84bSBrandon Whitchurch   Input Parameter:
7d092c84bSBrandon Whitchurch . sp - the function space object
8d092c84bSBrandon Whitchurch 
9d092c84bSBrandon Whitchurch   Output Parameter:
10d092c84bSBrandon Whitchurch . numSumSpaces - the number of spaces
11d092c84bSBrandon Whitchurch 
12d092c84bSBrandon Whitchurch   Level: intermediate
13d092c84bSBrandon Whitchurch 
14b24fb147SBarry Smith   Note:
15b24fb147SBarry Smith   The name NumSubspaces is slightly misleading because it is actually getting the number of defining spaces of the sum, not a number of Subspaces of it
16b24fb147SBarry Smith 
17dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
18d092c84bSBrandon Whitchurch @*/
PetscSpaceSumGetNumSubspaces(PetscSpace sp,PetscInt * numSumSpaces)19d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp, PetscInt *numSumSpaces)
20d71ae5a4SJacob Faibussowitsch {
21d092c84bSBrandon Whitchurch   PetscFunctionBegin;
22d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
234f572ea9SToby Isaac   PetscAssertPointer(numSumSpaces, 2);
24cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumGetNumSubspaces_C", (PetscSpace, PetscInt *), (sp, numSumSpaces));
253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26d092c84bSBrandon Whitchurch }
27d092c84bSBrandon Whitchurch 
28d092c84bSBrandon Whitchurch /*@
29b24fb147SBarry Smith   PetscSpaceSumSetNumSubspaces - Set the number of spaces in the sum space
30d092c84bSBrandon Whitchurch 
31d092c84bSBrandon Whitchurch   Input Parameters:
32d092c84bSBrandon Whitchurch + sp           - the function space object
33d092c84bSBrandon Whitchurch - numSumSpaces - the number of spaces
34d092c84bSBrandon Whitchurch 
35d092c84bSBrandon Whitchurch   Level: intermediate
36d092c84bSBrandon Whitchurch 
37b24fb147SBarry Smith   Note:
38b24fb147SBarry Smith   The name NumSubspaces is slightly misleading because it is actually setting the number of defining spaces of the sum, not a number of Subspaces of it
39b24fb147SBarry Smith 
40dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
41d092c84bSBrandon Whitchurch @*/
PetscSpaceSumSetNumSubspaces(PetscSpace sp,PetscInt numSumSpaces)42d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumSetNumSubspaces(PetscSpace sp, PetscInt numSumSpaces)
43d71ae5a4SJacob Faibussowitsch {
44d092c84bSBrandon Whitchurch   PetscFunctionBegin;
45d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
46cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumSetNumSubspaces_C", (PetscSpace, PetscInt), (sp, numSumSpaces));
473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48d092c84bSBrandon Whitchurch }
49d092c84bSBrandon Whitchurch 
50d092c84bSBrandon Whitchurch /*@
51d092c84bSBrandon Whitchurch   PetscSpaceSumGetConcatenate - Get the concatenate flag for this space.
52d092c84bSBrandon Whitchurch 
532fe279fdSBarry Smith   Input Parameter:
54d092c84bSBrandon Whitchurch . sp - the function space object
55d092c84bSBrandon Whitchurch 
562fe279fdSBarry Smith   Output Parameter:
57d092c84bSBrandon Whitchurch . concatenate - flag indicating whether subspaces are concatenated.
58d092c84bSBrandon Whitchurch 
59d092c84bSBrandon Whitchurch   Level: intermediate
60d092c84bSBrandon Whitchurch 
61a4e35b19SJacob Faibussowitsch   Notes:
62a4e35b19SJacob Faibussowitsch   A concatenated sum space will have the number of components equal to the sum of the number of
63a4e35b19SJacob Faibussowitsch   components of all subspaces. A non-concatenated, or direct sum space will have the same
64a4e35b19SJacob Faibussowitsch   number of components as its subspaces.
65a4e35b19SJacob Faibussowitsch 
66dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetConcatenate()`
67d092c84bSBrandon Whitchurch @*/
PetscSpaceSumGetConcatenate(PetscSpace sp,PetscBool * concatenate)68d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp, PetscBool *concatenate)
69d71ae5a4SJacob Faibussowitsch {
70d092c84bSBrandon Whitchurch   PetscFunctionBegin;
71d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
72cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumGetConcatenate_C", (PetscSpace, PetscBool *), (sp, concatenate));
733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74d092c84bSBrandon Whitchurch }
75d092c84bSBrandon Whitchurch 
76d092c84bSBrandon Whitchurch /*@
77d092c84bSBrandon Whitchurch   PetscSpaceSumSetConcatenate - Sets the concatenate flag for this space.
78d092c84bSBrandon Whitchurch 
79d092c84bSBrandon Whitchurch   Input Parameters:
80d092c84bSBrandon Whitchurch + sp          - the function space object
81d092c84bSBrandon Whitchurch - concatenate - are subspaces concatenated components (true) or direct summands (false)
82d092c84bSBrandon Whitchurch 
83d092c84bSBrandon Whitchurch   Level: intermediate
84dce8aebaSBarry Smith 
85a4e35b19SJacob Faibussowitsch   Notes:
86a4e35b19SJacob Faibussowitsch   A concatenated sum space will have the number of components equal to the sum of the number of
87a4e35b19SJacob Faibussowitsch   components of all subspaces. A non-concatenated, or direct sum space will have the same
88a4e35b19SJacob Faibussowitsch   number of components as its subspaces .
89a4e35b19SJacob Faibussowitsch 
90dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetConcatenate()`
91d092c84bSBrandon Whitchurch @*/
PetscSpaceSumSetConcatenate(PetscSpace sp,PetscBool concatenate)92d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp, PetscBool concatenate)
93d71ae5a4SJacob Faibussowitsch {
94d092c84bSBrandon Whitchurch   PetscFunctionBegin;
95d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
96cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumSetConcatenate_C", (PetscSpace, PetscBool), (sp, concatenate));
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98d092c84bSBrandon Whitchurch }
99d092c84bSBrandon Whitchurch 
100d092c84bSBrandon Whitchurch /*@
101b24fb147SBarry Smith   PetscSpaceSumGetSubspace - Get a space in the sum space
102d092c84bSBrandon Whitchurch 
103d092c84bSBrandon Whitchurch   Input Parameters:
104d092c84bSBrandon Whitchurch + sp - the function space object
105d092c84bSBrandon Whitchurch - s  - The space number
106d092c84bSBrandon Whitchurch 
107d092c84bSBrandon Whitchurch   Output Parameter:
108b24fb147SBarry Smith . subsp - the `PetscSpace`
109d092c84bSBrandon Whitchurch 
110d092c84bSBrandon Whitchurch   Level: intermediate
111d092c84bSBrandon Whitchurch 
112b24fb147SBarry Smith   Note:
113b24fb147SBarry Smith   The name GetSubspace is slightly misleading because it is actually getting one of the defining spaces of the sum, not a Subspace of it
114b24fb147SBarry Smith 
115dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
116d092c84bSBrandon Whitchurch @*/
PetscSpaceSumGetSubspace(PetscSpace sp,PetscInt s,PetscSpace * subsp)117d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp, PetscInt s, PetscSpace *subsp)
118d71ae5a4SJacob Faibussowitsch {
119d092c84bSBrandon Whitchurch   PetscFunctionBegin;
120d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
1214f572ea9SToby Isaac   PetscAssertPointer(subsp, 3);
122cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumGetSubspace_C", (PetscSpace, PetscInt, PetscSpace *), (sp, s, subsp));
1233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
124d092c84bSBrandon Whitchurch }
125d092c84bSBrandon Whitchurch 
126d092c84bSBrandon Whitchurch /*@
127b24fb147SBarry Smith   PetscSpaceSumSetSubspace - Set a space in the sum space
128d092c84bSBrandon Whitchurch 
129d092c84bSBrandon Whitchurch   Input Parameters:
130d092c84bSBrandon Whitchurch + sp    - the function space object
131d092c84bSBrandon Whitchurch . s     - The space number
132d092c84bSBrandon Whitchurch - subsp - the number of spaces
133d092c84bSBrandon Whitchurch 
134d092c84bSBrandon Whitchurch   Level: intermediate
135d092c84bSBrandon Whitchurch 
136b24fb147SBarry Smith   Note:
137b24fb147SBarry Smith   The name SetSubspace is slightly misleading because it is actually setting one of the defining spaces of the sum, not a Subspace of it
138b24fb147SBarry Smith 
139dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
140d092c84bSBrandon Whitchurch @*/
PetscSpaceSumSetSubspace(PetscSpace sp,PetscInt s,PetscSpace subsp)141d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp, PetscInt s, PetscSpace subsp)
142d71ae5a4SJacob Faibussowitsch {
143d092c84bSBrandon Whitchurch   PetscFunctionBegin;
144d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
145d092c84bSBrandon Whitchurch   if (subsp) PetscValidHeaderSpecific(subsp, PETSCSPACE_CLASSID, 3);
146cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumSetSubspace_C", (PetscSpace, PetscInt, PetscSpace), (sp, s, subsp));
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148d092c84bSBrandon Whitchurch }
149d092c84bSBrandon Whitchurch 
PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space,PetscInt * numSumSpaces)150d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space, PetscInt *numSumSpaces)
151d71ae5a4SJacob Faibussowitsch {
152d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
153d092c84bSBrandon Whitchurch 
154d092c84bSBrandon Whitchurch   PetscFunctionBegin;
155d092c84bSBrandon Whitchurch   *numSumSpaces = sum->numSumSpaces;
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
157d092c84bSBrandon Whitchurch }
158d092c84bSBrandon Whitchurch 
PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space,PetscInt numSumSpaces)159d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space, PetscInt numSumSpaces)
160d71ae5a4SJacob Faibussowitsch {
161d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
162d092c84bSBrandon Whitchurch   PetscInt        Ns  = sum->numSumSpaces;
163d092c84bSBrandon Whitchurch 
164d092c84bSBrandon Whitchurch   PetscFunctionBegin;
165371d2eb7SMartin Diehl   PetscCheck(!sum->setupcalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of subspaces after setup called");
1663ba16761SJacob Faibussowitsch   if (numSumSpaces == Ns) PetscFunctionReturn(PETSC_SUCCESS);
167d092c84bSBrandon Whitchurch   if (Ns >= 0) {
168d092c84bSBrandon Whitchurch     PetscInt s;
16948a46eb9SPierre Jolivet     for (s = 0; s < Ns; ++s) PetscCall(PetscSpaceDestroy(&sum->sumspaces[s]));
1709566063dSJacob Faibussowitsch     PetscCall(PetscFree(sum->sumspaces));
171d092c84bSBrandon Whitchurch   }
172d092c84bSBrandon Whitchurch 
173d092c84bSBrandon Whitchurch   Ns = sum->numSumSpaces = numSumSpaces;
1749566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Ns, &sum->sumspaces));
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
176d092c84bSBrandon Whitchurch }
177d092c84bSBrandon Whitchurch 
PetscSpaceSumGetConcatenate_Sum(PetscSpace sp,PetscBool * concatenate)178d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp, PetscBool *concatenate)
179d71ae5a4SJacob Faibussowitsch {
180d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
181d092c84bSBrandon Whitchurch 
182d092c84bSBrandon Whitchurch   PetscFunctionBegin;
183d092c84bSBrandon Whitchurch   *concatenate = sum->concatenate;
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185d092c84bSBrandon Whitchurch }
186d092c84bSBrandon Whitchurch 
PetscSpaceSumSetConcatenate_Sum(PetscSpace sp,PetscBool concatenate)187d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp, PetscBool concatenate)
188d71ae5a4SJacob Faibussowitsch {
189d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
190d092c84bSBrandon Whitchurch 
191d092c84bSBrandon Whitchurch   PetscFunctionBegin;
192371d2eb7SMartin Diehl   PetscCheck(!sum->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change space concatenation after setup called.");
193d092c84bSBrandon Whitchurch 
194d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
1953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
196d092c84bSBrandon Whitchurch }
197d092c84bSBrandon Whitchurch 
PetscSpaceSumGetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace * subspace)198d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace *subspace)
199d71ae5a4SJacob Faibussowitsch {
200d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
201d092c84bSBrandon Whitchurch   PetscInt        Ns  = sum->numSumSpaces;
202d092c84bSBrandon Whitchurch 
203d092c84bSBrandon Whitchurch   PetscFunctionBegin;
20408401ef6SPierre Jolivet   PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first");
2051dca8a05SBarry Smith   PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
206d092c84bSBrandon Whitchurch 
207d092c84bSBrandon Whitchurch   *subspace = sum->sumspaces[s];
2083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209d092c84bSBrandon Whitchurch }
210d092c84bSBrandon Whitchurch 
PetscSpaceSumSetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace subspace)211d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace subspace)
212d71ae5a4SJacob Faibussowitsch {
213d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
214d092c84bSBrandon Whitchurch   PetscInt        Ns  = sum->numSumSpaces;
215d092c84bSBrandon Whitchurch 
216d092c84bSBrandon Whitchurch   PetscFunctionBegin;
217371d2eb7SMartin Diehl   PetscCheck(!sum->setupcalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change subspace after setup called");
21808401ef6SPierre Jolivet   PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first");
2191dca8a05SBarry Smith   PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
220d092c84bSBrandon Whitchurch 
2219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)subspace));
2229566063dSJacob Faibussowitsch   PetscCall(PetscSpaceDestroy(&sum->sumspaces[s]));
223d092c84bSBrandon Whitchurch   sum->sumspaces[s] = subspace;
2243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225d092c84bSBrandon Whitchurch }
226d092c84bSBrandon Whitchurch 
PetscSpaceSetFromOptions_Sum(PetscSpace sp,PetscOptionItems PetscOptionsObject)227ce78bad3SBarry Smith static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscSpace sp, PetscOptionItems PetscOptionsObject)
228d71ae5a4SJacob Faibussowitsch {
229d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
230d092c84bSBrandon Whitchurch   PetscInt        Ns, Nc, Nv, deg, i;
231d092c84bSBrandon Whitchurch   PetscBool       concatenate = PETSC_TRUE;
232d092c84bSBrandon Whitchurch   const char     *prefix;
233d092c84bSBrandon Whitchurch 
234d092c84bSBrandon Whitchurch   PetscFunctionBegin;
2359566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
2363ba16761SJacob Faibussowitsch   if (!Nv) PetscFunctionReturn(PETSC_SUCCESS);
2379566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
2389566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns));
2399566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(sp, &deg, NULL));
240d092c84bSBrandon Whitchurch   Ns = (Ns == PETSC_DEFAULT) ? 1 : Ns;
241d092c84bSBrandon Whitchurch 
242d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace sum options");
2439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-petscspace_sum_spaces", "The number of subspaces", "PetscSpaceSumSetNumSubspaces", Ns, &Ns, NULL, 0));
2449371c9d4SSatish Balay   PetscCall(PetscOptionsBool("-petscspace_sum_concatenate", "Subspaces are concatenated components of the final space", "PetscSpaceSumSetFromOptions", concatenate, &concatenate, NULL));
245d0609cedSBarry Smith   PetscOptionsHeadEnd();
246d092c84bSBrandon Whitchurch 
2471dca8a05SBarry Smith   PetscCheck(Ns >= 0 && (Nv <= 0 || Ns != 0), PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a sum space of %" PetscInt_FMT " spaces", Ns);
24848a46eb9SPierre Jolivet   if (Ns != sum->numSumSpaces) PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns));
2499566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
250d092c84bSBrandon Whitchurch   for (i = 0; i < Ns; ++i) {
251d092c84bSBrandon Whitchurch     PetscInt   sNv;
252d092c84bSBrandon Whitchurch     PetscSpace subspace;
253d092c84bSBrandon Whitchurch 
2549566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, i, &subspace));
255d092c84bSBrandon Whitchurch     if (!subspace) {
256d092c84bSBrandon Whitchurch       char subspacePrefix[256];
257d092c84bSBrandon Whitchurch 
2589566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subspace));
2599566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subspace, prefix));
26063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(subspacePrefix, 256, "sumcomp_%" PetscInt_FMT "_", i));
2619566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subspace, subspacePrefix));
2621baa6e33SBarry Smith     } else PetscCall(PetscObjectReference((PetscObject)subspace));
2639566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetFromOptions(subspace));
2649566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(subspace, &sNv));
26563a3b9bcSJacob Faibussowitsch     PetscCheck(sNv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has not been set properly, number of variables is 0.", i);
2669566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetSubspace(sp, i, subspace));
2679566063dSJacob Faibussowitsch     PetscCall(PetscSpaceDestroy(&subspace));
268d092c84bSBrandon Whitchurch   }
2693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
270d092c84bSBrandon Whitchurch }
271d092c84bSBrandon Whitchurch 
PetscSpaceSetUp_Sum(PetscSpace sp)272d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
273d71ae5a4SJacob Faibussowitsch {
274d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum         = (PetscSpace_Sum *)sp->data;
275d092c84bSBrandon Whitchurch   PetscBool       concatenate = PETSC_TRUE;
276642c7897SToby Isaac   PetscBool       uniform;
2771690c2aeSBarry Smith   PetscInt        Nv, Ns, Nc, i, sum_Nc = 0, deg = PETSC_INT_MAX, maxDeg = PETSC_INT_MIN;
278642c7897SToby Isaac   PetscInt        minNc, maxNc;
279d092c84bSBrandon Whitchurch 
280d092c84bSBrandon Whitchurch   PetscFunctionBegin;
281371d2eb7SMartin Diehl   if (sum->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
282d092c84bSBrandon Whitchurch 
2839566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
2849566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
2859566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns));
286d092c84bSBrandon Whitchurch   if (Ns == PETSC_DEFAULT) {
287d092c84bSBrandon Whitchurch     Ns = 1;
2889566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns));
289d092c84bSBrandon Whitchurch   }
29063a3b9bcSJacob Faibussowitsch   PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have %" PetscInt_FMT " subspaces", Ns);
291642c7897SToby Isaac   uniform = PETSC_TRUE;
292642c7897SToby Isaac   if (Ns) {
293642c7897SToby Isaac     PetscSpace s0;
294d092c84bSBrandon Whitchurch 
2959566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, 0, &s0));
296642c7897SToby Isaac     for (PetscInt i = 1; i < Ns; i++) {
297642c7897SToby Isaac       PetscSpace si;
298642c7897SToby Isaac 
2999566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
300642c7897SToby Isaac       if (si != s0) {
301642c7897SToby Isaac         uniform = PETSC_FALSE;
302642c7897SToby Isaac         break;
303642c7897SToby Isaac       }
304642c7897SToby Isaac     }
305642c7897SToby Isaac   }
306642c7897SToby Isaac 
307642c7897SToby Isaac   minNc = Nc;
308642c7897SToby Isaac   maxNc = Nc;
309d092c84bSBrandon Whitchurch   for (i = 0; i < Ns; ++i) {
310d092c84bSBrandon Whitchurch     PetscInt   sNv, sNc, iDeg, iMaxDeg;
311d092c84bSBrandon Whitchurch     PetscSpace si;
312d092c84bSBrandon Whitchurch 
3139566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
3149566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(si));
3159566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(si, &sNv));
31663a3b9bcSJacob Faibussowitsch     PetscCheck(sNv == Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has %" PetscInt_FMT " variables, space has %" PetscInt_FMT ".", i, sNv, Nv);
3179566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumComponents(si, &sNc));
318d092c84bSBrandon Whitchurch     if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
319642c7897SToby Isaac     minNc = PetscMin(minNc, sNc);
320642c7897SToby Isaac     maxNc = PetscMax(maxNc, sNc);
321d092c84bSBrandon Whitchurch     sum_Nc += sNc;
3229566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
3239566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(si, &iDeg, &iMaxDeg));
324642c7897SToby Isaac     deg    = PetscMin(deg, iDeg);
325d092c84bSBrandon Whitchurch     maxDeg = PetscMax(maxDeg, iMaxDeg);
326d092c84bSBrandon Whitchurch   }
327d092c84bSBrandon Whitchurch 
3287a46b595SBarry Smith   if (concatenate) PetscCheck(sum_Nc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Total number of subspace components (%" PetscInt_FMT ") does not match number of target space components (%" PetscInt_FMT ").", sum_Nc, Nc);
3297a46b595SBarry Smith   else PetscCheck(minNc == Nc && maxNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspaces must have same number of components as the target space.");
330d092c84bSBrandon Whitchurch 
331d092c84bSBrandon Whitchurch   sp->degree       = deg;
332d092c84bSBrandon Whitchurch   sp->maxDegree    = maxDeg;
333d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
334642c7897SToby Isaac   sum->uniform     = uniform;
335371d2eb7SMartin Diehl   sum->setupcalled = PETSC_TRUE;
3363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
337d092c84bSBrandon Whitchurch }
338d092c84bSBrandon Whitchurch 
PetscSpaceSumView_Ascii(PetscSpace sp,PetscViewer v)339d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp, PetscViewer v)
340d71ae5a4SJacob Faibussowitsch {
341d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum         = (PetscSpace_Sum *)sp->data;
342d092c84bSBrandon Whitchurch   PetscBool       concatenate = sum->concatenate;
343d092c84bSBrandon Whitchurch   PetscInt        i, Ns = sum->numSumSpaces;
344d092c84bSBrandon Whitchurch 
345d092c84bSBrandon Whitchurch   PetscFunctionBegin;
3461baa6e33SBarry Smith   if (concatenate) PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " concatenated subspaces%s\n", Ns, sum->uniform ? " (all identical)" : ""));
3471baa6e33SBarry Smith   else PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " subspaces%s\n", Ns, sum->uniform ? " (all identical)" : ""));
348642c7897SToby Isaac   for (i = 0; i < (sum->uniform ? (Ns > 0 ? 1 : 0) : Ns); ++i) {
3499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(v));
3509566063dSJacob Faibussowitsch     PetscCall(PetscSpaceView(sum->sumspaces[i], v));
3519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(v));
352d092c84bSBrandon Whitchurch   }
3533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
354d092c84bSBrandon Whitchurch }
355d092c84bSBrandon Whitchurch 
PetscSpaceView_Sum(PetscSpace sp,PetscViewer viewer)356d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp, PetscViewer viewer)
357d71ae5a4SJacob Faibussowitsch {
358*9f196a02SMartin Diehl   PetscBool isascii;
359d092c84bSBrandon Whitchurch 
360d092c84bSBrandon Whitchurch   PetscFunctionBegin;
361*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
362*9f196a02SMartin Diehl   if (isascii) PetscCall(PetscSpaceSumView_Ascii(sp, viewer));
3633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
364d092c84bSBrandon Whitchurch }
365d092c84bSBrandon Whitchurch 
PetscSpaceDestroy_Sum(PetscSpace sp)366d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
367d71ae5a4SJacob Faibussowitsch {
368d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
369d092c84bSBrandon Whitchurch   PetscInt        i, Ns = sum->numSumSpaces;
370d092c84bSBrandon Whitchurch 
371d092c84bSBrandon Whitchurch   PetscFunctionBegin;
37248a46eb9SPierre Jolivet   for (i = 0; i < Ns; ++i) PetscCall(PetscSpaceDestroy(&sum->sumspaces[i]));
3739566063dSJacob Faibussowitsch   PetscCall(PetscFree(sum->sumspaces));
374642c7897SToby Isaac   if (sum->heightsubspaces) {
375642c7897SToby Isaac     PetscInt d;
376642c7897SToby Isaac 
377642c7897SToby Isaac     /* sp->Nv is the spatial dimension, so it is equal to the number
378642c7897SToby Isaac      * of subspaces on higher co-dimension points */
37948a46eb9SPierre Jolivet     for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&sum->heightsubspaces[d]));
380642c7897SToby Isaac   }
3819566063dSJacob Faibussowitsch   PetscCall(PetscFree(sum->heightsubspaces));
3829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", NULL));
3839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", NULL));
3849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", NULL));
3859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", NULL));
3862e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", NULL));
3872e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", NULL));
3882dce792eSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetInterleave_C", NULL));
3892dce792eSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetInterleave_C", NULL));
3909566063dSJacob Faibussowitsch   PetscCall(PetscFree(sum));
3913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
392d092c84bSBrandon Whitchurch }
393d092c84bSBrandon Whitchurch 
PetscSpaceGetDimension_Sum(PetscSpace sp,PetscInt * dim)394d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp, PetscInt *dim)
395d71ae5a4SJacob Faibussowitsch {
396d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
397d092c84bSBrandon Whitchurch   PetscInt        i, d = 0, Ns = sum->numSumSpaces;
398d092c84bSBrandon Whitchurch 
399d092c84bSBrandon Whitchurch   PetscFunctionBegin;
400371d2eb7SMartin Diehl   if (!sum->setupcalled) {
4019566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
4029566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDimension(sp, dim));
4033ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
404642c7897SToby Isaac   }
405d092c84bSBrandon Whitchurch 
406d092c84bSBrandon Whitchurch   for (i = 0; i < Ns; ++i) {
407d092c84bSBrandon Whitchurch     PetscInt id;
408d092c84bSBrandon Whitchurch 
4099566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDimension(sum->sumspaces[i], &id));
410d092c84bSBrandon Whitchurch     d += id;
411d092c84bSBrandon Whitchurch   }
412d092c84bSBrandon Whitchurch 
413d092c84bSBrandon Whitchurch   *dim = d;
4143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
415d092c84bSBrandon Whitchurch }
416d092c84bSBrandon Whitchurch 
PetscSpaceEvaluate_Sum(PetscSpace sp,PetscInt npoints,const PetscReal points[],PetscReal B[],PetscReal D[],PetscReal H[])417d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
418d71ae5a4SJacob Faibussowitsch {
419d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum         = (PetscSpace_Sum *)sp->data;
420d092c84bSBrandon Whitchurch   PetscBool       concatenate = sum->concatenate;
421d092c84bSBrandon Whitchurch   DM              dm          = sp->dm;
422d092c84bSBrandon Whitchurch   PetscInt        Nc = sp->Nc, Nv = sp->Nv, Ns = sum->numSumSpaces;
423d092c84bSBrandon Whitchurch   PetscInt        i, s, offset, ncoffset, pdimfull, numelB, numelD, numelH;
424d092c84bSBrandon Whitchurch   PetscReal      *sB = NULL, *sD = NULL, *sH = NULL;
425d092c84bSBrandon Whitchurch 
426d092c84bSBrandon Whitchurch   PetscFunctionBegin;
427371d2eb7SMartin Diehl   if (!sum->setupcalled) {
4289566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
4299566063dSJacob Faibussowitsch     PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
4303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
431d092c84bSBrandon Whitchurch   }
4329566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDimension(sp, &pdimfull));
433d092c84bSBrandon Whitchurch   numelB = npoints * pdimfull * Nc;
434d092c84bSBrandon Whitchurch   numelD = numelB * Nv;
435d092c84bSBrandon Whitchurch   numelH = numelD * Nv;
43648a46eb9SPierre Jolivet   if (B || D || H) PetscCall(DMGetWorkArray(dm, numelB, MPIU_REAL, &sB));
43748a46eb9SPierre Jolivet   if (D || H) PetscCall(DMGetWorkArray(dm, numelD, MPIU_REAL, &sD));
43848a46eb9SPierre Jolivet   if (H) PetscCall(DMGetWorkArray(dm, numelH, MPIU_REAL, &sH));
439d092c84bSBrandon Whitchurch   if (B)
440d092c84bSBrandon Whitchurch     for (i = 0; i < numelB; ++i) B[i] = 0.;
441d092c84bSBrandon Whitchurch   if (D)
442d092c84bSBrandon Whitchurch     for (i = 0; i < numelD; ++i) D[i] = 0.;
443d092c84bSBrandon Whitchurch   if (H)
444d092c84bSBrandon Whitchurch     for (i = 0; i < numelH; ++i) H[i] = 0.;
445d092c84bSBrandon Whitchurch 
446d092c84bSBrandon Whitchurch   for (s = 0, offset = 0, ncoffset = 0; s < Ns; ++s) {
447d092c84bSBrandon Whitchurch     PetscInt sNv, spdim, sNc, p;
448d092c84bSBrandon Whitchurch 
4499566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(sum->sumspaces[s], &sNv));
4509566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumComponents(sum->sumspaces[s], &sNc));
4519566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDimension(sum->sumspaces[s], &spdim));
4521dca8a05SBarry Smith     PetscCheck(offset + spdim <= pdimfull, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspace dimensions exceed target space dimension.");
45348a46eb9SPierre Jolivet     if (s == 0 || !sum->uniform) PetscCall(PetscSpaceEvaluate(sum->sumspaces[s], npoints, points, sB, sD, sH));
454d092c84bSBrandon Whitchurch     if (B || D || H) {
455d092c84bSBrandon Whitchurch       for (p = 0; p < npoints; ++p) {
456d092c84bSBrandon Whitchurch         PetscInt j;
457d092c84bSBrandon Whitchurch 
458d092c84bSBrandon Whitchurch         for (j = 0; j < spdim; ++j) {
459d092c84bSBrandon Whitchurch           PetscInt c;
4602dce792eSToby Isaac           PetscInt b = sum->interleave_basis ? (j * Ns + s) : (j + offset);
461d092c84bSBrandon Whitchurch 
462d092c84bSBrandon Whitchurch           for (c = 0; c < sNc; ++c) {
463d092c84bSBrandon Whitchurch             PetscInt compoffset, BInd, sBInd;
464d092c84bSBrandon Whitchurch 
4652dce792eSToby Isaac             compoffset = concatenate ? (sum->interleave_components ? (c * Ns + s) : (c + ncoffset)) : c;
4662dce792eSToby Isaac             BInd       = (p * pdimfull + b) * Nc + compoffset;
467d092c84bSBrandon Whitchurch             sBInd      = (p * spdim + j) * sNc + c;
468642c7897SToby Isaac             if (B) B[BInd] = sB[sBInd];
469d092c84bSBrandon Whitchurch             if (D || H) {
470d092c84bSBrandon Whitchurch               PetscInt v;
471d092c84bSBrandon Whitchurch 
472d092c84bSBrandon Whitchurch               for (v = 0; v < Nv; ++v) {
473d092c84bSBrandon Whitchurch                 PetscInt DInd, sDInd;
474d092c84bSBrandon Whitchurch 
475d092c84bSBrandon Whitchurch                 DInd  = BInd * Nv + v;
476d092c84bSBrandon Whitchurch                 sDInd = sBInd * Nv + v;
477642c7897SToby Isaac                 if (D) D[DInd] = sD[sDInd];
478d092c84bSBrandon Whitchurch                 if (H) {
479d092c84bSBrandon Whitchurch                   PetscInt v2;
480d092c84bSBrandon Whitchurch 
481d092c84bSBrandon Whitchurch                   for (v2 = 0; v2 < Nv; ++v2) {
482d092c84bSBrandon Whitchurch                     PetscInt HInd, sHInd;
483d092c84bSBrandon Whitchurch 
484d092c84bSBrandon Whitchurch                     HInd    = DInd * Nv + v2;
485d092c84bSBrandon Whitchurch                     sHInd   = sDInd * Nv + v2;
486642c7897SToby Isaac                     H[HInd] = sH[sHInd];
487d092c84bSBrandon Whitchurch                   }
488d092c84bSBrandon Whitchurch                 }
489d092c84bSBrandon Whitchurch               }
490d092c84bSBrandon Whitchurch             }
491d092c84bSBrandon Whitchurch           }
492d092c84bSBrandon Whitchurch         }
493d092c84bSBrandon Whitchurch       }
494d092c84bSBrandon Whitchurch     }
495d092c84bSBrandon Whitchurch     offset += spdim;
496d092c84bSBrandon Whitchurch     ncoffset += sNc;
497d092c84bSBrandon Whitchurch   }
498d092c84bSBrandon Whitchurch 
49948a46eb9SPierre Jolivet   if (H) PetscCall(DMRestoreWorkArray(dm, numelH, MPIU_REAL, &sH));
50048a46eb9SPierre Jolivet   if (D || H) PetscCall(DMRestoreWorkArray(dm, numelD, MPIU_REAL, &sD));
50148a46eb9SPierre Jolivet   if (B || D || H) PetscCall(DMRestoreWorkArray(dm, numelB, MPIU_REAL, &sB));
5023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
503d092c84bSBrandon Whitchurch }
504d092c84bSBrandon Whitchurch 
PetscSpaceGetHeightSubspace_Sum(PetscSpace sp,PetscInt height,PetscSpace * subsp)505d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetHeightSubspace_Sum(PetscSpace sp, PetscInt height, PetscSpace *subsp)
506d71ae5a4SJacob Faibussowitsch {
507642c7897SToby Isaac   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
508642c7897SToby Isaac   PetscInt        Nc, dim, order;
509642c7897SToby Isaac   PetscBool       tensor;
510642c7897SToby Isaac 
511642c7897SToby Isaac   PetscFunctionBegin;
5129566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
5139566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &dim));
5149566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(sp, &order, NULL));
5159566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
5161dca8a05SBarry 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);
5179566063dSJacob Faibussowitsch   if (!sum->heightsubspaces) PetscCall(PetscCalloc1(dim, &sum->heightsubspaces));
518642c7897SToby Isaac   if (height <= dim) {
519642c7897SToby Isaac     if (!sum->heightsubspaces[height - 1]) {
520642c7897SToby Isaac       PetscSpace  sub;
521642c7897SToby Isaac       const char *name;
522642c7897SToby Isaac 
5239566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
5249566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
5259566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)sub, name));
5269566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetType(sub, PETSCSPACESUM));
5279566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumSetNumSubspaces(sub, sum->numSumSpaces));
5289566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumSetConcatenate(sub, sum->concatenate));
5299566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumComponents(sub, Nc));
5309566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
531642c7897SToby Isaac       for (PetscInt i = 0; i < sum->numSumSpaces; i++) {
532642c7897SToby Isaac         PetscSpace subh;
533642c7897SToby Isaac 
5349566063dSJacob Faibussowitsch         PetscCall(PetscSpaceGetHeightSubspace(sum->sumspaces[i], height, &subh));
5359566063dSJacob Faibussowitsch         PetscCall(PetscSpaceSumSetSubspace(sub, i, subh));
536642c7897SToby Isaac       }
5379566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetUp(sub));
538642c7897SToby Isaac       sum->heightsubspaces[height - 1] = sub;
539642c7897SToby Isaac     }
540642c7897SToby Isaac     *subsp = sum->heightsubspaces[height - 1];
541642c7897SToby Isaac   } else {
542642c7897SToby Isaac     *subsp = NULL;
543642c7897SToby Isaac   }
5443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545642c7897SToby Isaac }
546642c7897SToby Isaac 
5472dce792eSToby Isaac /*@
5482dce792eSToby Isaac   PetscSpaceSumSetInterleave - Set whether the basis functions and components of a uniform sum are interleaved
5492dce792eSToby Isaac 
5502dce792eSToby Isaac   Logically collective
5512dce792eSToby Isaac 
5522dce792eSToby Isaac   Input Parameters:
5532dce792eSToby Isaac + sp                    - a `PetscSpace` of type `PETSCSPACESUM`
5542dce792eSToby Isaac . interleave_basis      - if `PETSC_TRUE`, the basis vectors of the subspaces are interleaved
5552dce792eSToby Isaac - interleave_components - if `PETSC_TRUE` and the space concatenates components (`PetscSpaceSumGetConcatenate()`),
5562dce792eSToby Isaac                           interleave the concatenated components
5572dce792eSToby Isaac 
5582dce792eSToby Isaac   Level: developer
5592dce792eSToby Isaac 
5602dce792eSToby Isaac .seealso: `PetscSpace`, `PETSCSPACESUM`, `PETSCFEVECTOR`, `PetscSpaceSumGetInterleave()`
5612dce792eSToby Isaac @*/
PetscSpaceSumSetInterleave(PetscSpace sp,PetscBool interleave_basis,PetscBool interleave_components)5622dce792eSToby Isaac PetscErrorCode PetscSpaceSumSetInterleave(PetscSpace sp, PetscBool interleave_basis, PetscBool interleave_components)
5632dce792eSToby Isaac {
5642dce792eSToby Isaac   PetscFunctionBegin;
5652dce792eSToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
5662dce792eSToby Isaac   PetscTryMethod(sp, "PetscSpaceSumSetInterleave_C", (PetscSpace, PetscBool, PetscBool), (sp, interleave_basis, interleave_components));
5672dce792eSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
5682dce792eSToby Isaac }
5692dce792eSToby Isaac 
PetscSpaceSumSetInterleave_Sum(PetscSpace sp,PetscBool interleave_basis,PetscBool interleave_components)5702dce792eSToby Isaac static PetscErrorCode PetscSpaceSumSetInterleave_Sum(PetscSpace sp, PetscBool interleave_basis, PetscBool interleave_components)
5712dce792eSToby Isaac {
5722dce792eSToby Isaac   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
5734d86920dSPierre Jolivet 
5742dce792eSToby Isaac   PetscFunctionBegin;
5752dce792eSToby Isaac   sum->interleave_basis      = interleave_basis;
5762dce792eSToby Isaac   sum->interleave_components = interleave_components;
5772dce792eSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
5782dce792eSToby Isaac }
5792dce792eSToby Isaac 
5802dce792eSToby Isaac /*@
5812dce792eSToby Isaac   PetscSpaceSumGetInterleave - Get whether the basis functions and components of a uniform sum are interleaved
5822dce792eSToby Isaac 
5832dce792eSToby Isaac   Logically collective
5842dce792eSToby Isaac 
5852dce792eSToby Isaac   Input Parameter:
5862dce792eSToby Isaac . sp - a `PetscSpace` of type `PETSCSPACESUM`
5872dce792eSToby Isaac 
5882dce792eSToby Isaac   Output Parameters:
5892dce792eSToby Isaac + interleave_basis      - if `PETSC_TRUE`, the basis vectors of the subspaces are interleaved
5902dce792eSToby Isaac - interleave_components - if `PETSC_TRUE` and the space concatenates components (`PetscSpaceSumGetConcatenate()`),
5912dce792eSToby Isaac                           interleave the concatenated components
5922dce792eSToby Isaac 
5932dce792eSToby Isaac   Level: developer
5942dce792eSToby Isaac 
5952dce792eSToby Isaac .seealso: `PetscSpace`, `PETSCSPACESUM`, `PETSCFEVECTOR`, `PetscSpaceSumSetInterleave()`
5962dce792eSToby Isaac @*/
PetscSpaceSumGetInterleave(PetscSpace sp,PeOp PetscBool * interleave_basis,PeOp PetscBool * interleave_components)597ce78bad3SBarry Smith PetscErrorCode PetscSpaceSumGetInterleave(PetscSpace sp, PeOp PetscBool *interleave_basis, PeOp PetscBool *interleave_components)
5982dce792eSToby Isaac {
5992dce792eSToby Isaac   PetscFunctionBegin;
6002dce792eSToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
6012dce792eSToby Isaac   if (interleave_basis) PetscAssertPointer(interleave_basis, 2);
6022dce792eSToby Isaac   if (interleave_components) PetscAssertPointer(interleave_components, 3);
6032dce792eSToby Isaac   PetscTryMethod(sp, "PetscSpaceSumGetInterleave_C", (PetscSpace, PetscBool *, PetscBool *), (sp, interleave_basis, interleave_components));
6042dce792eSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
6052dce792eSToby Isaac }
6062dce792eSToby Isaac 
PetscSpaceSumGetInterleave_Sum(PetscSpace sp,PetscBool * interleave_basis,PetscBool * interleave_components)6072dce792eSToby Isaac static PetscErrorCode PetscSpaceSumGetInterleave_Sum(PetscSpace sp, PetscBool *interleave_basis, PetscBool *interleave_components)
6082dce792eSToby Isaac {
6092dce792eSToby Isaac   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
6104d86920dSPierre Jolivet 
6112dce792eSToby Isaac   PetscFunctionBegin;
6122dce792eSToby Isaac   if (interleave_basis) *interleave_basis = sum->interleave_basis;
6132dce792eSToby Isaac   if (interleave_components) *interleave_components = sum->interleave_components;
6142dce792eSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
6152dce792eSToby Isaac }
6162dce792eSToby Isaac 
PetscSpaceInitialize_Sum(PetscSpace sp)617d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
618d71ae5a4SJacob Faibussowitsch {
619d092c84bSBrandon Whitchurch   PetscFunctionBegin;
620d092c84bSBrandon Whitchurch   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Sum;
621d092c84bSBrandon Whitchurch   sp->ops->setup             = PetscSpaceSetUp_Sum;
622d092c84bSBrandon Whitchurch   sp->ops->view              = PetscSpaceView_Sum;
623d092c84bSBrandon Whitchurch   sp->ops->destroy           = PetscSpaceDestroy_Sum;
624d092c84bSBrandon Whitchurch   sp->ops->getdimension      = PetscSpaceGetDimension_Sum;
625d092c84bSBrandon Whitchurch   sp->ops->evaluate          = PetscSpaceEvaluate_Sum;
626642c7897SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Sum;
627d092c84bSBrandon Whitchurch 
6289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", PetscSpaceSumGetNumSubspaces_Sum));
6299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", PetscSpaceSumSetNumSubspaces_Sum));
6309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", PetscSpaceSumGetSubspace_Sum));
6319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", PetscSpaceSumSetSubspace_Sum));
6329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", PetscSpaceSumGetConcatenate_Sum));
6339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", PetscSpaceSumSetConcatenate_Sum));
6342dce792eSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetInterleave_C", PetscSpaceSumGetInterleave_Sum));
6352dce792eSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetInterleave_C", PetscSpaceSumSetInterleave_Sum));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
637d092c84bSBrandon Whitchurch }
638d092c84bSBrandon Whitchurch 
639d092c84bSBrandon Whitchurch /*MC
640dce8aebaSBarry Smith   PETSCSPACESUM = "sum" - A `PetscSpace` object that encapsulates a sum of subspaces.
641d092c84bSBrandon Whitchurch 
642d092c84bSBrandon Whitchurch   Level: intermediate
643d092c84bSBrandon Whitchurch 
644b24fb147SBarry Smith   Note:
645b24fb147SBarry Smith    That sum can either be direct or a concatenation. For example if A and B are spaces each with 2 components,
646b24fb147SBarry Smith   the direct sum of A and B will also have 2 components while the concatenated sum will have 4 components. In both cases A and B must be defined over the
647b24fb147SBarry Smith   same number of variables.
648b24fb147SBarry Smith 
649b24fb147SBarry Smith .seealso: `PetscSpace`, `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`, `PetscSpaceSumGetNumSubspaces()`, `PetscSpaceSumSetNumSubspaces()`,
650b24fb147SBarry Smith           `PetscSpaceSumGetConcatenate()`, `PetscSpaceSumSetConcatenate()`
651d092c84bSBrandon Whitchurch M*/
PetscSpaceCreate_Sum(PetscSpace sp)652d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
653d71ae5a4SJacob Faibussowitsch {
654d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum;
655d092c84bSBrandon Whitchurch 
656d092c84bSBrandon Whitchurch   PetscFunctionBegin;
657d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
6584dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sum));
659642c7897SToby Isaac   sum->numSumSpaces = PETSC_DEFAULT;
660d092c84bSBrandon Whitchurch   sp->data          = sum;
6619566063dSJacob Faibussowitsch   PetscCall(PetscSpaceInitialize_Sum(sp));
6623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
663d092c84bSBrandon Whitchurch }
664d092c84bSBrandon Whitchurch 
PetscSpaceCreateSum(PetscInt numSubspaces,const PetscSpace subspaces[],PetscBool concatenate,PetscSpace * sumSpace)665d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces, const PetscSpace subspaces[], PetscBool concatenate, PetscSpace *sumSpace)
666d71ae5a4SJacob Faibussowitsch {
667d092c84bSBrandon Whitchurch   PetscInt i, Nv, Nc = 0;
668d092c84bSBrandon Whitchurch 
669d092c84bSBrandon Whitchurch   PetscFunctionBegin;
6709566063dSJacob Faibussowitsch   PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]), sumSpace));
6719566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetType(*sumSpace, PETSCSPACESUM));
6729566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumSetNumSubspaces(*sumSpace, numSubspaces));
6739566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumSetConcatenate(*sumSpace, concatenate));
674d092c84bSBrandon Whitchurch   for (i = 0; i < numSubspaces; ++i) {
675d092c84bSBrandon Whitchurch     PetscInt sNc;
676d092c84bSBrandon Whitchurch 
6779566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetSubspace(*sumSpace, i, subspaces[i]));
6789566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumComponents(subspaces[i], &sNc));
679d092c84bSBrandon Whitchurch     if (concatenate) Nc += sNc;
680d092c84bSBrandon Whitchurch     else Nc = sNc;
681d092c84bSBrandon Whitchurch   }
6829566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(subspaces[0], &Nv));
6839566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumComponents(*sumSpace, Nc));
6849566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumVariables(*sumSpace, Nv));
6859566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetUp(*sumSpace));
6863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
687d092c84bSBrandon Whitchurch }
688