xref: /petsc/src/dm/dt/space/impls/sum/spacesum.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
1d092c84bSBrandon Whitchurch #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2d092c84bSBrandon Whitchurch /*@
3d092c84bSBrandon Whitchurch   PetscSpaceSumGetNumSubspaces - Get the number of spaces in the sum
4d092c84bSBrandon Whitchurch 
5d092c84bSBrandon Whitchurch   Input Parameter:
6d092c84bSBrandon Whitchurch   . sp  - the function space object
7d092c84bSBrandon Whitchurch 
8d092c84bSBrandon Whitchurch   Output Parameter:
9d092c84bSBrandon Whitchurch   . numSumSpaces - the number of spaces
10d092c84bSBrandon Whitchurch 
11d092c84bSBrandon Whitchurch Level: intermediate
12d092c84bSBrandon Whitchurch 
13d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumSetNumSubspaces(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
14d092c84bSBrandon Whitchurch @*/
15d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp,PetscInt *numSumSpaces)
16d092c84bSBrandon Whitchurch {
17d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
18d092c84bSBrandon Whitchurch 
19d092c84bSBrandon Whitchurch   PetscFunctionBegin;
20d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
21d092c84bSBrandon Whitchurch   PetscValidIntPointer(numSumSpaces,2);
22d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumGetNumSubspaces_C",(PetscSpace,PetscInt*),(sp,numSumSpaces));CHKERRQ(ierr);
23d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
24d092c84bSBrandon Whitchurch }
25d092c84bSBrandon Whitchurch 
26d092c84bSBrandon Whitchurch /*@
27d092c84bSBrandon Whitchurch   PetscSpaceSumSetNumSubspaces - Set the number of spaces in the sum
28d092c84bSBrandon Whitchurch 
29d092c84bSBrandon Whitchurch   Input Parameters:
30d092c84bSBrandon Whitchurch   + sp  - the function space object
31d092c84bSBrandon Whitchurch   - numSumSpaces - the number of spaces
32d092c84bSBrandon Whitchurch 
33d092c84bSBrandon Whitchurch Level: intermediate
34d092c84bSBrandon Whitchurch 
35d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumGetNumSubspaces(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
36d092c84bSBrandon Whitchurch @*/
37d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumSetNumSubspaces(PetscSpace sp,PetscInt numSumSpaces)
38d092c84bSBrandon Whitchurch {
39d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
40d092c84bSBrandon Whitchurch 
41d092c84bSBrandon Whitchurch   PetscFunctionBegin;
42d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
43d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumSetNumSubspaces_C",(PetscSpace,PetscInt),(sp,numSumSpaces));CHKERRQ(ierr);
44d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
45d092c84bSBrandon Whitchurch }
46d092c84bSBrandon Whitchurch 
47d092c84bSBrandon Whitchurch /*@
48d092c84bSBrandon Whitchurch  PetscSpaceSumGetConcatenate - Get the concatenate flag for this space.
49d092c84bSBrandon 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,
50d092c84bSBrandon Whitchurch  or direct sum space will have the same number of components as its subspaces .
51d092c84bSBrandon Whitchurch 
52d092c84bSBrandon Whitchurch  Input Parameters:
53d092c84bSBrandon Whitchurch  . sp - the function space object
54d092c84bSBrandon Whitchurch 
55d092c84bSBrandon Whitchurch  Output Parameters:
56d092c84bSBrandon Whitchurch  . concatenate - flag indicating whether subspaces are concatenated.
57d092c84bSBrandon Whitchurch 
58d092c84bSBrandon Whitchurch Level: intermediate
59d092c84bSBrandon Whitchurch 
60d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumSetConcatenate()
61d092c84bSBrandon Whitchurch @*/
62d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp,PetscBool *concatenate)
63d092c84bSBrandon Whitchurch {
64d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
65d092c84bSBrandon Whitchurch 
66d092c84bSBrandon Whitchurch   PetscFunctionBegin;
67d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
68d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumGetConcatenate_C",(PetscSpace,PetscBool*),(sp,concatenate));CHKERRQ(ierr);
69d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
70d092c84bSBrandon Whitchurch }
71d092c84bSBrandon Whitchurch 
72d092c84bSBrandon Whitchurch /*@
73d092c84bSBrandon Whitchurch   PetscSpaceSumSetConcatenate - Sets the concatenate flag for this space.
74d092c84bSBrandon 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,
75d092c84bSBrandon Whitchurch  or direct sum space will have the same number of components as its subspaces .
76d092c84bSBrandon Whitchurch 
77d092c84bSBrandon Whitchurch  Input Parameters:
78d092c84bSBrandon Whitchurch   + sp - the function space object
79d092c84bSBrandon Whitchurch   - concatenate - are subspaces concatenated components (true) or direct summands (false)
80d092c84bSBrandon Whitchurch 
81d092c84bSBrandon Whitchurch Level: intermediate
82d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumGetConcatenate()
83d092c84bSBrandon Whitchurch @*/
84d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp,PetscBool concatenate)
85d092c84bSBrandon Whitchurch {
86d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
87d092c84bSBrandon Whitchurch 
88d092c84bSBrandon Whitchurch   PetscFunctionBegin;
89d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
90d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumSetConcatenate_C",(PetscSpace,PetscBool),(sp,concatenate));CHKERRQ(ierr);
91d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
92d092c84bSBrandon Whitchurch }
93d092c84bSBrandon Whitchurch 
94d092c84bSBrandon Whitchurch /*@
95d092c84bSBrandon Whitchurch   PetscSpaceSumGetSubspace - Get a space in the sum
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:
102d092c84bSBrandon Whitchurch   . subsp - the PetscSpace
103d092c84bSBrandon Whitchurch 
104d092c84bSBrandon Whitchurch Level: intermediate
105d092c84bSBrandon Whitchurch 
106d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumSetSubspace(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
107d092c84bSBrandon Whitchurch @*/
108d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp,PetscInt s,PetscSpace *subsp)
109d092c84bSBrandon Whitchurch {
110d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
111d092c84bSBrandon Whitchurch 
112d092c84bSBrandon Whitchurch   PetscFunctionBegin;
113d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
114d092c84bSBrandon Whitchurch   PetscValidPointer(subsp,3);
115d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumGetSubspace_C",(PetscSpace,PetscInt,PetscSpace*),(sp,s,subsp));CHKERRQ(ierr);
116d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
117d092c84bSBrandon Whitchurch }
118d092c84bSBrandon Whitchurch 
119d092c84bSBrandon Whitchurch /*@
120d092c84bSBrandon Whitchurch   PetscSpaceSumSetSubspace - Set a space in the sum
121d092c84bSBrandon Whitchurch 
122d092c84bSBrandon Whitchurch   Input Parameters:
123d092c84bSBrandon Whitchurch   + sp    - the function space object
124d092c84bSBrandon Whitchurch   . s     - The space number
125d092c84bSBrandon Whitchurch   - subsp - the number of spaces
126d092c84bSBrandon Whitchurch 
127d092c84bSBrandon Whitchurch Level: intermediate
128d092c84bSBrandon Whitchurch 
129d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumGetSubspace(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
130d092c84bSBrandon Whitchurch @*/
131d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp,PetscInt s,PetscSpace subsp)
132d092c84bSBrandon Whitchurch {
133d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
134d092c84bSBrandon Whitchurch 
135d092c84bSBrandon Whitchurch   PetscFunctionBegin;
136d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
137d092c84bSBrandon Whitchurch   if (subsp) PetscValidHeaderSpecific(subsp,PETSCSPACE_CLASSID,3);
138d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumSetSubspace_C",(PetscSpace,PetscInt,PetscSpace),(sp,s,subsp));CHKERRQ(ierr);
139d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
140d092c84bSBrandon Whitchurch }
141d092c84bSBrandon Whitchurch 
142d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space,PetscInt *numSumSpaces)
143d092c84bSBrandon Whitchurch {
144d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
145d092c84bSBrandon Whitchurch 
146d092c84bSBrandon Whitchurch   PetscFunctionBegin;
147d092c84bSBrandon Whitchurch   *numSumSpaces = sum->numSumSpaces;
148d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
149d092c84bSBrandon Whitchurch }
150d092c84bSBrandon Whitchurch 
151d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space,PetscInt numSumSpaces)
152d092c84bSBrandon Whitchurch {
153d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
154d092c84bSBrandon Whitchurch   PetscInt       Ns   = sum->numSumSpaces;
155d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
156d092c84bSBrandon Whitchurch 
157d092c84bSBrandon Whitchurch   PetscFunctionBegin;
158*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(sum->setupCalled,PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Cannot change number of subspaces after setup called");
159d092c84bSBrandon Whitchurch   if (numSumSpaces == Ns) PetscFunctionReturn(0);
160d092c84bSBrandon Whitchurch   if (Ns >= 0) {
161d092c84bSBrandon Whitchurch     PetscInt s;
162d092c84bSBrandon Whitchurch     for (s=0; s<Ns; ++s) {
163d092c84bSBrandon Whitchurch       ierr = PetscSpaceDestroy(&sum->sumspaces[s]);CHKERRQ(ierr);
164d092c84bSBrandon Whitchurch     }
165d092c84bSBrandon Whitchurch     ierr = PetscFree(sum->sumspaces);CHKERRQ(ierr);
166d092c84bSBrandon Whitchurch   }
167d092c84bSBrandon Whitchurch 
168d092c84bSBrandon Whitchurch   Ns   = sum->numSumSpaces = numSumSpaces;
169d092c84bSBrandon Whitchurch   ierr = PetscCalloc1(Ns,&sum->sumspaces);CHKERRQ(ierr);
170d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
171d092c84bSBrandon Whitchurch }
172d092c84bSBrandon Whitchurch 
173d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp,PetscBool *concatenate)
174d092c84bSBrandon Whitchurch {
175d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
176d092c84bSBrandon Whitchurch 
177d092c84bSBrandon Whitchurch   PetscFunctionBegin;
178d092c84bSBrandon Whitchurch   *concatenate = sum->concatenate;
179d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
180d092c84bSBrandon Whitchurch }
181d092c84bSBrandon Whitchurch 
182d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp,PetscBool concatenate)
183d092c84bSBrandon Whitchurch {
184d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
185d092c84bSBrandon Whitchurch 
186d092c84bSBrandon Whitchurch   PetscFunctionBegin;
187*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(sum->setupCalled,PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Cannot change space concatenation after setup called.");
188d092c84bSBrandon Whitchurch 
189d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
190d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
191d092c84bSBrandon Whitchurch }
192d092c84bSBrandon Whitchurch 
193d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace *subspace)
194d092c84bSBrandon Whitchurch {
195d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
196d092c84bSBrandon Whitchurch   PetscInt       Ns   = sum->numSumSpaces;
197d092c84bSBrandon Whitchurch 
198d092c84bSBrandon Whitchurch   PetscFunctionBegin;
199*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ns < 0,PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSpaceSumSetNumSubspaces() first");
200*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(s<0 || s>=Ns,PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_OUTOFRANGE,"Invalid subspace number %D",subspace);
201d092c84bSBrandon Whitchurch 
202d092c84bSBrandon Whitchurch   *subspace = sum->sumspaces[s];
203d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
204d092c84bSBrandon Whitchurch }
205d092c84bSBrandon Whitchurch 
206d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace subspace)
207d092c84bSBrandon Whitchurch {
208d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
209d092c84bSBrandon Whitchurch   PetscInt       Ns   = sum->numSumSpaces;
210d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
211d092c84bSBrandon Whitchurch 
212d092c84bSBrandon Whitchurch   PetscFunctionBegin;
213*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(sum->setupCalled,PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Cannot change subspace after setup called");
214*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ns < 0,PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSpaceSumSetNumSubspaces() first");
215*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(s < 0 || s >= Ns,PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_OUTOFRANGE,"Invalid subspace number %D",subspace);
216d092c84bSBrandon Whitchurch 
217d092c84bSBrandon Whitchurch   ierr              = PetscObjectReference((PetscObject)subspace);CHKERRQ(ierr);
218d092c84bSBrandon Whitchurch   ierr              = PetscSpaceDestroy(&sum->sumspaces[s]);CHKERRQ(ierr);
219d092c84bSBrandon Whitchurch   sum->sumspaces[s] = subspace;
220d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
221d092c84bSBrandon Whitchurch }
222d092c84bSBrandon Whitchurch 
223d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscOptionItems *PetscOptionsObject,PetscSpace sp)
224d092c84bSBrandon Whitchurch {
225d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
226d092c84bSBrandon Whitchurch   PetscInt       Ns,Nc,Nv,deg,i;
227d092c84bSBrandon Whitchurch   PetscBool      concatenate = PETSC_TRUE;
228d092c84bSBrandon Whitchurch   const char     *prefix;
229d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
230d092c84bSBrandon Whitchurch 
231d092c84bSBrandon Whitchurch   PetscFunctionBegin;
232d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumVariables(sp,&Nv);CHKERRQ(ierr);
233d092c84bSBrandon Whitchurch   if (!Nv) PetscFunctionReturn(0);
234d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumComponents(sp,&Nc);CHKERRQ(ierr);
235d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumGetNumSubspaces(sp,&Ns);CHKERRQ(ierr);
236d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetDegree(sp,&deg,NULL);CHKERRQ(ierr);
237d092c84bSBrandon Whitchurch   Ns   = (Ns == PETSC_DEFAULT) ? 1 : Ns;
238d092c84bSBrandon Whitchurch 
239d092c84bSBrandon Whitchurch   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSpace sum options");CHKERRQ(ierr);
240d092c84bSBrandon Whitchurch   ierr = PetscOptionsBoundedInt("-petscspace_sum_spaces","The number of subspaces","PetscSpaceSumSetNumSubspaces",Ns,&Ns,NULL,0);CHKERRQ(ierr);
241d092c84bSBrandon Whitchurch   ierr = PetscOptionsBool("-petscspace_sum_concatenate","Subspaces are concatenated components of the final space","PetscSpaceSumSetFromOptions",
242d092c84bSBrandon Whitchurch                           concatenate,&concatenate,NULL);CHKERRQ(ierr);
243d092c84bSBrandon Whitchurch   ierr = PetscOptionsTail();CHKERRQ(ierr);
244d092c84bSBrandon Whitchurch 
245*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ns < 0 || (Nv > 0 && Ns == 0),PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have a sum space of %D spaces",Ns);
246d092c84bSBrandon Whitchurch   if (Ns != sum->numSumSpaces) {
247d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetNumSubspaces(sp,Ns);CHKERRQ(ierr);
248d092c84bSBrandon Whitchurch   }
249d092c84bSBrandon Whitchurch   ierr = PetscObjectGetOptionsPrefix((PetscObject)sp,&prefix);CHKERRQ(ierr);
250d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
251d092c84bSBrandon Whitchurch     PetscInt   sNv;
252d092c84bSBrandon Whitchurch     PetscSpace subspace;
253d092c84bSBrandon Whitchurch 
254d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumGetSubspace(sp,i,&subspace);CHKERRQ(ierr);
255d092c84bSBrandon Whitchurch     if (!subspace) {
256d092c84bSBrandon Whitchurch       char subspacePrefix[256];
257d092c84bSBrandon Whitchurch 
258d092c84bSBrandon Whitchurch       ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)sp),&subspace);CHKERRQ(ierr);
259d092c84bSBrandon Whitchurch       ierr = PetscObjectSetOptionsPrefix((PetscObject)subspace,prefix);CHKERRQ(ierr);
260417c287bSToby Isaac       ierr = PetscSNPrintf(subspacePrefix,256,"sumcomp_%D_",i);CHKERRQ(ierr);
261d092c84bSBrandon Whitchurch       ierr = PetscObjectAppendOptionsPrefix((PetscObject)subspace,subspacePrefix);CHKERRQ(ierr);
262d092c84bSBrandon Whitchurch     } else {
263d092c84bSBrandon Whitchurch       ierr = PetscObjectReference((PetscObject)subspace);CHKERRQ(ierr);
264d092c84bSBrandon Whitchurch     }
265d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetFromOptions(subspace);CHKERRQ(ierr);
266d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumVariables(subspace,&sNv);CHKERRQ(ierr);
267*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!sNv,PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Subspace %D has not been set properly, number of variables is 0.",i);
268d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetSubspace(sp,i,subspace);CHKERRQ(ierr);
269d092c84bSBrandon Whitchurch     ierr = PetscSpaceDestroy(&subspace);CHKERRQ(ierr);
270d092c84bSBrandon Whitchurch   }
271d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
272d092c84bSBrandon Whitchurch }
273d092c84bSBrandon Whitchurch 
274d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
275d092c84bSBrandon Whitchurch {
276d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
277d092c84bSBrandon Whitchurch   PetscBool      concatenate = PETSC_TRUE;
278642c7897SToby Isaac   PetscBool      uniform;
279642c7897SToby Isaac   PetscInt       Nv,Ns,Nc,i,sum_Nc = 0,deg = PETSC_MAX_INT,maxDeg = PETSC_MIN_INT;
280642c7897SToby Isaac   PetscInt       minNc,maxNc;
281d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
282d092c84bSBrandon Whitchurch 
283d092c84bSBrandon Whitchurch   PetscFunctionBegin;
284d092c84bSBrandon Whitchurch   if (sum->setupCalled) PetscFunctionReturn(0);
285d092c84bSBrandon Whitchurch 
286d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumVariables(sp,&Nv);CHKERRQ(ierr);
287d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumComponents(sp,&Nc);CHKERRQ(ierr);
288d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumGetNumSubspaces(sp,&Ns);CHKERRQ(ierr);
289d092c84bSBrandon Whitchurch   if (Ns == PETSC_DEFAULT) {
290d092c84bSBrandon Whitchurch     Ns   = 1;
291d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetNumSubspaces(sp,Ns);CHKERRQ(ierr);
292d092c84bSBrandon Whitchurch   }
293*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ns < 0,PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have %D subspaces", Ns);
294642c7897SToby Isaac   uniform = PETSC_TRUE;
295642c7897SToby Isaac   if (Ns) {
296642c7897SToby Isaac     PetscSpace s0;
297d092c84bSBrandon Whitchurch 
298642c7897SToby Isaac     ierr = PetscSpaceSumGetSubspace(sp,0,&s0);CHKERRQ(ierr);
299642c7897SToby Isaac     for (PetscInt i = 1; i < Ns; i++) {
300642c7897SToby Isaac       PetscSpace si;
301642c7897SToby Isaac 
302642c7897SToby Isaac       ierr = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
303642c7897SToby Isaac       if (si != s0) {
304642c7897SToby Isaac         uniform = PETSC_FALSE;
305642c7897SToby Isaac         break;
306642c7897SToby Isaac       }
307642c7897SToby Isaac     }
308642c7897SToby Isaac   }
309642c7897SToby Isaac 
310642c7897SToby Isaac   minNc = Nc;
311642c7897SToby Isaac   maxNc = Nc;
312d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
313d092c84bSBrandon Whitchurch     PetscInt   sNv,sNc,iDeg,iMaxDeg;
314d092c84bSBrandon Whitchurch     PetscSpace si;
315d092c84bSBrandon Whitchurch 
316d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
317d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetUp(si);CHKERRQ(ierr);
318d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumVariables(si,&sNv);CHKERRQ(ierr);
319*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(sNv != Nv,PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Subspace %D has %D variables, space has %D.",i,sNv,Nv);
320d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumComponents(si,&sNc);CHKERRQ(ierr);
321d092c84bSBrandon Whitchurch     if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
322642c7897SToby Isaac     minNc = PetscMin(minNc, sNc);
323642c7897SToby Isaac     maxNc = PetscMax(maxNc, sNc);
324d092c84bSBrandon Whitchurch     sum_Nc += sNc;
325d092c84bSBrandon Whitchurch     ierr    = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
326d092c84bSBrandon Whitchurch     ierr    = PetscSpaceGetDegree(si,&iDeg,&iMaxDeg);CHKERRQ(ierr);
327642c7897SToby Isaac     deg     = PetscMin(deg,iDeg);
328d092c84bSBrandon Whitchurch     maxDeg  = PetscMax(maxDeg,iMaxDeg);
329d092c84bSBrandon Whitchurch   }
330d092c84bSBrandon Whitchurch 
331d092c84bSBrandon Whitchurch   if (concatenate) {
332d092c84bSBrandon Whitchurch     if (sum_Nc != Nc) {
33398921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Total number of subspace components (%D) does not match number of target space components (%D).",sum_Nc,Nc);
334d092c84bSBrandon Whitchurch     }
335d092c84bSBrandon Whitchurch   } else {
336*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(minNc != Nc || maxNc != Nc,PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Subspaces must have same number of components as the target space.");
337d092c84bSBrandon Whitchurch   }
338d092c84bSBrandon Whitchurch 
339d092c84bSBrandon Whitchurch   sp->degree       = deg;
340d092c84bSBrandon Whitchurch   sp->maxDegree    = maxDeg;
341d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
342642c7897SToby Isaac   sum->uniform     = uniform;
343d092c84bSBrandon Whitchurch   sum->setupCalled = PETSC_TRUE;
344d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
345d092c84bSBrandon Whitchurch }
346d092c84bSBrandon Whitchurch 
347d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp,PetscViewer v)
348d092c84bSBrandon Whitchurch {
349d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
350d092c84bSBrandon Whitchurch   PetscBool      concatenate = sum->concatenate;
351d092c84bSBrandon Whitchurch   PetscInt       i,Ns         = sum->numSumSpaces;
352d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
353d092c84bSBrandon Whitchurch 
354d092c84bSBrandon Whitchurch   PetscFunctionBegin;
355d092c84bSBrandon Whitchurch   if (concatenate) {
356642c7897SToby Isaac     ierr = PetscViewerASCIIPrintf(v,"Sum space of %D concatenated subspaces%s\n",Ns, sum->uniform ? " (all identical)": "");CHKERRQ(ierr);
357d092c84bSBrandon Whitchurch   } else {
358642c7897SToby Isaac     ierr = PetscViewerASCIIPrintf(v,"Sum space of %D subspaces%s\n",Ns, sum->uniform ? " (all identical)" : "");CHKERRQ(ierr);
359d092c84bSBrandon Whitchurch   }
360642c7897SToby Isaac   for (i=0; i < (sum->uniform ? (Ns > 0 ? 1 : 0) : Ns); ++i) {
361d092c84bSBrandon Whitchurch     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
362d092c84bSBrandon Whitchurch     ierr = PetscSpaceView(sum->sumspaces[i],v);CHKERRQ(ierr);
363d092c84bSBrandon Whitchurch     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
364d092c84bSBrandon Whitchurch   }
365d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
366d092c84bSBrandon Whitchurch }
367d092c84bSBrandon Whitchurch 
368d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp,PetscViewer viewer)
369d092c84bSBrandon Whitchurch {
370d092c84bSBrandon Whitchurch   PetscBool      iascii;
371d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
372d092c84bSBrandon Whitchurch 
373d092c84bSBrandon Whitchurch   PetscFunctionBegin;
374d092c84bSBrandon Whitchurch   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
375d092c84bSBrandon Whitchurch   if (iascii) {
376d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumView_Ascii(sp,viewer);CHKERRQ(ierr);
377d092c84bSBrandon Whitchurch   }
378d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
379d092c84bSBrandon Whitchurch }
380d092c84bSBrandon Whitchurch 
381d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
382d092c84bSBrandon Whitchurch {
383d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
384d092c84bSBrandon Whitchurch   PetscInt       i,Ns   = sum->numSumSpaces;
385d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
386d092c84bSBrandon Whitchurch 
387d092c84bSBrandon Whitchurch   PetscFunctionBegin;
388d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
389d092c84bSBrandon Whitchurch     ierr = PetscSpaceDestroy(&sum->sumspaces[i]);CHKERRQ(ierr);
390d092c84bSBrandon Whitchurch   }
391d092c84bSBrandon Whitchurch   ierr = PetscFree(sum->sumspaces);CHKERRQ(ierr);
392642c7897SToby Isaac   if (sum->heightsubspaces) {
393642c7897SToby Isaac     PetscInt d;
394642c7897SToby Isaac 
395642c7897SToby Isaac     /* sp->Nv is the spatial dimension, so it is equal to the number
396642c7897SToby Isaac      * of subspaces on higher co-dimension points */
397642c7897SToby Isaac     for (d = 0; d < sp->Nv; ++d) {
398642c7897SToby Isaac       ierr = PetscSpaceDestroy(&sum->heightsubspaces[d]);CHKERRQ(ierr);
399642c7897SToby Isaac     }
400642c7897SToby Isaac   }
401642c7897SToby Isaac   ierr = PetscFree(sum->heightsubspaces);CHKERRQ(ierr);
402d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",NULL);CHKERRQ(ierr);
403d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",NULL);CHKERRQ(ierr);
404d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",NULL);CHKERRQ(ierr);
405d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",NULL);CHKERRQ(ierr);
406d092c84bSBrandon Whitchurch   ierr = PetscFree(sum);CHKERRQ(ierr);
407d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
408d092c84bSBrandon Whitchurch }
409d092c84bSBrandon Whitchurch 
410d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp,PetscInt *dim)
411d092c84bSBrandon Whitchurch {
412d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
413d092c84bSBrandon Whitchurch   PetscInt       i,d = 0,Ns = sum->numSumSpaces;
414d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
415d092c84bSBrandon Whitchurch 
416d092c84bSBrandon Whitchurch   PetscFunctionBegin;
417642c7897SToby Isaac   if (!sum->setupCalled) {
418d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetUp(sp);CHKERRQ(ierr);
419642c7897SToby Isaac     ierr = PetscSpaceGetDimension(sp, dim);CHKERRQ(ierr);
420642c7897SToby Isaac     PetscFunctionReturn(0);
421642c7897SToby Isaac   }
422d092c84bSBrandon Whitchurch 
423d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
424d092c84bSBrandon Whitchurch     PetscInt id;
425d092c84bSBrandon Whitchurch 
426d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetDimension(sum->sumspaces[i],&id);CHKERRQ(ierr);
427d092c84bSBrandon Whitchurch     d   += id;
428d092c84bSBrandon Whitchurch   }
429d092c84bSBrandon Whitchurch 
430d092c84bSBrandon Whitchurch   *dim = d;
431d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
432d092c84bSBrandon Whitchurch }
433d092c84bSBrandon Whitchurch 
434d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp,PetscInt npoints,const PetscReal points[],PetscReal B[],PetscReal D[],PetscReal H[])
435d092c84bSBrandon Whitchurch {
436d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
437d092c84bSBrandon Whitchurch   PetscBool      concatenate = sum->concatenate;
438d092c84bSBrandon Whitchurch   DM             dm = sp->dm;
439d092c84bSBrandon Whitchurch   PetscInt       Nc = sp->Nc,Nv = sp->Nv,Ns = sum->numSumSpaces;
440d092c84bSBrandon Whitchurch   PetscInt       i,s,offset,ncoffset,pdimfull,numelB,numelD,numelH;
441d092c84bSBrandon Whitchurch   PetscReal      *sB = NULL,*sD = NULL,*sH = NULL;
442d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
443d092c84bSBrandon Whitchurch 
444d092c84bSBrandon Whitchurch   PetscFunctionBegin;
445d092c84bSBrandon Whitchurch   if (!sum->setupCalled) {
446d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetUp(sp);CHKERRQ(ierr);
447642c7897SToby Isaac     ierr = PetscSpaceEvaluate(sp, npoints, points, B, D, H);CHKERRQ(ierr);
448642c7897SToby Isaac     PetscFunctionReturn(0);
449d092c84bSBrandon Whitchurch   }
450d092c84bSBrandon Whitchurch   ierr   = PetscSpaceGetDimension(sp,&pdimfull);CHKERRQ(ierr);
451d092c84bSBrandon Whitchurch   numelB = npoints*pdimfull*Nc;
452d092c84bSBrandon Whitchurch   numelD = numelB*Nv;
453d092c84bSBrandon Whitchurch   numelH = numelD*Nv;
454d092c84bSBrandon Whitchurch   if (B || D || H) {
455d092c84bSBrandon Whitchurch     ierr = DMGetWorkArray(dm,numelB,MPIU_REAL,&sB);CHKERRQ(ierr);
456d092c84bSBrandon Whitchurch   }
457d092c84bSBrandon Whitchurch   if (D || H) {
458d092c84bSBrandon Whitchurch     ierr = DMGetWorkArray(dm,numelD,MPIU_REAL,&sD);CHKERRQ(ierr);
459d092c84bSBrandon Whitchurch   }
460d092c84bSBrandon Whitchurch   if (H) {
461d092c84bSBrandon Whitchurch     ierr = DMGetWorkArray(dm,numelH,MPIU_REAL,&sH);CHKERRQ(ierr);
462d092c84bSBrandon Whitchurch   }
463d092c84bSBrandon Whitchurch   if (B)
464d092c84bSBrandon Whitchurch     for (i=0; i<numelB; ++i) B[i] = 0.;
465d092c84bSBrandon Whitchurch   if (D)
466d092c84bSBrandon Whitchurch     for (i=0; i<numelD; ++i) D[i] = 0.;
467d092c84bSBrandon Whitchurch   if (H)
468d092c84bSBrandon Whitchurch     for (i=0; i<numelH; ++i) H[i] = 0.;
469d092c84bSBrandon Whitchurch 
470d092c84bSBrandon Whitchurch   for (s=0,offset=0,ncoffset=0; s<Ns; ++s) {
471d092c84bSBrandon Whitchurch     PetscInt sNv,spdim,sNc,p;
472d092c84bSBrandon Whitchurch 
473d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumVariables(sum->sumspaces[s],&sNv);CHKERRQ(ierr);
474d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumComponents(sum->sumspaces[s],&sNc);CHKERRQ(ierr);
475d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetDimension(sum->sumspaces[s],&spdim);CHKERRQ(ierr);
476*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offset + spdim > pdimfull,PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Subspace dimensions exceed target space dimension.");
477642c7897SToby Isaac     if (s == 0 || !sum->uniform) {
478d092c84bSBrandon Whitchurch       ierr = PetscSpaceEvaluate(sum->sumspaces[s],npoints,points,sB,sD,sH);CHKERRQ(ierr);
479642c7897SToby Isaac     }
480d092c84bSBrandon Whitchurch     if (B || D || H) {
481d092c84bSBrandon Whitchurch       for (p=0; p<npoints; ++p) {
482d092c84bSBrandon Whitchurch         PetscInt j;
483d092c84bSBrandon Whitchurch 
484d092c84bSBrandon Whitchurch         for (j=0; j<spdim; ++j) {
485d092c84bSBrandon Whitchurch           PetscInt c;
486d092c84bSBrandon Whitchurch 
487d092c84bSBrandon Whitchurch           for (c=0; c<sNc; ++c) {
488d092c84bSBrandon Whitchurch             PetscInt compoffset,BInd,sBInd;
489d092c84bSBrandon Whitchurch 
490d092c84bSBrandon Whitchurch             compoffset = concatenate ? c+ncoffset : c;
491d092c84bSBrandon Whitchurch             BInd       = (p*pdimfull + j + offset)*Nc + compoffset;
492d092c84bSBrandon Whitchurch             sBInd      = (p*spdim + j)*sNc + c;
493642c7897SToby Isaac             if (B) B[BInd] = sB[sBInd];
494d092c84bSBrandon Whitchurch             if (D || H) {
495d092c84bSBrandon Whitchurch               PetscInt v;
496d092c84bSBrandon Whitchurch 
497d092c84bSBrandon Whitchurch               for (v=0; v<Nv; ++v) {
498d092c84bSBrandon Whitchurch                 PetscInt DInd,sDInd;
499d092c84bSBrandon Whitchurch 
500d092c84bSBrandon Whitchurch                 DInd  = BInd*Nv + v;
501d092c84bSBrandon Whitchurch                 sDInd = sBInd*Nv + v;
502642c7897SToby Isaac                 if (D) D[DInd] = sD[sDInd];
503d092c84bSBrandon Whitchurch                 if (H) {
504d092c84bSBrandon Whitchurch                   PetscInt v2;
505d092c84bSBrandon Whitchurch 
506d092c84bSBrandon Whitchurch                   for (v2=0; v2<Nv; ++v2) {
507d092c84bSBrandon Whitchurch                     PetscInt HInd,sHInd;
508d092c84bSBrandon Whitchurch 
509d092c84bSBrandon Whitchurch                     HInd    = DInd*Nv + v2;
510d092c84bSBrandon Whitchurch                     sHInd   = sDInd*Nv + v2;
511642c7897SToby Isaac                     H[HInd] = sH[sHInd];
512d092c84bSBrandon Whitchurch                   }
513d092c84bSBrandon Whitchurch                 }
514d092c84bSBrandon Whitchurch               }
515d092c84bSBrandon Whitchurch             }
516d092c84bSBrandon Whitchurch           }
517d092c84bSBrandon Whitchurch         }
518d092c84bSBrandon Whitchurch       }
519d092c84bSBrandon Whitchurch     }
520d092c84bSBrandon Whitchurch     offset   += spdim;
521d092c84bSBrandon Whitchurch     ncoffset += sNc;
522d092c84bSBrandon Whitchurch   }
523d092c84bSBrandon Whitchurch 
524d092c84bSBrandon Whitchurch   if (H) {
525d092c84bSBrandon Whitchurch     ierr = DMRestoreWorkArray(dm,numelH,MPIU_REAL,&sH);CHKERRQ(ierr);
526d092c84bSBrandon Whitchurch   }
527d092c84bSBrandon Whitchurch   if (D || H) {
528d092c84bSBrandon Whitchurch     ierr = DMRestoreWorkArray(dm,numelD,MPIU_REAL,&sD);CHKERRQ(ierr);
529d092c84bSBrandon Whitchurch   }
530d092c84bSBrandon Whitchurch   if (B || D || H) {
531d092c84bSBrandon Whitchurch     ierr = DMRestoreWorkArray(dm,numelB,MPIU_REAL,&sB);CHKERRQ(ierr);
532d092c84bSBrandon Whitchurch   }
533d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
534d092c84bSBrandon Whitchurch }
535d092c84bSBrandon Whitchurch 
536642c7897SToby Isaac static PetscErrorCode PetscSpaceGetHeightSubspace_Sum(PetscSpace sp, PetscInt height, PetscSpace *subsp)
537642c7897SToby Isaac {
538642c7897SToby Isaac   PetscSpace_Sum  *sum = (PetscSpace_Sum *) sp->data;
539642c7897SToby Isaac   PetscInt         Nc, dim, order;
540642c7897SToby Isaac   PetscBool        tensor;
541642c7897SToby Isaac   PetscErrorCode   ierr;
542642c7897SToby Isaac 
543642c7897SToby Isaac   PetscFunctionBegin;
544642c7897SToby Isaac   ierr = PetscSpaceGetNumComponents(sp, &Nc);CHKERRQ(ierr);
545642c7897SToby Isaac   ierr = PetscSpaceGetNumVariables(sp, &dim);CHKERRQ(ierr);
546642c7897SToby Isaac   ierr = PetscSpaceGetDegree(sp, &order, NULL);CHKERRQ(ierr);
547642c7897SToby Isaac   ierr = PetscSpacePolynomialGetTensor(sp, &tensor);CHKERRQ(ierr);
548*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(height > dim || height < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %D for dimension %D space", height, dim);
549642c7897SToby Isaac   if (!sum->heightsubspaces) {ierr = PetscCalloc1(dim, &sum->heightsubspaces);CHKERRQ(ierr);}
550642c7897SToby Isaac   if (height <= dim) {
551642c7897SToby Isaac     if (!sum->heightsubspaces[height-1]) {
552642c7897SToby Isaac       PetscSpace  sub;
553642c7897SToby Isaac       const char *name;
554642c7897SToby Isaac 
555642c7897SToby Isaac       ierr = PetscSpaceCreate(PetscObjectComm((PetscObject) sp), &sub);CHKERRQ(ierr);
556642c7897SToby Isaac       ierr = PetscObjectGetName((PetscObject) sp,  &name);CHKERRQ(ierr);
557642c7897SToby Isaac       ierr = PetscObjectSetName((PetscObject) sub,  name);CHKERRQ(ierr);
558642c7897SToby Isaac       ierr = PetscSpaceSetType(sub, PETSCSPACESUM);CHKERRQ(ierr);
559642c7897SToby Isaac       ierr = PetscSpaceSumSetNumSubspaces(sub, sum->numSumSpaces);CHKERRQ(ierr);
560642c7897SToby Isaac       ierr = PetscSpaceSumSetConcatenate(sub, sum->concatenate);CHKERRQ(ierr);
561642c7897SToby Isaac       ierr = PetscSpaceSetNumComponents(sub, Nc);CHKERRQ(ierr);
562642c7897SToby Isaac       ierr = PetscSpaceSetNumVariables(sub, dim-height);CHKERRQ(ierr);
563642c7897SToby Isaac       for (PetscInt i = 0; i < sum->numSumSpaces; i++) {
564642c7897SToby Isaac         PetscSpace subh;
565642c7897SToby Isaac 
566642c7897SToby Isaac         ierr = PetscSpaceGetHeightSubspace(sum->sumspaces[i], height, &subh);CHKERRQ(ierr);
567642c7897SToby Isaac         ierr = PetscSpaceSumSetSubspace(sub, i, subh);CHKERRQ(ierr);
568642c7897SToby Isaac       }
569642c7897SToby Isaac       ierr = PetscSpaceSetUp(sub);CHKERRQ(ierr);
570642c7897SToby Isaac       sum->heightsubspaces[height-1] = sub;
571642c7897SToby Isaac     }
572642c7897SToby Isaac     *subsp = sum->heightsubspaces[height-1];
573642c7897SToby Isaac   } else {
574642c7897SToby Isaac     *subsp = NULL;
575642c7897SToby Isaac   }
576642c7897SToby Isaac   PetscFunctionReturn(0);
577642c7897SToby Isaac }
578642c7897SToby Isaac 
579d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
580d092c84bSBrandon Whitchurch {
581d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
582d092c84bSBrandon Whitchurch 
583d092c84bSBrandon Whitchurch   PetscFunctionBegin;
584d092c84bSBrandon Whitchurch   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Sum;
585d092c84bSBrandon Whitchurch   sp->ops->setup             = PetscSpaceSetUp_Sum;
586d092c84bSBrandon Whitchurch   sp->ops->view              = PetscSpaceView_Sum;
587d092c84bSBrandon Whitchurch   sp->ops->destroy           = PetscSpaceDestroy_Sum;
588d092c84bSBrandon Whitchurch   sp->ops->getdimension      = PetscSpaceGetDimension_Sum;
589d092c84bSBrandon Whitchurch   sp->ops->evaluate          = PetscSpaceEvaluate_Sum;
590642c7897SToby Isaac   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Sum;
591d092c84bSBrandon Whitchurch 
592d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",PetscSpaceSumGetNumSubspaces_Sum);CHKERRQ(ierr);
593d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",PetscSpaceSumSetNumSubspaces_Sum);CHKERRQ(ierr);
594d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",PetscSpaceSumGetSubspace_Sum);CHKERRQ(ierr);
595d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",PetscSpaceSumSetSubspace_Sum);CHKERRQ(ierr);
596d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetConcatenate_C",PetscSpaceSumGetConcatenate_Sum);CHKERRQ(ierr);
597d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetConcatenate_C",PetscSpaceSumSetConcatenate_Sum);CHKERRQ(ierr);
598d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
599d092c84bSBrandon Whitchurch }
600d092c84bSBrandon Whitchurch 
601d092c84bSBrandon Whitchurch /*MC
602d092c84bSBrandon Whitchurch   PETSCSPACESUM = "sum" - A PetscSpace object that encapsulates a sum of subspaces.
603d092c84bSBrandon Whitchurch   That sum can either be direct or concatenate a concatenation.For example if A and B are spaces each with 2 components,
604d092c84bSBrandon Whitchurch   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
605d092c84bSBrandon Whitchurch   same number of variables.
606d092c84bSBrandon Whitchurch 
607d092c84bSBrandon Whitchurch Level: intermediate
608d092c84bSBrandon Whitchurch 
609d092c84bSBrandon Whitchurch .seealso: PetscSpaceType, PetscSpaceCreate(), PetscSpaceSetType()
610d092c84bSBrandon Whitchurch M*/
611d092c84bSBrandon Whitchurch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
612d092c84bSBrandon Whitchurch {
613d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum;
614d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
615d092c84bSBrandon Whitchurch 
616d092c84bSBrandon Whitchurch   PetscFunctionBegin;
617d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
618d092c84bSBrandon Whitchurch   ierr     = PetscNewLog(sp,&sum);CHKERRQ(ierr);
619642c7897SToby Isaac   sum->numSumSpaces = PETSC_DEFAULT;
620d092c84bSBrandon Whitchurch   sp->data = sum;
621d092c84bSBrandon Whitchurch   ierr     = PetscSpaceInitialize_Sum(sp);CHKERRQ(ierr);
622d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
623d092c84bSBrandon Whitchurch }
624d092c84bSBrandon Whitchurch 
625d092c84bSBrandon Whitchurch PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces,const PetscSpace subspaces[],PetscBool concatenate,PetscSpace *sumSpace)
626d092c84bSBrandon Whitchurch {
627d092c84bSBrandon Whitchurch   PetscInt       i,Nv,Nc = 0;
628d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
629d092c84bSBrandon Whitchurch 
630d092c84bSBrandon Whitchurch   PetscFunctionBegin;
631d092c84bSBrandon Whitchurch   if (sumSpace) {
632d092c84bSBrandon Whitchurch     ierr = PetscSpaceDestroy(sumSpace);CHKERRQ(ierr);
633d092c84bSBrandon Whitchurch   }
634d092c84bSBrandon Whitchurch   ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]),sumSpace);CHKERRQ(ierr);
635d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetType(*sumSpace,PETSCSPACESUM);CHKERRQ(ierr);
636d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumSetNumSubspaces(*sumSpace,numSubspaces);CHKERRQ(ierr);
637d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumSetConcatenate(*sumSpace,concatenate);CHKERRQ(ierr);
638d092c84bSBrandon Whitchurch   for (i=0; i<numSubspaces; ++i) {
639d092c84bSBrandon Whitchurch     PetscInt sNc;
640d092c84bSBrandon Whitchurch 
641d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetSubspace(*sumSpace,i,subspaces[i]);CHKERRQ(ierr);
642d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumComponents(subspaces[i],&sNc);CHKERRQ(ierr);
643d092c84bSBrandon Whitchurch     if (concatenate) Nc += sNc;
644d092c84bSBrandon Whitchurch     else Nc = sNc;
645d092c84bSBrandon Whitchurch   }
646d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumVariables(subspaces[0],&Nv);CHKERRQ(ierr);
647d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetNumComponents(*sumSpace,Nc);CHKERRQ(ierr);
648d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetNumVariables(*sumSpace,Nv);CHKERRQ(ierr);
649d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetUp(*sumSpace);CHKERRQ(ierr);
650d092c84bSBrandon Whitchurch 
651d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
652d092c84bSBrandon Whitchurch }
653