xref: /petsc/src/dm/dt/space/impls/sum/spacesum.c (revision b24fb147d2f783efb2f58813f80260c02fe8ea96)
1d092c84bSBrandon Whitchurch #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2*b24fb147SBarry Smith 
3d092c84bSBrandon Whitchurch /*@
4*b24fb147SBarry 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 
14*b24fb147SBarry Smith   Note:
15*b24fb147SBarry 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
16*b24fb147SBarry Smith 
17dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
18d092c84bSBrandon Whitchurch @*/
19d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp, PetscInt *numSumSpaces)
20d71ae5a4SJacob Faibussowitsch {
21d092c84bSBrandon Whitchurch   PetscFunctionBegin;
22d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
23d092c84bSBrandon Whitchurch   PetscValidIntPointer(numSumSpaces, 2);
24cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumGetNumSubspaces_C", (PetscSpace, PetscInt *), (sp, numSumSpaces));
253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26d092c84bSBrandon Whitchurch }
27d092c84bSBrandon Whitchurch 
28d092c84bSBrandon Whitchurch /*@
29*b24fb147SBarry 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 
37*b24fb147SBarry Smith   Note:
38*b24fb147SBarry 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
39*b24fb147SBarry Smith 
40dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
41d092c84bSBrandon Whitchurch @*/
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  A concatenated sum space will have number of components equal to the sum of the number of components of all subspaces. A non-concatenated,
53d092c84bSBrandon Whitchurch  or direct sum space will have the same number of components as its subspaces.
54d092c84bSBrandon Whitchurch 
552fe279fdSBarry Smith  Input Parameter:
56d092c84bSBrandon Whitchurch . sp - the function space object
57d092c84bSBrandon Whitchurch 
582fe279fdSBarry Smith  Output Parameter:
59d092c84bSBrandon Whitchurch . concatenate - flag indicating whether subspaces are concatenated.
60d092c84bSBrandon Whitchurch 
61d092c84bSBrandon Whitchurch   Level: intermediate
62d092c84bSBrandon Whitchurch 
63dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetConcatenate()`
64d092c84bSBrandon Whitchurch @*/
65d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp, PetscBool *concatenate)
66d71ae5a4SJacob Faibussowitsch {
67d092c84bSBrandon Whitchurch   PetscFunctionBegin;
68d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
69cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumGetConcatenate_C", (PetscSpace, PetscBool *), (sp, concatenate));
703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71d092c84bSBrandon Whitchurch }
72d092c84bSBrandon Whitchurch 
73d092c84bSBrandon Whitchurch /*@
74d092c84bSBrandon Whitchurch   PetscSpaceSumSetConcatenate - Sets the concatenate flag for this space.
75d092c84bSBrandon Whitchurch   A concatenated sum space will have number of components equal to the sum of the number of components of all subspaces. A non-concatenated,
76d092c84bSBrandon Whitchurch   or direct sum space will have the same number of components as its subspaces .
77d092c84bSBrandon Whitchurch 
78d092c84bSBrandon Whitchurch  Input Parameters:
79d092c84bSBrandon Whitchurch + sp - the function space object
80d092c84bSBrandon Whitchurch - concatenate - are subspaces concatenated components (true) or direct summands (false)
81d092c84bSBrandon Whitchurch 
82d092c84bSBrandon Whitchurch   Level: intermediate
83dce8aebaSBarry Smith 
84dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetConcatenate()`
85d092c84bSBrandon Whitchurch @*/
86d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp, PetscBool concatenate)
87d71ae5a4SJacob Faibussowitsch {
88d092c84bSBrandon Whitchurch   PetscFunctionBegin;
89d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
90cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumSetConcatenate_C", (PetscSpace, PetscBool), (sp, concatenate));
913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92d092c84bSBrandon Whitchurch }
93d092c84bSBrandon Whitchurch 
94d092c84bSBrandon Whitchurch /*@
95*b24fb147SBarry Smith   PetscSpaceSumGetSubspace - Get a space in the sum space
96d092c84bSBrandon Whitchurch 
97d092c84bSBrandon Whitchurch   Input Parameters:
98d092c84bSBrandon Whitchurch + sp - the function space object
99d092c84bSBrandon Whitchurch - s  - The space number
100d092c84bSBrandon Whitchurch 
101d092c84bSBrandon Whitchurch   Output Parameter:
102*b24fb147SBarry Smith . subsp - the `PetscSpace`
103d092c84bSBrandon Whitchurch 
104d092c84bSBrandon Whitchurch   Level: intermediate
105d092c84bSBrandon Whitchurch 
106*b24fb147SBarry Smith   Note:
107*b24fb147SBarry 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
108*b24fb147SBarry Smith 
109dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
110d092c84bSBrandon Whitchurch @*/
111d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp, PetscInt s, PetscSpace *subsp)
112d71ae5a4SJacob Faibussowitsch {
113d092c84bSBrandon Whitchurch   PetscFunctionBegin;
114d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
115d092c84bSBrandon Whitchurch   PetscValidPointer(subsp, 3);
116cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumGetSubspace_C", (PetscSpace, PetscInt, PetscSpace *), (sp, s, subsp));
1173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118d092c84bSBrandon Whitchurch }
119d092c84bSBrandon Whitchurch 
120d092c84bSBrandon Whitchurch /*@
121*b24fb147SBarry Smith   PetscSpaceSumSetSubspace - Set a space in the sum space
122d092c84bSBrandon Whitchurch 
123d092c84bSBrandon Whitchurch   Input Parameters:
124d092c84bSBrandon Whitchurch + sp    - the function space object
125d092c84bSBrandon Whitchurch . s     - The space number
126d092c84bSBrandon Whitchurch - subsp - the number of spaces
127d092c84bSBrandon Whitchurch 
128d092c84bSBrandon Whitchurch   Level: intermediate
129d092c84bSBrandon Whitchurch 
130*b24fb147SBarry Smith   Note:
131*b24fb147SBarry 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
132*b24fb147SBarry Smith 
133dce8aebaSBarry Smith .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
134d092c84bSBrandon Whitchurch @*/
135d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp, PetscInt s, PetscSpace subsp)
136d71ae5a4SJacob Faibussowitsch {
137d092c84bSBrandon Whitchurch   PetscFunctionBegin;
138d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
139d092c84bSBrandon Whitchurch   if (subsp) PetscValidHeaderSpecific(subsp, PETSCSPACE_CLASSID, 3);
140cac4c232SBarry Smith   PetscTryMethod(sp, "PetscSpaceSumSetSubspace_C", (PetscSpace, PetscInt, PetscSpace), (sp, s, subsp));
1413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
142d092c84bSBrandon Whitchurch }
143d092c84bSBrandon Whitchurch 
144d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space, PetscInt *numSumSpaces)
145d71ae5a4SJacob Faibussowitsch {
146d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
147d092c84bSBrandon Whitchurch 
148d092c84bSBrandon Whitchurch   PetscFunctionBegin;
149d092c84bSBrandon Whitchurch   *numSumSpaces = sum->numSumSpaces;
1503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151d092c84bSBrandon Whitchurch }
152d092c84bSBrandon Whitchurch 
153d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space, PetscInt numSumSpaces)
154d71ae5a4SJacob Faibussowitsch {
155d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
156d092c84bSBrandon Whitchurch   PetscInt        Ns  = sum->numSumSpaces;
157d092c84bSBrandon Whitchurch 
158d092c84bSBrandon Whitchurch   PetscFunctionBegin;
15928b400f6SJacob Faibussowitsch   PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of subspaces after setup called");
1603ba16761SJacob Faibussowitsch   if (numSumSpaces == Ns) PetscFunctionReturn(PETSC_SUCCESS);
161d092c84bSBrandon Whitchurch   if (Ns >= 0) {
162d092c84bSBrandon Whitchurch     PetscInt s;
16348a46eb9SPierre Jolivet     for (s = 0; s < Ns; ++s) PetscCall(PetscSpaceDestroy(&sum->sumspaces[s]));
1649566063dSJacob Faibussowitsch     PetscCall(PetscFree(sum->sumspaces));
165d092c84bSBrandon Whitchurch   }
166d092c84bSBrandon Whitchurch 
167d092c84bSBrandon Whitchurch   Ns = sum->numSumSpaces = numSumSpaces;
1689566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Ns, &sum->sumspaces));
1693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
170d092c84bSBrandon Whitchurch }
171d092c84bSBrandon Whitchurch 
172d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp, PetscBool *concatenate)
173d71ae5a4SJacob Faibussowitsch {
174d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
175d092c84bSBrandon Whitchurch 
176d092c84bSBrandon Whitchurch   PetscFunctionBegin;
177d092c84bSBrandon Whitchurch   *concatenate = sum->concatenate;
1783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
179d092c84bSBrandon Whitchurch }
180d092c84bSBrandon Whitchurch 
181d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp, PetscBool concatenate)
182d71ae5a4SJacob Faibussowitsch {
183d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
184d092c84bSBrandon Whitchurch 
185d092c84bSBrandon Whitchurch   PetscFunctionBegin;
18628b400f6SJacob Faibussowitsch   PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change space concatenation after setup called.");
187d092c84bSBrandon Whitchurch 
188d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
1893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
190d092c84bSBrandon Whitchurch }
191d092c84bSBrandon Whitchurch 
192d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace *subspace)
193d71ae5a4SJacob Faibussowitsch {
194d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
195d092c84bSBrandon Whitchurch   PetscInt        Ns  = sum->numSumSpaces;
196d092c84bSBrandon Whitchurch 
197d092c84bSBrandon Whitchurch   PetscFunctionBegin;
19808401ef6SPierre Jolivet   PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first");
1991dca8a05SBarry Smith   PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
200d092c84bSBrandon Whitchurch 
201d092c84bSBrandon Whitchurch   *subspace = sum->sumspaces[s];
2023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
203d092c84bSBrandon Whitchurch }
204d092c84bSBrandon Whitchurch 
205d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace subspace)
206d71ae5a4SJacob Faibussowitsch {
207d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
208d092c84bSBrandon Whitchurch   PetscInt        Ns  = sum->numSumSpaces;
209d092c84bSBrandon Whitchurch 
210d092c84bSBrandon Whitchurch   PetscFunctionBegin;
21128b400f6SJacob Faibussowitsch   PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change subspace after setup called");
21208401ef6SPierre Jolivet   PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first");
2131dca8a05SBarry Smith   PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
214d092c84bSBrandon Whitchurch 
2159566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)subspace));
2169566063dSJacob Faibussowitsch   PetscCall(PetscSpaceDestroy(&sum->sumspaces[s]));
217d092c84bSBrandon Whitchurch   sum->sumspaces[s] = subspace;
2183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219d092c84bSBrandon Whitchurch }
220d092c84bSBrandon Whitchurch 
221d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscSpace sp, PetscOptionItems *PetscOptionsObject)
222d71ae5a4SJacob Faibussowitsch {
223d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
224d092c84bSBrandon Whitchurch   PetscInt        Ns, Nc, Nv, deg, i;
225d092c84bSBrandon Whitchurch   PetscBool       concatenate = PETSC_TRUE;
226d092c84bSBrandon Whitchurch   const char     *prefix;
227d092c84bSBrandon Whitchurch 
228d092c84bSBrandon Whitchurch   PetscFunctionBegin;
2299566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
2303ba16761SJacob Faibussowitsch   if (!Nv) PetscFunctionReturn(PETSC_SUCCESS);
2319566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
2329566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns));
2339566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(sp, &deg, NULL));
234d092c84bSBrandon Whitchurch   Ns = (Ns == PETSC_DEFAULT) ? 1 : Ns;
235d092c84bSBrandon Whitchurch 
236d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace sum options");
2379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-petscspace_sum_spaces", "The number of subspaces", "PetscSpaceSumSetNumSubspaces", Ns, &Ns, NULL, 0));
2389371c9d4SSatish Balay   PetscCall(PetscOptionsBool("-petscspace_sum_concatenate", "Subspaces are concatenated components of the final space", "PetscSpaceSumSetFromOptions", concatenate, &concatenate, NULL));
239d0609cedSBarry Smith   PetscOptionsHeadEnd();
240d092c84bSBrandon Whitchurch 
2411dca8a05SBarry 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);
24248a46eb9SPierre Jolivet   if (Ns != sum->numSumSpaces) PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns));
2439566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
244d092c84bSBrandon Whitchurch   for (i = 0; i < Ns; ++i) {
245d092c84bSBrandon Whitchurch     PetscInt   sNv;
246d092c84bSBrandon Whitchurch     PetscSpace subspace;
247d092c84bSBrandon Whitchurch 
2489566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, i, &subspace));
249d092c84bSBrandon Whitchurch     if (!subspace) {
250d092c84bSBrandon Whitchurch       char subspacePrefix[256];
251d092c84bSBrandon Whitchurch 
2529566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subspace));
2539566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subspace, prefix));
25463a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(subspacePrefix, 256, "sumcomp_%" PetscInt_FMT "_", i));
2559566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subspace, subspacePrefix));
2561baa6e33SBarry Smith     } else PetscCall(PetscObjectReference((PetscObject)subspace));
2579566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetFromOptions(subspace));
2589566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(subspace, &sNv));
25963a3b9bcSJacob Faibussowitsch     PetscCheck(sNv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has not been set properly, number of variables is 0.", i);
2609566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetSubspace(sp, i, subspace));
2619566063dSJacob Faibussowitsch     PetscCall(PetscSpaceDestroy(&subspace));
262d092c84bSBrandon Whitchurch   }
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
264d092c84bSBrandon Whitchurch }
265d092c84bSBrandon Whitchurch 
266d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
267d71ae5a4SJacob Faibussowitsch {
268d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum         = (PetscSpace_Sum *)sp->data;
269d092c84bSBrandon Whitchurch   PetscBool       concatenate = PETSC_TRUE;
270642c7897SToby Isaac   PetscBool       uniform;
271642c7897SToby Isaac   PetscInt        Nv, Ns, Nc, i, sum_Nc = 0, deg = PETSC_MAX_INT, maxDeg = PETSC_MIN_INT;
272642c7897SToby Isaac   PetscInt        minNc, maxNc;
273d092c84bSBrandon Whitchurch 
274d092c84bSBrandon Whitchurch   PetscFunctionBegin;
2753ba16761SJacob Faibussowitsch   if (sum->setupCalled) PetscFunctionReturn(PETSC_SUCCESS);
276d092c84bSBrandon Whitchurch 
2779566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
2789566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
2799566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns));
280d092c84bSBrandon Whitchurch   if (Ns == PETSC_DEFAULT) {
281d092c84bSBrandon Whitchurch     Ns = 1;
2829566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns));
283d092c84bSBrandon Whitchurch   }
28463a3b9bcSJacob Faibussowitsch   PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have %" PetscInt_FMT " subspaces", Ns);
285642c7897SToby Isaac   uniform = PETSC_TRUE;
286642c7897SToby Isaac   if (Ns) {
287642c7897SToby Isaac     PetscSpace s0;
288d092c84bSBrandon Whitchurch 
2899566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, 0, &s0));
290642c7897SToby Isaac     for (PetscInt i = 1; i < Ns; i++) {
291642c7897SToby Isaac       PetscSpace si;
292642c7897SToby Isaac 
2939566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
294642c7897SToby Isaac       if (si != s0) {
295642c7897SToby Isaac         uniform = PETSC_FALSE;
296642c7897SToby Isaac         break;
297642c7897SToby Isaac       }
298642c7897SToby Isaac     }
299642c7897SToby Isaac   }
300642c7897SToby Isaac 
301642c7897SToby Isaac   minNc = Nc;
302642c7897SToby Isaac   maxNc = Nc;
303d092c84bSBrandon Whitchurch   for (i = 0; i < Ns; ++i) {
304d092c84bSBrandon Whitchurch     PetscInt   sNv, sNc, iDeg, iMaxDeg;
305d092c84bSBrandon Whitchurch     PetscSpace si;
306d092c84bSBrandon Whitchurch 
3079566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
3089566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(si));
3099566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(si, &sNv));
31063a3b9bcSJacob 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);
3119566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumComponents(si, &sNc));
312d092c84bSBrandon Whitchurch     if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
313642c7897SToby Isaac     minNc = PetscMin(minNc, sNc);
314642c7897SToby Isaac     maxNc = PetscMax(maxNc, sNc);
315d092c84bSBrandon Whitchurch     sum_Nc += sNc;
3169566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
3179566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(si, &iDeg, &iMaxDeg));
318642c7897SToby Isaac     deg    = PetscMin(deg, iDeg);
319d092c84bSBrandon Whitchurch     maxDeg = PetscMax(maxDeg, iMaxDeg);
320d092c84bSBrandon Whitchurch   }
321d092c84bSBrandon Whitchurch 
3227a46b595SBarry 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);
3237a46b595SBarry 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.");
324d092c84bSBrandon Whitchurch 
325d092c84bSBrandon Whitchurch   sp->degree       = deg;
326d092c84bSBrandon Whitchurch   sp->maxDegree    = maxDeg;
327d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
328642c7897SToby Isaac   sum->uniform     = uniform;
329d092c84bSBrandon Whitchurch   sum->setupCalled = PETSC_TRUE;
3303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
331d092c84bSBrandon Whitchurch }
332d092c84bSBrandon Whitchurch 
333d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp, PetscViewer v)
334d71ae5a4SJacob Faibussowitsch {
335d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum         = (PetscSpace_Sum *)sp->data;
336d092c84bSBrandon Whitchurch   PetscBool       concatenate = sum->concatenate;
337d092c84bSBrandon Whitchurch   PetscInt        i, Ns = sum->numSumSpaces;
338d092c84bSBrandon Whitchurch 
339d092c84bSBrandon Whitchurch   PetscFunctionBegin;
3401baa6e33SBarry Smith   if (concatenate) PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " concatenated subspaces%s\n", Ns, sum->uniform ? " (all identical)" : ""));
3411baa6e33SBarry Smith   else PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " subspaces%s\n", Ns, sum->uniform ? " (all identical)" : ""));
342642c7897SToby Isaac   for (i = 0; i < (sum->uniform ? (Ns > 0 ? 1 : 0) : Ns); ++i) {
3439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(v));
3449566063dSJacob Faibussowitsch     PetscCall(PetscSpaceView(sum->sumspaces[i], v));
3459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(v));
346d092c84bSBrandon Whitchurch   }
3473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
348d092c84bSBrandon Whitchurch }
349d092c84bSBrandon Whitchurch 
350d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp, PetscViewer viewer)
351d71ae5a4SJacob Faibussowitsch {
352d092c84bSBrandon Whitchurch   PetscBool iascii;
353d092c84bSBrandon Whitchurch 
354d092c84bSBrandon Whitchurch   PetscFunctionBegin;
3559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3561baa6e33SBarry Smith   if (iascii) PetscCall(PetscSpaceSumView_Ascii(sp, viewer));
3573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
358d092c84bSBrandon Whitchurch }
359d092c84bSBrandon Whitchurch 
360d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
361d71ae5a4SJacob Faibussowitsch {
362d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
363d092c84bSBrandon Whitchurch   PetscInt        i, Ns = sum->numSumSpaces;
364d092c84bSBrandon Whitchurch 
365d092c84bSBrandon Whitchurch   PetscFunctionBegin;
36648a46eb9SPierre Jolivet   for (i = 0; i < Ns; ++i) PetscCall(PetscSpaceDestroy(&sum->sumspaces[i]));
3679566063dSJacob Faibussowitsch   PetscCall(PetscFree(sum->sumspaces));
368642c7897SToby Isaac   if (sum->heightsubspaces) {
369642c7897SToby Isaac     PetscInt d;
370642c7897SToby Isaac 
371642c7897SToby Isaac     /* sp->Nv is the spatial dimension, so it is equal to the number
372642c7897SToby Isaac      * of subspaces on higher co-dimension points */
37348a46eb9SPierre Jolivet     for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&sum->heightsubspaces[d]));
374642c7897SToby Isaac   }
3759566063dSJacob Faibussowitsch   PetscCall(PetscFree(sum->heightsubspaces));
3769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", NULL));
3779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", NULL));
3789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", NULL));
3799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", NULL));
3802e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", NULL));
3812e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", NULL));
3829566063dSJacob Faibussowitsch   PetscCall(PetscFree(sum));
3833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
384d092c84bSBrandon Whitchurch }
385d092c84bSBrandon Whitchurch 
386d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp, PetscInt *dim)
387d71ae5a4SJacob Faibussowitsch {
388d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
389d092c84bSBrandon Whitchurch   PetscInt        i, d = 0, Ns = sum->numSumSpaces;
390d092c84bSBrandon Whitchurch 
391d092c84bSBrandon Whitchurch   PetscFunctionBegin;
392642c7897SToby Isaac   if (!sum->setupCalled) {
3939566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
3949566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDimension(sp, dim));
3953ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
396642c7897SToby Isaac   }
397d092c84bSBrandon Whitchurch 
398d092c84bSBrandon Whitchurch   for (i = 0; i < Ns; ++i) {
399d092c84bSBrandon Whitchurch     PetscInt id;
400d092c84bSBrandon Whitchurch 
4019566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDimension(sum->sumspaces[i], &id));
402d092c84bSBrandon Whitchurch     d += id;
403d092c84bSBrandon Whitchurch   }
404d092c84bSBrandon Whitchurch 
405d092c84bSBrandon Whitchurch   *dim = d;
4063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
407d092c84bSBrandon Whitchurch }
408d092c84bSBrandon Whitchurch 
409d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
410d71ae5a4SJacob Faibussowitsch {
411d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum         = (PetscSpace_Sum *)sp->data;
412d092c84bSBrandon Whitchurch   PetscBool       concatenate = sum->concatenate;
413d092c84bSBrandon Whitchurch   DM              dm          = sp->dm;
414d092c84bSBrandon Whitchurch   PetscInt        Nc = sp->Nc, Nv = sp->Nv, Ns = sum->numSumSpaces;
415d092c84bSBrandon Whitchurch   PetscInt        i, s, offset, ncoffset, pdimfull, numelB, numelD, numelH;
416d092c84bSBrandon Whitchurch   PetscReal      *sB = NULL, *sD = NULL, *sH = NULL;
417d092c84bSBrandon Whitchurch 
418d092c84bSBrandon Whitchurch   PetscFunctionBegin;
419d092c84bSBrandon Whitchurch   if (!sum->setupCalled) {
4209566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetUp(sp));
4219566063dSJacob Faibussowitsch     PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
4223ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
423d092c84bSBrandon Whitchurch   }
4249566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDimension(sp, &pdimfull));
425d092c84bSBrandon Whitchurch   numelB = npoints * pdimfull * Nc;
426d092c84bSBrandon Whitchurch   numelD = numelB * Nv;
427d092c84bSBrandon Whitchurch   numelH = numelD * Nv;
42848a46eb9SPierre Jolivet   if (B || D || H) PetscCall(DMGetWorkArray(dm, numelB, MPIU_REAL, &sB));
42948a46eb9SPierre Jolivet   if (D || H) PetscCall(DMGetWorkArray(dm, numelD, MPIU_REAL, &sD));
43048a46eb9SPierre Jolivet   if (H) PetscCall(DMGetWorkArray(dm, numelH, MPIU_REAL, &sH));
431d092c84bSBrandon Whitchurch   if (B)
432d092c84bSBrandon Whitchurch     for (i = 0; i < numelB; ++i) B[i] = 0.;
433d092c84bSBrandon Whitchurch   if (D)
434d092c84bSBrandon Whitchurch     for (i = 0; i < numelD; ++i) D[i] = 0.;
435d092c84bSBrandon Whitchurch   if (H)
436d092c84bSBrandon Whitchurch     for (i = 0; i < numelH; ++i) H[i] = 0.;
437d092c84bSBrandon Whitchurch 
438d092c84bSBrandon Whitchurch   for (s = 0, offset = 0, ncoffset = 0; s < Ns; ++s) {
439d092c84bSBrandon Whitchurch     PetscInt sNv, spdim, sNc, p;
440d092c84bSBrandon Whitchurch 
4419566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumVariables(sum->sumspaces[s], &sNv));
4429566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumComponents(sum->sumspaces[s], &sNc));
4439566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDimension(sum->sumspaces[s], &spdim));
4441dca8a05SBarry Smith     PetscCheck(offset + spdim <= pdimfull, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspace dimensions exceed target space dimension.");
44548a46eb9SPierre Jolivet     if (s == 0 || !sum->uniform) PetscCall(PetscSpaceEvaluate(sum->sumspaces[s], npoints, points, sB, sD, sH));
446d092c84bSBrandon Whitchurch     if (B || D || H) {
447d092c84bSBrandon Whitchurch       for (p = 0; p < npoints; ++p) {
448d092c84bSBrandon Whitchurch         PetscInt j;
449d092c84bSBrandon Whitchurch 
450d092c84bSBrandon Whitchurch         for (j = 0; j < spdim; ++j) {
451d092c84bSBrandon Whitchurch           PetscInt c;
452d092c84bSBrandon Whitchurch 
453d092c84bSBrandon Whitchurch           for (c = 0; c < sNc; ++c) {
454d092c84bSBrandon Whitchurch             PetscInt compoffset, BInd, sBInd;
455d092c84bSBrandon Whitchurch 
456d092c84bSBrandon Whitchurch             compoffset = concatenate ? c + ncoffset : c;
457d092c84bSBrandon Whitchurch             BInd       = (p * pdimfull + j + offset) * Nc + compoffset;
458d092c84bSBrandon Whitchurch             sBInd      = (p * spdim + j) * sNc + c;
459642c7897SToby Isaac             if (B) B[BInd] = sB[sBInd];
460d092c84bSBrandon Whitchurch             if (D || H) {
461d092c84bSBrandon Whitchurch               PetscInt v;
462d092c84bSBrandon Whitchurch 
463d092c84bSBrandon Whitchurch               for (v = 0; v < Nv; ++v) {
464d092c84bSBrandon Whitchurch                 PetscInt DInd, sDInd;
465d092c84bSBrandon Whitchurch 
466d092c84bSBrandon Whitchurch                 DInd  = BInd * Nv + v;
467d092c84bSBrandon Whitchurch                 sDInd = sBInd * Nv + v;
468642c7897SToby Isaac                 if (D) D[DInd] = sD[sDInd];
469d092c84bSBrandon Whitchurch                 if (H) {
470d092c84bSBrandon Whitchurch                   PetscInt v2;
471d092c84bSBrandon Whitchurch 
472d092c84bSBrandon Whitchurch                   for (v2 = 0; v2 < Nv; ++v2) {
473d092c84bSBrandon Whitchurch                     PetscInt HInd, sHInd;
474d092c84bSBrandon Whitchurch 
475d092c84bSBrandon Whitchurch                     HInd    = DInd * Nv + v2;
476d092c84bSBrandon Whitchurch                     sHInd   = sDInd * Nv + v2;
477642c7897SToby Isaac                     H[HInd] = sH[sHInd];
478d092c84bSBrandon Whitchurch                   }
479d092c84bSBrandon Whitchurch                 }
480d092c84bSBrandon Whitchurch               }
481d092c84bSBrandon Whitchurch             }
482d092c84bSBrandon Whitchurch           }
483d092c84bSBrandon Whitchurch         }
484d092c84bSBrandon Whitchurch       }
485d092c84bSBrandon Whitchurch     }
486d092c84bSBrandon Whitchurch     offset += spdim;
487d092c84bSBrandon Whitchurch     ncoffset += sNc;
488d092c84bSBrandon Whitchurch   }
489d092c84bSBrandon Whitchurch 
49048a46eb9SPierre Jolivet   if (H) PetscCall(DMRestoreWorkArray(dm, numelH, MPIU_REAL, &sH));
49148a46eb9SPierre Jolivet   if (D || H) PetscCall(DMRestoreWorkArray(dm, numelD, MPIU_REAL, &sD));
49248a46eb9SPierre Jolivet   if (B || D || H) PetscCall(DMRestoreWorkArray(dm, numelB, MPIU_REAL, &sB));
4933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494d092c84bSBrandon Whitchurch }
495d092c84bSBrandon Whitchurch 
496d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceGetHeightSubspace_Sum(PetscSpace sp, PetscInt height, PetscSpace *subsp)
497d71ae5a4SJacob Faibussowitsch {
498642c7897SToby Isaac   PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
499642c7897SToby Isaac   PetscInt        Nc, dim, order;
500642c7897SToby Isaac   PetscBool       tensor;
501642c7897SToby Isaac 
502642c7897SToby Isaac   PetscFunctionBegin;
5039566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
5049566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(sp, &dim));
5059566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(sp, &order, NULL));
5069566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
5071dca8a05SBarry 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);
5089566063dSJacob Faibussowitsch   if (!sum->heightsubspaces) PetscCall(PetscCalloc1(dim, &sum->heightsubspaces));
509642c7897SToby Isaac   if (height <= dim) {
510642c7897SToby Isaac     if (!sum->heightsubspaces[height - 1]) {
511642c7897SToby Isaac       PetscSpace  sub;
512642c7897SToby Isaac       const char *name;
513642c7897SToby Isaac 
5149566063dSJacob Faibussowitsch       PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
5159566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)sp, &name));
5169566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)sub, name));
5179566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetType(sub, PETSCSPACESUM));
5189566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumSetNumSubspaces(sub, sum->numSumSpaces));
5199566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSumSetConcatenate(sub, sum->concatenate));
5209566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumComponents(sub, Nc));
5219566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
522642c7897SToby Isaac       for (PetscInt i = 0; i < sum->numSumSpaces; i++) {
523642c7897SToby Isaac         PetscSpace subh;
524642c7897SToby Isaac 
5259566063dSJacob Faibussowitsch         PetscCall(PetscSpaceGetHeightSubspace(sum->sumspaces[i], height, &subh));
5269566063dSJacob Faibussowitsch         PetscCall(PetscSpaceSumSetSubspace(sub, i, subh));
527642c7897SToby Isaac       }
5289566063dSJacob Faibussowitsch       PetscCall(PetscSpaceSetUp(sub));
529642c7897SToby Isaac       sum->heightsubspaces[height - 1] = sub;
530642c7897SToby Isaac     }
531642c7897SToby Isaac     *subsp = sum->heightsubspaces[height - 1];
532642c7897SToby Isaac   } else {
533642c7897SToby Isaac     *subsp = NULL;
534642c7897SToby Isaac   }
5353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536642c7897SToby Isaac }
537642c7897SToby Isaac 
538d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
539d71ae5a4SJacob Faibussowitsch {
540d092c84bSBrandon Whitchurch   PetscFunctionBegin;
541d092c84bSBrandon Whitchurch   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Sum;
542d092c84bSBrandon Whitchurch   sp->ops->setup             = PetscSpaceSetUp_Sum;
543d092c84bSBrandon Whitchurch   sp->ops->view              = PetscSpaceView_Sum;
544d092c84bSBrandon Whitchurch   sp->ops->destroy           = PetscSpaceDestroy_Sum;
545d092c84bSBrandon Whitchurch   sp->ops->getdimension      = PetscSpaceGetDimension_Sum;
546d092c84bSBrandon Whitchurch   sp->ops->evaluate          = PetscSpaceEvaluate_Sum;
547642c7897SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Sum;
548d092c84bSBrandon Whitchurch 
5499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", PetscSpaceSumGetNumSubspaces_Sum));
5509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", PetscSpaceSumSetNumSubspaces_Sum));
5519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", PetscSpaceSumGetSubspace_Sum));
5529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", PetscSpaceSumSetSubspace_Sum));
5539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", PetscSpaceSumGetConcatenate_Sum));
5549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", PetscSpaceSumSetConcatenate_Sum));
5553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
556d092c84bSBrandon Whitchurch }
557d092c84bSBrandon Whitchurch 
558d092c84bSBrandon Whitchurch /*MC
559dce8aebaSBarry Smith   PETSCSPACESUM = "sum" - A `PetscSpace` object that encapsulates a sum of subspaces.
560d092c84bSBrandon Whitchurch 
561d092c84bSBrandon Whitchurch   Level: intermediate
562d092c84bSBrandon Whitchurch 
563*b24fb147SBarry Smith   Note:
564*b24fb147SBarry Smith    That sum can either be direct or a concatenation. For example if A and B are spaces each with 2 components,
565*b24fb147SBarry 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
566*b24fb147SBarry Smith   same number of variables.
567*b24fb147SBarry Smith 
568*b24fb147SBarry Smith .seealso: `PetscSpace`, `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`, `PetscSpaceSumGetNumSubspaces()`, `PetscSpaceSumSetNumSubspaces()`,
569*b24fb147SBarry Smith           `PetscSpaceSumGetConcatenate()`, `PetscSpaceSumSetConcatenate()`
570d092c84bSBrandon Whitchurch M*/
571d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
572d71ae5a4SJacob Faibussowitsch {
573d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum;
574d092c84bSBrandon Whitchurch 
575d092c84bSBrandon Whitchurch   PetscFunctionBegin;
576d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1);
5774dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sum));
578642c7897SToby Isaac   sum->numSumSpaces = PETSC_DEFAULT;
579d092c84bSBrandon Whitchurch   sp->data          = sum;
5809566063dSJacob Faibussowitsch   PetscCall(PetscSpaceInitialize_Sum(sp));
5813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
582d092c84bSBrandon Whitchurch }
583d092c84bSBrandon Whitchurch 
584d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces, const PetscSpace subspaces[], PetscBool concatenate, PetscSpace *sumSpace)
585d71ae5a4SJacob Faibussowitsch {
586d092c84bSBrandon Whitchurch   PetscInt i, Nv, Nc = 0;
587d092c84bSBrandon Whitchurch 
588d092c84bSBrandon Whitchurch   PetscFunctionBegin;
5891baa6e33SBarry Smith   if (sumSpace) PetscCall(PetscSpaceDestroy(sumSpace));
5909566063dSJacob Faibussowitsch   PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]), sumSpace));
5919566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetType(*sumSpace, PETSCSPACESUM));
5929566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumSetNumSubspaces(*sumSpace, numSubspaces));
5939566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSumSetConcatenate(*sumSpace, concatenate));
594d092c84bSBrandon Whitchurch   for (i = 0; i < numSubspaces; ++i) {
595d092c84bSBrandon Whitchurch     PetscInt sNc;
596d092c84bSBrandon Whitchurch 
5979566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSumSetSubspace(*sumSpace, i, subspaces[i]));
5989566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetNumComponents(subspaces[i], &sNc));
599d092c84bSBrandon Whitchurch     if (concatenate) Nc += sNc;
600d092c84bSBrandon Whitchurch     else Nc = sNc;
601d092c84bSBrandon Whitchurch   }
6029566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetNumVariables(subspaces[0], &Nv));
6039566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumComponents(*sumSpace, Nc));
6049566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumVariables(*sumSpace, Nv));
6059566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetUp(*sumSpace));
606d092c84bSBrandon Whitchurch 
6073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
608d092c84bSBrandon Whitchurch }
609